@aminnairi/react-router 1.1.0 → 2.0.1
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/.eslintrc.cjs +13 -0
- package/README.md +185 -315
- package/index.tsx +77 -18
- package/package.json +11 -2
- package/tsconfig.json +16 -0
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
env: { browser: true, es2020: true },
|
|
4
|
+
extends: [
|
|
5
|
+
'eslint:recommended',
|
|
6
|
+
'plugin:@typescript-eslint/recommended',
|
|
7
|
+
'plugin:react-hooks/recommended',
|
|
8
|
+
],
|
|
9
|
+
ignorePatterns: ['dist', '.eslintrc.cjs', 'index.js'],
|
|
10
|
+
parser: '@typescript-eslint/parser',
|
|
11
|
+
plugins: [],
|
|
12
|
+
rules: {},
|
|
13
|
+
}
|
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ cd project
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
### Dependencies installation
|
|
20
|
+
|
|
20
21
|
```bash
|
|
21
22
|
npm install
|
|
22
23
|
```
|
|
@@ -41,10 +42,8 @@ import { createPage } from "@aminnairi/react-router";
|
|
|
41
42
|
export const home = createPage({
|
|
42
43
|
path: "/",
|
|
43
44
|
element: function Home() {
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
);
|
|
47
|
-
}
|
|
45
|
+
return <h1>Home page</h1>;
|
|
46
|
+
},
|
|
48
47
|
});
|
|
49
48
|
```
|
|
50
49
|
|
|
@@ -59,12 +58,8 @@ import { home } from "./pages/home";
|
|
|
59
58
|
export const Fallback = () => {
|
|
60
59
|
const navigateToHomePage = useNavigateToPage(home);
|
|
61
60
|
|
|
62
|
-
return (
|
|
63
|
-
|
|
64
|
-
Go back home
|
|
65
|
-
</button>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
61
|
+
return <button onClick={() => navigateToHomePage({})}>Go back home</button>;
|
|
62
|
+
};
|
|
68
63
|
```
|
|
69
64
|
|
|
70
65
|
```bash
|
|
@@ -82,30 +77,26 @@ export const Issue = () => {
|
|
|
82
77
|
return (
|
|
83
78
|
<Fragment>
|
|
84
79
|
<h1>An issue occurred</h1>
|
|
85
|
-
<button onClick={
|
|
86
|
-
Go back home
|
|
87
|
-
</button>
|
|
80
|
+
<button onClick={() => navigateToHomePage({})}>Go back home</button>
|
|
88
81
|
</Fragment>
|
|
89
82
|
);
|
|
90
|
-
}
|
|
83
|
+
};
|
|
91
84
|
```
|
|
92
85
|
|
|
93
86
|
```bash
|
|
94
87
|
touch src/router/index.ts
|
|
95
88
|
```
|
|
96
89
|
|
|
97
|
-
```
|
|
90
|
+
```ts
|
|
98
91
|
import { createRouter } from "@aminnairi/react-router";
|
|
99
|
-
import { Fallback } from "./
|
|
100
|
-
import { Issue } from "./
|
|
101
|
-
import { home } from "./
|
|
92
|
+
import { Fallback } from "./fallback";
|
|
93
|
+
import { Issue } from "./issue";
|
|
94
|
+
import { home } from "./pages/home";
|
|
102
95
|
|
|
103
96
|
export const router = createRouter({
|
|
104
97
|
fallback: Fallback,
|
|
105
98
|
issue: Issue,
|
|
106
|
-
pages: [
|
|
107
|
-
home
|
|
108
|
-
]
|
|
99
|
+
pages: [home],
|
|
109
100
|
});
|
|
110
101
|
```
|
|
111
102
|
|
|
@@ -117,9 +108,7 @@ touch src/App.tsx
|
|
|
117
108
|
import { router } from "./router";
|
|
118
109
|
|
|
119
110
|
export default function App() {
|
|
120
|
-
return
|
|
121
|
-
<router.View />
|
|
122
|
-
);
|
|
111
|
+
return <router.View />;
|
|
123
112
|
}
|
|
124
113
|
```
|
|
125
114
|
|
|
@@ -144,7 +133,7 @@ createRoot(rootElement).render(
|
|
|
144
133
|
<router.Provider>
|
|
145
134
|
<App />
|
|
146
135
|
</router.Provider>
|
|
147
|
-
</StrictMode
|
|
136
|
+
</StrictMode>,
|
|
148
137
|
);
|
|
149
138
|
```
|
|
150
139
|
|
|
@@ -166,10 +155,8 @@ import { createPage } from "@aminnairi/react-router";
|
|
|
166
155
|
createPage({
|
|
167
156
|
path: "/",
|
|
168
157
|
element: function Home() {
|
|
169
|
-
return
|
|
170
|
-
|
|
171
|
-
);
|
|
172
|
-
}
|
|
158
|
+
return <h1>Home</h1>;
|
|
159
|
+
},
|
|
173
160
|
});
|
|
174
161
|
```
|
|
175
162
|
|
|
@@ -181,24 +168,14 @@ import { createPage, createRouter } from "@aminnairi/react-router";
|
|
|
181
168
|
const home = createPage({
|
|
182
169
|
path: "/",
|
|
183
170
|
element: function Home() {
|
|
184
|
-
return
|
|
185
|
-
|
|
186
|
-
);
|
|
187
|
-
}
|
|
171
|
+
return <h1>Home</h1>;
|
|
172
|
+
},
|
|
188
173
|
});
|
|
189
174
|
|
|
190
175
|
createRouter({
|
|
191
|
-
fallback: () =>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
</h1>
|
|
195
|
-
),
|
|
196
|
-
issue: () => (
|
|
197
|
-
<h1>
|
|
198
|
-
An error occurred
|
|
199
|
-
</h1>
|
|
200
|
-
),
|
|
201
|
-
pages: [home]
|
|
176
|
+
fallback: () => <h1>Not found</h1>,
|
|
177
|
+
issue: () => <h1>An error occurred</h1>,
|
|
178
|
+
pages: [home],
|
|
202
179
|
});
|
|
203
180
|
```
|
|
204
181
|
|
|
@@ -209,11 +186,9 @@ import { createPage } from "@aminnairi/react-router";
|
|
|
209
186
|
|
|
210
187
|
createPage({
|
|
211
188
|
path: "/users/:user",
|
|
212
|
-
element: function User({ parameters: { user }}) {
|
|
213
|
-
return
|
|
214
|
-
|
|
215
|
-
);
|
|
216
|
-
}
|
|
189
|
+
element: function User({ parameters: { user } }) {
|
|
190
|
+
return <h1>User#{user}</h1>;
|
|
191
|
+
},
|
|
217
192
|
});
|
|
218
193
|
```
|
|
219
194
|
|
|
@@ -224,11 +199,13 @@ import { createPage } from "@aminnairi/react-router";
|
|
|
224
199
|
|
|
225
200
|
createPage({
|
|
226
201
|
path: "/users/:user/articles/:article",
|
|
227
|
-
element: function UserArticle({ parameters: { user, article }}) {
|
|
202
|
+
element: function UserArticle({ parameters: { user, article } }) {
|
|
228
203
|
return (
|
|
229
|
-
<h1>
|
|
204
|
+
<h1>
|
|
205
|
+
Article#{article} of user#{user}
|
|
206
|
+
</h1>
|
|
230
207
|
);
|
|
231
|
-
}
|
|
208
|
+
},
|
|
232
209
|
});
|
|
233
210
|
```
|
|
234
211
|
|
|
@@ -243,10 +220,8 @@ import { createPage, useNavigateToPage } from "@aminnairi/react-router";
|
|
|
243
220
|
const login = createPage({
|
|
244
221
|
path: "/login",
|
|
245
222
|
element: function Login() {
|
|
246
|
-
return
|
|
247
|
-
|
|
248
|
-
);
|
|
249
|
-
}
|
|
223
|
+
return <h1>Login</h1>;
|
|
224
|
+
},
|
|
250
225
|
});
|
|
251
226
|
|
|
252
227
|
const about = createPage({
|
|
@@ -256,15 +231,11 @@ const about = createPage({
|
|
|
256
231
|
|
|
257
232
|
return (
|
|
258
233
|
<Fragment>
|
|
259
|
-
<h1>
|
|
260
|
-
|
|
261
|
-
</h1>
|
|
262
|
-
<button onClick={navigateToLoginPage}>
|
|
263
|
-
Login
|
|
264
|
-
</button>
|
|
234
|
+
<h1>About Us</h1>
|
|
235
|
+
<button onClick={() => navigateToLoginPage({})}>Login</button>
|
|
265
236
|
</Fragment>
|
|
266
237
|
);
|
|
267
|
-
}
|
|
238
|
+
},
|
|
268
239
|
});
|
|
269
240
|
|
|
270
241
|
createPage({
|
|
@@ -274,15 +245,11 @@ createPage({
|
|
|
274
245
|
|
|
275
246
|
return (
|
|
276
247
|
<Fragment>
|
|
277
|
-
<h1>
|
|
278
|
-
|
|
279
|
-
</h1>
|
|
280
|
-
<button onClick={navigateToAboutPage}>
|
|
281
|
-
About Us
|
|
282
|
-
</button>
|
|
248
|
+
<h1>Home</h1>
|
|
249
|
+
<button onClick={() => navigateToAboutPage({})}>About Us</button>
|
|
283
250
|
</Fragment>
|
|
284
251
|
);
|
|
285
|
-
}
|
|
252
|
+
},
|
|
286
253
|
});
|
|
287
254
|
```
|
|
288
255
|
|
|
@@ -294,11 +261,9 @@ import { createPage, useNavigateToPage } from "@aminnairi/react-router";
|
|
|
294
261
|
|
|
295
262
|
const user = createPage({
|
|
296
263
|
path: "/users/:user",
|
|
297
|
-
element: function User({ parameters: { user }}) {
|
|
298
|
-
return
|
|
299
|
-
|
|
300
|
-
);
|
|
301
|
-
}
|
|
264
|
+
element: function User({ parameters: { user } }) {
|
|
265
|
+
return <h1>User#{user}</h1>;
|
|
266
|
+
},
|
|
302
267
|
});
|
|
303
268
|
|
|
304
269
|
createPage({
|
|
@@ -308,15 +273,13 @@ createPage({
|
|
|
308
273
|
|
|
309
274
|
return (
|
|
310
275
|
<Fragment>
|
|
311
|
-
<h1>
|
|
312
|
-
Home
|
|
313
|
-
</h1>
|
|
276
|
+
<h1>Home</h1>
|
|
314
277
|
<button onClick={() => navigateToUserPage({ user: "123" })}>
|
|
315
278
|
User#123
|
|
316
279
|
</button>
|
|
317
280
|
</Fragment>
|
|
318
281
|
);
|
|
319
|
-
}
|
|
282
|
+
},
|
|
320
283
|
});
|
|
321
284
|
```
|
|
322
285
|
|
|
@@ -332,22 +295,14 @@ import { createRouter, createPage } from "@aminnairi/react-router";
|
|
|
332
295
|
const home = createPage({
|
|
333
296
|
path: "/",
|
|
334
297
|
element: function Home() {
|
|
335
|
-
return
|
|
336
|
-
|
|
337
|
-
);
|
|
338
|
-
}
|
|
298
|
+
return <h1>Home</h1>;
|
|
299
|
+
},
|
|
339
300
|
});
|
|
340
301
|
|
|
341
302
|
const router = createRouter({
|
|
342
|
-
fallback: () =>
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
issue: () => (
|
|
346
|
-
<h1>An error occurred</h1>
|
|
347
|
-
),
|
|
348
|
-
pages: [
|
|
349
|
-
home
|
|
350
|
-
]
|
|
303
|
+
fallback: () => <h1>Not found</h1>,
|
|
304
|
+
issue: () => <h1>An error occurred</h1>,
|
|
305
|
+
pages: [home],
|
|
351
306
|
});
|
|
352
307
|
|
|
353
308
|
const rootElement = document.getElementById("root");
|
|
@@ -367,51 +322,47 @@ const App = () => {
|
|
|
367
322
|
<main>
|
|
368
323
|
<router.View />
|
|
369
324
|
</main>
|
|
370
|
-
<footer>
|
|
371
|
-
Credit © Yourself 2025
|
|
372
|
-
</footer>
|
|
325
|
+
<footer>Credit © Yourself 2025</footer>
|
|
373
326
|
</Fragment>
|
|
374
327
|
);
|
|
375
|
-
}
|
|
328
|
+
};
|
|
376
329
|
|
|
377
330
|
root.render(
|
|
378
331
|
<StrictMode>
|
|
379
332
|
<router.Provider>
|
|
380
333
|
<App />
|
|
381
334
|
</router.Provider>
|
|
382
|
-
</StrictMode
|
|
335
|
+
</StrictMode>,
|
|
383
336
|
);
|
|
384
337
|
```
|
|
385
338
|
|
|
386
339
|
You can also activate the View Transition Web API if you want before each page renders. This is nice because by default, the browser already has some styling that allows for a smooth and simple transition between pages.
|
|
387
340
|
|
|
388
|
-
All you have to do is to
|
|
341
|
+
All you have to do is to provide a `transition` function in the arguments of the `createRouter` function. This function receives the navigation direction (`"pushstate"` or `"popstate"`) and a `next` callback to render the next page.
|
|
342
|
+
|
|
343
|
+
This library also exports a `slideFadeTransition` that you can use out-of-the-box.
|
|
389
344
|
|
|
390
345
|
```tsx
|
|
391
346
|
import { Fragment, StrictMode } from "react";
|
|
392
347
|
import { createRoot } from "react-dom/client";
|
|
393
|
-
import {
|
|
348
|
+
import {
|
|
349
|
+
createRouter,
|
|
350
|
+
createPage,
|
|
351
|
+
slideFadeTransition,
|
|
352
|
+
} from "@aminnairi/react-router";
|
|
394
353
|
|
|
395
354
|
const home = createPage({
|
|
396
355
|
path: "/",
|
|
397
356
|
element: function Page() {
|
|
398
|
-
return
|
|
399
|
-
|
|
400
|
-
);
|
|
401
|
-
}
|
|
357
|
+
return <h1>Home</h1>;
|
|
358
|
+
},
|
|
402
359
|
});
|
|
403
360
|
|
|
404
361
|
const router = createRouter({
|
|
405
|
-
transition:
|
|
406
|
-
fallback: () =>
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
issue: () => (
|
|
410
|
-
<h1>An error occurred</h1>
|
|
411
|
-
),
|
|
412
|
-
pages: [
|
|
413
|
-
home
|
|
414
|
-
]
|
|
362
|
+
transition: slideFadeTransition,
|
|
363
|
+
fallback: () => <h1>Not found</h1>,
|
|
364
|
+
issue: () => <h1>An error occurred</h1>,
|
|
365
|
+
pages: [home],
|
|
415
366
|
});
|
|
416
367
|
|
|
417
368
|
const rootElement = document.getElementById("root");
|
|
@@ -431,19 +382,17 @@ const App = () => {
|
|
|
431
382
|
<main>
|
|
432
383
|
<router.View />
|
|
433
384
|
</main>
|
|
434
|
-
<footer>
|
|
435
|
-
Credit © Yourself 2025
|
|
436
|
-
</footer>
|
|
385
|
+
<footer>Credit © Yourself 2025</footer>
|
|
437
386
|
</Fragment>
|
|
438
387
|
);
|
|
439
|
-
}
|
|
388
|
+
};
|
|
440
389
|
|
|
441
390
|
root.render(
|
|
442
391
|
<StrictMode>
|
|
443
392
|
<router.Provider>
|
|
444
393
|
<App />
|
|
445
394
|
</router.Provider>
|
|
446
|
-
</StrictMode
|
|
395
|
+
</StrictMode>,
|
|
447
396
|
);
|
|
448
397
|
```
|
|
449
398
|
|
|
@@ -457,29 +406,20 @@ import { createRouter, createPage } from "@aminnairi/react-router";
|
|
|
457
406
|
const home = createPage({
|
|
458
407
|
path: "/",
|
|
459
408
|
element: function Home() {
|
|
460
|
-
return
|
|
461
|
-
|
|
462
|
-
);
|
|
463
|
-
}
|
|
409
|
+
return <h1>Home</h1>;
|
|
410
|
+
},
|
|
464
411
|
});
|
|
465
412
|
|
|
466
413
|
const router = createRouter({
|
|
467
|
-
|
|
468
|
-
fallback: () => (
|
|
469
|
-
<h1>Not found</h1>
|
|
470
|
-
),
|
|
414
|
+
fallback: () => <h1>Not found</h1>,
|
|
471
415
|
issue: ({ error, reset }) => (
|
|
472
|
-
|
|
473
|
-
<
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
</Fragment>
|
|
478
|
-
);
|
|
416
|
+
<Fragment>
|
|
417
|
+
<h1>Error</h1>
|
|
418
|
+
<p>{error.message}</p>
|
|
419
|
+
<button onClick={reset}>Reset</button>
|
|
420
|
+
</Fragment>
|
|
479
421
|
),
|
|
480
|
-
pages: [
|
|
481
|
-
home
|
|
482
|
-
]
|
|
422
|
+
pages: [home],
|
|
483
423
|
});
|
|
484
424
|
|
|
485
425
|
const rootElement = document.getElementById("root");
|
|
@@ -499,19 +439,17 @@ const App = () => {
|
|
|
499
439
|
<main>
|
|
500
440
|
<router.View />
|
|
501
441
|
</main>
|
|
502
|
-
<footer>
|
|
503
|
-
Credit © Yourself 2025
|
|
504
|
-
</footer>
|
|
442
|
+
<footer>Credit © Yourself 2025</footer>
|
|
505
443
|
</Fragment>
|
|
506
444
|
);
|
|
507
|
-
}
|
|
445
|
+
};
|
|
508
446
|
|
|
509
447
|
root.render(
|
|
510
448
|
<StrictMode>
|
|
511
449
|
<router.Provider>
|
|
512
450
|
<App />
|
|
513
451
|
</router.Provider>
|
|
514
|
-
</StrictMode
|
|
452
|
+
</StrictMode>,
|
|
515
453
|
);
|
|
516
454
|
```
|
|
517
455
|
|
|
@@ -525,35 +463,26 @@ import { createRouter, createPage, createIssue } from "@aminnairi/react-router";
|
|
|
525
463
|
const home = createPage({
|
|
526
464
|
path: "/",
|
|
527
465
|
element: function Home() {
|
|
528
|
-
return
|
|
529
|
-
|
|
530
|
-
);
|
|
531
|
-
}
|
|
466
|
+
return <h1>Home</h1>;
|
|
467
|
+
},
|
|
532
468
|
});
|
|
533
469
|
|
|
534
470
|
const Fallback = () => {
|
|
535
|
-
return
|
|
536
|
-
|
|
537
|
-
);
|
|
538
|
-
}
|
|
471
|
+
return <h1>Not found</h1>;
|
|
472
|
+
};
|
|
539
473
|
|
|
540
474
|
const Issue = createIssue(({ error, reset }) => (
|
|
541
|
-
|
|
542
|
-
<
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
</Fragment>
|
|
547
|
-
);
|
|
475
|
+
<Fragment>
|
|
476
|
+
<h1>Error</h1>
|
|
477
|
+
<p>{error.message}</p>
|
|
478
|
+
<button onClick={reset}>Reset</button>
|
|
479
|
+
</Fragment>
|
|
548
480
|
));
|
|
549
481
|
|
|
550
482
|
const router = createRouter({
|
|
551
|
-
transition: true,
|
|
552
483
|
fallback: Fallback,
|
|
553
484
|
issue: Issue,
|
|
554
|
-
pages: [
|
|
555
|
-
home
|
|
556
|
-
]
|
|
485
|
+
pages: [home],
|
|
557
486
|
});
|
|
558
487
|
|
|
559
488
|
const rootElement = document.getElementById("root");
|
|
@@ -573,17 +502,17 @@ const App = () => {
|
|
|
573
502
|
<main>
|
|
574
503
|
<router.View />
|
|
575
504
|
</main>
|
|
576
|
-
<footer>
|
|
577
|
-
Credit © Yourself 2025
|
|
578
|
-
</footer>
|
|
505
|
+
<footer>Credit © Yourself 2025</footer>
|
|
579
506
|
</Fragment>
|
|
580
507
|
);
|
|
581
|
-
}
|
|
508
|
+
};
|
|
582
509
|
|
|
583
510
|
root.render(
|
|
584
511
|
<StrictMode>
|
|
585
|
-
<
|
|
586
|
-
|
|
512
|
+
<router.Provider>
|
|
513
|
+
<App />
|
|
514
|
+
</router.Provider>
|
|
515
|
+
</StrictMode>,
|
|
587
516
|
);
|
|
588
517
|
```
|
|
589
518
|
|
|
@@ -594,15 +523,18 @@ You don't have to manually append this prefix when creating pages, its automatic
|
|
|
594
523
|
```tsx
|
|
595
524
|
import { Fragment, StrictMode } from "react";
|
|
596
525
|
import { createRoot } from "react-dom/client";
|
|
597
|
-
import {
|
|
526
|
+
import {
|
|
527
|
+
createRouter,
|
|
528
|
+
createPage,
|
|
529
|
+
createIssue,
|
|
530
|
+
useNavigateToPage,
|
|
531
|
+
} from "@aminnairi/react-router";
|
|
598
532
|
|
|
599
533
|
const home = createPage({
|
|
600
534
|
path: "/",
|
|
601
535
|
element: function Home() {
|
|
602
|
-
return
|
|
603
|
-
|
|
604
|
-
);
|
|
605
|
-
}
|
|
536
|
+
return <h1>Home</h1>;
|
|
537
|
+
},
|
|
606
538
|
});
|
|
607
539
|
|
|
608
540
|
const Fallback = () => {
|
|
@@ -611,31 +543,24 @@ const Fallback = () => {
|
|
|
611
543
|
return (
|
|
612
544
|
<Fragment>
|
|
613
545
|
<h1>Not found</h1>
|
|
614
|
-
<button onClick={navigateToHomePage}>
|
|
615
|
-
Go Back Home
|
|
616
|
-
</button>
|
|
546
|
+
<button onClick={() => navigateToHomePage({})}>Go Back Home</button>
|
|
617
547
|
</Fragment>
|
|
618
548
|
);
|
|
619
|
-
}
|
|
549
|
+
};
|
|
620
550
|
|
|
621
551
|
const Issue = createIssue(({ error, reset }) => (
|
|
622
|
-
|
|
623
|
-
<
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
</Fragment>
|
|
628
|
-
);
|
|
552
|
+
<Fragment>
|
|
553
|
+
<h1>Error</h1>
|
|
554
|
+
<p>{error.message}</p>
|
|
555
|
+
<button onClick={reset}>Reset</button>
|
|
556
|
+
</Fragment>
|
|
629
557
|
));
|
|
630
558
|
|
|
631
559
|
const router = createRouter({
|
|
632
560
|
prefix: "/portfolio",
|
|
633
|
-
transition: true,
|
|
634
561
|
fallback: Fallback,
|
|
635
562
|
issue: Issue,
|
|
636
|
-
pages: [
|
|
637
|
-
home
|
|
638
|
-
]
|
|
563
|
+
pages: [home],
|
|
639
564
|
});
|
|
640
565
|
|
|
641
566
|
const rootElement = document.getElementById("root");
|
|
@@ -655,17 +580,17 @@ const App = () => {
|
|
|
655
580
|
<main>
|
|
656
581
|
<router.View />
|
|
657
582
|
</main>
|
|
658
|
-
<footer>
|
|
659
|
-
Credit © Yourself 2025
|
|
660
|
-
</footer>
|
|
583
|
+
<footer>Credit © Yourself 2025</footer>
|
|
661
584
|
</Fragment>
|
|
662
585
|
);
|
|
663
|
-
}
|
|
586
|
+
};
|
|
664
587
|
|
|
665
588
|
root.render(
|
|
666
589
|
<StrictMode>
|
|
667
|
-
<
|
|
668
|
-
|
|
590
|
+
<router.Provider>
|
|
591
|
+
<App />
|
|
592
|
+
</router.Provider>
|
|
593
|
+
</StrictMode>,
|
|
669
594
|
);
|
|
670
595
|
```
|
|
671
596
|
|
|
@@ -679,13 +604,11 @@ It accepts a page that has been created using `createPage`.
|
|
|
679
604
|
import { Fragment } from "react";
|
|
680
605
|
import { createPage, useNavigateToPage } from "@aminnairi/react-router";
|
|
681
606
|
|
|
682
|
-
const home =
|
|
607
|
+
const home = createPage({
|
|
683
608
|
path: "/",
|
|
684
609
|
element: function Home() {
|
|
685
|
-
return
|
|
686
|
-
|
|
687
|
-
);
|
|
688
|
-
}
|
|
610
|
+
return <h1>Home</h1>;
|
|
611
|
+
},
|
|
689
612
|
});
|
|
690
613
|
|
|
691
614
|
createPage({
|
|
@@ -696,10 +619,10 @@ createPage({
|
|
|
696
619
|
return (
|
|
697
620
|
<Fragment>
|
|
698
621
|
<h1>About</h1>
|
|
699
|
-
<button onClick={navigateToHomePage}>Home</button>
|
|
622
|
+
<button onClick={() => navigateToHomePage({})}>Home</button>
|
|
700
623
|
</Fragment>
|
|
701
624
|
);
|
|
702
|
-
}
|
|
625
|
+
},
|
|
703
626
|
});
|
|
704
627
|
```
|
|
705
628
|
|
|
@@ -711,13 +634,11 @@ The parameters should always be provided as string, as they are the only data ty
|
|
|
711
634
|
import { Fragment } from "react";
|
|
712
635
|
import { createPage, useNavigateToPage } from "@aminnairi/react-router";
|
|
713
636
|
|
|
714
|
-
const user =
|
|
637
|
+
const user = createPage({
|
|
715
638
|
path: "/users/:user",
|
|
716
|
-
element: function User({ parameters: { user }}) {
|
|
717
|
-
return
|
|
718
|
-
|
|
719
|
-
);
|
|
720
|
-
}
|
|
639
|
+
element: function User({ parameters: { user } }) {
|
|
640
|
+
return <h1>User#{user}</h1>;
|
|
641
|
+
},
|
|
721
642
|
});
|
|
722
643
|
|
|
723
644
|
createPage({
|
|
@@ -728,10 +649,12 @@ createPage({
|
|
|
728
649
|
return (
|
|
729
650
|
<Fragment>
|
|
730
651
|
<h1>About</h1>
|
|
731
|
-
<button onClick={() => navigateToUserPage({ user: "123" })}>
|
|
652
|
+
<button onClick={() => navigateToUserPage({ user: "123" })}>
|
|
653
|
+
Home
|
|
654
|
+
</button>
|
|
732
655
|
</Fragment>
|
|
733
656
|
);
|
|
734
|
-
}
|
|
657
|
+
},
|
|
735
658
|
});
|
|
736
659
|
```
|
|
737
660
|
|
|
@@ -745,13 +668,11 @@ The created component is simply a `<a href="...">{children}</a>` under the hood
|
|
|
745
668
|
import { Fragment } from "react";
|
|
746
669
|
import { createPage, useLink } from "@aminnairi/react-router";
|
|
747
670
|
|
|
748
|
-
const user =
|
|
671
|
+
const user = createPage({
|
|
749
672
|
path: "/users/:user",
|
|
750
|
-
element: function User({ parameters: { user }}) {
|
|
751
|
-
return
|
|
752
|
-
|
|
753
|
-
);
|
|
754
|
-
}
|
|
673
|
+
element: function User({ parameters: { user } }) {
|
|
674
|
+
return <h1>User#{user}</h1>;
|
|
675
|
+
},
|
|
755
676
|
});
|
|
756
677
|
|
|
757
678
|
createPage({
|
|
@@ -765,7 +686,7 @@ createPage({
|
|
|
765
686
|
<Link parameters={{ user: "123" }}>User#123</Link>
|
|
766
687
|
</Fragment>
|
|
767
688
|
);
|
|
768
|
-
}
|
|
689
|
+
},
|
|
769
690
|
});
|
|
770
691
|
```
|
|
771
692
|
|
|
@@ -782,7 +703,7 @@ import { createPage, useSearch } from "@aminnairi/react-router";
|
|
|
782
703
|
createPage({
|
|
783
704
|
path: "/users",
|
|
784
705
|
element: function Home() {
|
|
785
|
-
const
|
|
706
|
+
const search = useSearch();
|
|
786
707
|
const sortedByDate = useMemo(() => search.get("sort-by") === "date", [search]);
|
|
787
708
|
|
|
788
709
|
return (
|
|
@@ -807,10 +728,8 @@ createPage({
|
|
|
807
728
|
element: function OauthCallback() {
|
|
808
729
|
const token = useHash();
|
|
809
730
|
|
|
810
|
-
return
|
|
811
|
-
|
|
812
|
-
);
|
|
813
|
-
}
|
|
731
|
+
return <h1>You token is {token}</h1>;
|
|
732
|
+
},
|
|
814
733
|
});
|
|
815
734
|
```
|
|
816
735
|
|
|
@@ -825,13 +744,13 @@ This function is mainly used in the internals of the `createRouter` and in most
|
|
|
825
744
|
```typescript
|
|
826
745
|
import { doesRouteMatchPath } from "@aminnairi/react-router";
|
|
827
746
|
|
|
828
|
-
|
|
747
|
+
doesRouteMatchPath("/", "/"); // true
|
|
829
748
|
|
|
830
|
-
|
|
749
|
+
doesRouteMatchPath("/", "/about"); // false
|
|
831
750
|
|
|
832
|
-
|
|
751
|
+
doesRouteMatchPath("/users/:user", "/users/123"); // true
|
|
833
752
|
|
|
834
|
-
|
|
753
|
+
doesRouteMatchPath("/users/:user", "/users/123/articles"); // false
|
|
835
754
|
```
|
|
836
755
|
|
|
837
756
|
You can also optionally provide a prefix.
|
|
@@ -839,13 +758,13 @@ You can also optionally provide a prefix.
|
|
|
839
758
|
```typescript
|
|
840
759
|
import { doesRouteMatchPath } from "@aminnairi/react-router";
|
|
841
760
|
|
|
842
|
-
|
|
761
|
+
doesRouteMatchPath("/", "/github", "/github"); // true
|
|
843
762
|
|
|
844
|
-
|
|
763
|
+
doesRouteMatchPath("/", "/github/about", "/github"); // false
|
|
845
764
|
|
|
846
|
-
|
|
765
|
+
doesRouteMatchPath("/users/:user", "/github/users/123", "/github"); // true
|
|
847
766
|
|
|
848
|
-
|
|
767
|
+
doesRouteMatchPath("/users/:user", "/github/users/123/articles", "/github"); // false
|
|
849
768
|
```
|
|
850
769
|
|
|
851
770
|
### getParameters
|
|
@@ -857,13 +776,13 @@ This function is mainly used in the internals of the `createRouter` and in most
|
|
|
857
776
|
```typescript
|
|
858
777
|
import { getParameters } from "@aminnairi/react-router";
|
|
859
778
|
|
|
860
|
-
getParameters("/", "/"); //
|
|
779
|
+
getParameters("/", "/"); // {}
|
|
861
780
|
|
|
862
|
-
getParameters("/", "/about"); //
|
|
781
|
+
getParameters("/", "/about"); // {}
|
|
863
782
|
|
|
864
783
|
getParameters("/users/:user", "/users/123"); // { user: "123" }
|
|
865
784
|
|
|
866
|
-
getParameters("/users/:user", "/users/123/articles"); // {
|
|
785
|
+
getParameters("/users/:user", "/users/123/articles"); // {}
|
|
867
786
|
```
|
|
868
787
|
|
|
869
788
|
You can also provide an optional prefix.
|
|
@@ -871,91 +790,13 @@ You can also provide an optional prefix.
|
|
|
871
790
|
```typescript
|
|
872
791
|
import { getParameters } from "@aminnairi/react-router";
|
|
873
792
|
|
|
874
|
-
getParameters("/", "/github", "/github"); //
|
|
793
|
+
getParameters("/", "/github", "/github"); // {}
|
|
875
794
|
|
|
876
|
-
getParameters("/", "/github/about", "/github"); //
|
|
795
|
+
getParameters("/", "/github/about", "/github"); // {}
|
|
877
796
|
|
|
878
797
|
getParameters("/users/:user", "/github/users/123", "/github"); // { user: "123" }
|
|
879
798
|
|
|
880
|
-
getParameters("/users/:user", "/github/users/123/articles", "/github"); // {
|
|
881
|
-
```
|
|
882
|
-
|
|
883
|
-
### findPage
|
|
884
|
-
|
|
885
|
-
Return a page that matches the `window.location.pathname` property containing the current URI of the page from an array of pages.
|
|
886
|
-
|
|
887
|
-
If it does not match any pages, it returns `undefined` instead.
|
|
888
|
-
|
|
889
|
-
This function is mainly used in the internals of the `createRouter` and in most case should not be necessary.
|
|
890
|
-
|
|
891
|
-
```tsx
|
|
892
|
-
import { findPage, createPage } from "@aminnairi/react-router";
|
|
893
|
-
|
|
894
|
-
const home = createPage({
|
|
895
|
-
path: "/",
|
|
896
|
-
element: () => <h1>Home</h1>
|
|
897
|
-
});
|
|
898
|
-
|
|
899
|
-
const about = createPage({
|
|
900
|
-
path: "/about",
|
|
901
|
-
element: () => <h1>About</h1>
|
|
902
|
-
});
|
|
903
|
-
|
|
904
|
-
const login = createPage({
|
|
905
|
-
path: "/login",
|
|
906
|
-
element: () => <h1>Login</h1>
|
|
907
|
-
});
|
|
908
|
-
|
|
909
|
-
const pages = [
|
|
910
|
-
home.page,
|
|
911
|
-
about.page,
|
|
912
|
-
login.page
|
|
913
|
-
];
|
|
914
|
-
|
|
915
|
-
const foundPage = findPage(pages, "/login");
|
|
916
|
-
|
|
917
|
-
if (foundPage) {
|
|
918
|
-
console.log("Found a page matching the current location");
|
|
919
|
-
console.log(foundPage.path);
|
|
920
|
-
} else {
|
|
921
|
-
console.log("No page matching the current location.");
|
|
922
|
-
}
|
|
923
|
-
```
|
|
924
|
-
|
|
925
|
-
You can also provide an optional prefix.
|
|
926
|
-
|
|
927
|
-
```tsx
|
|
928
|
-
import { findPage, createPage } from "@aminnairi/react-router";
|
|
929
|
-
|
|
930
|
-
const home = createPage({
|
|
931
|
-
path: "/",
|
|
932
|
-
element: () => <h1>Home</h1>
|
|
933
|
-
});
|
|
934
|
-
|
|
935
|
-
const about = createPage({
|
|
936
|
-
path: "/about",
|
|
937
|
-
element: () => <h1>About</h1>
|
|
938
|
-
});
|
|
939
|
-
|
|
940
|
-
const login = createPage({
|
|
941
|
-
path: "/login",
|
|
942
|
-
element: () => <h1>Login</h1>
|
|
943
|
-
});
|
|
944
|
-
|
|
945
|
-
const pages = [
|
|
946
|
-
home.page,
|
|
947
|
-
about.page,
|
|
948
|
-
login.page
|
|
949
|
-
];
|
|
950
|
-
|
|
951
|
-
const foundPage = findPage(pages, "/github/login", "/github");
|
|
952
|
-
|
|
953
|
-
if (foundPage) {
|
|
954
|
-
console.log("Found a page matching the current location");
|
|
955
|
-
console.log(foundPage.path);
|
|
956
|
-
} else {
|
|
957
|
-
console.log("No page matching the current location.");
|
|
958
|
-
}
|
|
799
|
+
getParameters("/users/:user", "/github/users/123/articles", "/github"); // {}
|
|
959
800
|
```
|
|
960
801
|
|
|
961
802
|
### sanitizePath
|
|
@@ -994,9 +835,7 @@ This means that you can use this library with other popular solutions for handli
|
|
|
994
835
|
|
|
995
836
|
### Transition
|
|
996
837
|
|
|
997
|
-
Support for the View Transition API is built-in and allows for painless and smooth view transition out-of-the-box
|
|
998
|
-
|
|
999
|
-
This can also easily be disabled if needed.
|
|
838
|
+
Support for the View Transition API is built-in and allows for painless and smooth view transition out-of-the-box. You can create your own transition animation, and the library also exports a `slideFadeTransition` ready to be used.
|
|
1000
839
|
|
|
1001
840
|
### Error handling
|
|
1002
841
|
|
|
@@ -1010,12 +849,43 @@ See [`LICENSE`](./LICENSE).
|
|
|
1010
849
|
|
|
1011
850
|
### Versions
|
|
1012
851
|
|
|
852
|
+
- [`2.0.1`](#201)
|
|
853
|
+
- [`2.0.0`](#200)
|
|
1013
854
|
- [`1.1.0`](#110)
|
|
1014
855
|
- [`1.0.1`](#101)
|
|
1015
856
|
- [`1.0.0`](#100)
|
|
1016
857
|
- [`0.1.1`](#011)
|
|
1017
858
|
- [`0.1.0`](#010)
|
|
1018
859
|
|
|
860
|
+
### 2.0.1
|
|
861
|
+
|
|
862
|
+
#### Major changes
|
|
863
|
+
|
|
864
|
+
None.
|
|
865
|
+
|
|
866
|
+
#### Minor changes
|
|
867
|
+
|
|
868
|
+
- Now running a linter with eslint and TypeScript and a stricter configuration to prevent type errors
|
|
869
|
+
|
|
870
|
+
#### Bug & security fixes
|
|
871
|
+
|
|
872
|
+
- Fixed an error while the error boundary was not using an override when using a stricter typescript configuration
|
|
873
|
+
|
|
874
|
+
### 2.0.0
|
|
875
|
+
|
|
876
|
+
#### Major changes
|
|
877
|
+
|
|
878
|
+
- The `transition` property in `createRouter` is now a function instead of a boolean, which allows for more control over the animation. This is a breaking change.
|
|
879
|
+
- A `slideFadeTransition` is now exported and can be used directly.
|
|
880
|
+
|
|
881
|
+
#### Minor changes
|
|
882
|
+
|
|
883
|
+
None.
|
|
884
|
+
|
|
885
|
+
#### Bug & security fixes
|
|
886
|
+
|
|
887
|
+
None.
|
|
888
|
+
|
|
1019
889
|
### 1.1.0
|
|
1020
890
|
|
|
1021
891
|
#### Major changes
|
|
@@ -1088,4 +958,4 @@ None.
|
|
|
1088
958
|
|
|
1089
959
|
#### Bug & security fixes
|
|
1090
960
|
|
|
1091
|
-
None.
|
|
961
|
+
None.
|
package/index.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
1
2
|
import { useEffect, useState, FunctionComponent, useMemo, Component, PropsWithChildren, createContext, SetStateAction, Dispatch, ReactNode, useContext, useCallback, memo, MouseEvent } from "react";
|
|
2
3
|
|
|
3
4
|
export type AbsolutePath<Path extends string> =
|
|
@@ -25,8 +26,10 @@ export interface Page<Path extends string> {
|
|
|
25
26
|
element: FunctionComponent<PageComponentProps<Path>>
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
export type Transition = (direction: NavigationDirection, next: () => void) => void;
|
|
30
|
+
|
|
28
31
|
export interface CreateRouterOptions<Path extends string> {
|
|
29
|
-
transition?:
|
|
32
|
+
transition?: Transition,
|
|
30
33
|
prefix?: string,
|
|
31
34
|
pages: Array<Page<Path>>
|
|
32
35
|
fallback: FunctionComponent
|
|
@@ -99,7 +102,7 @@ export interface IssueProps {
|
|
|
99
102
|
|
|
100
103
|
export interface ErrorBoundaryProps {
|
|
101
104
|
fallback: FunctionComponent<IssueProps>,
|
|
102
|
-
transition
|
|
105
|
+
transition?: Transition
|
|
103
106
|
}
|
|
104
107
|
|
|
105
108
|
export interface ErrorBoundaryState {
|
|
@@ -113,13 +116,13 @@ export class ErrorBoundary extends Component<PropsWithChildren<ErrorBoundaryProp
|
|
|
113
116
|
this.state = { error: null };
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
static getDerivedStateFromError(error: unknown) {
|
|
119
|
+
public static getDerivedStateFromError(error: unknown) {
|
|
117
120
|
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
118
121
|
|
|
119
122
|
return { error: normalizedError };
|
|
120
123
|
}
|
|
121
124
|
|
|
122
|
-
render() {
|
|
125
|
+
public override render() {
|
|
123
126
|
const viewTransitionSupported = typeof document.startViewTransition === "function";
|
|
124
127
|
|
|
125
128
|
if (this.state.error) {
|
|
@@ -177,6 +180,11 @@ const Context = createContext<ContextInterface>({
|
|
|
177
180
|
setHash: () => { }
|
|
178
181
|
});
|
|
179
182
|
|
|
183
|
+
enum NavigationDirection {
|
|
184
|
+
Forward = "pushstate",
|
|
185
|
+
Backward = "popstate"
|
|
186
|
+
}
|
|
187
|
+
|
|
180
188
|
export const useNavigateToPage = <Path extends string>(page: Page<Path>) => {
|
|
181
189
|
const { prefix } = useContext(Context);
|
|
182
190
|
|
|
@@ -193,10 +201,16 @@ export const useNavigateToPage = <Path extends string>(page: Page<Path>) => {
|
|
|
193
201
|
window.history.pushState(null, pathWithParameters, pathWithParameters);
|
|
194
202
|
}
|
|
195
203
|
|
|
196
|
-
window.dispatchEvent(new CustomEvent(
|
|
197
|
-
}, [page]);
|
|
204
|
+
window.dispatchEvent(new CustomEvent(NavigationDirection.Forward));
|
|
205
|
+
}, [page, prefix]);
|
|
198
206
|
};
|
|
199
207
|
|
|
208
|
+
export const useNavigateBack = () => {
|
|
209
|
+
return useCallback(() => {
|
|
210
|
+
window.dispatchEvent(new CustomEvent(NavigationDirection.Backward));
|
|
211
|
+
}, []);
|
|
212
|
+
}
|
|
213
|
+
|
|
200
214
|
export const useIsActivePage = (page: Page<string>) => {
|
|
201
215
|
const { pathname, prefix } = useContext(Context);
|
|
202
216
|
|
|
@@ -223,12 +237,12 @@ export const useLink = <Path extends string>(page: Page<Path>) => {
|
|
|
223
237
|
return Object.entries(parameters).reduce((previousPath, [parameterName, parameterValue]) => {
|
|
224
238
|
return previousPath.replace(`:${parameterName}`, parameterValue);
|
|
225
239
|
}, sanitizePath(`${prefix ?? ""}/${page.path}`));
|
|
226
|
-
}, []);
|
|
240
|
+
}, [prefix, page, parameters]);
|
|
227
241
|
|
|
228
242
|
const navigate = useCallback((event: MouseEvent) => {
|
|
229
243
|
event.preventDefault();
|
|
230
244
|
navigateToPage(parameters);
|
|
231
|
-
}, []);
|
|
245
|
+
}, [navigateToPage, parameters]);
|
|
232
246
|
|
|
233
247
|
return (
|
|
234
248
|
<a
|
|
@@ -243,12 +257,45 @@ export const useLink = <Path extends string>(page: Page<Path>) => {
|
|
|
243
257
|
return Link;
|
|
244
258
|
};
|
|
245
259
|
|
|
246
|
-
export const
|
|
260
|
+
export const slideFadeTransition: Transition = async (direction: NavigationDirection, next) => {
|
|
261
|
+
const transition = document.startViewTransition(() => {
|
|
262
|
+
next();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
await transition.ready;
|
|
266
|
+
|
|
267
|
+
document.documentElement.animate(
|
|
268
|
+
[
|
|
269
|
+
{ transform: 'translateX(0)', opacity: 1 },
|
|
270
|
+
{ transform: `translateX(${direction === NavigationDirection.Forward ? '100%' : '-100%'})`, opacity: 0 }
|
|
271
|
+
],
|
|
272
|
+
{
|
|
273
|
+
duration: 250,
|
|
274
|
+
easing: "ease-in-out",
|
|
275
|
+
fill: "both",
|
|
276
|
+
pseudoElement: "::view-transition-old(root)",
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
document.documentElement.animate(
|
|
281
|
+
[
|
|
282
|
+
{ transform: `translateX(${direction === NavigationDirection.Forward ? '-100%' : '100%'})`, opacity: 0 },
|
|
283
|
+
{ transform: 'translateX(0)', opacity: 1 }
|
|
284
|
+
],
|
|
285
|
+
{
|
|
286
|
+
duration: 250,
|
|
287
|
+
easing: "ease-in-out",
|
|
288
|
+
fill: "both",
|
|
289
|
+
pseudoElement: "::view-transition-new(root)",
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export const createRouter = <Path extends string>({ pages, fallback, transition, issue, prefix }: CreateRouterOptions<Path>) => {
|
|
247
295
|
const Provider = ({ children }: ProviderProps) => {
|
|
248
296
|
const [pathname, setPathname] = useState(sanitizePath(window.location.pathname));
|
|
249
297
|
const [search, setSearch] = useState(new URLSearchParams(sanitizePath(window.location.search)));
|
|
250
298
|
const [hash, setHash] = useState(window.location.hash);
|
|
251
|
-
const shouldTransitionBetweenPages = useMemo(() => typeof document.startViewTransition === "function" && withViewTransition ? true : false, [withViewTransition]);
|
|
252
299
|
|
|
253
300
|
const value = useMemo(() => {
|
|
254
301
|
return {
|
|
@@ -263,9 +310,9 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
263
310
|
}, [prefix, pathname, search, hash]);
|
|
264
311
|
|
|
265
312
|
useEffect(() => {
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
|
|
313
|
+
const onNavigation = async (direction: NavigationDirection) => {
|
|
314
|
+
if (transition) {
|
|
315
|
+
transition(direction, () => {
|
|
269
316
|
setPathname(sanitizePath(window.location.pathname));
|
|
270
317
|
});
|
|
271
318
|
|
|
@@ -273,18 +320,28 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
273
320
|
}
|
|
274
321
|
|
|
275
322
|
setPathname(sanitizePath(window.location.pathname));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const onNavigationForward = () => {
|
|
326
|
+
onNavigation(NavigationDirection.Forward);
|
|
276
327
|
};
|
|
277
328
|
|
|
278
|
-
|
|
329
|
+
const onNavigationBackward = () => {
|
|
330
|
+
onNavigation(NavigationDirection.Backward);
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
window.addEventListener(NavigationDirection.Forward, onNavigationForward);
|
|
334
|
+
window.addEventListener(NavigationDirection.Backward, onNavigationBackward);
|
|
279
335
|
|
|
280
336
|
return () => {
|
|
281
|
-
window.removeEventListener(
|
|
337
|
+
window.removeEventListener(NavigationDirection.Forward, onNavigationForward);
|
|
338
|
+
window.removeEventListener(NavigationDirection.Backward, onNavigationBackward);
|
|
282
339
|
}
|
|
283
340
|
}, []);
|
|
284
341
|
|
|
285
342
|
return (
|
|
286
343
|
<Context.Provider value={value}>
|
|
287
|
-
<ErrorBoundary fallback={issue}
|
|
344
|
+
<ErrorBoundary fallback={issue}>
|
|
288
345
|
{children}
|
|
289
346
|
</ErrorBoundary>
|
|
290
347
|
</Context.Provider>
|
|
@@ -306,7 +363,9 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
306
363
|
|
|
307
364
|
if (page) {
|
|
308
365
|
return (
|
|
309
|
-
<
|
|
366
|
+
<div >
|
|
367
|
+
<page.element parameters={parameters} />
|
|
368
|
+
</div>
|
|
310
369
|
);
|
|
311
370
|
}
|
|
312
371
|
|
|
@@ -319,4 +378,4 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
319
378
|
View,
|
|
320
379
|
Provider,
|
|
321
380
|
};
|
|
322
|
-
}
|
|
381
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@aminnairi/react-router",
|
|
4
4
|
"description": "Type-safe router for the React library",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "2.0.1",
|
|
6
6
|
"homepage": "https://github.com/aminnairi/react-router#readme",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"bugs": {
|
|
@@ -26,5 +26,14 @@
|
|
|
26
26
|
],
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": ">=18.0.0"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
|
35
|
+
"@typescript-eslint/parser": "^7.2.0",
|
|
36
|
+
"eslint": "^8.57.0",
|
|
37
|
+
"eslint-plugin-react-hooks": "^4.6.0"
|
|
29
38
|
}
|
|
30
|
-
}
|
|
39
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react-jsx",
|
|
4
|
+
"target": "esnext",
|
|
5
|
+
"module": "esnext",
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"noFallthroughCasesInSwitch": true,
|
|
10
|
+
"noUncheckedIndexedAccess": true,
|
|
11
|
+
"noImplicitOverride": true,
|
|
12
|
+
"exactOptionalPropertyTypes": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"isolatedModules": true
|
|
15
|
+
}
|
|
16
|
+
}
|