Skip to content

Commit 0238061

Browse files
committed
chore: replace lodash.debounce with inline implementation
Replace lodash.debounce with a lightweight inline debounce utility, removing the lodash.debounce and @types/lodash.debounce dependencies. The inline implementation supports the same options used by ParentSize (delay and leading), handles leading+trailing edge calls correctly, provides cancel(), and resets state before invoking callbacks to support re-entrant calls safely. - New src/debounce.ts (0.46KB gzip vs external package) - Updated ParentSize.tsx import - Removed lodash.debounce from rollup externals in vite.config.ts - Removed lodash.debounce + @types/lodash.debounce from package.json
1 parent 931c11f commit 0238061

5 files changed

Lines changed: 57 additions & 29 deletions

File tree

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,12 @@
3939
},
4040
"dependencies": {
4141
"blurhash": "2.0.5",
42-
"lodash.debounce": "4.0.8",
4342
"react-merge-refs": "2.1.1",
4443
"thumbhash": "0.1.1"
4544
},
4645
"devDependencies": {
4746
"@splinetool/runtime": "^1.10.29",
4847
"@types/animejs": "^3.1.12",
49-
"@types/lodash.debounce": "^4.0.9",
5048
"@types/node": "^20.14.1",
5149
"@types/react": "^18.3.3",
5250
"@types/react-dom": "^18.3.0",

src/ParentSize.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Modified version of
22
// https://github.com/airbnb/visx/blob/master/packages/visx-responsive/src/components/ParentSize.tsx
33
'use client';
4-
import debounce from 'lodash.debounce';
4+
import debounce from './debounce';
55
import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
66
import { mergeRefs } from 'react-merge-refs';
77

src/debounce.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
type DebouncedFunction<T extends (...args: any[]) => void> = T & {
2+
cancel: () => void;
3+
};
4+
5+
export default function debounce<T extends (...args: any[]) => void>(
6+
fn: T,
7+
delay: number,
8+
{ leading = false }: { leading?: boolean } = {}
9+
): DebouncedFunction<T> {
10+
let timeoutId: ReturnType<typeof setTimeout> | undefined;
11+
let isLeadingInvoked = false;
12+
let lastThis: unknown;
13+
let lastArgs: Parameters<T> | undefined;
14+
15+
const debounced = function (this: unknown, ...args: Parameters<T>) {
16+
lastThis = this;
17+
lastArgs = args;
18+
19+
if (leading && !isLeadingInvoked) {
20+
isLeadingInvoked = true;
21+
fn.apply(this, args);
22+
lastArgs = undefined; // Clear so we can detect subsequent calls
23+
}
24+
25+
if (timeoutId !== undefined) {
26+
clearTimeout(timeoutId);
27+
}
28+
29+
timeoutId = setTimeout(() => {
30+
const thisCtx = lastThis;
31+
const thisArgs = lastArgs;
32+
// Reset state BEFORE calling fn so re-entrant calls work correctly
33+
isLeadingInvoked = false;
34+
timeoutId = undefined;
35+
lastArgs = undefined;
36+
37+
if (!leading) {
38+
fn.apply(thisCtx, thisArgs!);
39+
} else if (thisArgs !== undefined) {
40+
// Leading+trailing: only fire trailing if there were calls after the leading
41+
fn.apply(thisCtx, thisArgs);
42+
}
43+
}, delay);
44+
} as DebouncedFunction<T>;
45+
46+
debounced.cancel = () => {
47+
if (timeoutId !== undefined) {
48+
clearTimeout(timeoutId);
49+
}
50+
timeoutId = undefined;
51+
isLeadingInvoked = false;
52+
lastArgs = undefined;
53+
};
54+
55+
return debounced;
56+
}

vite.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export default defineConfig({
3333
'next/image',
3434
// these are the dependencies, they are listed in the package.json already
3535
'blurhash',
36-
'lodash.debounce',
3736
'react-merge-refs',
3837
'thumbhash',
3938
],

yarn.lock

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,14 +1095,12 @@ __metadata:
10951095
dependencies:
10961096
"@splinetool/runtime": ^1.10.29
10971097
"@types/animejs": ^3.1.12
1098-
"@types/lodash.debounce": ^4.0.9
10991098
"@types/node": ^20.14.1
11001099
"@types/react": ^18.3.3
11011100
"@types/react-dom": ^18.3.0
11021101
"@vitejs/plugin-react": ^4.3.0
11031102
animejs: ^3.2.2
11041103
blurhash: 2.0.5
1105-
lodash.debounce: 4.0.8
11061104
modern-normalize: ^1.1.0
11071105
next: 15.0.0-rc.0
11081106
np: ^10.0.5
@@ -1223,22 +1221,6 @@ __metadata:
12231221
languageName: node
12241222
linkType: hard
12251223

1226-
"@types/lodash.debounce@npm:^4.0.9":
1227-
version: 4.0.9
1228-
resolution: "@types/lodash.debounce@npm:4.0.9"
1229-
dependencies:
1230-
"@types/lodash": "*"
1231-
checksum: 8183a152e01928e3b97ca773f6ae6038b8695e76493ba8bf6b743ec143948a62294fbc9d49fa4a78b52265b3ba4892ef57534e0c13d04aa0f111671b5a944feb
1232-
languageName: node
1233-
linkType: hard
1234-
1235-
"@types/lodash@npm:*":
1236-
version: 4.14.191
1237-
resolution: "@types/lodash@npm:4.14.191"
1238-
checksum: ba0d5434e10690869f32d5ea49095250157cae502f10d57de0a723fd72229ce6c6a4979576f0f13e0aa9fbe3ce2457bfb9fa7d4ec3d6daba56730a51906d1491
1239-
languageName: node
1240-
linkType: hard
1241-
12421224
"@types/node@npm:^20.14.1":
12431225
version: 20.14.1
12441226
resolution: "@types/node@npm:20.14.1"
@@ -3545,13 +3527,6 @@ __metadata:
35453527
languageName: node
35463528
linkType: hard
35473529

3548-
"lodash.debounce@npm:4.0.8":
3549-
version: 4.0.8
3550-
resolution: "lodash.debounce@npm:4.0.8"
3551-
checksum: a3f527d22c548f43ae31c861ada88b2637eb48ac6aa3eb56e82d44917971b8aa96fbb37aa60efea674dc4ee8c42074f90f7b1f772e9db375435f6c83a19b3bc6
3552-
languageName: node
3553-
linkType: hard
3554-
35553530
"lodash.zip@npm:^4.2.0":
35563531
version: 4.2.0
35573532
resolution: "lodash.zip@npm:4.2.0"

0 commit comments

Comments
 (0)