@perch33/react-usefilter-hook 1.0.3 → 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 CHANGED
@@ -7,6 +7,7 @@ Ideal for search bars, dynamic lists, admin dashboards, e-commerce filters, etc.
7
7
  ![downloads](https://img.shields.io/npm/dm/@perch33/react-usefilter-hook)
8
8
  ![license](https://img.shields.io/npm/l/@perch33/react-usefilter-hook)
9
9
  ![types](https://img.shields.io/badge/types-TypeScript-blue)
10
+ ![Next.js](https://img.shields.io/badge/Next.js-App%20Router%20Ready-black)
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
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
- const searchText = normalizarTexto(e.target.value);
28
- setFilterText(searchText);
26
+ setFilterText(e.target.value);
29
27
  };
30
- /** Filtra la lista cada vez que cambia el texto o los datos */
31
- (0, react_1.useEffect)(() => {
32
- const filteredItems = data.filter((item) => {
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(filterText);
37
+ return normalizarTexto(valorCampo).includes(searchText);
35
38
  });
36
- setFilteredData(filteredItems);
37
- if (filteredItems.length === 0 && filterText !== "") {
38
- setError(errorComponent);
39
- }
40
- else {
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,
@@ -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,r)=>{const[a,l]=(0,react_1.useState)(""),[o,n]=(0,react_1.useState)(e),[s,u]=(0,react_1.useState)(null);return(0,react_1.useEffect)(()=>{const l=e.filter(e=>normalizarTexto(String(e[t])).includes(a));n(l),0===l.length&&""!==a?u(r):u(null)},[e,a,t]),{filterText:a,filteredData:o,error:s,handleFilterChange:e=>{const t=normalizarTexto(e.target.value);l(t)}}};exports.useFilter=useFilter;
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
- import { useState, useEffect } from "react";
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
- const searchText = normalizarTexto(e.target.value);
25
- setFilterText(searchText);
23
+ setFilterText(e.target.value);
26
24
  };
27
- /** Filtra la lista cada vez que cambia el texto o los datos */
28
- useEffect(() => {
29
- const filteredItems = data.filter((item) => {
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(filterText);
34
+ return normalizarTexto(valorCampo).includes(searchText);
32
35
  });
33
- setFilteredData(filteredItems);
34
- if (filteredItems.length === 0 && filterText !== "") {
35
- setError(errorComponent);
36
- }
37
- else {
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,
@@ -1 +1 @@
1
- import{useState,useEffect}from"react";function normalizarTexto(e){return e.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[.,/#!$%^&*;:{}=\-_`~()¿?¡!]/g,"").toLowerCase().trim()}export const useFilter=(e,t,r)=>{const[a,l]=useState(""),[n,o]=useState(e),[u,i]=useState(null);return useEffect(()=>{const l=e.filter(e=>normalizarTexto(String(e[t])).includes(a));o(l),0===l.length&&""!==a?i(r):i(null)},[e,a,t]),{filterText:a,filteredData:n,error:u,handleFilterChange:e=>{const t=normalizarTexto(e.target.value);l(t)}}};
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)}}};
@@ -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.3",
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
- "clean": "rimraf dist",
23
- "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"
24
- },
25
- "keywords": [
26
- "react",
27
- "hook",
28
- "filter",
29
- "usefilter",
30
- "search",
31
- "list filter",
32
- "normalization",
33
- "typescript",
34
- "frontend",
35
- "react hook",
36
- "filter hook"
37
- ],
38
- "author": "Percy Chuzon <contacto@percychuzon.com>",
39
- "license": "MIT",
40
- "homepage": "https://react-usefilter-hook.percychuzon.com/",
41
- "repository": {
42
- "type": "git",
43
- "url": "https://github.com/perch733/perch733-react-usefilter-hook.git"
44
- },
45
- "bugs": {
46
- "url": "https://github.com/perch733/perch733-react-usefilter-hook/issues"
47
- },
48
- "publishConfig": {
49
- "access": "public"
50
- },
51
- "peerDependencies": {
52
- "react": ">=17.0.0",
53
- "react-dom": ">=17.0.0"
54
- },
55
- "devDependencies": {
56
- "@types/react": "^18.3.21",
57
- "@types/react-dom": "^18.3.7",
58
- "rimraf": "^6.0.1",
59
- "typescript": "^5.8.3",
60
- "terser": "^5.39.2"
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
+ }