chore(frontend): replace lodash/debounce with use-debounce, drop lodash

The 8 flow-view search inputs used lodash/debounce via useMemo(()=>debounce(fn,500))
+ .cancel() cleanup. Swap to useDebouncedCallback(fn,500) from use-debounce — already
the repo idiom (data-table, input-search, use-table-state) with identical
leading:false/trailing:true semantics and the same .cancel() API. Drops lodash +
@types/lodash (a whole general-purpose lib kept for one function).

tsc + lint + build + full vitest (813) green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sergey Kozyrenko
2026-07-02 14:21:33 +07:00
co-authored by Claude Opus 4.8
parent 54ac6c4adb
commit ebdf8b012e
10 changed files with 32 additions and 82 deletions
-2
View File
@@ -66,7 +66,6 @@
"graphql": "^16.14.2",
"graphql-ws": "^6.0.8",
"highlight.js": "^11.11.1",
"lodash": "^4.18.1",
"lowlight": "^3.3.0",
"lru-cache": "^11.5.1",
"lucide-react": "^1.20.0",
@@ -104,7 +103,6 @@
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/lodash": "^4.17.24",
"@types/node": "^24.13.2",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
-16
View File
@@ -158,9 +158,6 @@ importers:
highlight.js:
specifier: ^11.11.1
version: 11.11.1
lodash:
specifier: ^4.18.1
version: 4.18.1
lowlight:
specifier: ^3.3.0
version: 3.3.0
@@ -267,9 +264,6 @@ importers:
'@testing-library/user-event':
specifier: ^14.6.1
version: 14.6.1(@testing-library/dom@10.4.1)
'@types/lodash':
specifier: ^4.17.24
version: 4.17.24
'@types/node':
specifier: ^24.13.2
version: 24.13.2
@@ -2394,9 +2388,6 @@ packages:
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/lodash@4.17.24':
resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==}
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
@@ -4069,9 +4060,6 @@ packages:
lodash.sortby@4.7.0:
resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
lodash@4.18.1:
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
log-symbols@7.0.1:
resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==}
engines: {node: '>=18'}
@@ -7766,8 +7754,6 @@ snapshots:
'@types/json-schema@7.0.15': {}
'@types/lodash@4.17.24': {}
'@types/mdast@4.0.4':
dependencies:
'@types/unist': 3.0.3
@@ -9606,8 +9592,6 @@ snapshots:
lodash.sortby@4.7.0: {}
lodash@4.18.1: {}
log-symbols@7.0.1:
dependencies:
is-unicode-supported: 2.1.0
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import debounce from 'lodash/debounce';
import { Bot, ChevronDown, ListFilter, Search, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
@@ -47,13 +47,9 @@ function FlowAgents() {
const searchValue = form.watch('search');
const filter = form.watch('filter');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import debounce from 'lodash/debounce';
import { Check, ChevronDown, ListFilter, Loader2, Plus, Search, Trash2, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import type { AssistantFragmentFragment, ProviderFragmentFragment } from '@/graphql/types';
@@ -322,13 +322,9 @@ function FlowAssistantMessages({ className }: FlowAssistantMessagesProps) {
const searchValue = form.watch('search');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import debounce from 'lodash/debounce';
import { ChevronDown, Inbox, ListFilter, Search, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
@@ -57,13 +57,9 @@ function FlowAutomationMessages({ className }: FlowAutomationMessagesProps) {
const searchValue = form.watch('search');
const filter = form.watch('filter');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import debounce from 'lodash/debounce';
import { Camera, ChevronDown, Search, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
@@ -38,13 +38,9 @@ function FlowScreenshots() {
const searchValue = form.watch('search');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import debounce from 'lodash/debounce';
import { ChevronDown, ListTodo, Search, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
@@ -43,13 +43,9 @@ function FlowTasks() {
const searchValue = form.watch('search');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);
@@ -1,9 +1,9 @@
import { zodResolver } from '@hookform/resolvers/zod';
import '@xterm/xterm/css/xterm.css';
import debounce from 'lodash/debounce';
import { ChevronDown, ChevronUp, ListFilter, Search, X } from 'lucide-react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import Terminal from '@/components/shared/terminal';
@@ -47,13 +47,9 @@ function FlowTerminal() {
const searchValue = form.watch('search');
const filter = form.watch('filter');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import debounce from 'lodash/debounce';
import { ChevronDown, ListFilter, Search, Wrench, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
@@ -47,13 +47,9 @@ function FlowTools() {
const searchValue = form.watch('search');
const filter = form.watch('filter');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import debounce from 'lodash/debounce';
import { ChevronDown, Database, ListFilter, Search, X } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
@@ -47,13 +47,9 @@ function FlowVectorStores() {
const searchValue = form.watch('search');
const filter = form.watch('filter');
const debouncedUpdateSearch = useMemo(
() =>
debounce((value: string) => {
setDebouncedSearchValue(value);
}, 500),
[],
);
const debouncedUpdateSearch = useDebouncedCallback((value: string) => {
setDebouncedSearchValue(value);
}, 500);
useEffect(() => {
debouncedUpdateSearch(searchValue);