@perch33/react-usefilter-hook 1.0.2 → 1.0.4
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.
- package/README.md +20 -14
- package/dist/cjs/index.js +16 -16
- package/dist/cjs/index.min.js +1 -1
- package/dist/esm/index.js +17 -17
- package/dist/esm/index.min.js +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +66 -62
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Ideal for search bars, dynamic lists, admin dashboards, e-commerce filters, etc.
|
|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
10
|
+

|
|
10
11
|
|
|
11
12
|
---
|
|
12
13
|
|
|
@@ -16,6 +17,7 @@ Ideal for search bars, dynamic lists, admin dashboards, e-commerce filters, etc.
|
|
|
16
17
|
- ✂️ Removes punctuation and special characters
|
|
17
18
|
- 🔎 Case-insensitive search
|
|
18
19
|
- ⚛️ Fully typed with TypeScript
|
|
20
|
+
- 🚀 **Next.js App Router Compatible** (`"use client"` included)
|
|
19
21
|
- 🔁 Auto-updates when `data` changes
|
|
20
22
|
- 🔧 Accepts custom error component
|
|
21
23
|
- 🧩 Framework-agnostic, works in any React project
|
|
@@ -32,7 +34,6 @@ or
|
|
|
32
34
|
|
|
33
35
|
```sh
|
|
34
36
|
yarn add @perch33/react-usefilter-hook
|
|
35
|
-
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
## 🚀 Usage Example (Basic)
|
|
@@ -121,31 +122,37 @@ useFilter<T>(data, key, errorComponent);
|
|
|
121
122
|
### ⚙️ How filtering works
|
|
122
123
|
|
|
123
124
|
- This hook automatically:
|
|
124
|
-
|
|
125
125
|
- Converts text to lowercase
|
|
126
|
-
|
|
127
126
|
- Removes accents (áéíóú → aeiou)
|
|
128
|
-
|
|
129
127
|
- Removes punctuation and special characters
|
|
130
|
-
|
|
131
128
|
- Performs a normalized comparison
|
|
132
|
-
|
|
133
129
|
- Filters in real time as the user types
|
|
134
130
|
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 🔍 Used in Production (Real Examples)
|
|
134
|
+
|
|
135
|
+
This hook is currently used in my personal website:
|
|
136
|
+
|
|
137
|
+
- 🎼 **Music Scores / Partituras**
|
|
138
|
+
Live search using `useFilter` to filter music scores dynamically.
|
|
139
|
+
👉 https://www.percychuzon.com/partituras
|
|
140
|
+
|
|
141
|
+
- ✍️ **Blog**
|
|
142
|
+
Used to filter blog posts instantly with accent-insensitive matching.
|
|
143
|
+
👉 https://www.percychuzon.com/blog
|
|
144
|
+
|
|
145
|
+
These sections demonstrate real-world usage of the hook with dynamic content,
|
|
146
|
+
search inputs, and accent-normalized filtering.
|
|
147
|
+
|
|
135
148
|
### 💡 When to use this hook?
|
|
136
149
|
|
|
137
150
|
- Product search inputs
|
|
138
|
-
|
|
139
151
|
- Admin panel filters
|
|
140
|
-
|
|
141
152
|
- Searchable dropdowns
|
|
142
|
-
|
|
143
153
|
- User lists
|
|
144
|
-
|
|
145
154
|
- Blog post search
|
|
146
|
-
|
|
147
155
|
- Table filtering
|
|
148
|
-
|
|
149
156
|
- Autocomplete components
|
|
150
157
|
|
|
151
158
|
## 📁 Project Structure
|
|
@@ -153,7 +160,6 @@ useFilter<T>(data, key, errorComponent);
|
|
|
153
160
|
Your installation will contain:
|
|
154
161
|
|
|
155
162
|
```
|
|
156
|
-
|
|
157
163
|
dist/
|
|
158
164
|
├─ cjs/
|
|
159
165
|
├─ esm/
|
|
@@ -166,4 +172,4 @@ README.md
|
|
|
166
172
|
|
|
167
173
|
**Percy Chuzon**
|
|
168
174
|
📧 [contacto@percychuzon.com](mailto:contacto@percychuzon.com)
|
|
169
|
-
🌐 [https://
|
|
175
|
+
🌐 [https://www.percychuzon.com](https://www.percychuzon.com)
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
"use client";
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.useFilter = void 0;
|
|
4
5
|
const react_1 = require("react");
|
|
@@ -20,27 +21,26 @@ function normalizarTexto(texto) {
|
|
|
20
21
|
}
|
|
21
22
|
const useFilter = (data, key, errorComponent) => {
|
|
22
23
|
const [filterText, setFilterText] = (0, react_1.useState)("");
|
|
23
|
-
const [filteredData, setFilteredData] = (0, react_1.useState)(data);
|
|
24
|
-
const [error, setError] = (0, react_1.useState)(null);
|
|
25
24
|
/** Maneja el texto que escribe el usuario en el input */
|
|
26
25
|
const handleFilterChange = (e) => {
|
|
27
|
-
|
|
28
|
-
setFilterText(searchText);
|
|
26
|
+
setFilterText(e.target.value);
|
|
29
27
|
};
|
|
30
|
-
/** Filtra la lista
|
|
31
|
-
(0, react_1.
|
|
32
|
-
|
|
28
|
+
/** Filtra la lista de forma eficiente usando useMemo */
|
|
29
|
+
const { filteredData, error } = (0, react_1.useMemo)(() => {
|
|
30
|
+
// Si no hay texto, devolvemos todo sin error
|
|
31
|
+
if (!filterText) {
|
|
32
|
+
return { filteredData: data, error: null };
|
|
33
|
+
}
|
|
34
|
+
const searchText = normalizarTexto(filterText);
|
|
35
|
+
const filtered = data.filter((item) => {
|
|
33
36
|
const valorCampo = String(item[key]);
|
|
34
|
-
return normalizarTexto(valorCampo).includes(
|
|
37
|
+
return normalizarTexto(valorCampo).includes(searchText);
|
|
35
38
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
setError(null);
|
|
42
|
-
}
|
|
43
|
-
}, [data, filterText, key]);
|
|
39
|
+
return {
|
|
40
|
+
filteredData: filtered,
|
|
41
|
+
error: filtered.length === 0 ? errorComponent : null
|
|
42
|
+
};
|
|
43
|
+
}, [data, filterText, key, errorComponent]);
|
|
44
44
|
return {
|
|
45
45
|
filterText,
|
|
46
46
|
filteredData,
|
package/dist/cjs/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useFilter=void 0;const react_1=require("react");function normalizarTexto(e){return e.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[.,/#!$%^&*;:{}=\-_`~()¿?¡!]/g,"").toLowerCase().trim()}const useFilter=(e,t
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useFilter=void 0;const react_1=require("react");function normalizarTexto(e){return e.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[.,/#!$%^&*;:{}=\-_`~()¿?¡!]/g,"").toLowerCase().trim()}const useFilter=(e,r,t)=>{const[a,l]=(0,react_1.useState)(""),{filteredData:o,error:i}=(0,react_1.useMemo)(()=>{if(!a)return{filteredData:e,error:null};const l=normalizarTexto(a),o=e.filter(e=>normalizarTexto(String(e[r])).includes(l));return{filteredData:o,error:0===o.length?t:null}},[e,a,r,t]);return{filterText:a,filteredData:o,error:i,handleFilterChange:e=>{l(e.target.value)}}};exports.useFilter=useFilter;
|
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useMemo } from "react";
|
|
2
3
|
/**
|
|
3
4
|
* 🔠 Normaliza texto para facilitar búsquedas:
|
|
4
5
|
* - Convierte a minúsculas
|
|
@@ -17,27 +18,26 @@ function normalizarTexto(texto) {
|
|
|
17
18
|
}
|
|
18
19
|
export const useFilter = (data, key, errorComponent) => {
|
|
19
20
|
const [filterText, setFilterText] = useState("");
|
|
20
|
-
const [filteredData, setFilteredData] = useState(data);
|
|
21
|
-
const [error, setError] = useState(null);
|
|
22
21
|
/** Maneja el texto que escribe el usuario en el input */
|
|
23
22
|
const handleFilterChange = (e) => {
|
|
24
|
-
|
|
25
|
-
setFilterText(searchText);
|
|
23
|
+
setFilterText(e.target.value);
|
|
26
24
|
};
|
|
27
|
-
/** Filtra la lista
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
/** Filtra la lista de forma eficiente usando useMemo */
|
|
26
|
+
const { filteredData, error } = useMemo(() => {
|
|
27
|
+
// Si no hay texto, devolvemos todo sin error
|
|
28
|
+
if (!filterText) {
|
|
29
|
+
return { filteredData: data, error: null };
|
|
30
|
+
}
|
|
31
|
+
const searchText = normalizarTexto(filterText);
|
|
32
|
+
const filtered = data.filter((item) => {
|
|
30
33
|
const valorCampo = String(item[key]);
|
|
31
|
-
return normalizarTexto(valorCampo).includes(
|
|
34
|
+
return normalizarTexto(valorCampo).includes(searchText);
|
|
32
35
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
setError(null);
|
|
39
|
-
}
|
|
40
|
-
}, [data, filterText, key]);
|
|
36
|
+
return {
|
|
37
|
+
filteredData: filtered,
|
|
38
|
+
error: filtered.length === 0 ? errorComponent : null
|
|
39
|
+
};
|
|
40
|
+
}, [data, filterText, key, errorComponent]);
|
|
41
41
|
return {
|
|
42
42
|
filterText,
|
|
43
43
|
filteredData,
|
package/dist/esm/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useState,
|
|
1
|
+
import{useState,useMemo}from"react";function normalizarTexto(e){return e.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[.,/#!$%^&*;:{}=\-_`~()¿?¡!]/g,"").toLowerCase().trim()}export const useFilter=(e,r,t)=>{const[a,l]=useState(""),{filteredData:o,error:n}=useMemo(()=>{if(!a)return{filteredData:e,error:null};const l=normalizarTexto(a),o=e.filter(e=>normalizarTexto(String(e[r])).includes(l));return{filteredData:o,error:0===o.length?t:null}},[e,a,r,t]);return{filterText:a,filteredData:o,error:n,handleFilterChange:e=>{l(e.target.value)}}};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { ChangeEvent } from "react";
|
|
|
6
6
|
*
|
|
7
7
|
* ✔ Permite filtrar un array (data) según un campo específico (key)
|
|
8
8
|
* ✔ Devuelve:
|
|
9
|
-
* - filterText → texto escrito por el usuario
|
|
9
|
+
* - filterText → texto escrito por el usuario (raw)
|
|
10
10
|
* - filteredData → lista filtrada
|
|
11
11
|
* - error → componente mostrado cuando no hay resultados
|
|
12
12
|
* - handleFilterChange → manejador para input de búsqueda
|
package/package.json
CHANGED
|
@@ -1,62 +1,66 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@perch33/react-usefilter-hook",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A lightweight and reusable React hook for filtering lists with accent normalization, punctuation removal and TypeScript support.",
|
|
5
|
-
"main": "dist/cjs/index.min.js",
|
|
6
|
-
"module": "dist/esm/index.min.js",
|
|
7
|
-
"types": "dist/types/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"import": "./dist/esm/index.min.js",
|
|
11
|
-
"require": "./dist/cjs/index.min.js",
|
|
12
|
-
"types": "./dist/types/index.d.ts"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"dist/cjs",
|
|
17
|
-
"dist/esm",
|
|
18
|
-
"dist/types"
|
|
19
|
-
],
|
|
20
|
-
"sideEffects": false,
|
|
21
|
-
"scripts": {
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"react
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"@
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@perch33/react-usefilter-hook",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "A lightweight and reusable React hook for filtering lists with accent normalization, punctuation removal and TypeScript support.",
|
|
5
|
+
"main": "dist/cjs/index.min.js",
|
|
6
|
+
"module": "dist/esm/index.min.js",
|
|
7
|
+
"types": "dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/esm/index.min.js",
|
|
11
|
+
"require": "./dist/cjs/index.min.js",
|
|
12
|
+
"types": "./dist/types/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/cjs",
|
|
17
|
+
"dist/esm",
|
|
18
|
+
"dist/types"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"clean": "rimraf dist",
|
|
24
|
+
"build": "npm run clean && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json && terser dist/cjs/index.js -o dist/cjs/index.min.js --compress --mangle && terser dist/esm/index.js -o dist/esm/index.min.js --compress --mangle"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"react",
|
|
28
|
+
"hook",
|
|
29
|
+
"filter",
|
|
30
|
+
"usefilter",
|
|
31
|
+
"search",
|
|
32
|
+
"list filter",
|
|
33
|
+
"normalization",
|
|
34
|
+
"typescript",
|
|
35
|
+
"frontend",
|
|
36
|
+
"react hook",
|
|
37
|
+
"filter hook"
|
|
38
|
+
],
|
|
39
|
+
"author": "Percy Chuzon <contacto@percychuzon.com>",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"homepage": "https://react-usefilter-hook.percychuzon.com/",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/perch733/perch733-react-usefilter-hook.git"
|
|
45
|
+
},
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/perch733/perch733-react-usefilter-hook/issues"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"react": ">=17.0.0",
|
|
54
|
+
"react-dom": ">=17.0.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@testing-library/react": "^16.3.1",
|
|
58
|
+
"@types/react": "^18.3.21",
|
|
59
|
+
"@types/react-dom": "^18.3.7",
|
|
60
|
+
"jsdom": "^27.4.0",
|
|
61
|
+
"rimraf": "^6.0.1",
|
|
62
|
+
"terser": "^5.39.2",
|
|
63
|
+
"typescript": "^5.8.3",
|
|
64
|
+
"vitest": "^4.0.17"
|
|
65
|
+
}
|
|
66
|
+
}
|