@arielgonzaguer/michi-router 1.3.0 → 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.
- package/README.md +5 -309
- package/dist/index.d.ts +73 -1
- package/dist/index.js +7 -17
- package/dist/index.mjs +7 -0
- package/package.json +27 -13
- package/dist/michi-router/Michi-router.d.ts +0 -21
- package/dist/michi-router/Michi-router.js +0 -109
- package/dist/michi-router/index.d.ts +0 -2
- package/dist/michi-router/index.js +0 -7
- package/dist/michi-router/types.d.ts +0 -27
- package/dist/michi-router/types.js +0 -2
package/README.md
CHANGED
|
@@ -4,37 +4,18 @@
|
|
|
4
4
|

|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
# ¡IMPORTANTE!
|
|
9
|
-
|
|
10
|
-
Las versiones 1.1.x publicadas antes del 18/marzo/2025 están rotas, contienen errores y han sido eliminadas.
|
|
11
|
-
La versión estable es la 1.2.2.
|
|
12
|
-
Si tienes alguna de estas versiones instaladas (1.1.x), actualízala a la versión 1.2.2 ejecutando el siguiente comando:
|
|
13
|
-
```bash
|
|
14
|
-
npm install @arielgonzaguer/michi-router@latest
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Gracias por su comprensión 😸
|
|
7
|
+

|
|
19
8
|
|
|
20
9
|
# Michi Router
|
|
21
10
|
|
|
22
11
|
El router minimalista y simple para React.
|
|
23
12
|
El objetivo principal de esta herramienta es proporcionar la funcionalidad básica de enrutamiento.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
## Características
|
|
27
|
-
|
|
28
|
-
- Es ideal para proyectos pequeños o que solo necesitan una funcionalidad básica de enrutamiento.
|
|
29
|
-
- No requiere de ninguna configuración adicional.
|
|
30
|
-
- No requiere de ninguna dependencia externa.
|
|
31
|
-
- Creado con TypeScript.
|
|
13
|
+
No requiere de ninguna dependencia externa, ideal para proyectos pequeños.
|
|
14
|
+
Creado con TypeScript.
|
|
32
15
|
|
|
33
16
|
## Compatibilidad
|
|
34
17
|
|
|
35
|
-
- React
|
|
36
|
-
- Funciona con proyectos creados con Vite.
|
|
37
|
-
- Totalmente tipado con TypeScript.
|
|
18
|
+
- React 17+
|
|
38
19
|
|
|
39
20
|
## Instalación
|
|
40
21
|
|
|
@@ -42,289 +23,4 @@ El objetivo principal de esta herramienta es proporcionar la funcionalidad bási
|
|
|
42
23
|
npm install @arielgonzaguer/michi-router
|
|
43
24
|
```
|
|
44
25
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```tsx
|
|
48
|
-
// src/App.jsx //
|
|
49
|
-
import { RouterProvider } from "@arielgonzaguer/michi-router";
|
|
50
|
-
|
|
51
|
-
// puede crear rutas en un archivo separado o en el mismo archivo
|
|
52
|
-
const routes = [
|
|
53
|
-
{ path: "/", component: <Home /> },
|
|
54
|
-
{ path: "/about", component: <About /> },
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
function App() {
|
|
58
|
-
return (
|
|
59
|
-
<RouterProvider routes={routes}>
|
|
60
|
-
{/* Esto se muestra si no se encuentra una ruta */}
|
|
61
|
-
<div>404: Page not found</div>
|
|
62
|
-
</RouterProvider>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Usando Link
|
|
68
|
-
|
|
69
|
-
#### Usando el componente Link solo con prop to
|
|
70
|
-
|
|
71
|
-
```tsx
|
|
72
|
-
import { Link } from "@arielgonzaguer/michi-router";
|
|
73
|
-
|
|
74
|
-
function NavigationComponent() {
|
|
75
|
-
return (
|
|
76
|
-
<nav>
|
|
77
|
-
<Link to="/">Home</Link>
|
|
78
|
-
<Link to="/about">About</Link>
|
|
79
|
-
</nav>
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
#### Usando el componente Link con todas las props
|
|
85
|
-
|
|
86
|
-
```tsx
|
|
87
|
-
<Link
|
|
88
|
-
to="/contact"
|
|
89
|
-
className="nav-link"
|
|
90
|
-
target="_blank"
|
|
91
|
-
rel="noopener noreferrer"
|
|
92
|
-
aria-label="Contacto"
|
|
93
|
-
>
|
|
94
|
-
Contacto
|
|
95
|
-
</Link>
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Navegación programática (Hook useNavigate)
|
|
99
|
-
|
|
100
|
-
```tsx
|
|
101
|
-
import { useNavigate } from "@arielgonzaguer/michi-router";
|
|
102
|
-
|
|
103
|
-
function NavigateButton() {
|
|
104
|
-
const navigate = useNavigate();
|
|
105
|
-
return;
|
|
106
|
-
<button onClick={() => navigate("/gatos")}>Ir a Gatos</button>;
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Organización de rutas en archivos separados
|
|
111
|
-
|
|
112
|
-
Puede organizar sus rutas en archivos separados.
|
|
113
|
-
Primero cree un archivo con las rutas:
|
|
114
|
-
|
|
115
|
-
```tsx
|
|
116
|
-
// routes.tsx
|
|
117
|
-
import Home from "./pages/Home";
|
|
118
|
-
import About from "./pages/About";
|
|
119
|
-
import Products from "./pages/Products";
|
|
120
|
-
import NotFound from "./pages/NotFound";
|
|
121
|
-
|
|
122
|
-
export const routes = [
|
|
123
|
-
{ path: "/", component: <Home /> },
|
|
124
|
-
{ path: "/about", component: <About /> },
|
|
125
|
-
{ path: "/products", component: <Products /> },
|
|
126
|
-
];
|
|
127
|
-
|
|
128
|
-
export const notFoundPage = <NotFound />;
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
Después utilice este archivo en su componente que maneja el enrutado:
|
|
132
|
-
|
|
133
|
-
```tsx
|
|
134
|
-
// App.tsx
|
|
135
|
-
import { RouterProvider } from "@arielgonzaguer/michi-router";
|
|
136
|
-
import { routes, notFoundPage } from "./routes";
|
|
137
|
-
|
|
138
|
-
function App() {
|
|
139
|
-
return <RouterProvider routes={routes}>{notFoundPage}</RouterProvider>;
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Protección de rutas
|
|
144
|
-
|
|
145
|
-
Si necesita que sus rutas se mantengan protegidas, puede usar un componente que cumpla este propósito, como el siguiente:
|
|
146
|
-
|
|
147
|
-
```tsx
|
|
148
|
-
// Protected.tsx
|
|
149
|
-
import { useEffect } from "react";
|
|
150
|
-
import { useNavigate } from "@arielgonzaguer/michi-router";
|
|
151
|
-
import useAuthStore from "../store/useAuthStore"; // esta sería la store que maneja la autenticacación en su proyecto
|
|
152
|
-
import { ReactNode } from "react"; // tipado
|
|
153
|
-
|
|
154
|
-
export default function Protected({ children }: { children: ReactNode }) {
|
|
155
|
-
const navigate = useNavigate();
|
|
156
|
-
const { user } = useAuthStore();
|
|
157
|
-
|
|
158
|
-
useEffect(() => {
|
|
159
|
-
if (!user) {
|
|
160
|
-
navigate("/login"); // si no hay usuario autenticado en la store, redirige al login
|
|
161
|
-
}
|
|
162
|
-
}, [user, navigate]);
|
|
163
|
-
|
|
164
|
-
return user ? children : null; // Devuelve los hijos solo si la persona usuaria está autenticada
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Después, puede usar ese componente en el archivo dónde maneja sus rutas:
|
|
169
|
-
|
|
170
|
-
```tsx
|
|
171
|
-
// MichiRouter.tsx
|
|
172
|
-
import { RouterProvider } from "@arielgonzaguer/michi-router";
|
|
173
|
-
import Home from "../pages/Home";
|
|
174
|
-
import ActualizarGatos from "../pages/ActualizarGatos";
|
|
175
|
-
import VerGatos from "../pages/VerGatos";
|
|
176
|
-
import AgregarGatos from "../pages/AgregarGatos";
|
|
177
|
-
import NotFoud404 from "../components/NotFound404";
|
|
178
|
-
import Index from "../pages/Index";
|
|
179
|
-
|
|
180
|
-
// protección de rutas
|
|
181
|
-
import Protected from "./Protected";
|
|
182
|
-
|
|
183
|
-
// layout
|
|
184
|
-
import BaseLayout from "../layouts/BaseLayout";
|
|
185
|
-
|
|
186
|
-
const rutas = [
|
|
187
|
-
{ path: "/", component: <Home /> },
|
|
188
|
-
// encapsule los componente a elegir dentro de <Protected>
|
|
189
|
-
{
|
|
190
|
-
path: "/index",
|
|
191
|
-
component: (
|
|
192
|
-
<Protected>
|
|
193
|
-
<Index />
|
|
194
|
-
</Protected>
|
|
195
|
-
),
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
path: "/actualizar-gatos",
|
|
199
|
-
component: (
|
|
200
|
-
<Protected>
|
|
201
|
-
<ActualizarGatos />
|
|
202
|
-
</Protected>
|
|
203
|
-
),
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
path: "/ver-gatos",
|
|
207
|
-
component: (
|
|
208
|
-
<Protected>
|
|
209
|
-
<VerGatos />{" "}
|
|
210
|
-
</Protected>
|
|
211
|
-
),
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
path: "/agregar-gatos",
|
|
215
|
-
component: (
|
|
216
|
-
<Protected>
|
|
217
|
-
<AgregarGatos />
|
|
218
|
-
</Protected>
|
|
219
|
-
),
|
|
220
|
-
},
|
|
221
|
-
];
|
|
222
|
-
|
|
223
|
-
export default function MichiRouter() {
|
|
224
|
-
return (
|
|
225
|
-
<RouterProvider routes={rutas} layout={BaseLayout}>
|
|
226
|
-
<NotFoud404 />
|
|
227
|
-
</RouterProvider>
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Usando un Layout General
|
|
233
|
-
|
|
234
|
-
Puede aplicar un layout común a todas tus rutas:
|
|
235
|
-
|
|
236
|
-
```tsx
|
|
237
|
-
import { RouterProvider } from "@arielgonzaguer/michi-router";
|
|
238
|
-
import MainLayout from "./layouts/MainLayout";
|
|
239
|
-
|
|
240
|
-
const routes = [
|
|
241
|
-
{ path: "/", component: <Home /> },
|
|
242
|
-
{ path: "/felinos-ferales", component: <Ferales /> },
|
|
243
|
-
];
|
|
244
|
-
|
|
245
|
-
function App() {
|
|
246
|
-
return (
|
|
247
|
-
<RouterProvider routes={routes} layout={MainLayout}>
|
|
248
|
-
<div>404: Page not found</div>
|
|
249
|
-
</RouterProvider>
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Ejemplo de un componente Layout
|
|
254
|
-
function MainLayout({ children }) {
|
|
255
|
-
return (
|
|
256
|
-
<div className="layout">
|
|
257
|
-
<header>
|
|
258
|
-
<nav>
|
|
259
|
-
<Link to="/">Home</Link>
|
|
260
|
-
<Link to="/felinos-ferales">Ferales</Link>
|
|
261
|
-
</nav>
|
|
262
|
-
</header>
|
|
263
|
-
<main>{children}</main>
|
|
264
|
-
<footer>Michi-router 😸</footer>
|
|
265
|
-
</div>
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## API
|
|
271
|
-
|
|
272
|
-
### `<RouterProvider>`
|
|
273
|
-
|
|
274
|
-
Componente principal para el enrutamiento.
|
|
275
|
-
|
|
276
|
-
**Props:**
|
|
277
|
-
|
|
278
|
-
- `routes`: Array de objetos con `path` y `component`.
|
|
279
|
-
- `children`: Elemento a mostrar cuando no hay ruta coincidente.
|
|
280
|
-
- `layout`: Componente opcional que funciona como layout general para todas las rutas.
|
|
281
|
-
|
|
282
|
-
### `<Link>`
|
|
283
|
-
|
|
284
|
-
Componente para navegación declarativa.
|
|
285
|
-
|
|
286
|
-
**Props:**
|
|
287
|
-
|
|
288
|
-
- `to`: Ruta destino.
|
|
289
|
-
- `children`: Contenido del enlace.
|
|
290
|
-
- `className`: Clases CSS opcionales.
|
|
291
|
-
- `...rest`: Cualquier otra prop válida para elementos `<a>` de HTML.
|
|
292
|
-
|
|
293
|
-
### `useNavigate()`
|
|
294
|
-
|
|
295
|
-
Hook para navegación programática.
|
|
296
|
-
|
|
297
|
-
**Retorna:**
|
|
298
|
-
|
|
299
|
-
- Función navigate que acepta la ruta como parámetro.
|
|
300
|
-
|
|
301
|
-
## Próximas características
|
|
302
|
-
|
|
303
|
-
- [ ] Transiciones entre rutas.
|
|
304
|
-
|
|
305
|
-
```jsx
|
|
306
|
-
<RouterProvider routes={routes} transitions={true} transitionDuration={300}>
|
|
307
|
-
<NotFound />
|
|
308
|
-
</RouterProvider>
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
## Solución de problemas comunes
|
|
312
|
-
|
|
313
|
-
### El componente no se renderiza después de navegar
|
|
314
|
-
|
|
315
|
-
Asegúrese de que la ruta en el array `routes` coincida exactamente con la URL, incluyendo barras diagonales.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
## Contribuir
|
|
319
|
-
|
|
320
|
-
Las contribuciones son bienvenidas. Por favor, sigue estos pasos:
|
|
321
|
-
|
|
322
|
-
1. Fork el repositorio.
|
|
323
|
-
2. Crea una rama para tu feature (`git checkout -b feature/amazing-feature`).
|
|
324
|
-
3. Haz commit de tus cambios (`git commit -m 'Add some amazing feature'`).
|
|
325
|
-
4. Push a la rama (`git push origin feature/amazing-feature`).
|
|
326
|
-
5. Abre un Pull Request.
|
|
327
|
-
|
|
328
|
-
## Licencia
|
|
329
|
-
|
|
330
|
-
MIT
|
|
26
|
+
Visite la [Documentación oficial](https://michirouter.vercel.app/) para más detalles.
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,73 @@
|
|
|
1
|
-
|
|
1
|
+
import React$1, { ReactNode } from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
interface LayoutProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
interface Route {
|
|
8
|
+
path: string;
|
|
9
|
+
component: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
interface RouterContextType {
|
|
12
|
+
path: string;
|
|
13
|
+
navigate: (to: string) => void;
|
|
14
|
+
}
|
|
15
|
+
interface RouterProviderProps {
|
|
16
|
+
routes: Array<{
|
|
17
|
+
path: string;
|
|
18
|
+
component: React.ReactNode;
|
|
19
|
+
}>;
|
|
20
|
+
children?: React.ReactNode;
|
|
21
|
+
layout?: React.ComponentType<{
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
26
|
+
to: string;
|
|
27
|
+
children: ReactNode;
|
|
28
|
+
className?: string;
|
|
29
|
+
}
|
|
30
|
+
interface ProtectedProps {
|
|
31
|
+
children: JSX.Element;
|
|
32
|
+
configObject: {
|
|
33
|
+
states: {
|
|
34
|
+
user: any;
|
|
35
|
+
isLoading: boolean;
|
|
36
|
+
};
|
|
37
|
+
redirectionPath: string;
|
|
38
|
+
loadingComponent?: ReactNode;
|
|
39
|
+
defaultMessage?: string | undefined;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Proveedor principal del enrutador.
|
|
45
|
+
* @param routes - Array de rutas disponibles
|
|
46
|
+
* @param children - Contenido a mostrar cuando no hay coincidencia de ruta (404)
|
|
47
|
+
* @param layout - Componente de layout opcional para envolver todas las rutas
|
|
48
|
+
*/
|
|
49
|
+
declare function RouterProvider({ routes, children, layout: Layout }: RouterProviderProps): react_jsx_runtime.JSX.Element;
|
|
50
|
+
/**
|
|
51
|
+
* Componente Link para navegación declarativa.
|
|
52
|
+
* Previene la recarga de página y utiliza el historial del navegador.
|
|
53
|
+
*/
|
|
54
|
+
declare const Link: ({ to, children, className, ...rest }: LinkProps & React$1.AnchorHTMLAttributes<HTMLAnchorElement>) => react_jsx_runtime.JSX.Element;
|
|
55
|
+
/**
|
|
56
|
+
* Hook para acceder a la función de navegación programática.
|
|
57
|
+
* @returns Función navigate que permite cambiar de ruta
|
|
58
|
+
*/
|
|
59
|
+
declare const useNavigate: () => (to: string) => void;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Un componente que restringe el acceso a sus hijos según el estado de autenticación del usuario.
|
|
63
|
+
*
|
|
64
|
+
* Si el usuario no está autenticado, redirige a la página de landing ("/").
|
|
65
|
+
* De lo contrario, renderiza sus hijos.
|
|
66
|
+
*
|
|
67
|
+
* @param {Object} props - Props del componente
|
|
68
|
+
* @param {React.ReactNode} props.children - Los nodos React a renderizar si el usuario está autenticado.
|
|
69
|
+
* @returns {JSX.Element|null} Los hijos si está autenticado, de lo contrario loader.
|
|
70
|
+
*/
|
|
71
|
+
declare function Protected({ children, configObject }: ProtectedProps): JSX.Element | null;
|
|
72
|
+
|
|
73
|
+
export { type LayoutProps, Link, type LinkProps, Protected, type ProtectedProps, type Route, type RouterContextType, RouterProvider, type RouterProviderProps, useNavigate };
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./michi-router"), exports);
|
|
1
|
+
"use strict";var p=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var w=(t,e)=>{for(var n in e)p(t,n,{get:e[n],enumerable:!0})},y=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of C(e))!x.call(t,r)&&r!==n&&p(t,r,{get:()=>e[r],enumerable:!(o=h(e,r))||o.enumerable});return t};var L=t=>y(p({},"__esModule",{value:!0}),t);var E={};w(E,{Link:()=>g,Protected:()=>c,RouterProvider:()=>m,useNavigate:()=>u});module.exports=L(E);var a=require("react"),d=require("react/jsx-runtime"),l=(0,a.createContext)({path:window.location.pathname,navigate:()=>{console.warn("RouterContext usado fuera de RouterProvider")}});function m({routes:t,children:e,layout:n}){let[o,r]=(0,a.useState)(window.location.pathname);(0,a.useEffect)(()=>{let s=()=>r(window.location.pathname);return window.addEventListener("popstate",s),()=>window.removeEventListener("popstate",s)},[]);let i=(0,a.useCallback)(s=>{window.history.pushState({},"",s),r(s)},[]),P=t.find(s=>s.path===o),f=P?P.component:e;try{return(0,d.jsx)(l.Provider,{value:{path:o,navigate:i},children:n?(0,d.jsx)(n,{children:f}):f})}catch(s){return console.error("Error en RouterProvider:",s),(0,d.jsx)("div",{children:"Error en el enrutador. Consulta la consola para m\xE1s detalles."})}}var g=({to:t,children:e,className:n,...o})=>{let{navigate:r}=(0,a.useContext)(l);return(0,d.jsx)("a",{href:t,className:n,onClick:i=>{i.preventDefault(),r(t)},...o,children:e})},u=()=>{let{navigate:t}=(0,a.useContext)(l);return t};var v=require("react");var R=require("react/jsx-runtime");function c({children:t,configObject:e}){let n=u(),o={states:e?.states||null,redirectionPath:e?.redirectionPath||"/",loadingComponent:e?.loadingComponent||null,defaultMessage:e?.defaultMessage||void 0};if(!o.states)return console.error(`Componente Protected: El objeto de configuraci\xF3n es inv\xE1lido. Este es el formato esperado:
|
|
2
|
+
{
|
|
3
|
+
states: { user: any; isLoading: boolean };
|
|
4
|
+
redirectionPath: string;
|
|
5
|
+
loadingComponent?: React.ReactNode;
|
|
6
|
+
defaultMessage?: string;
|
|
7
|
+
}`),null;let{user:r,isLoading:i}=o.states;return(0,v.useEffect)(()=>{!i&&!r&&n(o.redirectionPath)},[i,r,n,o.redirectionPath]),i?o.loadingComponent?o.loadingComponent:o.defaultMessage?(0,R.jsx)("div",{children:o.defaultMessage}):null:r?t:null}0&&(module.exports={Link,Protected,RouterProvider,useNavigate});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{useCallback as f,createContext as m,useContext as c,useState as g,useEffect as v}from"react";import{jsx as i}from"react/jsx-runtime";var d=m({path:window.location.pathname,navigate:()=>{console.warn("RouterContext usado fuera de RouterProvider")}});function R({routes:o,children:r,layout:a}){let[e,n]=g(window.location.pathname);v(()=>{let t=()=>n(window.location.pathname);return window.addEventListener("popstate",t),()=>window.removeEventListener("popstate",t)},[]);let s=f(t=>{window.history.pushState({},"",t),n(t)},[]),p=o.find(t=>t.path===e),l=p?p.component:r;try{return i(d.Provider,{value:{path:e,navigate:s},children:a?i(a,{children:l}):l})}catch(t){return console.error("Error en RouterProvider:",t),i("div",{children:"Error en el enrutador. Consulta la consola para m\xE1s detalles."})}}var h=({to:o,children:r,className:a,...e})=>{let{navigate:n}=c(d);return i("a",{href:o,className:a,onClick:s=>{s.preventDefault(),n(o)},...e,children:r})},u=()=>{let{navigate:o}=c(d);return o};import{useEffect as C}from"react";import{jsx as x}from"react/jsx-runtime";function P({children:o,configObject:r}){let a=u(),e={states:r?.states||null,redirectionPath:r?.redirectionPath||"/",loadingComponent:r?.loadingComponent||null,defaultMessage:r?.defaultMessage||void 0};if(!e.states)return console.error(`Componente Protected: El objeto de configuraci\xF3n es inv\xE1lido. Este es el formato esperado:
|
|
2
|
+
{
|
|
3
|
+
states: { user: any; isLoading: boolean };
|
|
4
|
+
redirectionPath: string;
|
|
5
|
+
loadingComponent?: React.ReactNode;
|
|
6
|
+
defaultMessage?: string;
|
|
7
|
+
}`),null;let{user:n,isLoading:s}=e.states;return C(()=>{!s&&!n&&a(e.redirectionPath)},[s,n,a,e.redirectionPath]),s?e.loadingComponent?e.loadingComponent:e.defaultMessage?x("div",{children:e.defaultMessage}):null:n?o:null}export{h as Link,P as Protected,R as RouterProvider,u as useNavigate};
|
package/package.json
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arielgonzaguer/michi-router",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"description": "El router minimalista y simple para React.\nEl objetivo principal de esta herramienta es proporcionar la funcionalidad básica de enrutamiento.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
7
8
|
"types": "dist/index.d.ts",
|
|
8
9
|
"files": [
|
|
9
|
-
"dist"
|
|
10
|
+
"dist/index.mjs",
|
|
11
|
+
"dist/index.js",
|
|
12
|
+
"dist/index.d.ts"
|
|
10
13
|
],
|
|
11
14
|
"scripts": {
|
|
12
15
|
"build": "tsc",
|
|
13
|
-
"prepare": "npm run build",
|
|
16
|
+
"prepare": "npm run build:bundle",
|
|
14
17
|
"clean": "rimraf dist",
|
|
15
18
|
"prebuild": "npm run clean",
|
|
16
|
-
"prepublishOnly": "npm run build"
|
|
19
|
+
"prepublishOnly": "npm run build:bundle",
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"test:watch": "vitest --watch",
|
|
22
|
+
"build:bundle": "tsup src/index.ts --format esm,cjs --minify --dts --out-dir dist --external react --external react-dom"
|
|
17
23
|
},
|
|
18
24
|
"keywords": [
|
|
25
|
+
"enrutado",
|
|
19
26
|
"react",
|
|
20
27
|
"router",
|
|
21
28
|
"typescript",
|
|
@@ -24,17 +31,24 @@
|
|
|
24
31
|
"gatos"
|
|
25
32
|
],
|
|
26
33
|
"peerDependencies": {
|
|
27
|
-
"react": ">=
|
|
28
|
-
"react-dom": ">=
|
|
34
|
+
"react": ">=17.0.0",
|
|
35
|
+
"react-dom": ">=17.0.0"
|
|
29
36
|
},
|
|
30
37
|
"devDependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"react": "
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
38
|
+
"@swc/core": "1.13.5",
|
|
39
|
+
"@testing-library/jest-dom": "6.0.0",
|
|
40
|
+
"@testing-library/react": "14.0.0",
|
|
41
|
+
"@types/jest": "29.5.3",
|
|
42
|
+
"@types/react": "18.3.18",
|
|
43
|
+
"@types/react-dom": "18.3.5",
|
|
44
|
+
"jsdom": "26.1.0",
|
|
45
|
+
"react": "18.3.1",
|
|
46
|
+
"react-dom": "18.3.1",
|
|
47
|
+
"rimraf": "6.0.1",
|
|
48
|
+
"tsup": "8.5.0",
|
|
49
|
+
"typescript": "4.9.5",
|
|
50
|
+
"vitest": "3.2.4"
|
|
37
51
|
},
|
|
38
|
-
"author": "Ariel
|
|
52
|
+
"author": "Ariel Gonzales Agüero",
|
|
39
53
|
"license": "MIT"
|
|
40
54
|
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { RouterContextType, RouterProviderProps, LinkProps } from './types';
|
|
3
|
-
declare const RouterContext: React.Context<RouterContextType>;
|
|
4
|
-
/**
|
|
5
|
-
* Proveedor principal del enrutador.
|
|
6
|
-
* @param routes - Array de rutas disponibles
|
|
7
|
-
* @param children - Contenido a mostrar cuando no hay coincidencia de ruta (404)
|
|
8
|
-
* @param layout - Componente de layout opcional para envolver todas las rutas
|
|
9
|
-
*/
|
|
10
|
-
export declare function RouterProvider({ routes, children, layout: Layout }: RouterProviderProps): React.JSX.Element;
|
|
11
|
-
/**
|
|
12
|
-
* Componente Link para navegación declarativa.
|
|
13
|
-
* Previene la recarga de página y utiliza el historial del navegador.
|
|
14
|
-
*/
|
|
15
|
-
export declare const Link: ({ to, children, className, ...rest }: LinkProps & React.AnchorHTMLAttributes<HTMLAnchorElement>) => React.JSX.Element;
|
|
16
|
-
/**
|
|
17
|
-
* Hook para acceder a la función de navegación programática.
|
|
18
|
-
* @returns Función navigate que permite cambiar de ruta
|
|
19
|
-
*/
|
|
20
|
-
export declare const useNavigate: () => (to: string) => void;
|
|
21
|
-
export { RouterContext };
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
-
}
|
|
19
|
-
Object.defineProperty(o, k2, desc);
|
|
20
|
-
}) : (function(o, m, k, k2) {
|
|
21
|
-
if (k2 === undefined) k2 = k;
|
|
22
|
-
o[k2] = m[k];
|
|
23
|
-
}));
|
|
24
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
-
}) : function(o, v) {
|
|
27
|
-
o["default"] = v;
|
|
28
|
-
});
|
|
29
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
-
if (mod && mod.__esModule) return mod;
|
|
31
|
-
var result = {};
|
|
32
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
-
__setModuleDefault(result, mod);
|
|
34
|
-
return result;
|
|
35
|
-
};
|
|
36
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
37
|
-
var t = {};
|
|
38
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
39
|
-
t[p] = s[p];
|
|
40
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
41
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
42
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
43
|
-
t[p[i]] = s[p[i]];
|
|
44
|
-
}
|
|
45
|
-
return t;
|
|
46
|
-
};
|
|
47
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.RouterContext = exports.useNavigate = exports.Link = exports.RouterProvider = void 0;
|
|
49
|
-
var react_1 = __importStar(require("react"));
|
|
50
|
-
// Creación del contexto con un valor inicial
|
|
51
|
-
var RouterContext = (0, react_1.createContext)({
|
|
52
|
-
path: window.location.pathname,
|
|
53
|
-
navigate: function () {
|
|
54
|
-
console.warn('RouterContext usado fuera de RouterProvider');
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
exports.RouterContext = RouterContext;
|
|
58
|
-
/**
|
|
59
|
-
* Proveedor principal del enrutador.
|
|
60
|
-
* @param routes - Array de rutas disponibles
|
|
61
|
-
* @param children - Contenido a mostrar cuando no hay coincidencia de ruta (404)
|
|
62
|
-
* @param layout - Componente de layout opcional para envolver todas las rutas
|
|
63
|
-
*/
|
|
64
|
-
function RouterProvider(_a) {
|
|
65
|
-
var routes = _a.routes, children = _a.children, Layout = _a.layout;
|
|
66
|
-
var _b = (0, react_1.useState)(window.location.pathname), path = _b[0], setPath = _b[1];
|
|
67
|
-
(0, react_1.useEffect)(function () {
|
|
68
|
-
var handlePopState = function () { return setPath(window.location.pathname); };
|
|
69
|
-
window.addEventListener('popstate', handlePopState);
|
|
70
|
-
return function () { return window.removeEventListener('popstate', handlePopState); };
|
|
71
|
-
}, []);
|
|
72
|
-
var navigate = (0, react_1.useCallback)(function (to) {
|
|
73
|
-
window.history.pushState({}, '', to);
|
|
74
|
-
setPath(to);
|
|
75
|
-
}, []);
|
|
76
|
-
// Encontrar la ruta actual
|
|
77
|
-
var currentRoute = routes.find(function (route) { return route.path === path; });
|
|
78
|
-
var routeContent = currentRoute ? currentRoute.component : children;
|
|
79
|
-
try {
|
|
80
|
-
return (react_1.default.createElement(RouterContext.Provider, { value: { path: path, navigate: navigate } }, Layout ? (react_1.default.createElement(Layout, null, routeContent)) : (routeContent)));
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
console.error('Error en RouterProvider:', error);
|
|
84
|
-
return react_1.default.createElement("div", null, "Error en el enrutador. Consulta la consola para m\u00E1s detalles.");
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
exports.RouterProvider = RouterProvider;
|
|
88
|
-
/**
|
|
89
|
-
* Componente Link para navegación declarativa.
|
|
90
|
-
* Previene la recarga de página y utiliza el historial del navegador.
|
|
91
|
-
*/
|
|
92
|
-
var Link = function (_a) {
|
|
93
|
-
var to = _a.to, children = _a.children, className = _a.className, rest = __rest(_a, ["to", "children", "className"]);
|
|
94
|
-
var navigate = (0, react_1.useContext)(RouterContext).navigate;
|
|
95
|
-
return (react_1.default.createElement("a", __assign({ href: to, className: className, onClick: function (e) {
|
|
96
|
-
e.preventDefault();
|
|
97
|
-
navigate(to);
|
|
98
|
-
} }, rest), children));
|
|
99
|
-
};
|
|
100
|
-
exports.Link = Link;
|
|
101
|
-
/**
|
|
102
|
-
* Hook para acceder a la función de navegación programática.
|
|
103
|
-
* @returns Función navigate que permite cambiar de ruta
|
|
104
|
-
*/
|
|
105
|
-
var useNavigate = function () {
|
|
106
|
-
var navigate = (0, react_1.useContext)(RouterContext).navigate;
|
|
107
|
-
return navigate;
|
|
108
|
-
};
|
|
109
|
-
exports.useNavigate = useNavigate;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useNavigate = exports.Link = exports.RouterProvider = void 0;
|
|
4
|
-
var Michi_router_1 = require("./Michi-router");
|
|
5
|
-
Object.defineProperty(exports, "RouterProvider", { enumerable: true, get: function () { return Michi_router_1.RouterProvider; } });
|
|
6
|
-
Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return Michi_router_1.Link; } });
|
|
7
|
-
Object.defineProperty(exports, "useNavigate", { enumerable: true, get: function () { return Michi_router_1.useNavigate; } });
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
export interface LayoutProps {
|
|
3
|
-
children: ReactNode;
|
|
4
|
-
}
|
|
5
|
-
export interface Route {
|
|
6
|
-
path: string;
|
|
7
|
-
component: ReactNode;
|
|
8
|
-
}
|
|
9
|
-
export interface RouterContextType {
|
|
10
|
-
path: string;
|
|
11
|
-
navigate: (to: string) => void;
|
|
12
|
-
}
|
|
13
|
-
export interface RouterProviderProps {
|
|
14
|
-
routes: Array<{
|
|
15
|
-
path: string;
|
|
16
|
-
component: React.ReactNode;
|
|
17
|
-
}>;
|
|
18
|
-
children?: React.ReactNode;
|
|
19
|
-
layout?: React.ComponentType<{
|
|
20
|
-
children: React.ReactNode;
|
|
21
|
-
}>;
|
|
22
|
-
}
|
|
23
|
-
export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
24
|
-
to: string;
|
|
25
|
-
children: ReactNode;
|
|
26
|
-
className?: string;
|
|
27
|
-
}
|