@aminnairi/react-router 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -139
- package/index.tsx +71 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ export const Fallback = () => {
|
|
|
60
60
|
const navigateToHomePage = useNavigateToPage(home);
|
|
61
61
|
|
|
62
62
|
return (
|
|
63
|
-
<button onClick={navigateToHomePage}>
|
|
63
|
+
<button onClick={() => navigateToHomePage({})}>
|
|
64
64
|
Go back home
|
|
65
65
|
</button>
|
|
66
66
|
);
|
|
@@ -82,7 +82,7 @@ export const Issue = () => {
|
|
|
82
82
|
return (
|
|
83
83
|
<Fragment>
|
|
84
84
|
<h1>An issue occurred</h1>
|
|
85
|
-
<button onClick={
|
|
85
|
+
<button onClick={() => navigateToHomePage({})}>
|
|
86
86
|
Go back home
|
|
87
87
|
</button>
|
|
88
88
|
</Fragment>
|
|
@@ -94,11 +94,11 @@ export const Issue = () => {
|
|
|
94
94
|
touch src/router/index.ts
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
```
|
|
97
|
+
```ts
|
|
98
98
|
import { createRouter } from "@aminnairi/react-router";
|
|
99
|
-
import { Fallback } from "./
|
|
100
|
-
import { Issue } from "./
|
|
101
|
-
import { home } from "./
|
|
99
|
+
import { Fallback } from "./fallback";
|
|
100
|
+
import { Issue } from "./issue";
|
|
101
|
+
import { home } from "./pages/home";
|
|
102
102
|
|
|
103
103
|
export const router = createRouter({
|
|
104
104
|
fallback: Fallback,
|
|
@@ -259,7 +259,7 @@ const about = createPage({
|
|
|
259
259
|
<h1>
|
|
260
260
|
About Us
|
|
261
261
|
</h1>
|
|
262
|
-
<button onClick={navigateToLoginPage}>
|
|
262
|
+
<button onClick={() => navigateToLoginPage({})}>
|
|
263
263
|
Login
|
|
264
264
|
</button>
|
|
265
265
|
</Fragment>
|
|
@@ -277,7 +277,7 @@ createPage({
|
|
|
277
277
|
<h1>
|
|
278
278
|
Home
|
|
279
279
|
</h1>
|
|
280
|
-
<button onClick={navigateToAboutPage}>
|
|
280
|
+
<button onClick={() => navigateToAboutPage({})}>
|
|
281
281
|
About Us
|
|
282
282
|
</button>
|
|
283
283
|
</Fragment>
|
|
@@ -385,12 +385,14 @@ root.render(
|
|
|
385
385
|
|
|
386
386
|
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
387
|
|
|
388
|
-
All you have to do is to
|
|
388
|
+
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.
|
|
389
|
+
|
|
390
|
+
This library also exports a `slideFadeTransition` that you can use out-of-the-box.
|
|
389
391
|
|
|
390
392
|
```tsx
|
|
391
393
|
import { Fragment, StrictMode } from "react";
|
|
392
394
|
import { createRoot } from "react-dom/client";
|
|
393
|
-
import { createRouter, createPage } from "@aminnairi/react-router";
|
|
395
|
+
import { createRouter, createPage, slideFadeTransition } from "@aminnairi/react-router";
|
|
394
396
|
|
|
395
397
|
const home = createPage({
|
|
396
398
|
path: "/",
|
|
@@ -402,7 +404,7 @@ const home = createPage({
|
|
|
402
404
|
});
|
|
403
405
|
|
|
404
406
|
const router = createRouter({
|
|
405
|
-
transition:
|
|
407
|
+
transition: slideFadeTransition,
|
|
406
408
|
fallback: () => (
|
|
407
409
|
<h1>Not found</h1>
|
|
408
410
|
),
|
|
@@ -464,18 +466,15 @@ const home = createPage({
|
|
|
464
466
|
});
|
|
465
467
|
|
|
466
468
|
const router = createRouter({
|
|
467
|
-
transition: true,
|
|
468
469
|
fallback: () => (
|
|
469
470
|
<h1>Not found</h1>
|
|
470
471
|
),
|
|
471
472
|
issue: ({ error, reset }) => (
|
|
472
|
-
|
|
473
|
-
<
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
</Fragment>
|
|
478
|
-
);
|
|
473
|
+
<Fragment>
|
|
474
|
+
<h1>Error</h1>
|
|
475
|
+
<p>{error.message}</p>
|
|
476
|
+
<button onClick={reset}>Reset</button>
|
|
477
|
+
</Fragment>
|
|
479
478
|
),
|
|
480
479
|
pages: [
|
|
481
480
|
home
|
|
@@ -538,17 +537,14 @@ const Fallback = () => {
|
|
|
538
537
|
}
|
|
539
538
|
|
|
540
539
|
const Issue = createIssue(({ error, reset }) => (
|
|
541
|
-
|
|
542
|
-
<
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
</Fragment>
|
|
547
|
-
);
|
|
540
|
+
<Fragment>
|
|
541
|
+
<h1>Error</h1>
|
|
542
|
+
<p>{error.message}</p>
|
|
543
|
+
<button onClick={reset}>Reset</button>
|
|
544
|
+
</Fragment>
|
|
548
545
|
));
|
|
549
546
|
|
|
550
547
|
const router = createRouter({
|
|
551
|
-
transition: true,
|
|
552
548
|
fallback: Fallback,
|
|
553
549
|
issue: Issue,
|
|
554
550
|
pages: [
|
|
@@ -582,7 +578,9 @@ const App = () => {
|
|
|
582
578
|
|
|
583
579
|
root.render(
|
|
584
580
|
<StrictMode>
|
|
585
|
-
<
|
|
581
|
+
<router.Provider>
|
|
582
|
+
<App />
|
|
583
|
+
</router.Provider>
|
|
586
584
|
</StrictMode>
|
|
587
585
|
);
|
|
588
586
|
```
|
|
@@ -611,7 +609,7 @@ const Fallback = () => {
|
|
|
611
609
|
return (
|
|
612
610
|
<Fragment>
|
|
613
611
|
<h1>Not found</h1>
|
|
614
|
-
<button onClick={navigateToHomePage}>
|
|
612
|
+
<button onClick={() => navigateToHomePage({})}>
|
|
615
613
|
Go Back Home
|
|
616
614
|
</button>
|
|
617
615
|
</Fragment>
|
|
@@ -619,18 +617,15 @@ const Fallback = () => {
|
|
|
619
617
|
}
|
|
620
618
|
|
|
621
619
|
const Issue = createIssue(({ error, reset }) => (
|
|
622
|
-
|
|
623
|
-
<
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
</Fragment>
|
|
628
|
-
);
|
|
620
|
+
<Fragment>
|
|
621
|
+
<h1>Error</h1>
|
|
622
|
+
<p>{error.message}</p>
|
|
623
|
+
<button onClick={reset}>Reset</button>
|
|
624
|
+
</Fragment>
|
|
629
625
|
));
|
|
630
626
|
|
|
631
627
|
const router = createRouter({
|
|
632
628
|
prefix: "/portfolio",
|
|
633
|
-
transition: true,
|
|
634
629
|
fallback: Fallback,
|
|
635
630
|
issue: Issue,
|
|
636
631
|
pages: [
|
|
@@ -664,7 +659,9 @@ const App = () => {
|
|
|
664
659
|
|
|
665
660
|
root.render(
|
|
666
661
|
<StrictMode>
|
|
667
|
-
<
|
|
662
|
+
<router.Provider>
|
|
663
|
+
<App />
|
|
664
|
+
</router.Provider>
|
|
668
665
|
</StrictMode>
|
|
669
666
|
);
|
|
670
667
|
```
|
|
@@ -679,7 +676,7 @@ It accepts a page that has been created using `createPage`.
|
|
|
679
676
|
import { Fragment } from "react";
|
|
680
677
|
import { createPage, useNavigateToPage } from "@aminnairi/react-router";
|
|
681
678
|
|
|
682
|
-
const home =
|
|
679
|
+
const home = createPage({
|
|
683
680
|
path: "/",
|
|
684
681
|
element: function Home() {
|
|
685
682
|
return (
|
|
@@ -696,7 +693,7 @@ createPage({
|
|
|
696
693
|
return (
|
|
697
694
|
<Fragment>
|
|
698
695
|
<h1>About</h1>
|
|
699
|
-
<button onClick={navigateToHomePage}>Home</button>
|
|
696
|
+
<button onClick={() => navigateToHomePage({})}>Home</button>
|
|
700
697
|
</Fragment>
|
|
701
698
|
);
|
|
702
699
|
}
|
|
@@ -711,7 +708,7 @@ The parameters should always be provided as string, as they are the only data ty
|
|
|
711
708
|
import { Fragment } from "react";
|
|
712
709
|
import { createPage, useNavigateToPage } from "@aminnairi/react-router";
|
|
713
710
|
|
|
714
|
-
const user =
|
|
711
|
+
const user = createPage({
|
|
715
712
|
path: "/users/:user",
|
|
716
713
|
element: function User({ parameters: { user }}) {
|
|
717
714
|
return (
|
|
@@ -745,7 +742,7 @@ The created component is simply a `<a href="...">{children}</a>` under the hood
|
|
|
745
742
|
import { Fragment } from "react";
|
|
746
743
|
import { createPage, useLink } from "@aminnairi/react-router";
|
|
747
744
|
|
|
748
|
-
const user =
|
|
745
|
+
const user = createPage({
|
|
749
746
|
path: "/users/:user",
|
|
750
747
|
element: function User({ parameters: { user }}) {
|
|
751
748
|
return (
|
|
@@ -782,7 +779,7 @@ import { createPage, useSearch } from "@aminnairi/react-router";
|
|
|
782
779
|
createPage({
|
|
783
780
|
path: "/users",
|
|
784
781
|
element: function Home() {
|
|
785
|
-
const
|
|
782
|
+
const search = useSearch();
|
|
786
783
|
const sortedByDate = useMemo(() => search.get("sort-by") === "date", [search]);
|
|
787
784
|
|
|
788
785
|
return (
|
|
@@ -825,13 +822,13 @@ This function is mainly used in the internals of the `createRouter` and in most
|
|
|
825
822
|
```typescript
|
|
826
823
|
import { doesRouteMatchPath } from "@aminnairi/react-router";
|
|
827
824
|
|
|
828
|
-
|
|
825
|
+
doesRouteMatchPath("/", "/"); // true
|
|
829
826
|
|
|
830
|
-
|
|
827
|
+
doesRouteMatchPath("/", "/about"); // false
|
|
831
828
|
|
|
832
|
-
|
|
829
|
+
doesRouteMatchPath("/users/:user", "/users/123"); // true
|
|
833
830
|
|
|
834
|
-
|
|
831
|
+
doesRouteMatchPath("/users/:user", "/users/123/articles"); // false
|
|
835
832
|
```
|
|
836
833
|
|
|
837
834
|
You can also optionally provide a prefix.
|
|
@@ -839,13 +836,13 @@ You can also optionally provide a prefix.
|
|
|
839
836
|
```typescript
|
|
840
837
|
import { doesRouteMatchPath } from "@aminnairi/react-router";
|
|
841
838
|
|
|
842
|
-
|
|
839
|
+
doesRouteMatchPath("/", "/github", "/github"); // true
|
|
843
840
|
|
|
844
|
-
|
|
841
|
+
doesRouteMatchPath("/", "/github/about", "/github"); // false
|
|
845
842
|
|
|
846
|
-
|
|
843
|
+
doesRouteMatchPath("/users/:user", "/github/users/123", "/github"); // true
|
|
847
844
|
|
|
848
|
-
|
|
845
|
+
doesRouteMatchPath("/users/:user", "/github/users/123/articles", "/github"); // false
|
|
849
846
|
```
|
|
850
847
|
|
|
851
848
|
### getParameters
|
|
@@ -857,13 +854,13 @@ This function is mainly used in the internals of the `createRouter` and in most
|
|
|
857
854
|
```typescript
|
|
858
855
|
import { getParameters } from "@aminnairi/react-router";
|
|
859
856
|
|
|
860
|
-
getParameters("/", "/"); //
|
|
857
|
+
getParameters("/", "/"); // {}
|
|
861
858
|
|
|
862
|
-
getParameters("/", "/about"); //
|
|
859
|
+
getParameters("/", "/about"); // {}
|
|
863
860
|
|
|
864
861
|
getParameters("/users/:user", "/users/123"); // { user: "123" }
|
|
865
862
|
|
|
866
|
-
getParameters("/users/:user", "/users/123/articles"); // {
|
|
863
|
+
getParameters("/users/:user", "/users/123/articles"); // {}
|
|
867
864
|
```
|
|
868
865
|
|
|
869
866
|
You can also provide an optional prefix.
|
|
@@ -871,91 +868,13 @@ You can also provide an optional prefix.
|
|
|
871
868
|
```typescript
|
|
872
869
|
import { getParameters } from "@aminnairi/react-router";
|
|
873
870
|
|
|
874
|
-
getParameters("/", "/github", "/github"); //
|
|
871
|
+
getParameters("/", "/github", "/github"); // {}
|
|
875
872
|
|
|
876
|
-
getParameters("/", "/github/about", "/github"); //
|
|
873
|
+
getParameters("/", "/github/about", "/github"); // {}
|
|
877
874
|
|
|
878
875
|
getParameters("/users/:user", "/github/users/123", "/github"); // { user: "123" }
|
|
879
876
|
|
|
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
|
-
}
|
|
877
|
+
getParameters("/users/:user", "/github/users/123/articles", "/github"); // {}
|
|
959
878
|
```
|
|
960
879
|
|
|
961
880
|
### sanitizePath
|
|
@@ -994,9 +913,7 @@ This means that you can use this library with other popular solutions for handli
|
|
|
994
913
|
|
|
995
914
|
### Transition
|
|
996
915
|
|
|
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.
|
|
916
|
+
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
917
|
|
|
1001
918
|
### Error handling
|
|
1002
919
|
|
|
@@ -1010,12 +927,28 @@ See [`LICENSE`](./LICENSE).
|
|
|
1010
927
|
|
|
1011
928
|
### Versions
|
|
1012
929
|
|
|
930
|
+
- [`2.0.0`](#200)
|
|
1013
931
|
- [`1.1.0`](#110)
|
|
1014
932
|
- [`1.0.1`](#101)
|
|
1015
933
|
- [`1.0.0`](#100)
|
|
1016
934
|
- [`0.1.1`](#011)
|
|
1017
935
|
- [`0.1.0`](#010)
|
|
1018
936
|
|
|
937
|
+
### 2.0.0
|
|
938
|
+
|
|
939
|
+
#### Major changes
|
|
940
|
+
|
|
941
|
+
- 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.
|
|
942
|
+
- A `slideFadeTransition` is now exported and can be used directly.
|
|
943
|
+
|
|
944
|
+
#### Minor changes
|
|
945
|
+
|
|
946
|
+
None.
|
|
947
|
+
|
|
948
|
+
#### Bug & security fixes
|
|
949
|
+
|
|
950
|
+
None.
|
|
951
|
+
|
|
1019
952
|
### 1.1.0
|
|
1020
953
|
|
|
1021
954
|
#### Major changes
|
|
@@ -1088,4 +1021,4 @@ None.
|
|
|
1088
1021
|
|
|
1089
1022
|
#### Bug & security fixes
|
|
1090
1023
|
|
|
1091
|
-
None.
|
|
1024
|
+
None.
|
package/index.tsx
CHANGED
|
@@ -25,8 +25,10 @@ export interface Page<Path extends string> {
|
|
|
25
25
|
element: FunctionComponent<PageComponentProps<Path>>
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
export type Transition = (direction: NavigationDirection, next: () => void) => void;
|
|
29
|
+
|
|
28
30
|
export interface CreateRouterOptions<Path extends string> {
|
|
29
|
-
transition?:
|
|
31
|
+
transition?: Transition,
|
|
30
32
|
prefix?: string,
|
|
31
33
|
pages: Array<Page<Path>>
|
|
32
34
|
fallback: FunctionComponent
|
|
@@ -99,7 +101,7 @@ export interface IssueProps {
|
|
|
99
101
|
|
|
100
102
|
export interface ErrorBoundaryProps {
|
|
101
103
|
fallback: FunctionComponent<IssueProps>,
|
|
102
|
-
transition
|
|
104
|
+
transition?: Transition
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
export interface ErrorBoundaryState {
|
|
@@ -177,6 +179,11 @@ const Context = createContext<ContextInterface>({
|
|
|
177
179
|
setHash: () => { }
|
|
178
180
|
});
|
|
179
181
|
|
|
182
|
+
enum NavigationDirection {
|
|
183
|
+
Forward = "pushstate",
|
|
184
|
+
Backward = "popstate"
|
|
185
|
+
}
|
|
186
|
+
|
|
180
187
|
export const useNavigateToPage = <Path extends string>(page: Page<Path>) => {
|
|
181
188
|
const { prefix } = useContext(Context);
|
|
182
189
|
|
|
@@ -193,10 +200,16 @@ export const useNavigateToPage = <Path extends string>(page: Page<Path>) => {
|
|
|
193
200
|
window.history.pushState(null, pathWithParameters, pathWithParameters);
|
|
194
201
|
}
|
|
195
202
|
|
|
196
|
-
window.dispatchEvent(new CustomEvent(
|
|
203
|
+
window.dispatchEvent(new CustomEvent(NavigationDirection.Forward));
|
|
197
204
|
}, [page]);
|
|
198
205
|
};
|
|
199
206
|
|
|
207
|
+
export const useNavigateBack = () => {
|
|
208
|
+
return useCallback(() => {
|
|
209
|
+
window.dispatchEvent(new CustomEvent(NavigationDirection.Backward));
|
|
210
|
+
}, []);
|
|
211
|
+
}
|
|
212
|
+
|
|
200
213
|
export const useIsActivePage = (page: Page<string>) => {
|
|
201
214
|
const { pathname, prefix } = useContext(Context);
|
|
202
215
|
|
|
@@ -243,12 +256,45 @@ export const useLink = <Path extends string>(page: Page<Path>) => {
|
|
|
243
256
|
return Link;
|
|
244
257
|
};
|
|
245
258
|
|
|
246
|
-
export const
|
|
259
|
+
export const slideFadeTransition: Transition = async (direction: NavigationDirection, next) => {
|
|
260
|
+
const transition = document.startViewTransition(() => {
|
|
261
|
+
next();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
await transition.ready;
|
|
265
|
+
|
|
266
|
+
document.documentElement.animate(
|
|
267
|
+
[
|
|
268
|
+
{ transform: 'translateX(0)', opacity: 1 },
|
|
269
|
+
{ transform: `translateX(${direction === NavigationDirection.Forward ? '100%' : '-100%'})`, opacity: 0 }
|
|
270
|
+
],
|
|
271
|
+
{
|
|
272
|
+
duration: 250,
|
|
273
|
+
easing: "ease-in-out",
|
|
274
|
+
fill: "both",
|
|
275
|
+
pseudoElement: "::view-transition-old(root)",
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
document.documentElement.animate(
|
|
280
|
+
[
|
|
281
|
+
{ transform: `translateX(${direction === NavigationDirection.Forward ? '-100%' : '100%'})`, opacity: 0 },
|
|
282
|
+
{ transform: 'translateX(0)', opacity: 1 }
|
|
283
|
+
],
|
|
284
|
+
{
|
|
285
|
+
duration: 250,
|
|
286
|
+
easing: "ease-in-out",
|
|
287
|
+
fill: "both",
|
|
288
|
+
pseudoElement: "::view-transition-new(root)",
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export const createRouter = <Path extends string>({ pages, fallback, transition, issue, prefix }: CreateRouterOptions<Path>) => {
|
|
247
294
|
const Provider = ({ children }: ProviderProps) => {
|
|
248
295
|
const [pathname, setPathname] = useState(sanitizePath(window.location.pathname));
|
|
249
296
|
const [search, setSearch] = useState(new URLSearchParams(sanitizePath(window.location.search)));
|
|
250
297
|
const [hash, setHash] = useState(window.location.hash);
|
|
251
|
-
const shouldTransitionBetweenPages = useMemo(() => typeof document.startViewTransition === "function" && withViewTransition ? true : false, [withViewTransition]);
|
|
252
298
|
|
|
253
299
|
const value = useMemo(() => {
|
|
254
300
|
return {
|
|
@@ -263,9 +309,9 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
263
309
|
}, [prefix, pathname, search, hash]);
|
|
264
310
|
|
|
265
311
|
useEffect(() => {
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
|
|
312
|
+
const onNavigation = async (direction: NavigationDirection) => {
|
|
313
|
+
if (transition) {
|
|
314
|
+
transition(direction, () => {
|
|
269
315
|
setPathname(sanitizePath(window.location.pathname));
|
|
270
316
|
});
|
|
271
317
|
|
|
@@ -273,18 +319,28 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
273
319
|
}
|
|
274
320
|
|
|
275
321
|
setPathname(sanitizePath(window.location.pathname));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const onNavigationForward = () => {
|
|
325
|
+
onNavigation(NavigationDirection.Forward);
|
|
276
326
|
};
|
|
277
327
|
|
|
278
|
-
|
|
328
|
+
const onNavigationBackward = () => {
|
|
329
|
+
onNavigation(NavigationDirection.Backward);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
window.addEventListener(NavigationDirection.Forward, onNavigationForward);
|
|
333
|
+
window.addEventListener(NavigationDirection.Backward, onNavigationBackward);
|
|
279
334
|
|
|
280
335
|
return () => {
|
|
281
|
-
window.removeEventListener(
|
|
336
|
+
window.removeEventListener(NavigationDirection.Forward, onNavigationForward);
|
|
337
|
+
window.removeEventListener(NavigationDirection.Backward, onNavigationBackward);
|
|
282
338
|
}
|
|
283
339
|
}, []);
|
|
284
340
|
|
|
285
341
|
return (
|
|
286
342
|
<Context.Provider value={value}>
|
|
287
|
-
<ErrorBoundary fallback={issue}
|
|
343
|
+
<ErrorBoundary fallback={issue}>
|
|
288
344
|
{children}
|
|
289
345
|
</ErrorBoundary>
|
|
290
346
|
</Context.Provider>
|
|
@@ -306,7 +362,9 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
306
362
|
|
|
307
363
|
if (page) {
|
|
308
364
|
return (
|
|
309
|
-
<
|
|
365
|
+
<div >
|
|
366
|
+
<page.element parameters={parameters} />
|
|
367
|
+
</div>
|
|
310
368
|
);
|
|
311
369
|
}
|
|
312
370
|
|
|
@@ -319,4 +377,4 @@ export const createRouter = <Path extends string>({ pages, fallback, transition:
|
|
|
319
377
|
View,
|
|
320
378
|
Provider,
|
|
321
379
|
};
|
|
322
|
-
}
|
|
380
|
+
}
|
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.0",
|
|
6
6
|
"homepage": "https://github.com/aminnairi/react-router#readme",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"bugs": {
|
|
@@ -27,4 +27,4 @@
|
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": ">=18.0.0"
|
|
29
29
|
}
|
|
30
|
-
}
|
|
30
|
+
}
|