@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
+ ![npm version](https://img.shields.io/npm/v/@arielgonzaguer/michi-router)
4
+ ![bundle size](https://img.shields.io/bundlephobia/minzip/@arielgonzaguer/michi-router)
5
+ ![license](https://img.shields.io/npm/l/@arielgonzaguer/michi-router)
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
- ## Usage
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
- // Usando Link
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
- export declare function RouterProvider({ routes, children, layout: Layout }: RouterProviderProps & {
5
- layout?: React.ComponentType<{
6
- children: React.ReactNode;
7
- }>;
8
- }): React.JSX.Element;
9
- export declare const Link: ({ to, children, className }: LinkProps) => React.JSX.Element;
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 __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
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 = __importDefault(require("react"));
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, react_2.createContext)({
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, react_2.useState)(window.location.pathname), path = _b[0], setPath = _b[1];
18
- (0, react_2.useEffect)(function () {
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
- return (react_1.default.createElement(RouterContext.Provider, { value: { path: path, navigate: navigate } }, Layout ? (react_1.default.createElement(Layout, null, routeContent)) : (routeContent)));
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, react_2.useContext)(RouterContext).navigate;
35
- return (react_1.default.createElement("a", { href: to, className: className, style: { marginRight: '1rem' }, onClick: function (e) {
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, react_2.useContext)(RouterContext).navigate;
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;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arielgonzaguer/michi-router",
3
3
  "private": false,
4
- "version": "1.0.1",
4
+ "version": "1.0.3",
5
5
  "description": "The minimalist and simple router for React",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",