@alwatr/debounce 1.1.20 โ†’ 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../src/debounce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,OAAO;IAK1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJrC,OAAO,CAAC,SAAS,CAAC,CAA0B;IAC5C,OAAO,CAAC,gBAAgB,CAAC,CAA0B;IACnD,OAAO,CAAC,UAAU,CAAC,CAAgB;gBAEN,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IAKzD;;;OAGG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;;;;;;;;;;;;;;OAgBG;IACI,OAAO,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;IAwB5C;;;;;;;;;;;;;;;OAeG;IACI,MAAM,IAAI,IAAI;IAUrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAMjB;;;;;;;;;;;;;;;;;OAiBG;IACI,KAAK,IAAI,IAAI;IAOpB;;OAEG;IACH,OAAO,CAAC,QAAQ;CAOjB"}
1
+ {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../src/debounce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,OAAO;IAK1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJrC,OAAO,CAAC,SAAS,CAAC,CAA0B;IAC5C,OAAO,CAAC,gBAAgB,CAAC,CAA0B;IACnD,OAAO,CAAC,UAAU,CAAC,CAAgB;gBAEN,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IAOzD;;;OAGG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;;;;;;;;;;;;;;OAgBG;IACI,OAAO,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;IAwB5C;;;;;;;;;;;;;;;OAeG;IACI,MAAM,IAAI,IAAI;IAUrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAMjB;;;;;;;;;;;;;;;;;OAiBG;IACI,KAAK,IAAI,IAAI;IAOpB;;OAEG;IACH,OAAO,CAAC,QAAQ;CAOjB"}
package/dist/main.js ADDED
@@ -0,0 +1,5 @@
1
+ /* ๐Ÿ“ฆ @alwatr/debounce v2.0.0 */
2
+ class z{config__;timerId__;maxWaitTimerId__;lastArgs__;constructor(q){this.config__=q;this.config__.trailing??=!0,this.flush=this.flush.bind(this),this.trigger=this.trigger.bind(this),this.cancel=this.cancel.bind(this)}get isPending(){return this.timerId__!==void 0}trigger(...q){if(this.lastArgs__=q,!this.isPending){if(this.config__.maxWait)this.maxWaitTimerId__=setTimeout(this.flush,this.config__.maxWait);if(this.config__.leading===!0)this.invoke__()}else clearTimeout(this.timerId__);this.timerId__=setTimeout(()=>{if(this.config__.trailing===!0)this.invoke__();this.cleanup__()},this.config__.delay)}cancel(){if(this.timerId__)clearTimeout(this.timerId__);if(this.maxWaitTimerId__)clearTimeout(this.maxWaitTimerId__);this.cleanup__()}cleanup__(){delete this.timerId__,delete this.maxWaitTimerId__,delete this.lastArgs__}flush(){if(this.isPending)this.invoke__();this.cancel()}invoke__(){if(this.lastArgs__)this.config__.func.apply(this.config__.thisContext,this.lastArgs__),this.lastArgs__=void 0}}function G(q){return new z(q)}export{G as createDebouncer,z as Debouncer};
3
+
4
+ //# debugId=D7DE4832A046BAB664756E2164756E21
5
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/debounce.ts", "../src/main.ts"],
4
+ "sourcesContent": [
5
+ "import type {DebouncerConfig} from './type.ts';\n\n/**\n * A powerful and type-safe Debouncer class.\n *\n * It encapsulates the debouncing logic, state, and provides a rich control API.\n * Debouncing delays function execution until after a specified delay has passed since the last invocation.\n * Useful for optimizing performance in scenarios like search inputs, resize events, or API calls.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: (text: string) => console.log('Searching:', text),\n * delay: 300,\n * leading: false,\n * trailing: true,\n * });\n *\n * // Debounce search input\n * debouncer.trigger('hello');\n * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms\n *\n * // Advanced: With leading edge\n * const leadingDebouncer = new Debouncer({\n * func: () => console.log('Immediate and delayed'),\n * delay: 500,\n * leading: true,\n * trailing: true,\n * });\n * leadingDebouncer.trigger(); // Logs immediately, then again after 500ms if not cancelled\n * ```\n */\nexport class Debouncer<F extends AnyFunc> {\n private timerId__?: number | NodeJS.Timeout;\n private maxWaitTimerId__?: number | NodeJS.Timeout;\n private lastArgs__?: Parameters<F>;\n\n constructor(private readonly config__: DebouncerConfig<F>) {\n this.config__.trailing ??= true;\n this.flush = this.flush.bind(this);\n this.trigger = this.trigger.bind(this);\n this.cancel = this.cancel.bind(this);\n }\n\n /**\n * Checks if there is a pending execution scheduled.\n * Returns true if a timer is active, indicating a debounced call is waiting.\n */\n public get isPending(): boolean {\n return this.timerId__ !== undefined;\n }\n\n /**\n * Triggers the debounced function with the stored `thisContext`.\n * @param args The arguments to pass to the `func`.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: (value: number) => console.log('Value:', value),\n * delay: 500,\n * });\n * debouncer.trigger(42); // Logs after 500ms if not triggered again\n *\n * // Edge case: Rapid triggers only execute the last one\n * debouncer.trigger(1);\n * debouncer.trigger(2); // Only 2 will execute after delay\n * ```\n */\n public trigger(...args: Parameters<F>): void {\n this.lastArgs__ = args; // its an array even if triggered without any args\n const firstTrigger = !this.isPending;\n\n if (firstTrigger) {\n if (this.config__.maxWait) {\n this.maxWaitTimerId__ = setTimeout(this.flush, this.config__.maxWait);\n }\n if (this.config__.leading === true) {\n this.invoke__();\n }\n }\n else {\n clearTimeout(this.timerId__!);\n }\n\n this.timerId__ = setTimeout(() => {\n if (this.config__.trailing === true) {\n this.invoke__();\n }\n this.cleanup__();\n }, this.config__.delay);\n }\n\n /**\n * Cancels any pending debounced execution and cleans up internal state.\n * Useful for stopping execution when the operation is no longer needed (e.g., component unmount).\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: () => console.log('Executed'),\n * delay: 1000,\n * });\n * debouncer.trigger();\n * debouncer.cancel(); // Prevents execution\n *\n * // Note: After cancel, isPending becomes false\n * ```\n */\n public cancel(): void {\n if (this.timerId__) {\n clearTimeout(this.timerId__);\n }\n if (this.maxWaitTimerId__) {\n clearTimeout(this.maxWaitTimerId__);\n }\n this.cleanup__();\n }\n\n /**\n * Cleans up internal state by deleting timer and arguments.\n */\n private cleanup__(): void {\n delete this.timerId__;\n delete this.maxWaitTimerId__;\n delete this.lastArgs__;\n }\n\n /**\n * Immediately executes the pending function if one exists.\n * Bypasses the delay and cleans up state. If no pending call, does nothing.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: () => console.log('Flushed'),\n * delay: 1000,\n * });\n * debouncer.trigger();\n * setTimeout(() => debouncer.flush(), 500); // Executes immediately\n *\n * // Edge case: Flush after cancel does nothing\n * debouncer.cancel();\n * debouncer.flush(); // No execution\n * ```\n */\n public flush(): void {\n if (this.isPending) {\n this.invoke__();\n }\n this.cancel();\n }\n\n /**\n * The core execution logic.\n */\n private invoke__(): void {\n if (this.lastArgs__) {\n // only call if we have new args (skip trailing call if leading already called)\n this.config__.func.apply(this.config__.thisContext, this.lastArgs__);\n this.lastArgs__ = undefined;\n }\n }\n}\n",
6
+ "import {Debouncer} from './debounce.js';\n\nimport type {DebouncerConfig} from './type.js';\n\nexport * from './debounce.js';\nexport type * from './type.js';\n\n/**\n * Factory function for creating a Debouncer instance for better type inference.\n * @param config Configuration for the debouncer.\n *\n * @example\n * ```typescript\n * const debouncer = createDebouncer({\n * func: (text: string) => console.log('Searching:', text),\n * delay: 300,\n * leading: false,\n * trailing: true,\n * });\n *\n * // Debounce search input\n * debouncer.trigger('hello');\n * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms\n *\n * // With custom thisContext\n * const obj = { log: (msg: string) => console.log('Obj:', msg) };\n * const debouncerWithContext = createDebouncer({\n * func: obj.log,\n * thisContext: obj,\n * delay: 200,\n * });\n * debouncerWithContext.trigger('test'); // Logs 'Obj: test'\n * ```\n */\nexport function createDebouncer<F extends AnyFunc>(config: DebouncerConfig<F>): Debouncer<F> {\n return new Debouncer(config);\n}\n"
7
+ ],
8
+ "mappings": ";AAgCO,MAAM,CAA6B,CAKX,SAJrB,UACA,iBACA,WAER,WAAW,CAAkB,EAA8B,CAA9B,gBAC3B,KAAK,SAAS,WAAa,GAC3B,KAAK,MAAQ,KAAK,MAAM,KAAK,IAAI,EACjC,KAAK,QAAU,KAAK,QAAQ,KAAK,IAAI,EACrC,KAAK,OAAS,KAAK,OAAO,KAAK,IAAI,KAO1B,UAAS,EAAY,CAC9B,OAAO,KAAK,YAAc,OAoBrB,OAAO,IAAI,EAA2B,CAI3C,GAHA,KAAK,WAAa,EACG,CAAC,KAAK,UAET,CAChB,GAAI,KAAK,SAAS,QAChB,KAAK,iBAAmB,WAAW,KAAK,MAAO,KAAK,SAAS,OAAO,EAEtE,GAAI,KAAK,SAAS,UAAY,GAC5B,KAAK,SAAS,EAIhB,kBAAa,KAAK,SAAU,EAG9B,KAAK,UAAY,WAAW,IAAM,CAChC,GAAI,KAAK,SAAS,WAAa,GAC7B,KAAK,SAAS,EAEhB,KAAK,UAAU,GACd,KAAK,SAAS,KAAK,EAmBjB,MAAM,EAAS,CACpB,GAAI,KAAK,UACP,aAAa,KAAK,SAAS,EAE7B,GAAI,KAAK,iBACP,aAAa,KAAK,gBAAgB,EAEpC,KAAK,UAAU,EAMT,SAAS,EAAS,CACxB,OAAO,KAAK,UACZ,OAAO,KAAK,iBACZ,OAAO,KAAK,WAqBP,KAAK,EAAS,CACnB,GAAI,KAAK,UACP,KAAK,SAAS,EAEhB,KAAK,OAAO,EAMN,QAAQ,EAAS,CACvB,GAAI,KAAK,WAEP,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,YAAa,KAAK,UAAU,EACnE,KAAK,WAAa,OAGxB,CCjIO,SAAS,CAAkC,CAAC,EAA0C,CAC3F,OAAO,IAAI,EAAU,CAAM",
9
+ "debugId": "D7DE4832A046BAB664756E2164756E21",
10
+ "names": []
11
+ }
package/package.json CHANGED
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "name": "@alwatr/debounce",
3
3
  "description": "A powerful, modern, and type-safe debouncer utility designed for high-performance applications. It's framework-agnostic, works seamlessly in both Node.js and browsers, and provides a rich API for fine-grained control over function execution.",
4
- "version": "1.1.20",
4
+ "version": "2.0.0",
5
5
  "author": "S. Ali Mihandoost <ali.mihandoost@gmail.com>",
6
6
  "bugs": "https://github.com/Alwatr/nanolib/issues",
7
7
  "devDependencies": {
8
- "@alwatr/nano-build": "6.4.2",
9
- "@alwatr/prettier-config": "6.0.2",
10
- "@alwatr/tsconfig-base": "6.0.4",
11
- "@alwatr/type-helper": "7.0.2",
8
+ "@alwatr/nano-build": "7.0.0",
9
+ "@alwatr/prettier-config": "7.0.0",
10
+ "@alwatr/tsconfig-base": "7.0.0",
11
+ "@alwatr/type-helper": "8.0.0",
12
12
  "@types/node": "^24.12.0",
13
13
  "typescript": "^5.9.3"
14
14
  },
15
15
  "exports": {
16
16
  ".": {
17
17
  "types": "./dist/main.d.ts",
18
- "import": "./dist/main.mjs",
19
- "require": "./dist/main.cjs"
18
+ "default": "./dist/main.js"
20
19
  }
21
20
  },
22
21
  "files": [
23
- "**/*.{js,mjs,cjs,map,d.ts,html,md,LEGAL.txt}",
22
+ "**/*.{js,mjs,cjs,ts,map,d.ts,html,LEGAL.txt}",
23
+ "README.md",
24
24
  "LICENSE",
25
25
  "!demo/**/*",
26
26
  "!**/*.test.js"
@@ -51,8 +51,6 @@
51
51
  "utility"
52
52
  ],
53
53
  "license": "MPL-2.0",
54
- "main": "./dist/main.cjs",
55
- "module": "./dist/main.mjs",
56
54
  "prettier": "@alwatr/prettier-config",
57
55
  "publishConfig": {
58
56
  "access": "public"
@@ -65,12 +63,12 @@
65
63
  "scripts": {
66
64
  "b": "bun run build",
67
65
  "build": "bun run build:ts && bun run build:es",
68
- "build:es": "nano-build --preset=module",
66
+ "build:es": "nano-build --preset=module src/main.ts",
69
67
  "build:ts": "tsc --build",
70
68
  "c": "bun run clean",
71
69
  "cb": "bun run clean && bun run build",
72
70
  "clean": "rm -rfv dist *.tsbuildinfo",
73
- "d": "bun run build:es && bun --enable-source-maps --trace-warnings",
71
+ "d": "bun run build:es && bun",
74
72
  "w": "bun run watch",
75
73
  "watch": "bun run watch:ts & bun run watch:es",
76
74
  "watch:es": "bun run build:es --watch",
@@ -79,5 +77,5 @@
79
77
  "sideEffects": false,
80
78
  "type": "module",
81
79
  "types": "./dist/main.d.ts",
82
- "gitHead": "c3889e3756b0a0f9b935a1b702a1373ac52cb379"
80
+ "gitHead": "056102a1c8a563bbae8a290b6830450f467322a3"
83
81
  }
@@ -0,0 +1,164 @@
1
+ import type {DebouncerConfig} from './type.ts';
2
+
3
+ /**
4
+ * A powerful and type-safe Debouncer class.
5
+ *
6
+ * It encapsulates the debouncing logic, state, and provides a rich control API.
7
+ * Debouncing delays function execution until after a specified delay has passed since the last invocation.
8
+ * Useful for optimizing performance in scenarios like search inputs, resize events, or API calls.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const debouncer = new Debouncer({
13
+ * func: (text: string) => console.log('Searching:', text),
14
+ * delay: 300,
15
+ * leading: false,
16
+ * trailing: true,
17
+ * });
18
+ *
19
+ * // Debounce search input
20
+ * debouncer.trigger('hello');
21
+ * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms
22
+ *
23
+ * // Advanced: With leading edge
24
+ * const leadingDebouncer = new Debouncer({
25
+ * func: () => console.log('Immediate and delayed'),
26
+ * delay: 500,
27
+ * leading: true,
28
+ * trailing: true,
29
+ * });
30
+ * leadingDebouncer.trigger(); // Logs immediately, then again after 500ms if not cancelled
31
+ * ```
32
+ */
33
+ export class Debouncer<F extends AnyFunc> {
34
+ private timerId__?: number | NodeJS.Timeout;
35
+ private maxWaitTimerId__?: number | NodeJS.Timeout;
36
+ private lastArgs__?: Parameters<F>;
37
+
38
+ constructor(private readonly config__: DebouncerConfig<F>) {
39
+ this.config__.trailing ??= true;
40
+ this.flush = this.flush.bind(this);
41
+ this.trigger = this.trigger.bind(this);
42
+ this.cancel = this.cancel.bind(this);
43
+ }
44
+
45
+ /**
46
+ * Checks if there is a pending execution scheduled.
47
+ * Returns true if a timer is active, indicating a debounced call is waiting.
48
+ */
49
+ public get isPending(): boolean {
50
+ return this.timerId__ !== undefined;
51
+ }
52
+
53
+ /**
54
+ * Triggers the debounced function with the stored `thisContext`.
55
+ * @param args The arguments to pass to the `func`.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * const debouncer = new Debouncer({
60
+ * func: (value: number) => console.log('Value:', value),
61
+ * delay: 500,
62
+ * });
63
+ * debouncer.trigger(42); // Logs after 500ms if not triggered again
64
+ *
65
+ * // Edge case: Rapid triggers only execute the last one
66
+ * debouncer.trigger(1);
67
+ * debouncer.trigger(2); // Only 2 will execute after delay
68
+ * ```
69
+ */
70
+ public trigger(...args: Parameters<F>): void {
71
+ this.lastArgs__ = args; // its an array even if triggered without any args
72
+ const firstTrigger = !this.isPending;
73
+
74
+ if (firstTrigger) {
75
+ if (this.config__.maxWait) {
76
+ this.maxWaitTimerId__ = setTimeout(this.flush, this.config__.maxWait);
77
+ }
78
+ if (this.config__.leading === true) {
79
+ this.invoke__();
80
+ }
81
+ }
82
+ else {
83
+ clearTimeout(this.timerId__!);
84
+ }
85
+
86
+ this.timerId__ = setTimeout(() => {
87
+ if (this.config__.trailing === true) {
88
+ this.invoke__();
89
+ }
90
+ this.cleanup__();
91
+ }, this.config__.delay);
92
+ }
93
+
94
+ /**
95
+ * Cancels any pending debounced execution and cleans up internal state.
96
+ * Useful for stopping execution when the operation is no longer needed (e.g., component unmount).
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const debouncer = new Debouncer({
101
+ * func: () => console.log('Executed'),
102
+ * delay: 1000,
103
+ * });
104
+ * debouncer.trigger();
105
+ * debouncer.cancel(); // Prevents execution
106
+ *
107
+ * // Note: After cancel, isPending becomes false
108
+ * ```
109
+ */
110
+ public cancel(): void {
111
+ if (this.timerId__) {
112
+ clearTimeout(this.timerId__);
113
+ }
114
+ if (this.maxWaitTimerId__) {
115
+ clearTimeout(this.maxWaitTimerId__);
116
+ }
117
+ this.cleanup__();
118
+ }
119
+
120
+ /**
121
+ * Cleans up internal state by deleting timer and arguments.
122
+ */
123
+ private cleanup__(): void {
124
+ delete this.timerId__;
125
+ delete this.maxWaitTimerId__;
126
+ delete this.lastArgs__;
127
+ }
128
+
129
+ /**
130
+ * Immediately executes the pending function if one exists.
131
+ * Bypasses the delay and cleans up state. If no pending call, does nothing.
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * const debouncer = new Debouncer({
136
+ * func: () => console.log('Flushed'),
137
+ * delay: 1000,
138
+ * });
139
+ * debouncer.trigger();
140
+ * setTimeout(() => debouncer.flush(), 500); // Executes immediately
141
+ *
142
+ * // Edge case: Flush after cancel does nothing
143
+ * debouncer.cancel();
144
+ * debouncer.flush(); // No execution
145
+ * ```
146
+ */
147
+ public flush(): void {
148
+ if (this.isPending) {
149
+ this.invoke__();
150
+ }
151
+ this.cancel();
152
+ }
153
+
154
+ /**
155
+ * The core execution logic.
156
+ */
157
+ private invoke__(): void {
158
+ if (this.lastArgs__) {
159
+ // only call if we have new args (skip trailing call if leading already called)
160
+ this.config__.func.apply(this.config__.thisContext, this.lastArgs__);
161
+ this.lastArgs__ = undefined;
162
+ }
163
+ }
164
+ }
package/src/main.ts ADDED
@@ -0,0 +1,37 @@
1
+ import {Debouncer} from './debounce.js';
2
+
3
+ import type {DebouncerConfig} from './type.js';
4
+
5
+ export * from './debounce.js';
6
+ export type * from './type.js';
7
+
8
+ /**
9
+ * Factory function for creating a Debouncer instance for better type inference.
10
+ * @param config Configuration for the debouncer.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const debouncer = createDebouncer({
15
+ * func: (text: string) => console.log('Searching:', text),
16
+ * delay: 300,
17
+ * leading: false,
18
+ * trailing: true,
19
+ * });
20
+ *
21
+ * // Debounce search input
22
+ * debouncer.trigger('hello');
23
+ * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms
24
+ *
25
+ * // With custom thisContext
26
+ * const obj = { log: (msg: string) => console.log('Obj:', msg) };
27
+ * const debouncerWithContext = createDebouncer({
28
+ * func: obj.log,
29
+ * thisContext: obj,
30
+ * delay: 200,
31
+ * });
32
+ * debouncerWithContext.trigger('test'); // Logs 'Obj: test'
33
+ * ```
34
+ */
35
+ export function createDebouncer<F extends AnyFunc>(config: DebouncerConfig<F>): Debouncer<F> {
36
+ return new Debouncer(config);
37
+ }
package/src/type.ts ADDED
@@ -0,0 +1,53 @@
1
+ import type {} from '@alwatr/type-helper';
2
+
3
+ /**
4
+ * A single configuration object for creating a Debouncer.
5
+ * This groups all settings for a cleaner API.
6
+ *
7
+ * Key notes:
8
+ * - `leading` and `trailing` control execution timing: leading executes immediately on first trigger, trailing after delay.
9
+ * - If both are true, execution happens on first trigger and last trigger (after delay).
10
+ * - `thisContext` ensures the `func` is bound to the correct `this` value, useful in class methods or event handlers.
11
+ * - `delay` must be a positive number.
12
+ */
13
+ export interface DebouncerConfig<F extends AnyFunc> {
14
+ /**
15
+ * The function to be executed after the delay.
16
+ * Can be any function type, with type safety enforced by generics.
17
+ */
18
+ func: F;
19
+
20
+ /**
21
+ * The `this` context to be used when invoking the func.
22
+ * If provided, it will be stored and used for all invocations.
23
+ * Omit if the func doesn't rely on `this` or uses arrow functions.
24
+ */
25
+ thisContext?: ThisParameterType<F>;
26
+
27
+ /**
28
+ * The delay in milliseconds before the function is executed.
29
+ * Must be a positive integer; affects performance and responsiveness.
30
+ */
31
+ delay: number;
32
+
33
+ /**
34
+ * The maximum time the `func` is allowed to be delayed before it's invoked.
35
+ * This is useful for guaranteeing execution of a function that's continuously triggered.
36
+ * If set, the function will be called after `maxWait` milliseconds, even if triggers are still occurring.
37
+ */
38
+ maxWait?: number;
39
+
40
+ /**
41
+ * If `true`, the function is called on the leading edge of the timeout.
42
+ * Useful for immediate feedback (e.g., button press).
43
+ * @default false
44
+ */
45
+ leading?: boolean;
46
+
47
+ /**
48
+ * If `true`, the function is called on the trailing edge of the timeout.
49
+ * Ensures the last call is executed after inactivity.
50
+ * @default true
51
+ */
52
+ trailing?: boolean;
53
+ }
package/CHANGELOG.md DELETED
@@ -1,165 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
-
6
- ## [1.1.20](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.19...@alwatr/debounce@1.1.20) (2026-03-16)
7
-
8
- ### ๐Ÿ”จ Code Refactoring
9
-
10
- * migrate build scripts from yarn to bun across multiple packages ([d90e962](https://github.com/Alwatr/nanolib/commit/d90e962f15e5c951e191d5f02341279b6472abc3))
11
-
12
- ### ๐Ÿ”— Dependencies update
13
-
14
- * bump the npm-dependencies group with 10 updates ([c48d9ba](https://github.com/Alwatr/nanolib/commit/c48d9baa1cd7c2dc144b3e01e0fda60bf87c074c))
15
-
16
- ## [1.1.19](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.18...@alwatr/debounce@1.1.19) (2026-02-18)
17
-
18
- ### ๐Ÿ”— Dependencies update
19
-
20
- * update @types/node to version 24.10.13 across multiple packages ([4c6d2a3](https://github.com/Alwatr/nanolib/commit/4c6d2a37ab26b1c86812b2aa38b2eca4ee097cb6))
21
-
22
- ## [1.1.18](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.17...@alwatr/debounce@1.1.18) (2025-12-23)
23
-
24
- ### ๐Ÿ”— Dependencies update
25
-
26
- * upgrade @types/node to version 24.10.4 and update related dependencies ([acf04df](https://github.com/Alwatr/nanolib/commit/acf04df71647f5a401ef5e6bbfffcc478e4326d2))
27
-
28
- ## [1.1.17](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.16...@alwatr/debounce@1.1.17) (2025-12-13)
29
-
30
- ### ๐Ÿ› Bug Fixes
31
-
32
- * rename `AnyFunction` type alias to `AnyFunc` ([9865edc](https://github.com/Alwatr/nanolib/commit/9865edced9d377390454a8cbe7b6c5a6551195cb))
33
-
34
- ## [1.1.16](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.15...@alwatr/debounce@1.1.16) (2025-12-13)
35
-
36
- ### ๐Ÿ”— Dependencies update
37
-
38
- * update `@types/node` and `[@lerna-lite](https://github.com/lerna-lite)` dependencies. ([8daa8fd](https://github.com/Alwatr/nanolib/commit/8daa8fd023d5414c9f95feb4319353c6ea34be31))
39
-
40
- ## [1.1.15](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.14...@alwatr/debounce@1.1.15) (2025-12-10)
41
-
42
- ### ๐Ÿ”— Dependencies update
43
-
44
- * Upgrade lerna-lite, prettier, types/node, and yarn dependencies. ([42a7fca](https://github.com/Alwatr/nanolib/commit/42a7fca15430aca2ac1eaa19496c2a2ebfc8c470))
45
-
46
- ## [1.1.14](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.13...@alwatr/debounce@1.1.14) (2025-11-18)
47
-
48
- ### ๐Ÿ”จ Code Refactoring
49
-
50
- * remove unnecessary type declarations from tsconfig.json files ([89bcc7d](https://github.com/Alwatr/nanolib/commit/89bcc7db839807110b80f8ba34414ea9734d9c75))
51
-
52
- ## [1.1.13](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.12...@alwatr/debounce@1.1.13) (2025-11-15)
53
-
54
- ### ๐Ÿ”— Dependencies update
55
-
56
- * bump the npm-dependencies group with 2 updates ([a80b84d](https://github.com/Alwatr/nanolib/commit/a80b84dada6c09b5e5621e7487c8ec13fff3c23a))
57
-
58
- ## [1.1.12](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.11...@alwatr/debounce@1.1.12) (2025-11-15)
59
-
60
- **Note:** Version bump only for package @alwatr/debounce
61
-
62
- ## [1.1.11](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.10...@alwatr/debounce@1.1.11) (2025-11-04)
63
-
64
- ### ๐Ÿ”— Dependencies update
65
-
66
- * bump the npm-dependencies group across 1 directory with 9 updates ([fdf29d5](https://github.com/Alwatr/nanolib/commit/fdf29d5aa89983cb06f79d42650a364521f5c4b9))
67
- * update @types/node from ^22.18.12 to ^24.10.0 across multiple packages ([1169a86](https://github.com/Alwatr/nanolib/commit/1169a86001da2abfbe99a7da33c8e92183f553f6))
68
-
69
- ## [1.1.10](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.9...@alwatr/debounce@1.1.10) (2025-10-06)
70
-
71
- ### ๐Ÿ”— Dependencies update
72
-
73
- * bump the npm-dependencies group with 4 updates ([9825815](https://github.com/Alwatr/nanolib/commit/982581552bbb4b97dca52af5e93a80937f0c3109))
74
-
75
- ## [1.1.9](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.8...@alwatr/debounce@1.1.9) (2025-09-27)
76
-
77
- ### ๐Ÿงน Miscellaneous Chores
78
-
79
- * exclude test files from package distribution ([86f4f2f](https://github.com/Alwatr/nanolib/commit/86f4f2f5985845c5cf3a3a9398de7b2f98ce53e7))
80
-
81
- ## [1.1.8](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.7...@alwatr/debounce@1.1.8) (2025-09-22)
82
-
83
- **Note:** Version bump only for package @alwatr/debounce
84
-
85
- ## [1.1.7](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.6...@alwatr/debounce@1.1.7) (2025-09-22)
86
-
87
- **Note:** Version bump only for package @alwatr/debounce
88
-
89
- ## [1.1.6](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.5...@alwatr/debounce@1.1.6) (2025-09-21)
90
-
91
- **Note:** Version bump only for package @alwatr/debounce
92
-
93
- ## [1.1.5](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.4...@alwatr/debounce@1.1.5) (2025-09-20)
94
-
95
- ### ๐Ÿ› Bug Fixes
96
-
97
- * add sideEffects property to package.json files for better tree-shaking ([c7b9e74](https://github.com/Alwatr/nanolib/commit/c7b9e74e1920c8e35b438742de61883ca62da58c))
98
- * add sideEffects property to package.json files for better tree-shaking ([e8402c4](https://github.com/Alwatr/nanolib/commit/e8402c481a14a1f807a37aaa862a936713d26176))
99
-
100
- ### ๐Ÿงน Miscellaneous Chores
101
-
102
- * remove duplicate sideEffects property from multiple package.json files ([b123f86](https://github.com/Alwatr/nanolib/commit/b123f86be81481de2314aae9bb2eeb629743d24c))
103
-
104
- ## [1.1.4](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.3...@alwatr/debounce@1.1.4) (2025-09-20)
105
-
106
- ### ๐Ÿ› Bug Fixes
107
-
108
- * bind flush method in Debouncer constructor for proper context handling ([bdbeaed](https://github.com/Alwatr/nanolib/commit/bdbeaeddb2492da65476c374e9707e335cc39726))
109
-
110
- ## [1.1.3](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.2...@alwatr/debounce@1.1.3) (2025-09-19)
111
-
112
- **Note:** Version bump only for package @alwatr/debounce
113
-
114
- ## [1.1.2](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.1...@alwatr/debounce@1.1.2) (2025-09-15)
115
-
116
- **Note:** Version bump only for package @alwatr/debounce
117
-
118
- ## [1.1.1](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.1.0...@alwatr/debounce@1.1.1) (2025-09-15)
119
-
120
- ### ๐Ÿ› Bug Fixes
121
-
122
- * bind flush method correctly in Debouncer and improve readability of invoke logic ([5ddb12c](https://github.com/Alwatr/nanolib/commit/5ddb12c7d5d6040edad0f37ae79b3f725481d1f7))
123
-
124
- ## [1.1.0](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.0.1...@alwatr/debounce@1.1.0) (2025-09-14)
125
-
126
- ### โœจ Features
127
-
128
- * add maxWait option to Debouncer for guaranteed execution ([a305a6e](https://github.com/Alwatr/nanolib/commit/a305a6e82f96feebe2e895cdd35676da0f8b79f6))
129
-
130
- ### ๐Ÿ› Bug Fixes
131
-
132
- * bind flush method in constructor for correct context ([671315c](https://github.com/Alwatr/nanolib/commit/671315cdadab448df660ae53c973eb71d4124699))
133
-
134
- ### ๐Ÿ”จ Code Refactoring
135
-
136
- * add missing type import for DebouncerConfig ([d0c5808](https://github.com/Alwatr/nanolib/commit/d0c5808f2b6eb6fe856f8a38f5a79d2c427cf928))
137
- * improve trigger logic and clean up documentation comments ([cce9162](https://github.com/Alwatr/nanolib/commit/cce9162f2ee1c1fa2978ba04cd1be2eac5302b9e))
138
- * simplify trailing call logic and ensure lastArgs are cleared after invocation ([e8f74da](https://github.com/Alwatr/nanolib/commit/e8f74da9660c0c44d2704eb863bb082bce9a5978))
139
- * streamline invoke logic and restore createDebouncer function ([9bdc412](https://github.com/Alwatr/nanolib/commit/9bdc4124cdea3b267c040ec770a002ed64a814ac))
140
-
141
- ## [1.0.1](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.0.0...@alwatr/debounce@1.0.1) (2025-09-14)
142
-
143
- ### ๐Ÿ”จ Code Refactoring
144
-
145
- * **debounce:** rename 'callback' to 'func' for consistency in API ([df7ede1](https://github.com/Alwatr/nanolib/commit/df7ede1a78109831cca22389bd2d69df2e0ae366))
146
-
147
- ## [1.0.0](https://github.com/Alwatr/nanolib/compare/@alwatr/debounce@1.0.0-rc.0...@alwatr/debounce@1.0.0) (2025-09-14)
148
-
149
- ### ๐Ÿ”จ Code Refactoring
150
-
151
- * **package:** update keywords in package.json for debounce, local-storage, and synapse packages ([09c9cca](https://github.com/Alwatr/nanolib/commit/09c9cca3cd600e9ffaf600fb1926c0ee884a1aa8))
152
-
153
- ## 1.0.0-rc.0 (2025-09-13)
154
-
155
- ### โœจ Features
156
-
157
- * add debounce package with initial implementation and configuration files ([6293660](https://github.com/Alwatr/nanolib/commit/62936605c246c825f15178b68ac22ee474b95cf5))
158
-
159
- ### ๐Ÿ”จ Code Refactoring
160
-
161
- * update Debouncer class and configuration interface for improved type safety and clarity ([f064a98](https://github.com/Alwatr/nanolib/commit/f064a98dfce1a7e997badac3002f02a16dffc57e))
162
-
163
- ### ๐Ÿ”— Dependencies update
164
-
165
- * update @types/node version to ^22.18.3 in multiple package.json files ([13db6fc](https://github.com/Alwatr/nanolib/commit/13db6fc176bc6cdcefedc50d77ac550bd5052c9a))
package/dist/main.cjs DELETED
@@ -1,3 +0,0 @@
1
- /** ๐Ÿ“ฆ @alwatr/debounce v1.1.20 */
2
- "use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var main_exports={};__export(main_exports,{Debouncer:()=>Debouncer,createDebouncer:()=>createDebouncer});module.exports=__toCommonJS(main_exports);var Debouncer=class{constructor(config__){this.config__=config__;this.config__.trailing??=true;this.flush=this.flush.bind(this)}get isPending(){return this.timerId__!==void 0}trigger(...args){this.lastArgs__=args;const firstTrigger=!this.isPending;if(firstTrigger){if(this.config__.maxWait){this.maxWaitTimerId__=setTimeout(this.flush,this.config__.maxWait)}if(this.config__.leading===true){this.invoke__()}}else{clearTimeout(this.timerId__)}this.timerId__=setTimeout(()=>{if(this.config__.trailing===true){this.invoke__()}this.cleanup__()},this.config__.delay)}cancel(){if(this.timerId__){clearTimeout(this.timerId__)}if(this.maxWaitTimerId__){clearTimeout(this.maxWaitTimerId__)}this.cleanup__()}cleanup__(){delete this.timerId__;delete this.maxWaitTimerId__;delete this.lastArgs__}flush(){if(this.isPending){this.invoke__()}this.cancel()}invoke__(){if(this.lastArgs__){this.config__.func.apply(this.config__.thisContext,this.lastArgs__);this.lastArgs__=void 0}}};function createDebouncer(config){return new Debouncer(config)}0&&(module.exports={Debouncer,createDebouncer});
3
- //# sourceMappingURL=main.cjs.map
package/dist/main.cjs.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/main.ts", "../src/debounce.ts"],
4
- "sourcesContent": ["import {Debouncer} from './debounce.js';\n\nimport type {DebouncerConfig} from './type.js';\n\nexport * from './debounce.js';\nexport type * from './type.js';\n\n/**\n * Factory function for creating a Debouncer instance for better type inference.\n * @param config Configuration for the debouncer.\n *\n * @example\n * ```typescript\n * const debouncer = createDebouncer({\n * func: (text: string) => console.log('Searching:', text),\n * delay: 300,\n * leading: false,\n * trailing: true,\n * });\n *\n * // Debounce search input\n * debouncer.trigger('hello');\n * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms\n *\n * // With custom thisContext\n * const obj = { log: (msg: string) => console.log('Obj:', msg) };\n * const debouncerWithContext = createDebouncer({\n * func: obj.log,\n * thisContext: obj,\n * delay: 200,\n * });\n * debouncerWithContext.trigger('test'); // Logs 'Obj: test'\n * ```\n */\nexport function createDebouncer<F extends AnyFunc>(config: DebouncerConfig<F>): Debouncer<F> {\n return new Debouncer(config);\n}\n", "import type {DebouncerConfig} from './type.ts';\n\n/**\n * A powerful and type-safe Debouncer class.\n *\n * It encapsulates the debouncing logic, state, and provides a rich control API.\n * Debouncing delays function execution until after a specified delay has passed since the last invocation.\n * Useful for optimizing performance in scenarios like search inputs, resize events, or API calls.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: (text: string) => console.log('Searching:', text),\n * delay: 300,\n * leading: false,\n * trailing: true,\n * });\n *\n * // Debounce search input\n * debouncer.trigger('hello');\n * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms\n *\n * // Advanced: With leading edge\n * const leadingDebouncer = new Debouncer({\n * func: () => console.log('Immediate and delayed'),\n * delay: 500,\n * leading: true,\n * trailing: true,\n * });\n * leadingDebouncer.trigger(); // Logs immediately, then again after 500ms if not cancelled\n * ```\n */\nexport class Debouncer<F extends AnyFunc> {\n private timerId__?: number | NodeJS.Timeout;\n private maxWaitTimerId__?: number | NodeJS.Timeout;\n private lastArgs__?: Parameters<F>;\n\n constructor(private readonly config__: DebouncerConfig<F>) {\n this.config__.trailing ??= true;\n this.flush = this.flush.bind(this);\n }\n\n /**\n * Checks if there is a pending execution scheduled.\n * Returns true if a timer is active, indicating a debounced call is waiting.\n */\n public get isPending(): boolean {\n return this.timerId__ !== undefined;\n }\n\n /**\n * Triggers the debounced function with the stored `thisContext`.\n * @param args The arguments to pass to the `func`.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: (value: number) => console.log('Value:', value),\n * delay: 500,\n * });\n * debouncer.trigger(42); // Logs after 500ms if not triggered again\n *\n * // Edge case: Rapid triggers only execute the last one\n * debouncer.trigger(1);\n * debouncer.trigger(2); // Only 2 will execute after delay\n * ```\n */\n public trigger(...args: Parameters<F>): void {\n this.lastArgs__ = args; // its an array even if triggered without any args\n const firstTrigger = !this.isPending;\n\n if (firstTrigger) {\n if (this.config__.maxWait) {\n this.maxWaitTimerId__ = setTimeout(this.flush, this.config__.maxWait);\n }\n if (this.config__.leading === true) {\n this.invoke__();\n }\n }\n else {\n clearTimeout(this.timerId__!);\n }\n\n this.timerId__ = setTimeout(() => {\n if (this.config__.trailing === true) {\n this.invoke__();\n }\n this.cleanup__();\n }, this.config__.delay);\n }\n\n /**\n * Cancels any pending debounced execution and cleans up internal state.\n * Useful for stopping execution when the operation is no longer needed (e.g., component unmount).\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: () => console.log('Executed'),\n * delay: 1000,\n * });\n * debouncer.trigger();\n * debouncer.cancel(); // Prevents execution\n *\n * // Note: After cancel, isPending becomes false\n * ```\n */\n public cancel(): void {\n if (this.timerId__) {\n clearTimeout(this.timerId__);\n }\n if (this.maxWaitTimerId__) {\n clearTimeout(this.maxWaitTimerId__);\n }\n this.cleanup__();\n }\n\n /**\n * Cleans up internal state by deleting timer and arguments.\n */\n private cleanup__(): void {\n delete this.timerId__;\n delete this.maxWaitTimerId__;\n delete this.lastArgs__;\n }\n\n /**\n * Immediately executes the pending function if one exists.\n * Bypasses the delay and cleans up state. If no pending call, does nothing.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: () => console.log('Flushed'),\n * delay: 1000,\n * });\n * debouncer.trigger();\n * setTimeout(() => debouncer.flush(), 500); // Executes immediately\n *\n * // Edge case: Flush after cancel does nothing\n * debouncer.cancel();\n * debouncer.flush(); // No execution\n * ```\n */\n public flush(): void {\n if (this.isPending) {\n this.invoke__();\n }\n this.cancel();\n }\n\n /**\n * The core execution logic.\n */\n private invoke__(): void {\n if (this.lastArgs__) {\n // only call if we have new args (skip trailing call if leading already called)\n this.config__.func.apply(this.config__.thisContext, this.lastArgs__);\n this.lastArgs__ = undefined;\n }\n }\n}\n"],
5
- "mappings": ";qqBAAA,mJCgCO,IAAM,UAAN,KAAmC,CAKxC,YAA6B,SAA8B,CAA9B,uBAC3B,KAAK,SAAS,WAAa,KAC3B,KAAK,MAAQ,KAAK,MAAM,KAAK,IAAI,CACnC,CAMA,IAAW,WAAqB,CAC9B,OAAO,KAAK,YAAc,MAC5B,CAmBO,WAAW,KAA2B,CAC3C,KAAK,WAAa,KAClB,MAAM,aAAe,CAAC,KAAK,UAE3B,GAAI,aAAc,CAChB,GAAI,KAAK,SAAS,QAAS,CACzB,KAAK,iBAAmB,WAAW,KAAK,MAAO,KAAK,SAAS,OAAO,CACtE,CACA,GAAI,KAAK,SAAS,UAAY,KAAM,CAClC,KAAK,SAAS,CAChB,CACF,KACK,CACH,aAAa,KAAK,SAAU,CAC9B,CAEA,KAAK,UAAY,WAAW,IAAM,CAChC,GAAI,KAAK,SAAS,WAAa,KAAM,CACnC,KAAK,SAAS,CAChB,CACA,KAAK,UAAU,CACjB,EAAG,KAAK,SAAS,KAAK,CACxB,CAkBO,QAAe,CACpB,GAAI,KAAK,UAAW,CAClB,aAAa,KAAK,SAAS,CAC7B,CACA,GAAI,KAAK,iBAAkB,CACzB,aAAa,KAAK,gBAAgB,CACpC,CACA,KAAK,UAAU,CACjB,CAKQ,WAAkB,CACxB,OAAO,KAAK,UACZ,OAAO,KAAK,iBACZ,OAAO,KAAK,UACd,CAoBO,OAAc,CACnB,GAAI,KAAK,UAAW,CAClB,KAAK,SAAS,CAChB,CACA,KAAK,OAAO,CACd,CAKQ,UAAiB,CACvB,GAAI,KAAK,WAAY,CAEnB,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,YAAa,KAAK,UAAU,EACnE,KAAK,WAAa,MACpB,CACF,CACF,ED/HO,SAAS,gBAAmC,OAA0C,CAC3F,OAAO,IAAI,UAAU,MAAM,CAC7B",
6
- "names": []
7
- }
package/dist/main.mjs DELETED
@@ -1,3 +0,0 @@
1
- /** ๐Ÿ“ฆ @alwatr/debounce v1.1.20 */
2
- var Debouncer=class{constructor(config__){this.config__=config__;this.config__.trailing??=true;this.flush=this.flush.bind(this)}get isPending(){return this.timerId__!==void 0}trigger(...args){this.lastArgs__=args;const firstTrigger=!this.isPending;if(firstTrigger){if(this.config__.maxWait){this.maxWaitTimerId__=setTimeout(this.flush,this.config__.maxWait)}if(this.config__.leading===true){this.invoke__()}}else{clearTimeout(this.timerId__)}this.timerId__=setTimeout(()=>{if(this.config__.trailing===true){this.invoke__()}this.cleanup__()},this.config__.delay)}cancel(){if(this.timerId__){clearTimeout(this.timerId__)}if(this.maxWaitTimerId__){clearTimeout(this.maxWaitTimerId__)}this.cleanup__()}cleanup__(){delete this.timerId__;delete this.maxWaitTimerId__;delete this.lastArgs__}flush(){if(this.isPending){this.invoke__()}this.cancel()}invoke__(){if(this.lastArgs__){this.config__.func.apply(this.config__.thisContext,this.lastArgs__);this.lastArgs__=void 0}}};function createDebouncer(config){return new Debouncer(config)}export{Debouncer,createDebouncer};
3
- //# sourceMappingURL=main.mjs.map
package/dist/main.mjs.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/debounce.ts", "../src/main.ts"],
4
- "sourcesContent": ["import type {DebouncerConfig} from './type.ts';\n\n/**\n * A powerful and type-safe Debouncer class.\n *\n * It encapsulates the debouncing logic, state, and provides a rich control API.\n * Debouncing delays function execution until after a specified delay has passed since the last invocation.\n * Useful for optimizing performance in scenarios like search inputs, resize events, or API calls.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: (text: string) => console.log('Searching:', text),\n * delay: 300,\n * leading: false,\n * trailing: true,\n * });\n *\n * // Debounce search input\n * debouncer.trigger('hello');\n * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms\n *\n * // Advanced: With leading edge\n * const leadingDebouncer = new Debouncer({\n * func: () => console.log('Immediate and delayed'),\n * delay: 500,\n * leading: true,\n * trailing: true,\n * });\n * leadingDebouncer.trigger(); // Logs immediately, then again after 500ms if not cancelled\n * ```\n */\nexport class Debouncer<F extends AnyFunc> {\n private timerId__?: number | NodeJS.Timeout;\n private maxWaitTimerId__?: number | NodeJS.Timeout;\n private lastArgs__?: Parameters<F>;\n\n constructor(private readonly config__: DebouncerConfig<F>) {\n this.config__.trailing ??= true;\n this.flush = this.flush.bind(this);\n }\n\n /**\n * Checks if there is a pending execution scheduled.\n * Returns true if a timer is active, indicating a debounced call is waiting.\n */\n public get isPending(): boolean {\n return this.timerId__ !== undefined;\n }\n\n /**\n * Triggers the debounced function with the stored `thisContext`.\n * @param args The arguments to pass to the `func`.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: (value: number) => console.log('Value:', value),\n * delay: 500,\n * });\n * debouncer.trigger(42); // Logs after 500ms if not triggered again\n *\n * // Edge case: Rapid triggers only execute the last one\n * debouncer.trigger(1);\n * debouncer.trigger(2); // Only 2 will execute after delay\n * ```\n */\n public trigger(...args: Parameters<F>): void {\n this.lastArgs__ = args; // its an array even if triggered without any args\n const firstTrigger = !this.isPending;\n\n if (firstTrigger) {\n if (this.config__.maxWait) {\n this.maxWaitTimerId__ = setTimeout(this.flush, this.config__.maxWait);\n }\n if (this.config__.leading === true) {\n this.invoke__();\n }\n }\n else {\n clearTimeout(this.timerId__!);\n }\n\n this.timerId__ = setTimeout(() => {\n if (this.config__.trailing === true) {\n this.invoke__();\n }\n this.cleanup__();\n }, this.config__.delay);\n }\n\n /**\n * Cancels any pending debounced execution and cleans up internal state.\n * Useful for stopping execution when the operation is no longer needed (e.g., component unmount).\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: () => console.log('Executed'),\n * delay: 1000,\n * });\n * debouncer.trigger();\n * debouncer.cancel(); // Prevents execution\n *\n * // Note: After cancel, isPending becomes false\n * ```\n */\n public cancel(): void {\n if (this.timerId__) {\n clearTimeout(this.timerId__);\n }\n if (this.maxWaitTimerId__) {\n clearTimeout(this.maxWaitTimerId__);\n }\n this.cleanup__();\n }\n\n /**\n * Cleans up internal state by deleting timer and arguments.\n */\n private cleanup__(): void {\n delete this.timerId__;\n delete this.maxWaitTimerId__;\n delete this.lastArgs__;\n }\n\n /**\n * Immediately executes the pending function if one exists.\n * Bypasses the delay and cleans up state. If no pending call, does nothing.\n *\n * @example\n * ```typescript\n * const debouncer = new Debouncer({\n * func: () => console.log('Flushed'),\n * delay: 1000,\n * });\n * debouncer.trigger();\n * setTimeout(() => debouncer.flush(), 500); // Executes immediately\n *\n * // Edge case: Flush after cancel does nothing\n * debouncer.cancel();\n * debouncer.flush(); // No execution\n * ```\n */\n public flush(): void {\n if (this.isPending) {\n this.invoke__();\n }\n this.cancel();\n }\n\n /**\n * The core execution logic.\n */\n private invoke__(): void {\n if (this.lastArgs__) {\n // only call if we have new args (skip trailing call if leading already called)\n this.config__.func.apply(this.config__.thisContext, this.lastArgs__);\n this.lastArgs__ = undefined;\n }\n }\n}\n", "import {Debouncer} from './debounce.js';\n\nimport type {DebouncerConfig} from './type.js';\n\nexport * from './debounce.js';\nexport type * from './type.js';\n\n/**\n * Factory function for creating a Debouncer instance for better type inference.\n * @param config Configuration for the debouncer.\n *\n * @example\n * ```typescript\n * const debouncer = createDebouncer({\n * func: (text: string) => console.log('Searching:', text),\n * delay: 300,\n * leading: false,\n * trailing: true,\n * });\n *\n * // Debounce search input\n * debouncer.trigger('hello');\n * debouncer.trigger('hello world'); // Only 'hello world' will log after 300ms\n *\n * // With custom thisContext\n * const obj = { log: (msg: string) => console.log('Obj:', msg) };\n * const debouncerWithContext = createDebouncer({\n * func: obj.log,\n * thisContext: obj,\n * delay: 200,\n * });\n * debouncerWithContext.trigger('test'); // Logs 'Obj: test'\n * ```\n */\nexport function createDebouncer<F extends AnyFunc>(config: DebouncerConfig<F>): Debouncer<F> {\n return new Debouncer(config);\n}\n"],
5
- "mappings": ";AAgCO,IAAM,UAAN,KAAmC,CAKxC,YAA6B,SAA8B,CAA9B,uBAC3B,KAAK,SAAS,WAAa,KAC3B,KAAK,MAAQ,KAAK,MAAM,KAAK,IAAI,CACnC,CAMA,IAAW,WAAqB,CAC9B,OAAO,KAAK,YAAc,MAC5B,CAmBO,WAAW,KAA2B,CAC3C,KAAK,WAAa,KAClB,MAAM,aAAe,CAAC,KAAK,UAE3B,GAAI,aAAc,CAChB,GAAI,KAAK,SAAS,QAAS,CACzB,KAAK,iBAAmB,WAAW,KAAK,MAAO,KAAK,SAAS,OAAO,CACtE,CACA,GAAI,KAAK,SAAS,UAAY,KAAM,CAClC,KAAK,SAAS,CAChB,CACF,KACK,CACH,aAAa,KAAK,SAAU,CAC9B,CAEA,KAAK,UAAY,WAAW,IAAM,CAChC,GAAI,KAAK,SAAS,WAAa,KAAM,CACnC,KAAK,SAAS,CAChB,CACA,KAAK,UAAU,CACjB,EAAG,KAAK,SAAS,KAAK,CACxB,CAkBO,QAAe,CACpB,GAAI,KAAK,UAAW,CAClB,aAAa,KAAK,SAAS,CAC7B,CACA,GAAI,KAAK,iBAAkB,CACzB,aAAa,KAAK,gBAAgB,CACpC,CACA,KAAK,UAAU,CACjB,CAKQ,WAAkB,CACxB,OAAO,KAAK,UACZ,OAAO,KAAK,iBACZ,OAAO,KAAK,UACd,CAoBO,OAAc,CACnB,GAAI,KAAK,UAAW,CAClB,KAAK,SAAS,CAChB,CACA,KAAK,OAAO,CACd,CAKQ,UAAiB,CACvB,GAAI,KAAK,WAAY,CAEnB,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,YAAa,KAAK,UAAU,EACnE,KAAK,WAAa,MACpB,CACF,CACF,EC/HO,SAAS,gBAAmC,OAA0C,CAC3F,OAAO,IAAI,UAAU,MAAM,CAC7B",
6
- "names": []
7
- }