@aminnairi/react-router 2.2.0 → 3.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 +213 -190
- package/index.tsx +416 -278
- package/package.json +4 -1
- package/.eslintrc.cjs +0 -13
- package/tsconfig.json +0 -16
package/README.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
Type-safe router for the React library
|
|
4
4
|
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- [Requirements](#requirements)
|
|
8
|
+
- [Usage](#usage)
|
|
9
|
+
- [Project initialization](#project-initialization)
|
|
10
|
+
- [Dependencies installation](#dependencies-installation)
|
|
11
|
+
- [Library installation](#library-installation)
|
|
12
|
+
- [Setup](#setup)
|
|
13
|
+
- [Startup](#startup)
|
|
14
|
+
- [API](#api)
|
|
15
|
+
- [createPage](#createpage)
|
|
16
|
+
- [useNavigateToPage](#usenavigatetopage)
|
|
17
|
+
- [createRouter](#createrouter)
|
|
18
|
+
- [useIsActivePage](#useisactivepage)
|
|
19
|
+
- [useLocale](#uselocale)
|
|
20
|
+
- [usePrefix](#useprefix)
|
|
21
|
+
- [usePath](#usepath)
|
|
22
|
+
- [Features](#features)
|
|
23
|
+
- [TypeScript](#typescript)
|
|
24
|
+
- [No codegen](#no-codegen)
|
|
25
|
+
- [Simplicity](#simplicity)
|
|
26
|
+
- [Transition](#transition)
|
|
27
|
+
- [Error handling](#error-handling)
|
|
28
|
+
- [License](#license)
|
|
29
|
+
- [Changelogs](#changelogs)
|
|
30
|
+
- [Versions](#versions)
|
|
31
|
+
- [3.0.0](#300)
|
|
32
|
+
- [2.1.0](#210)
|
|
33
|
+
- [2.0.1](#201)
|
|
34
|
+
- [2.0.0](#200)
|
|
35
|
+
- [1.1.0](#110)
|
|
36
|
+
- [1.0.1](#101)
|
|
37
|
+
- [1.0.0](#100)
|
|
38
|
+
- [0.1.1](#011)
|
|
39
|
+
- [0.1.0](#010)
|
|
40
|
+
|
|
5
41
|
## Requirements
|
|
6
42
|
|
|
7
43
|
- [Node](https://nodejs.org/)
|
|
@@ -58,7 +94,7 @@ import { home } from "./pages/home";
|
|
|
58
94
|
export const Fallback = () => {
|
|
59
95
|
const navigateToHomePage = useNavigateToPage(home);
|
|
60
96
|
|
|
61
|
-
return <button onClick={
|
|
97
|
+
return <button onClick={navigateToHomePage}>Go back home</button>;
|
|
62
98
|
};
|
|
63
99
|
```
|
|
64
100
|
|
|
@@ -77,7 +113,7 @@ export const Issue = () => {
|
|
|
77
113
|
return (
|
|
78
114
|
<Fragment>
|
|
79
115
|
<h1>An issue occurred</h1>
|
|
80
|
-
<button onClick={
|
|
116
|
+
<button onClick={navigateToHomePage}>Go back home</button>
|
|
81
117
|
</Fragment>
|
|
82
118
|
);
|
|
83
119
|
};
|
|
@@ -93,7 +129,7 @@ import { Fallback } from "./fallback";
|
|
|
93
129
|
import { Issue } from "./issue";
|
|
94
130
|
import { home } from "./pages/home";
|
|
95
131
|
|
|
96
|
-
export const
|
|
132
|
+
export const { RouterProvider, RouterView } = createRouter({
|
|
97
133
|
fallback: Fallback,
|
|
98
134
|
issue: Issue,
|
|
99
135
|
pages: [home],
|
|
@@ -105,10 +141,10 @@ touch src/App.tsx
|
|
|
105
141
|
```
|
|
106
142
|
|
|
107
143
|
```tsx
|
|
108
|
-
import {
|
|
144
|
+
import { RouterView } from "./router";
|
|
109
145
|
|
|
110
146
|
export default function App() {
|
|
111
|
-
return <
|
|
147
|
+
return <RouterView />;
|
|
112
148
|
}
|
|
113
149
|
```
|
|
114
150
|
|
|
@@ -119,7 +155,7 @@ touch src/main.tsx
|
|
|
119
155
|
```tsx
|
|
120
156
|
import { StrictMode } from "react";
|
|
121
157
|
import { createRoot } from "react-dom/client";
|
|
122
|
-
import {
|
|
158
|
+
import { RouterProvider } from "./router";
|
|
123
159
|
import App from "./App";
|
|
124
160
|
|
|
125
161
|
const rootElement = document.getElementById("root");
|
|
@@ -130,9 +166,9 @@ if (!rootElement) {
|
|
|
130
166
|
|
|
131
167
|
createRoot(rootElement).render(
|
|
132
168
|
<StrictMode>
|
|
133
|
-
<
|
|
169
|
+
<RouterProvider>
|
|
134
170
|
<App />
|
|
135
|
-
</
|
|
171
|
+
</RouterProvider>
|
|
136
172
|
</StrictMode>,
|
|
137
173
|
);
|
|
138
174
|
```
|
|
@@ -213,9 +249,11 @@ createPage({
|
|
|
213
249
|
|
|
214
250
|
You can navigate from one page from another.
|
|
215
251
|
|
|
252
|
+
Note: This hook is returned from `createRouter`, not imported directly from the library.
|
|
253
|
+
|
|
216
254
|
```tsx
|
|
217
255
|
import { Fragment } from "react";
|
|
218
|
-
import { createPage,
|
|
256
|
+
import { createPage, createRouter } from "@aminnairi/react-router";
|
|
219
257
|
|
|
220
258
|
const login = createPage({
|
|
221
259
|
path: "/login",
|
|
@@ -232,12 +270,18 @@ const about = createPage({
|
|
|
232
270
|
return (
|
|
233
271
|
<Fragment>
|
|
234
272
|
<h1>About Us</h1>
|
|
235
|
-
<button onClick={
|
|
273
|
+
<button onClick={navigateToLoginPage}>Login</button>
|
|
236
274
|
</Fragment>
|
|
237
275
|
);
|
|
238
276
|
},
|
|
239
277
|
});
|
|
240
278
|
|
|
279
|
+
const { useNavigateToPage } = createRouter({
|
|
280
|
+
fallback: () => <h1>Not found</h1>,
|
|
281
|
+
issue: () => <h1>An error occurred</h1>,
|
|
282
|
+
pages: [login, about],
|
|
283
|
+
});
|
|
284
|
+
|
|
241
285
|
createPage({
|
|
242
286
|
path: "/",
|
|
243
287
|
element: function Home() {
|
|
@@ -246,7 +290,7 @@ createPage({
|
|
|
246
290
|
return (
|
|
247
291
|
<Fragment>
|
|
248
292
|
<h1>Home</h1>
|
|
249
|
-
<button onClick={
|
|
293
|
+
<button onClick={navigateToAboutPage}>About Us</button>
|
|
250
294
|
</Fragment>
|
|
251
295
|
);
|
|
252
296
|
},
|
|
@@ -299,7 +343,7 @@ const home = createPage({
|
|
|
299
343
|
},
|
|
300
344
|
});
|
|
301
345
|
|
|
302
|
-
const
|
|
346
|
+
const { RouterProvider, RouterView } = createRouter({
|
|
303
347
|
fallback: () => <h1>Not found</h1>,
|
|
304
348
|
issue: () => <h1>An error occurred</h1>,
|
|
305
349
|
pages: [home],
|
|
@@ -320,7 +364,7 @@ const App = () => {
|
|
|
320
364
|
<h1>App</h1>
|
|
321
365
|
</header>
|
|
322
366
|
<main>
|
|
323
|
-
<
|
|
367
|
+
<RouterView />
|
|
324
368
|
</main>
|
|
325
369
|
<footer>Credit © Yourself 2025</footer>
|
|
326
370
|
</Fragment>
|
|
@@ -329,18 +373,18 @@ const App = () => {
|
|
|
329
373
|
|
|
330
374
|
root.render(
|
|
331
375
|
<StrictMode>
|
|
332
|
-
<
|
|
376
|
+
<RouterProvider>
|
|
333
377
|
<App />
|
|
334
|
-
</
|
|
378
|
+
</RouterProvider>
|
|
335
379
|
</StrictMode>,
|
|
336
380
|
);
|
|
337
381
|
```
|
|
338
382
|
|
|
339
383
|
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.
|
|
340
384
|
|
|
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 (`"
|
|
385
|
+
All you have to do is to provide a `transition` function in the arguments of the `createRouter` function. This function receives the navigation direction (`"forward"` or `"backward"`) and a `next` callback to render the next page.
|
|
342
386
|
|
|
343
|
-
This library also exports
|
|
387
|
+
This library also exports several transitions that you can use out-of-the-box: `slideHorizontalTransition`, `slideVerticalTransition`, `crossFadeTransition`, and `scaleFadeTransition`.
|
|
344
388
|
|
|
345
389
|
```tsx
|
|
346
390
|
import { Fragment, StrictMode } from "react";
|
|
@@ -348,7 +392,7 @@ import { createRoot } from "react-dom/client";
|
|
|
348
392
|
import {
|
|
349
393
|
createRouter,
|
|
350
394
|
createPage,
|
|
351
|
-
|
|
395
|
+
slideHorizontalTransition,
|
|
352
396
|
} from "@aminnairi/react-router";
|
|
353
397
|
|
|
354
398
|
const home = createPage({
|
|
@@ -358,8 +402,8 @@ const home = createPage({
|
|
|
358
402
|
},
|
|
359
403
|
});
|
|
360
404
|
|
|
361
|
-
const
|
|
362
|
-
transition:
|
|
405
|
+
const { RouterProvider, RouterView } = createRouter({
|
|
406
|
+
transition: slideHorizontalTransition,
|
|
363
407
|
fallback: () => <h1>Not found</h1>,
|
|
364
408
|
issue: () => <h1>An error occurred</h1>,
|
|
365
409
|
pages: [home],
|
|
@@ -380,7 +424,7 @@ const App = () => {
|
|
|
380
424
|
<h1>App</h1>
|
|
381
425
|
</header>
|
|
382
426
|
<main>
|
|
383
|
-
<
|
|
427
|
+
<RouterView />
|
|
384
428
|
</main>
|
|
385
429
|
<footer>Credit © Yourself 2025</footer>
|
|
386
430
|
</Fragment>
|
|
@@ -389,9 +433,9 @@ const App = () => {
|
|
|
389
433
|
|
|
390
434
|
root.render(
|
|
391
435
|
<StrictMode>
|
|
392
|
-
<
|
|
436
|
+
<RouterProvider>
|
|
393
437
|
<App />
|
|
394
|
-
</
|
|
438
|
+
</RouterProvider>
|
|
395
439
|
</StrictMode>,
|
|
396
440
|
);
|
|
397
441
|
```
|
|
@@ -410,13 +454,13 @@ const home = createPage({
|
|
|
410
454
|
},
|
|
411
455
|
});
|
|
412
456
|
|
|
413
|
-
const
|
|
457
|
+
const { RouterProvider, RouterView } = createRouter({
|
|
414
458
|
fallback: () => <h1>Not found</h1>,
|
|
415
|
-
issue: ({ error,
|
|
459
|
+
issue: ({ error, resetError }) => (
|
|
416
460
|
<Fragment>
|
|
417
461
|
<h1>Error</h1>
|
|
418
462
|
<p>{error.message}</p>
|
|
419
|
-
<button onClick={
|
|
463
|
+
<button onClick={resetError}>Reset</button>
|
|
420
464
|
</Fragment>
|
|
421
465
|
),
|
|
422
466
|
pages: [home],
|
|
@@ -437,7 +481,7 @@ const App = () => {
|
|
|
437
481
|
<h1>App</h1>
|
|
438
482
|
</header>
|
|
439
483
|
<main>
|
|
440
|
-
<
|
|
484
|
+
<RouterView />
|
|
441
485
|
</main>
|
|
442
486
|
<footer>Credit © Yourself 2025</footer>
|
|
443
487
|
</Fragment>
|
|
@@ -446,19 +490,19 @@ const App = () => {
|
|
|
446
490
|
|
|
447
491
|
root.render(
|
|
448
492
|
<StrictMode>
|
|
449
|
-
<
|
|
493
|
+
<RouterProvider>
|
|
450
494
|
<App />
|
|
451
|
-
</
|
|
495
|
+
</RouterProvider>
|
|
452
496
|
</StrictMode>,
|
|
453
497
|
);
|
|
454
498
|
```
|
|
455
499
|
|
|
456
|
-
You can also define
|
|
500
|
+
You can also define the issue component from the outside.
|
|
457
501
|
|
|
458
502
|
```tsx
|
|
459
503
|
import { Fragment, StrictMode } from "react";
|
|
460
504
|
import { createRoot } from "react-dom/client";
|
|
461
|
-
import { createRouter, createPage
|
|
505
|
+
import { createRouter, createPage } from "@aminnairi/react-router";
|
|
462
506
|
|
|
463
507
|
const home = createPage({
|
|
464
508
|
path: "/",
|
|
@@ -471,15 +515,15 @@ const Fallback = () => {
|
|
|
471
515
|
return <h1>Not found</h1>;
|
|
472
516
|
};
|
|
473
517
|
|
|
474
|
-
const Issue =
|
|
518
|
+
const Issue = ({ error, resetError }: { error: Error; resetError: () => void }) => (
|
|
475
519
|
<Fragment>
|
|
476
520
|
<h1>Error</h1>
|
|
477
521
|
<p>{error.message}</p>
|
|
478
|
-
<button onClick={
|
|
522
|
+
<button onClick={resetError}>Reset</button>
|
|
479
523
|
</Fragment>
|
|
480
|
-
)
|
|
524
|
+
);
|
|
481
525
|
|
|
482
|
-
const
|
|
526
|
+
const { RouterProvider, RouterView } = createRouter({
|
|
483
527
|
fallback: Fallback,
|
|
484
528
|
issue: Issue,
|
|
485
529
|
pages: [home],
|
|
@@ -500,7 +544,7 @@ const App = () => {
|
|
|
500
544
|
<h1>App</h1>
|
|
501
545
|
</header>
|
|
502
546
|
<main>
|
|
503
|
-
<
|
|
547
|
+
<RouterView />
|
|
504
548
|
</main>
|
|
505
549
|
<footer>Credit © Yourself 2025</footer>
|
|
506
550
|
</Fragment>
|
|
@@ -509,9 +553,9 @@ const App = () => {
|
|
|
509
553
|
|
|
510
554
|
root.render(
|
|
511
555
|
<StrictMode>
|
|
512
|
-
<
|
|
556
|
+
<RouterProvider>
|
|
513
557
|
<App />
|
|
514
|
-
</
|
|
558
|
+
</RouterProvider>
|
|
515
559
|
</StrictMode>,
|
|
516
560
|
);
|
|
517
561
|
```
|
|
@@ -526,7 +570,6 @@ import { createRoot } from "react-dom/client";
|
|
|
526
570
|
import {
|
|
527
571
|
createRouter,
|
|
528
572
|
createPage,
|
|
529
|
-
createIssue,
|
|
530
573
|
useNavigateToPage,
|
|
531
574
|
} from "@aminnairi/react-router";
|
|
532
575
|
|
|
@@ -543,20 +586,20 @@ const Fallback = () => {
|
|
|
543
586
|
return (
|
|
544
587
|
<Fragment>
|
|
545
588
|
<h1>Not found</h1>
|
|
546
|
-
<button onClick={
|
|
589
|
+
<button onClick={navigateToHomePage}>Go Back Home</button>
|
|
547
590
|
</Fragment>
|
|
548
591
|
);
|
|
549
592
|
};
|
|
550
593
|
|
|
551
|
-
const Issue =
|
|
594
|
+
const Issue = ({ error, resetError }: { error: Error; resetError: () => void }) => (
|
|
552
595
|
<Fragment>
|
|
553
596
|
<h1>Error</h1>
|
|
554
597
|
<p>{error.message}</p>
|
|
555
|
-
<button onClick={
|
|
598
|
+
<button onClick={resetError}>Reset</button>
|
|
556
599
|
</Fragment>
|
|
557
|
-
)
|
|
600
|
+
);
|
|
558
601
|
|
|
559
|
-
const
|
|
602
|
+
const { RouterProvider, RouterView } = createRouter({
|
|
560
603
|
prefix: "/portfolio",
|
|
561
604
|
fallback: Fallback,
|
|
562
605
|
issue: Issue,
|
|
@@ -578,7 +621,7 @@ const App = () => {
|
|
|
578
621
|
<h1>App</h1>
|
|
579
622
|
</header>
|
|
580
623
|
<main>
|
|
581
|
-
<
|
|
624
|
+
<RouterView />
|
|
582
625
|
</main>
|
|
583
626
|
<footer>Credit © Yourself 2025</footer>
|
|
584
627
|
</Fragment>
|
|
@@ -587,9 +630,9 @@ const App = () => {
|
|
|
587
630
|
|
|
588
631
|
root.render(
|
|
589
632
|
<StrictMode>
|
|
590
|
-
<
|
|
633
|
+
<RouterProvider>
|
|
591
634
|
<App />
|
|
592
|
-
</
|
|
635
|
+
</RouterProvider>
|
|
593
636
|
</StrictMode>,
|
|
594
637
|
);
|
|
595
638
|
```
|
|
@@ -600,9 +643,11 @@ Allow you to create a function that can then be called to navigate to another pa
|
|
|
600
643
|
|
|
601
644
|
It accepts a page that has been created using `createPage`.
|
|
602
645
|
|
|
646
|
+
Note: This hook is returned from `createRouter`, not imported directly from the library.
|
|
647
|
+
|
|
603
648
|
```tsx
|
|
604
649
|
import { Fragment } from "react";
|
|
605
|
-
import { createPage,
|
|
650
|
+
import { createPage, createRouter } from "@aminnairi/react-router";
|
|
606
651
|
|
|
607
652
|
const home = createPage({
|
|
608
653
|
path: "/",
|
|
@@ -611,6 +656,12 @@ const home = createPage({
|
|
|
611
656
|
},
|
|
612
657
|
});
|
|
613
658
|
|
|
659
|
+
const { useNavigateToPage } = createRouter({
|
|
660
|
+
fallback: () => <h1>Not found</h1>,
|
|
661
|
+
issue: () => <h1>An error occurred</h1>,
|
|
662
|
+
pages: [home],
|
|
663
|
+
});
|
|
664
|
+
|
|
614
665
|
createPage({
|
|
615
666
|
path: "/about",
|
|
616
667
|
element: function About() {
|
|
@@ -619,7 +670,7 @@ createPage({
|
|
|
619
670
|
return (
|
|
620
671
|
<Fragment>
|
|
621
672
|
<h1>About</h1>
|
|
622
|
-
<button onClick={
|
|
673
|
+
<button onClick={navigateToHomePage}>Home</button>
|
|
623
674
|
</Fragment>
|
|
624
675
|
);
|
|
625
676
|
},
|
|
@@ -632,7 +683,7 @@ The parameters should always be provided as string, as they are the only data ty
|
|
|
632
683
|
|
|
633
684
|
```tsx
|
|
634
685
|
import { Fragment } from "react";
|
|
635
|
-
import { createPage,
|
|
686
|
+
import { createPage, createRouter } from "@aminnairi/react-router";
|
|
636
687
|
|
|
637
688
|
const user = createPage({
|
|
638
689
|
path: "/users/:user",
|
|
@@ -658,200 +709,146 @@ createPage({
|
|
|
658
709
|
});
|
|
659
710
|
```
|
|
660
711
|
|
|
661
|
-
###
|
|
712
|
+
### useIsActivePage
|
|
662
713
|
|
|
663
|
-
Allow you to
|
|
714
|
+
Allow you to check if a page is currently active.
|
|
664
715
|
|
|
665
|
-
|
|
716
|
+
Note: This hook is returned from `createRouter`, not imported directly from the library.
|
|
666
717
|
|
|
667
718
|
```tsx
|
|
668
719
|
import { Fragment } from "react";
|
|
669
|
-
import { createPage,
|
|
720
|
+
import { createPage, createRouter } from "@aminnairi/react-router";
|
|
670
721
|
|
|
671
|
-
const
|
|
672
|
-
path: "/
|
|
673
|
-
element: function
|
|
674
|
-
return <h1>
|
|
722
|
+
const home = createPage({
|
|
723
|
+
path: "/",
|
|
724
|
+
element: function Home() {
|
|
725
|
+
return <h1>Home</h1>;
|
|
675
726
|
},
|
|
676
727
|
});
|
|
677
728
|
|
|
678
|
-
createPage({
|
|
729
|
+
const about = createPage({
|
|
679
730
|
path: "/about",
|
|
680
731
|
element: function About() {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
return (
|
|
684
|
-
<Fragment>
|
|
685
|
-
<h1>About</h1>
|
|
686
|
-
<Link parameters={{ user: "123" }}>User#123</Link>
|
|
687
|
-
</Fragment>
|
|
688
|
-
);
|
|
732
|
+
return <h1>About</h1>;
|
|
689
733
|
},
|
|
690
734
|
});
|
|
691
|
-
```
|
|
692
|
-
|
|
693
|
-
You can also provide a custom render function as the second argument to fully control the rendered output. This is useful when you want to use a different component library or need more control over the markup.
|
|
694
|
-
|
|
695
|
-
```tsx
|
|
696
|
-
import { Fragment } from "react";
|
|
697
|
-
import { createPage, useLink, UseLinkRenderFunction } from "@aminnairi/react-router";
|
|
698
735
|
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
},
|
|
736
|
+
const { useIsActivePage } = createRouter({
|
|
737
|
+
fallback: () => <h1>Not found</h1>,
|
|
738
|
+
issue: () => <h1>An error occurred</h1>,
|
|
739
|
+
pages: [home, about],
|
|
704
740
|
});
|
|
705
741
|
|
|
706
742
|
createPage({
|
|
707
|
-
path: "/
|
|
708
|
-
element: function
|
|
709
|
-
const
|
|
710
|
-
return (
|
|
711
|
-
<button className="nav-button" onClick={onClick}>
|
|
712
|
-
{children}
|
|
713
|
-
</button>
|
|
714
|
-
);
|
|
715
|
-
});
|
|
743
|
+
path: "/",
|
|
744
|
+
element: function Home() {
|
|
745
|
+
const isAboutActive = useIsActivePage(about);
|
|
716
746
|
|
|
717
747
|
return (
|
|
718
748
|
<Fragment>
|
|
719
|
-
<h1>
|
|
720
|
-
<
|
|
749
|
+
<h1>Home</h1>
|
|
750
|
+
<p>About page is {isAboutActive ? "active" : "not active"}</p>
|
|
721
751
|
</Fragment>
|
|
722
752
|
);
|
|
723
753
|
},
|
|
724
754
|
});
|
|
725
755
|
```
|
|
726
756
|
|
|
727
|
-
|
|
728
|
-
- `path`: The computed URL path with parameters filled in
|
|
729
|
-
- `onClick`: The click event handler that prevents default navigation and handles routing
|
|
730
|
-
- `children`: The children passed to the link component
|
|
731
|
-
|
|
732
|
-
### useSearch
|
|
757
|
+
### useLocale
|
|
733
758
|
|
|
734
|
-
Allow you to get
|
|
759
|
+
Allow you to get and set the current locale for internationalization.
|
|
735
760
|
|
|
736
|
-
This
|
|
761
|
+
Note: This hook is returned from `createRouter`, not imported directly from the library.
|
|
737
762
|
|
|
738
763
|
```tsx
|
|
739
|
-
import {
|
|
740
|
-
import { createPage,
|
|
764
|
+
import { Fragment } from "react";
|
|
765
|
+
import { createPage, createRouter } from "@aminnairi/react-router";
|
|
741
766
|
|
|
742
|
-
createPage({
|
|
743
|
-
path: "/
|
|
767
|
+
const home = createPage({
|
|
768
|
+
path: "/",
|
|
744
769
|
element: function Home() {
|
|
745
|
-
const
|
|
746
|
-
const sortedByDate = useMemo(() => search.get("sort-by") === "date", [search]);
|
|
770
|
+
const { locale, setLocale } = useLocale();
|
|
747
771
|
|
|
748
772
|
return (
|
|
749
|
-
<
|
|
750
|
-
|
|
773
|
+
<Fragment>
|
|
774
|
+
<h1>Home</h1>
|
|
775
|
+
<p>Current locale: {locale ?? "none"}</p>
|
|
776
|
+
<button onClick={() => setLocale("en")}>English</button>
|
|
777
|
+
<button onClick={() => setLocale("fr")}>Français</button>
|
|
778
|
+
</Fragment>
|
|
751
779
|
);
|
|
752
|
-
}
|
|
780
|
+
},
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
const { RouterProvider, RouterView, useLocale } = createRouter({
|
|
784
|
+
locales: ["en", "fr"],
|
|
785
|
+
fallback: () => <h1>Not found</h1>,
|
|
786
|
+
issue: () => <h1>An error occurred</h1>,
|
|
787
|
+
pages: [home],
|
|
753
788
|
});
|
|
754
789
|
```
|
|
755
790
|
|
|
756
|
-
|
|
791
|
+
### usePrefix
|
|
757
792
|
|
|
758
|
-
|
|
793
|
+
Allow you to get the current route prefix.
|
|
759
794
|
|
|
760
|
-
|
|
795
|
+
Note: This hook is returned from `createRouter`, not imported directly from the library.
|
|
761
796
|
|
|
762
797
|
```tsx
|
|
763
|
-
import {
|
|
798
|
+
import { Fragment } from "react";
|
|
799
|
+
import { createPage, createRouter } from "@aminnairi/react-router";
|
|
764
800
|
|
|
765
|
-
createPage({
|
|
766
|
-
path: "/
|
|
767
|
-
element: function
|
|
768
|
-
const
|
|
801
|
+
const home = createPage({
|
|
802
|
+
path: "/",
|
|
803
|
+
element: function Home() {
|
|
804
|
+
const { prefix } = usePrefix();
|
|
769
805
|
|
|
770
|
-
return
|
|
806
|
+
return (
|
|
807
|
+
<Fragment>
|
|
808
|
+
<h1>Home</h1>
|
|
809
|
+
<p>Current prefix: {prefix ?? "none"}</p>
|
|
810
|
+
</Fragment>
|
|
811
|
+
);
|
|
771
812
|
},
|
|
772
813
|
});
|
|
773
|
-
```
|
|
774
|
-
|
|
775
|
-
## Internal API
|
|
776
|
-
|
|
777
|
-
### doesRouteMatchPath
|
|
778
|
-
|
|
779
|
-
Return a boolean in case a route matches a path. A route is a URI that looks something like `/users/:user/articles` and a path is the browser's location pathname that looks something like `/users/123/articles`.
|
|
780
|
-
|
|
781
|
-
This function is mainly used in the internals of the `createRouter` and in most case should not be necessary.
|
|
782
|
-
|
|
783
|
-
```typescript
|
|
784
|
-
import { doesRouteMatchPath } from "@aminnairi/react-router";
|
|
785
|
-
|
|
786
|
-
doesRouteMatchPath("/", "/"); // true
|
|
787
|
-
|
|
788
|
-
doesRouteMatchPath("/", "/about"); // false
|
|
789
|
-
|
|
790
|
-
doesRouteMatchPath("/users/:user", "/users/123"); // true
|
|
791
|
-
|
|
792
|
-
doesRouteMatchPath("/users/:user", "/users/123/articles"); // false
|
|
793
|
-
```
|
|
794
|
-
|
|
795
|
-
You can also optionally provide a prefix.
|
|
796
|
-
|
|
797
|
-
```typescript
|
|
798
|
-
import { doesRouteMatchPath } from "@aminnairi/react-router";
|
|
799
|
-
|
|
800
|
-
doesRouteMatchPath("/", "/github", "/github"); // true
|
|
801
|
-
|
|
802
|
-
doesRouteMatchPath("/", "/github/about", "/github"); // false
|
|
803
|
-
|
|
804
|
-
doesRouteMatchPath("/users/:user", "/github/users/123", "/github"); // true
|
|
805
|
-
|
|
806
|
-
doesRouteMatchPath("/users/:user", "/github/users/123/articles", "/github"); // false
|
|
807
|
-
```
|
|
808
|
-
|
|
809
|
-
### getParameters
|
|
810
|
-
|
|
811
|
-
Return an object in case a route matches a path, with its dynamic parameters as output. It returns a generic `object` type in case no dynamic parameters are found in the URI. Note that the parameters are always strings, if you need to, convert them to other types explicitely.
|
|
812
|
-
|
|
813
|
-
This function is mainly used in the internals of the `createRouter` and in most case should not be necessary.
|
|
814
|
-
|
|
815
|
-
```typescript
|
|
816
|
-
import { getParameters } from "@aminnairi/react-router";
|
|
817
|
-
|
|
818
|
-
getParameters("/", "/"); // {}
|
|
819
|
-
|
|
820
|
-
getParameters("/", "/about"); // {}
|
|
821
|
-
|
|
822
|
-
getParameters("/users/:user", "/users/123"); // { user: "123" }
|
|
823
|
-
|
|
824
|
-
getParameters("/users/:user", "/users/123/articles"); // {}
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
You can also provide an optional prefix.
|
|
828
814
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
getParameters("/users/:user", "/github/users/123", "/github"); // { user: "123" }
|
|
837
|
-
|
|
838
|
-
getParameters("/users/:user", "/github/users/123/articles", "/github"); // {}
|
|
815
|
+
const { RouterProvider, RouterView, usePrefix } = createRouter({
|
|
816
|
+
prefix: "/portfolio",
|
|
817
|
+
fallback: () => <h1>Not found</h1>,
|
|
818
|
+
issue: () => <h1>An error occurred</h1>,
|
|
819
|
+
pages: [home],
|
|
820
|
+
});
|
|
839
821
|
```
|
|
840
822
|
|
|
841
|
-
###
|
|
823
|
+
### usePath
|
|
842
824
|
|
|
843
|
-
|
|
825
|
+
Allow you to get the current path.
|
|
844
826
|
|
|
845
|
-
|
|
846
|
-
import { sanitizePath } from "@aminnairi/react-router";
|
|
827
|
+
Note: This hook is returned from `createRouter`, not imported directly from the library.
|
|
847
828
|
|
|
848
|
-
|
|
829
|
+
```tsx
|
|
830
|
+
import { Fragment } from "react";
|
|
831
|
+
import { createPage, createRouter } from "@aminnairi/react-router";
|
|
849
832
|
|
|
850
|
-
|
|
833
|
+
const home = createPage({
|
|
834
|
+
path: "/",
|
|
835
|
+
element: function Home() {
|
|
836
|
+
const { path } = usePath();
|
|
851
837
|
|
|
852
|
-
|
|
838
|
+
return (
|
|
839
|
+
<Fragment>
|
|
840
|
+
<h1>Home</h1>
|
|
841
|
+
<p>Current path: {path}</p>
|
|
842
|
+
</Fragment>
|
|
843
|
+
);
|
|
844
|
+
},
|
|
845
|
+
});
|
|
853
846
|
|
|
854
|
-
|
|
847
|
+
const { RouterProvider, RouterView, usePath } = createRouter({
|
|
848
|
+
fallback: () => <h1>Not found</h1>,
|
|
849
|
+
issue: () => <h1>An error occurred</h1>,
|
|
850
|
+
pages: [home],
|
|
851
|
+
});
|
|
855
852
|
```
|
|
856
853
|
|
|
857
854
|
## Features
|
|
@@ -874,7 +871,7 @@ This means that you can use this library with other popular solutions for handli
|
|
|
874
871
|
|
|
875
872
|
### Transition
|
|
876
873
|
|
|
877
|
-
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
|
|
874
|
+
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 several transitions ready to be used: `slideHorizontalTransition`, `slideVerticalTransition`, `crossFadeTransition`, and `scaleFadeTransition`.
|
|
878
875
|
|
|
879
876
|
### Error handling
|
|
880
877
|
|
|
@@ -888,6 +885,7 @@ See [`LICENSE`](./LICENSE).
|
|
|
888
885
|
|
|
889
886
|
### Versions
|
|
890
887
|
|
|
888
|
+
- [`3.0.0`](#300)
|
|
891
889
|
- [`2.1.0`](#210)
|
|
892
890
|
- [`2.0.1`](#201)
|
|
893
891
|
- [`2.0.0`](#200)
|
|
@@ -897,6 +895,31 @@ See [`LICENSE`](./LICENSE).
|
|
|
897
895
|
- [`0.1.1`](#011)
|
|
898
896
|
- [`0.1.0`](#010)
|
|
899
897
|
|
|
898
|
+
### 3.0.0
|
|
899
|
+
|
|
900
|
+
#### Major changes
|
|
901
|
+
|
|
902
|
+
- Full rewrite of the library implementation
|
|
903
|
+
- Added `locales` support for internationalization
|
|
904
|
+
- Added `useLocale` hook for locale management
|
|
905
|
+
- Added `usePrefix` and `usePath` hooks
|
|
906
|
+
- Renamed `slideFadeTransition` to `slideHorizontalTransition` and added new transitions: `scaleFadeTransition`, `crossFadeTransition`, `slideVerticalTransition`
|
|
907
|
+
- Changed API structure: `router.View` → `router.RouterView` and `router.Provider` → `RouterProvider`
|
|
908
|
+
- Renamed `reset` to `resetError` in `IssueProps`
|
|
909
|
+
- Renamed internal functions: `doesRouteMatchPath` → `matchPath`, `getParameters` → `matchParameters`
|
|
910
|
+
- Added `Uri` class for URL parsing
|
|
911
|
+
- Changed `createRouter` return value structure
|
|
912
|
+
- Removed `useLink`, `useSearch`, and `useHash` hooks and `UseLinkRenderFunction` type
|
|
913
|
+
|
|
914
|
+
#### Minor changes
|
|
915
|
+
|
|
916
|
+
- Added better URL normalization with `normalize` function
|
|
917
|
+
- Improved error handling with `ErrorBoundary` component
|
|
918
|
+
|
|
919
|
+
#### Bug & security fixes
|
|
920
|
+
|
|
921
|
+
- None.
|
|
922
|
+
|
|
900
923
|
### 2.1.0
|
|
901
924
|
|
|
902
925
|
#### Major changes
|