@arielgonzaguer/michi-router 1.0.1 → 1.0.3
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
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
# Michi Router
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
3
7
|
El router minimalista y simple para React.
|
|
8
|
+
El objetivo principal de esta herramienta es proporcionar la funcionalidad básica de enrutamiento.
|
|
9
|
+
|
|
10
|
+
## Características
|
|
11
|
+
|
|
12
|
+
- Es ideal para proyectos pequeños o que solo necesitan una funcionalidad básica de enrutamiento.
|
|
13
|
+
- No requiere de ninguna configuración adicional.
|
|
14
|
+
- No requiere de ninguna dependencia externa.
|
|
15
|
+
- Creado con TypeScript.
|
|
16
|
+
- Ultra ligero. Menos de 20kb (más ligero y básico que otras librerías).
|
|
17
|
+
|
|
18
|
+
## Compatibilidad
|
|
19
|
+
|
|
20
|
+
- React 16.8+.
|
|
21
|
+
- Funciona con proyectos creados con Create React App, Vite, Next.js, etc.
|
|
22
|
+
- Totalmente tipado con TypeScript.
|
|
4
23
|
|
|
5
24
|
## Installation
|
|
6
25
|
|
|
@@ -8,9 +27,10 @@ El router minimalista y simple para React.
|
|
|
8
27
|
npm install @arielgonzaguer/michi-router
|
|
9
28
|
```
|
|
10
29
|
|
|
11
|
-
##
|
|
30
|
+
## Uso básico
|
|
12
31
|
|
|
13
32
|
```jsx
|
|
33
|
+
// src/App.jsx //
|
|
14
34
|
import { RouterProvider, Link } from "@arielgonzaguer/michi-router";
|
|
15
35
|
|
|
16
36
|
// puede crear rutas en un archivo separado o en el mismo archivo
|
|
@@ -27,8 +47,12 @@ function App() {
|
|
|
27
47
|
</RouterProvider>
|
|
28
48
|
);
|
|
29
49
|
}
|
|
50
|
+
```
|
|
30
51
|
|
|
31
|
-
|
|
52
|
+
### Usando Link
|
|
53
|
+
|
|
54
|
+
#### Usando el componente Link solo con prop to
|
|
55
|
+
```jsx
|
|
32
56
|
function NavigationComponent() {
|
|
33
57
|
return (
|
|
34
58
|
<nav>
|
|
@@ -37,14 +61,94 @@ function NavigationComponent() {
|
|
|
37
61
|
</nav>
|
|
38
62
|
);
|
|
39
63
|
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### Usando el componente Link con todas las props
|
|
67
|
+
```jsx
|
|
68
|
+
<Link
|
|
69
|
+
to="/contact"
|
|
70
|
+
className="nav-link"
|
|
71
|
+
target="_blank"
|
|
72
|
+
rel="noopener noreferrer"
|
|
73
|
+
aria-label="Contacto"
|
|
74
|
+
>
|
|
75
|
+
Contacto
|
|
76
|
+
</Link>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### Navegación programática (Hook useNavigate)
|
|
82
|
+
|
|
83
|
+
```jsx
|
|
84
|
+
import { useNavigate } from "@arielgonzaguer/michi-router";
|
|
40
85
|
|
|
41
|
-
// Usando useNavigate
|
|
42
86
|
function NavigateButton() {
|
|
43
87
|
const navigate = useNavigate();
|
|
44
88
|
return <button onClick={() => navigate("/about")}>Ir a About</button>;
|
|
45
89
|
}
|
|
46
90
|
```
|
|
47
91
|
|
|
92
|
+
### Organización de rutas en archivos separados
|
|
93
|
+
|
|
94
|
+
Para aplicaciones más grandes, puedes organizar tus rutas en archivos separados:
|
|
95
|
+
|
|
96
|
+
```jsx
|
|
97
|
+
// routes.js
|
|
98
|
+
import Home from "./pages/Home";
|
|
99
|
+
import About from "./pages/About";
|
|
100
|
+
import Products from "./pages/Products";
|
|
101
|
+
import NotFound from "./pages/NotFound";
|
|
102
|
+
|
|
103
|
+
export const routes = [
|
|
104
|
+
{ path: "/", component: <Home /> },
|
|
105
|
+
{ path: "/about", component: <About /> },
|
|
106
|
+
{ path: "/products", component: <Products /> },
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
export const notFoundPage = <NotFound />;
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```jsx
|
|
113
|
+
// App.jsx
|
|
114
|
+
import { RouterProvider } from "@arielgonzaguer/michi-router";
|
|
115
|
+
import { routes, notFoundPage } from "./routes";
|
|
116
|
+
|
|
117
|
+
function App() {
|
|
118
|
+
return <RouterProvider routes={routes}>{notFoundPage}</RouterProvider>;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Integración con sistemas de autenticación
|
|
123
|
+
|
|
124
|
+
```jsx
|
|
125
|
+
import { RouterProvider } from "@arielgonzaguer/michi-router";
|
|
126
|
+
import { useAuth } from "./auth-context";
|
|
127
|
+
|
|
128
|
+
function App() {
|
|
129
|
+
const { isAuthenticated } = useAuth();
|
|
130
|
+
|
|
131
|
+
// Definimos rutas condicionalmente basadas en autenticación
|
|
132
|
+
const routes = [
|
|
133
|
+
{ path: "/", component: <Home /> },
|
|
134
|
+
{ path: "/login", component: <Login /> },
|
|
135
|
+
// Solo agregamos estas rutas si el usuario está autenticado
|
|
136
|
+
...(isAuthenticated
|
|
137
|
+
? [
|
|
138
|
+
{ path: "/profile", component: <Profile /> },
|
|
139
|
+
{ path: "/admin", component: <Admin /> },
|
|
140
|
+
]
|
|
141
|
+
: []),
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<RouterProvider routes={routes}>
|
|
146
|
+
<div>404: Page not found</div>
|
|
147
|
+
</RouterProvider>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
48
152
|
### Usando un Layout General
|
|
49
153
|
|
|
50
154
|
Puedes aplicar un layout común a todas tus rutas:
|
|
@@ -91,9 +195,9 @@ Componente principal para el enrutamiento.
|
|
|
91
195
|
|
|
92
196
|
**Props:**
|
|
93
197
|
|
|
94
|
-
- `routes`: Array de objetos con `path` y `component
|
|
95
|
-
- `children`: Elemento a mostrar cuando no hay ruta coincidente
|
|
96
|
-
- `layout`: Componente opcional que funciona como layout general para todas las rutas
|
|
198
|
+
- `routes`: Array de objetos con `path` y `component`.
|
|
199
|
+
- `children`: Elemento a mostrar cuando no hay ruta coincidente.
|
|
200
|
+
- `layout`: Componente opcional que funciona como layout general para todas las rutas.
|
|
97
201
|
|
|
98
202
|
### `<Link>`
|
|
99
203
|
|
|
@@ -101,9 +205,10 @@ Componente para navegación declarativa.
|
|
|
101
205
|
|
|
102
206
|
**Props:**
|
|
103
207
|
|
|
104
|
-
- `to`: Ruta destino
|
|
105
|
-
- `children`: Contenido del enlace
|
|
106
|
-
- `className`: Clases CSS opcionales
|
|
208
|
+
- `to`: Ruta destino.
|
|
209
|
+
- `children`: Contenido del enlace.
|
|
210
|
+
- `className`: Clases CSS opcionales.
|
|
211
|
+
- `...rest`: Cualquier otra prop válida para elementos `<a>` de HTML.
|
|
107
212
|
|
|
108
213
|
### `useNavigate()`
|
|
109
214
|
|
|
@@ -111,7 +216,61 @@ Hook para navegación programática.
|
|
|
111
216
|
|
|
112
217
|
**Retorna:**
|
|
113
218
|
|
|
114
|
-
- Función navigate que acepta la ruta como parámetro
|
|
219
|
+
- Función navigate que acepta la ruta como parámetro.
|
|
220
|
+
|
|
221
|
+
## Próximas características
|
|
222
|
+
|
|
223
|
+
- [ ] Soporte para rutas anidadas.
|
|
224
|
+
|
|
225
|
+
```jsx
|
|
226
|
+
const routes = [
|
|
227
|
+
{
|
|
228
|
+
path: "/dashboard",
|
|
229
|
+
component: <Dashboard />,
|
|
230
|
+
children: [
|
|
231
|
+
{ path: "/users", component: <Users /> },
|
|
232
|
+
{ path: "/settings", component: <Settings /> },
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
];
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
- [ ] Transiciones entre rutas.
|
|
239
|
+
|
|
240
|
+
```jsx
|
|
241
|
+
<RouterProvider routes={routes} transitions={true} transitionDuration={300}>
|
|
242
|
+
<NotFound />
|
|
243
|
+
</RouterProvider>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Solución de problemas comunes
|
|
247
|
+
|
|
248
|
+
### El componente no se renderiza después de navegar
|
|
249
|
+
|
|
250
|
+
Asegúrate de que la ruta en el array `routes` coincida exactamente con la URL, incluyendo barras diagonales.
|
|
251
|
+
|
|
252
|
+
### Errores con TypeScript
|
|
253
|
+
|
|
254
|
+
Si estás usando TypeScript, asegúrate de importar los tipos correctamente:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import {
|
|
258
|
+
RouterProvider,
|
|
259
|
+
Link,
|
|
260
|
+
useNavigate,
|
|
261
|
+
} from "@arielgonzaguer/michi-router";
|
|
262
|
+
import type { RouterProviderProps } from "@arielgonzaguer/michi-router";
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Contribuir
|
|
266
|
+
|
|
267
|
+
Las contribuciones son bienvenidas. Por favor, sigue estos pasos:
|
|
268
|
+
|
|
269
|
+
1. Fork el repositorio.
|
|
270
|
+
2. Crea una rama para tu feature (`git checkout -b feature/amazing-feature`).
|
|
271
|
+
3. Haz commit de tus cambios (`git commit -m 'Add some amazing feature'`).
|
|
272
|
+
4. Push a la rama (`git push origin feature/amazing-feature`).
|
|
273
|
+
5. Abre un Pull Request.
|
|
115
274
|
|
|
116
275
|
## Licencia
|
|
117
276
|
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { RouterContextType, RouterProviderProps, LinkProps } from './types';
|
|
3
3
|
declare const RouterContext: React.Context<RouterContextType>;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
+
*/
|
|
10
20
|
export declare const useNavigate: () => (to: string) => void;
|
|
11
21
|
export { RouterContext };
|
|
@@ -1,45 +1,109 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
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;
|
|
4
46
|
};
|
|
5
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
48
|
exports.RouterContext = exports.useNavigate = exports.Link = exports.RouterProvider = void 0;
|
|
7
|
-
var react_1 =
|
|
8
|
-
var react_2 = require("react");
|
|
49
|
+
var react_1 = __importStar(require("react"));
|
|
9
50
|
// Creación del contexto con un valor inicial
|
|
10
|
-
var RouterContext = (0,
|
|
11
|
-
path:
|
|
12
|
-
navigate: function () {
|
|
51
|
+
var RouterContext = (0, react_1.createContext)({
|
|
52
|
+
path: window.location.pathname,
|
|
53
|
+
navigate: function () {
|
|
54
|
+
console.warn('RouterContext usado fuera de RouterProvider');
|
|
55
|
+
}
|
|
13
56
|
});
|
|
14
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
|
+
*/
|
|
15
64
|
function RouterProvider(_a) {
|
|
16
65
|
var routes = _a.routes, children = _a.children, Layout = _a.layout;
|
|
17
|
-
var _b = (0,
|
|
18
|
-
(0,
|
|
66
|
+
var _b = (0, react_1.useState)(window.location.pathname), path = _b[0], setPath = _b[1];
|
|
67
|
+
(0, react_1.useEffect)(function () {
|
|
19
68
|
var handlePopState = function () { return setPath(window.location.pathname); };
|
|
20
69
|
window.addEventListener('popstate', handlePopState);
|
|
21
70
|
return function () { return window.removeEventListener('popstate', handlePopState); };
|
|
22
71
|
}, []);
|
|
23
|
-
var navigate = function (to) {
|
|
72
|
+
var navigate = (0, react_1.useCallback)(function (to) {
|
|
24
73
|
window.history.pushState({}, '', to);
|
|
25
74
|
setPath(to);
|
|
26
|
-
};
|
|
75
|
+
}, []);
|
|
76
|
+
// Encontrar la ruta actual
|
|
27
77
|
var currentRoute = routes.find(function (route) { return route.path === path; });
|
|
28
78
|
var routeContent = currentRoute ? currentRoute.component : children;
|
|
29
|
-
|
|
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
|
+
}
|
|
30
86
|
}
|
|
31
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
|
+
*/
|
|
32
92
|
var Link = function (_a) {
|
|
33
|
-
var to = _a.to, children = _a.children, className = _a.className;
|
|
34
|
-
var navigate = (0,
|
|
35
|
-
return (react_1.default.createElement("a", { href: to, className: className,
|
|
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) {
|
|
36
96
|
e.preventDefault();
|
|
37
97
|
navigate(to);
|
|
38
|
-
} }, children));
|
|
98
|
+
} }, rest), children));
|
|
39
99
|
};
|
|
40
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
|
+
*/
|
|
41
105
|
var useNavigate = function () {
|
|
42
|
-
var navigate = (0,
|
|
106
|
+
var navigate = (0, react_1.useContext)(RouterContext).navigate;
|
|
43
107
|
return navigate;
|
|
44
108
|
};
|
|
45
109
|
exports.useNavigate = useNavigate;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { RouterProvider, Link, useNavigate } from './Michi-router';
|
|
2
|
-
export type { Route, RouterContextType, RouterProviderProps, LinkProps } from './types';
|
|
2
|
+
export type { Route, RouterContextType, RouterProviderProps, LinkProps, LayoutProps } from './types';
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
+
export interface LayoutProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
2
5
|
export interface Route {
|
|
3
6
|
path: string;
|
|
4
7
|
component: ReactNode;
|
|
@@ -17,7 +20,7 @@ export interface RouterProviderProps {
|
|
|
17
20
|
children: React.ReactNode;
|
|
18
21
|
}>;
|
|
19
22
|
}
|
|
20
|
-
export interface LinkProps {
|
|
23
|
+
export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
21
24
|
to: string;
|
|
22
25
|
children: ReactNode;
|
|
23
26
|
className?: string;
|