@solidjs/router 0.4.2 → 0.5.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 +19 -36
- package/dist/components.d.ts +5 -6
- package/dist/components.jsx +14 -19
- package/dist/index.js +54 -76
- package/dist/routing.d.ts +1 -1
- package/dist/routing.js +19 -13
- package/dist/types.d.ts +3 -3
- package/package.json +15 -14
package/README.md
CHANGED
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
<img src="https://assets.solidjs.com/banner?project=Router&type=core" alt="Solid Router" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
> 0.3.x only works with Solid v1.3.5 or later.
|
|
6
|
-
> `useData` has been renamed to `useRouteData` and no longer takes arguments. Refer to documentation below.
|
|
7
|
-
|
|
8
5
|
# Solid Router [](https://www.npmjs.org/package/@solidjs/router)
|
|
9
6
|
|
|
10
7
|
A router lets you change your view based on the URL in the browser. This allows your "single-page" application to simulate a traditional multipage site. To use Solid Router, you specify components called Routes that depend on the value of the URL (the "path"), and the router handles the mechanism of swapping them in and out.
|
|
@@ -101,7 +98,7 @@ export default function App() {
|
|
|
101
98
|
|
|
102
99
|
3. Lazy-load route components
|
|
103
100
|
|
|
104
|
-
This way, the `Users` and `Home` components will only be loaded if you're navigating to `/users` or
|
|
101
|
+
This way, the `Users` and `Home` components will only be loaded if you're navigating to `/users` or `/`, respectively.
|
|
105
102
|
|
|
106
103
|
```jsx
|
|
107
104
|
import { lazy } from "solid-js";
|
|
@@ -123,11 +120,11 @@ export default function App() {
|
|
|
123
120
|
|
|
124
121
|
## Create Links to Your Routes
|
|
125
122
|
|
|
126
|
-
Use the `
|
|
123
|
+
Use the `A` component to create an anchor tag that takes you to a route:
|
|
127
124
|
|
|
128
125
|
```jsx
|
|
129
126
|
import { lazy } from "solid-js";
|
|
130
|
-
import { Routes, Route,
|
|
127
|
+
import { Routes, Route, A } from "@solidjs/router"
|
|
131
128
|
const Users = lazy(() => import("./pages/Users"));
|
|
132
129
|
const Home = lazy(() => import("./pages/Home"));
|
|
133
130
|
|
|
@@ -135,8 +132,8 @@ export default function App() {
|
|
|
135
132
|
return <>
|
|
136
133
|
<h1>My Site with Lots of Pages</h1>
|
|
137
134
|
<nav>
|
|
138
|
-
<
|
|
139
|
-
<
|
|
135
|
+
<A href="/about">About</A>
|
|
136
|
+
<A href="/">Home</A>
|
|
140
137
|
</nav>
|
|
141
138
|
<Routes>
|
|
142
139
|
<Route path="/users" component={Users} />
|
|
@@ -147,33 +144,21 @@ export default function App() {
|
|
|
147
144
|
}
|
|
148
145
|
```
|
|
149
146
|
|
|
150
|
-
|
|
147
|
+
The `<A>` tag also has an `active` class if its href matches the current location, and `inactive` otherwise. **Note:** By default matching includes locations that are descendents (eg. href `/users` matches locations `/users` and `/users/123`), use the boolean `end` prop to prevent matching these. This is particularly useful for links to the root route `/` which would match everything.
|
|
151
148
|
|
|
152
|
-
Both of these components have these props:
|
|
153
149
|
|
|
154
150
|
| prop | type | description |
|
|
155
151
|
|----------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
156
152
|
| href | string | The path of the route to navigate to. This will be resolved relative to the route that the link is in, but you can preface it with `/` to refer back to the root. |
|
|
157
153
|
| noScroll | boolean | If true, turn off the default behavior of scrolling to the top of the new page |
|
|
158
154
|
| replace | boolean | If true, don't add a new entry to the browser history. (By default, the new page will be added to the browser history, so pressing the back button will take you to the previous route.) |
|
|
159
|
-
| state | unknown | [Push this value](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) to the history stack when navigating |
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`NavLink` additionally has:
|
|
163
|
-
|
|
164
|
-
| prop | type | description |
|
|
165
|
-
|----------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
155
|
+
| state | unknown | [Push this value](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) to the history stack when navigating | |
|
|
166
156
|
| inactiveClass | string | The class to show when the link is inactive (when the current location doesn't match the link) |
|
|
167
157
|
| activeClass | string | The class to show when the link is active |
|
|
168
158
|
| end | boolean | If `true`, only considers the link to be active when the curent location matches the `href` exactly; if `false`, check if the current location _starts with_ `href` |
|
|
169
159
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
If you have a same-domain path that you want to link to _without_ going through the router, set `rel="external"` on the link component.
|
|
174
|
-
|
|
175
160
|
### The Navigate Component
|
|
176
|
-
Solid Router provides a `Navigate` component that works similarly to `
|
|
161
|
+
Solid Router provides a `Navigate` component that works similarly to `A`, but it will _immediately_ navigate to the provided path as soon as the component is rendered. It also uses the `href` prop, but you have the additional option of passing a function to `href` that returns a path to navigate to:
|
|
177
162
|
|
|
178
163
|
```jsx
|
|
179
164
|
function getPath ({navigate, location}) {
|
|
@@ -183,9 +168,7 @@ function getPath ({navigate, location}) {
|
|
|
183
168
|
}
|
|
184
169
|
|
|
185
170
|
//Navigating to /redirect will redirect you to the result of getPath
|
|
186
|
-
<Route path="/redirect"
|
|
187
|
-
<Navigate href={getPath}/>
|
|
188
|
-
</Route>
|
|
171
|
+
<Route path="/redirect" element={<Navigate href={getPath}/>}/>
|
|
189
172
|
```
|
|
190
173
|
|
|
191
174
|
## Dynamic Routes
|
|
@@ -201,7 +184,7 @@ const Home = lazy(() => import("./pages/Home"));
|
|
|
201
184
|
|
|
202
185
|
export default function App() {
|
|
203
186
|
return <>
|
|
204
|
-
<h1>My Site with Lots of Pages
|
|
187
|
+
<h1>My Site with Lots of Pages</h1>
|
|
205
188
|
<Routes>
|
|
206
189
|
<Route path="/users" component={Users} />
|
|
207
190
|
<Route path="/users/:id" component={User} />
|
|
@@ -227,7 +210,7 @@ export default function User () {
|
|
|
227
210
|
|
|
228
211
|
const [userData] = createResource(() => params.id, fetchUser);
|
|
229
212
|
|
|
230
|
-
return <
|
|
213
|
+
return <A href={userData.twitter}>{userData.name}</A>
|
|
231
214
|
}
|
|
232
215
|
```
|
|
233
216
|
|
|
@@ -276,9 +259,9 @@ To do this, create a function that fetches and returns the data using `createRes
|
|
|
276
259
|
```js
|
|
277
260
|
import { lazy } from "solid-js";
|
|
278
261
|
import { Route } from "@solidjs/router";
|
|
279
|
-
import { fetchUser } ...
|
|
262
|
+
import { fetchUser } ...
|
|
280
263
|
|
|
281
|
-
const User = lazy(() => import("
|
|
264
|
+
const User = lazy(() => import("./pages/users/[id].js"));
|
|
282
265
|
|
|
283
266
|
//Data function
|
|
284
267
|
function UserData({params, location, navigate, data}) {
|
|
@@ -364,7 +347,7 @@ function PageWrapper () {
|
|
|
364
347
|
return <div>
|
|
365
348
|
<h1> We love our users! </h1>
|
|
366
349
|
<Outlet/>
|
|
367
|
-
<
|
|
350
|
+
<A href="/">Back Home</A>
|
|
368
351
|
</div>
|
|
369
352
|
}
|
|
370
353
|
|
|
@@ -404,7 +387,7 @@ You don't have to use JSX to set up your routes; you can pass an object directly
|
|
|
404
387
|
```jsx
|
|
405
388
|
import { lazy } from "solid-js";
|
|
406
389
|
import { render } from "solid-js/web";
|
|
407
|
-
import { Router, useRoutes,
|
|
390
|
+
import { Router, useRoutes, A } from "@solidjs/router";
|
|
408
391
|
|
|
409
392
|
const routes = [
|
|
410
393
|
{
|
|
@@ -435,12 +418,12 @@ function App() {
|
|
|
435
418
|
return (
|
|
436
419
|
<>
|
|
437
420
|
<h1>Awesome Site</h1>
|
|
438
|
-
<
|
|
421
|
+
<A class="nav" href="/">
|
|
439
422
|
Home
|
|
440
|
-
</
|
|
441
|
-
<
|
|
423
|
+
</A>
|
|
424
|
+
<A class="nav" href="/users">
|
|
442
425
|
Users
|
|
443
|
-
</
|
|
426
|
+
</A>
|
|
444
427
|
<Routes />
|
|
445
428
|
</>
|
|
446
429
|
);
|
package/dist/components.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ declare module "solid-js" {
|
|
|
6
6
|
state?: string;
|
|
7
7
|
noScroll?: boolean;
|
|
8
8
|
replace?: boolean;
|
|
9
|
+
link?: boolean;
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
}
|
|
@@ -27,7 +28,7 @@ export interface RoutesProps {
|
|
|
27
28
|
children: JSX.Element;
|
|
28
29
|
}
|
|
29
30
|
export declare const Routes: (props: RoutesProps) => JSX.Element;
|
|
30
|
-
export declare const useRoutes: (routes: RouteDefinition | RouteDefinition[], base?: string
|
|
31
|
+
export declare const useRoutes: (routes: RouteDefinition | RouteDefinition[], base?: string) => () => JSX.Element;
|
|
31
32
|
export declare type RouteProps = {
|
|
32
33
|
path: string | string[];
|
|
33
34
|
children?: JSX.Element;
|
|
@@ -42,19 +43,17 @@ export declare type RouteProps = {
|
|
|
42
43
|
});
|
|
43
44
|
export declare const Route: (props: RouteProps) => JSX.Element;
|
|
44
45
|
export declare const Outlet: () => JSX.Element;
|
|
45
|
-
export interface
|
|
46
|
+
export interface AnchorProps extends Omit<JSX.AnchorHTMLAttributes<HTMLAnchorElement>, "state"> {
|
|
46
47
|
href: string;
|
|
47
48
|
replace?: boolean;
|
|
48
49
|
noScroll?: boolean;
|
|
49
50
|
state?: unknown;
|
|
50
|
-
}
|
|
51
|
-
export declare function Link(props: LinkProps): JSX.Element;
|
|
52
|
-
export interface NavLinkProps extends LinkProps {
|
|
53
51
|
inactiveClass?: string;
|
|
54
52
|
activeClass?: string;
|
|
55
53
|
end?: boolean;
|
|
56
54
|
}
|
|
57
|
-
export declare function
|
|
55
|
+
export declare function A(props: AnchorProps): JSX.Element;
|
|
56
|
+
export { A as Link, A as NavLink, AnchorProps as LinkProps, AnchorProps as NavLinkProps };
|
|
58
57
|
export interface NavigateProps {
|
|
59
58
|
href: ((args: {
|
|
60
59
|
navigate: Navigator;
|
package/dist/components.jsx
CHANGED
|
@@ -54,7 +54,7 @@ export const Routes = (props) => {
|
|
|
54
54
|
return next;
|
|
55
55
|
}));
|
|
56
56
|
return (<Show when={routeStates() && root}>
|
|
57
|
-
{route => <RouteContextObj.Provider value={route}>{route.outlet()}</RouteContextObj.Provider>}
|
|
57
|
+
{((route) => (<RouteContextObj.Provider value={route}>{route.outlet()}</RouteContextObj.Provider>))}
|
|
58
58
|
</Show>);
|
|
59
59
|
};
|
|
60
60
|
export const useRoutes = (routes, base) => {
|
|
@@ -71,36 +71,31 @@ export const Route = (props) => {
|
|
|
71
71
|
export const Outlet = () => {
|
|
72
72
|
const route = useRoute();
|
|
73
73
|
return (<Show when={route.child}>
|
|
74
|
-
{child => <RouteContextObj.Provider value={child}>{child.outlet()}</RouteContextObj.Provider>}
|
|
74
|
+
{((child) => (<RouteContextObj.Provider value={child}>{child.outlet()}</RouteContextObj.Provider>))}
|
|
75
75
|
</Show>);
|
|
76
76
|
};
|
|
77
|
-
function
|
|
78
|
-
const [, rest] = splitProps(props, ["children", "to", "href", "state"]);
|
|
79
|
-
const href = useHref(() => props.to);
|
|
80
|
-
return (<a {...rest} href={href() || props.href} state={JSON.stringify(props.state)}>
|
|
81
|
-
{props.children}
|
|
82
|
-
</a>);
|
|
83
|
-
}
|
|
84
|
-
export function Link(props) {
|
|
85
|
-
const to = useResolvedPath(() => props.href);
|
|
86
|
-
return <LinkBase {...props} to={to()}/>;
|
|
87
|
-
}
|
|
88
|
-
export function NavLink(props) {
|
|
77
|
+
export function A(props) {
|
|
89
78
|
props = mergeProps({ inactiveClass: "inactive", activeClass: "active" }, props);
|
|
90
|
-
const [, rest] = splitProps(props, ["activeClass", "inactiveClass", "end"]);
|
|
91
|
-
const location = useLocation();
|
|
79
|
+
const [, rest] = splitProps(props, ["href", "state", "activeClass", "inactiveClass", "end"]);
|
|
92
80
|
const to = useResolvedPath(() => props.href);
|
|
81
|
+
const href = useHref(to);
|
|
82
|
+
const location = useLocation();
|
|
93
83
|
const isActive = createMemo(() => {
|
|
94
84
|
const to_ = to();
|
|
95
|
-
if (to_ === undefined)
|
|
85
|
+
if (to_ === undefined)
|
|
96
86
|
return false;
|
|
97
|
-
}
|
|
98
87
|
const path = to_.split(/[?#]/, 1)[0].toLowerCase();
|
|
99
88
|
const loc = location.pathname.toLowerCase();
|
|
100
89
|
return props.end ? path === loc : loc.startsWith(path);
|
|
101
90
|
});
|
|
102
|
-
return (<
|
|
91
|
+
return (<a link {...rest} href={href() || props.href} state={JSON.stringify(props.state)} classList={{
|
|
92
|
+
[props.inactiveClass]: !isActive(),
|
|
93
|
+
[props.activeClass]: isActive(),
|
|
94
|
+
...rest.classList
|
|
95
|
+
}} aria-current={isActive() ? "page" : undefined}/>);
|
|
103
96
|
}
|
|
97
|
+
// deprecated alias exports
|
|
98
|
+
export { A as Link, A as NavLink };
|
|
104
99
|
export function Navigate(props) {
|
|
105
100
|
const navigate = useNavigate();
|
|
106
101
|
const location = useLocation();
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isServer, createComponent as createComponent$1,
|
|
2
|
-
import { createSignal, onCleanup, runWithOwner, createMemo,
|
|
1
|
+
import { isServer, delegateEvents, createComponent as createComponent$1, spread, effect, setAttribute, classList, template } from 'solid-js/web';
|
|
2
|
+
import { createSignal, onCleanup, getOwner, runWithOwner, createMemo, createContext, useContext, untrack, createRenderEffect, createComponent, on, startTransition, resetErrorBoundaries, children, createRoot, Show, mergeProps, splitProps } from 'solid-js';
|
|
3
3
|
|
|
4
4
|
function bindEvent(target, type, handler) {
|
|
5
5
|
target.addEventListener(type, handler);
|
|
@@ -307,10 +307,9 @@ const useSearchParams = () => {
|
|
|
307
307
|
|
|
308
308
|
const setSearchParams = (params, options) => {
|
|
309
309
|
const searchString = untrack(() => mergeSearchString(location.search, params));
|
|
310
|
-
navigate(searchString, {
|
|
310
|
+
navigate(location.pathname + searchString, {
|
|
311
311
|
scroll: false,
|
|
312
|
-
...options
|
|
313
|
-
resolve: true
|
|
312
|
+
...options
|
|
314
313
|
});
|
|
315
314
|
};
|
|
316
315
|
|
|
@@ -485,7 +484,18 @@ function createRouterContext(integration, base = "", data, out) {
|
|
|
485
484
|
});
|
|
486
485
|
}
|
|
487
486
|
|
|
488
|
-
const [isRouting,
|
|
487
|
+
const [isRouting, setIsRouting] = createSignal(false);
|
|
488
|
+
|
|
489
|
+
const start = async callback => {
|
|
490
|
+
setIsRouting(true);
|
|
491
|
+
|
|
492
|
+
try {
|
|
493
|
+
await startTransition(callback);
|
|
494
|
+
} finally {
|
|
495
|
+
setIsRouting(false);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
|
|
489
499
|
const [reference, setReference] = createSignal(source().value);
|
|
490
500
|
const [state, setState] = createSignal(source().state);
|
|
491
501
|
const location = createLocation(reference, state);
|
|
@@ -624,21 +634,15 @@ function createRouterContext(integration, base = "", data, out) {
|
|
|
624
634
|
});
|
|
625
635
|
|
|
626
636
|
if (!isServer) {
|
|
627
|
-
function isSvg(el) {
|
|
628
|
-
return el.namespaceURI === "http://www.w3.org/2000/svg";
|
|
629
|
-
}
|
|
630
|
-
|
|
631
637
|
function handleAnchorClick(evt) {
|
|
632
638
|
if (evt.defaultPrevented || evt.button !== 0 || evt.metaKey || evt.altKey || evt.ctrlKey || evt.shiftKey) return;
|
|
633
639
|
const a = evt.composedPath().find(el => el instanceof Node && el.nodeName.toUpperCase() === "A");
|
|
634
|
-
if (!a) return;
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
const target = svg ? a.target.baseVal : a.target;
|
|
638
|
-
if (target || !href && !a.hasAttribute("state")) return;
|
|
640
|
+
if (!a || !a.hasAttribute("link")) return;
|
|
641
|
+
const href = a.href;
|
|
642
|
+
if (a.target || !href && !a.hasAttribute("state")) return;
|
|
639
643
|
const rel = (a.getAttribute("rel") || "").split(/\s+/);
|
|
640
644
|
if (a.hasAttribute("download") || rel && rel.includes("external")) return;
|
|
641
|
-
const url =
|
|
645
|
+
const url = new URL(href);
|
|
642
646
|
const pathname = urlDecode(url.pathname);
|
|
643
647
|
if (url.origin !== window.location.origin || basePath && pathname && !pathname.toLowerCase().startsWith(basePath.toLowerCase())) return;
|
|
644
648
|
const to = parsePath(pathname + urlDecode(url.search, true) + urlDecode(url.hash));
|
|
@@ -650,8 +654,10 @@ function createRouterContext(integration, base = "", data, out) {
|
|
|
650
654
|
scroll: !a.hasAttribute("noscroll"),
|
|
651
655
|
state: state && JSON.parse(state)
|
|
652
656
|
});
|
|
653
|
-
}
|
|
657
|
+
} // ensure delegated events run first
|
|
654
658
|
|
|
659
|
+
|
|
660
|
+
delegateEvents(["click"]);
|
|
655
661
|
document.addEventListener("click", handleAnchorClick);
|
|
656
662
|
onCleanup(() => document.removeEventListener("click", handleAnchorClick));
|
|
657
663
|
}
|
|
@@ -717,7 +723,7 @@ function createRouteContext(router, parent, child, match) {
|
|
|
717
723
|
return route;
|
|
718
724
|
}
|
|
719
725
|
|
|
720
|
-
const _tmpl$ = /*#__PURE__*/template(`<a></a>`, 2);
|
|
726
|
+
const _tmpl$ = /*#__PURE__*/template(`<a link></a>`, 2);
|
|
721
727
|
const Router = props => {
|
|
722
728
|
const {
|
|
723
729
|
source,
|
|
@@ -841,80 +847,52 @@ const Outlet = () => {
|
|
|
841
847
|
})
|
|
842
848
|
});
|
|
843
849
|
};
|
|
844
|
-
|
|
845
|
-
function LinkBase(props) {
|
|
846
|
-
const [, rest] = splitProps(props, ["children", "to", "href", "state"]);
|
|
847
|
-
const href = useHref(() => props.to);
|
|
848
|
-
return (() => {
|
|
849
|
-
const _el$ = _tmpl$.cloneNode(true);
|
|
850
|
-
|
|
851
|
-
spread(_el$, rest, false, true);
|
|
852
|
-
|
|
853
|
-
insert(_el$, () => props.children);
|
|
854
|
-
|
|
855
|
-
effect(_p$ => {
|
|
856
|
-
const _v$ = href() || props.href,
|
|
857
|
-
_v$2 = JSON.stringify(props.state);
|
|
858
|
-
|
|
859
|
-
_v$ !== _p$._v$ && setAttribute(_el$, "href", _p$._v$ = _v$);
|
|
860
|
-
_v$2 !== _p$._v$2 && setAttribute(_el$, "state", _p$._v$2 = _v$2);
|
|
861
|
-
return _p$;
|
|
862
|
-
}, {
|
|
863
|
-
_v$: undefined,
|
|
864
|
-
_v$2: undefined
|
|
865
|
-
});
|
|
866
|
-
|
|
867
|
-
return _el$;
|
|
868
|
-
})();
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
function Link(props) {
|
|
872
|
-
const to = useResolvedPath(() => props.href);
|
|
873
|
-
return createComponent$1(LinkBase, mergeProps$1(props, {
|
|
874
|
-
get to() {
|
|
875
|
-
return to();
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
}));
|
|
879
|
-
}
|
|
880
|
-
function NavLink(props) {
|
|
850
|
+
function A(props) {
|
|
881
851
|
props = mergeProps({
|
|
882
852
|
inactiveClass: "inactive",
|
|
883
853
|
activeClass: "active"
|
|
884
854
|
}, props);
|
|
885
|
-
const [, rest] = splitProps(props, ["activeClass", "inactiveClass", "end"]);
|
|
886
|
-
const location = useLocation();
|
|
855
|
+
const [, rest] = splitProps(props, ["href", "state", "activeClass", "inactiveClass", "end"]);
|
|
887
856
|
const to = useResolvedPath(() => props.href);
|
|
857
|
+
const href = useHref(to);
|
|
858
|
+
const location = useLocation();
|
|
888
859
|
const isActive = createMemo(() => {
|
|
889
860
|
const to_ = to();
|
|
890
|
-
|
|
891
|
-
if (to_ === undefined) {
|
|
892
|
-
return false;
|
|
893
|
-
}
|
|
894
|
-
|
|
861
|
+
if (to_ === undefined) return false;
|
|
895
862
|
const path = to_.split(/[?#]/, 1)[0].toLowerCase();
|
|
896
863
|
const loc = location.pathname.toLowerCase();
|
|
897
864
|
return props.end ? path === loc : loc.startsWith(path);
|
|
898
865
|
});
|
|
899
|
-
return
|
|
900
|
-
|
|
901
|
-
return to();
|
|
902
|
-
},
|
|
866
|
+
return (() => {
|
|
867
|
+
const _el$ = _tmpl$.cloneNode(true);
|
|
903
868
|
|
|
904
|
-
|
|
905
|
-
|
|
869
|
+
spread(_el$, rest, false, false);
|
|
870
|
+
|
|
871
|
+
effect(_p$ => {
|
|
872
|
+
const _v$ = href() || props.href,
|
|
873
|
+
_v$2 = JSON.stringify(props.state),
|
|
874
|
+
_v$3 = {
|
|
906
875
|
[props.inactiveClass]: !isActive(),
|
|
907
876
|
[props.activeClass]: isActive(),
|
|
908
877
|
...rest.classList
|
|
909
|
-
}
|
|
910
|
-
|
|
878
|
+
},
|
|
879
|
+
_v$4 = isActive() ? "page" : undefined;
|
|
911
880
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
881
|
+
_v$ !== _p$._v$ && setAttribute(_el$, "href", _p$._v$ = _v$);
|
|
882
|
+
_v$2 !== _p$._v$2 && setAttribute(_el$, "state", _p$._v$2 = _v$2);
|
|
883
|
+
_p$._v$3 = classList(_el$, _v$3, _p$._v$3);
|
|
884
|
+
_v$4 !== _p$._v$4 && setAttribute(_el$, "aria-current", _p$._v$4 = _v$4);
|
|
885
|
+
return _p$;
|
|
886
|
+
}, {
|
|
887
|
+
_v$: undefined,
|
|
888
|
+
_v$2: undefined,
|
|
889
|
+
_v$3: undefined,
|
|
890
|
+
_v$4: undefined
|
|
891
|
+
});
|
|
915
892
|
|
|
916
|
-
|
|
917
|
-
}
|
|
893
|
+
return _el$;
|
|
894
|
+
})();
|
|
895
|
+
} // deprecated alias exports
|
|
918
896
|
function Navigate(props) {
|
|
919
897
|
const navigate = useNavigate();
|
|
920
898
|
const location = useLocation();
|
|
@@ -933,4 +911,4 @@ function Navigate(props) {
|
|
|
933
911
|
return null;
|
|
934
912
|
}
|
|
935
913
|
|
|
936
|
-
export { Link, NavLink, Navigate, Outlet, Route, Router, Routes, mergeSearchString as _mergeSearchString, createIntegration, hashIntegration, normalizeIntegration, pathIntegration, staticIntegration, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, useResolvedPath, useRouteData, useRoutes, useSearchParams };
|
|
914
|
+
export { A, A as Link, A as NavLink, Navigate, Outlet, Route, Router, Routes, mergeSearchString as _mergeSearchString, createIntegration, hashIntegration, normalizeIntegration, pathIntegration, staticIntegration, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, useResolvedPath, useRouteData, useRoutes, useSearchParams };
|
package/dist/routing.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare const useMatch: (path: () => string) => Accessor<import("./types"
|
|
|
13
13
|
export declare const useParams: <T extends Params>() => T;
|
|
14
14
|
declare type MaybeReturnType<T> = T extends (...args: any) => infer R ? R : T;
|
|
15
15
|
export declare const useRouteData: <T>() => MaybeReturnType<T>;
|
|
16
|
-
export declare const useSearchParams: <T extends Params>() => [T, (params: SetParams, options?: Partial<NavigateOptions
|
|
16
|
+
export declare const useSearchParams: <T extends Params>() => [T, (params: SetParams, options?: Partial<NavigateOptions>) => void];
|
|
17
17
|
export declare function createRoutes(routeDef: RouteDefinition, base?: string, fallback?: Component): Route[];
|
|
18
18
|
export declare function createBranch(routes: Route[], index?: number): Branch;
|
|
19
19
|
export declare function createBranches(routeDef: RouteDefinition | RouteDefinition[], base?: string, fallback?: Component, stack?: Route[], branches?: Branch[]): Branch[];
|
package/dist/routing.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createComponent, createContext, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack, useContext,
|
|
2
|
-
import { isServer } from "solid-js/web";
|
|
1
|
+
import { createComponent, createContext, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack, useContext, startTransition, resetErrorBoundaries } from "solid-js";
|
|
2
|
+
import { isServer, delegateEvents } from "solid-js/web";
|
|
3
3
|
import { normalizeIntegration } from "./integration";
|
|
4
4
|
import { createMemoObject, extractSearchParams, invariant, resolvePath, createMatcher, joinPaths, scoreRoute, mergeSearchString, urlDecode, expandOptionals } from "./utils";
|
|
5
5
|
const MAX_REDIRECTS = 100;
|
|
@@ -34,7 +34,7 @@ export const useSearchParams = () => {
|
|
|
34
34
|
const navigate = useNavigate();
|
|
35
35
|
const setSearchParams = (params, options) => {
|
|
36
36
|
const searchString = untrack(() => mergeSearchString(location.search, params));
|
|
37
|
-
navigate(searchString, { scroll: false, ...options
|
|
37
|
+
navigate(location.pathname + searchString, { scroll: false, ...options });
|
|
38
38
|
};
|
|
39
39
|
return [location.query, setSearchParams];
|
|
40
40
|
};
|
|
@@ -179,7 +179,16 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
179
179
|
else if (basePath && !source().value) {
|
|
180
180
|
setSource({ value: basePath, replace: true, scroll: false });
|
|
181
181
|
}
|
|
182
|
-
const [isRouting,
|
|
182
|
+
const [isRouting, setIsRouting] = createSignal(false);
|
|
183
|
+
const start = async (callback) => {
|
|
184
|
+
setIsRouting(true);
|
|
185
|
+
try {
|
|
186
|
+
await startTransition(callback);
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
setIsRouting(false);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
183
192
|
const [reference, setReference] = createSignal(source().value);
|
|
184
193
|
const [state, setState] = createSignal(source().state);
|
|
185
194
|
const location = createLocation(reference, state);
|
|
@@ -292,9 +301,6 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
292
301
|
});
|
|
293
302
|
});
|
|
294
303
|
if (!isServer) {
|
|
295
|
-
function isSvg(el) {
|
|
296
|
-
return el.namespaceURI === "http://www.w3.org/2000/svg";
|
|
297
|
-
}
|
|
298
304
|
function handleAnchorClick(evt) {
|
|
299
305
|
if (evt.defaultPrevented ||
|
|
300
306
|
evt.button !== 0 ||
|
|
@@ -306,17 +312,15 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
306
312
|
const a = evt
|
|
307
313
|
.composedPath()
|
|
308
314
|
.find(el => el instanceof Node && el.nodeName.toUpperCase() === "A");
|
|
309
|
-
if (!a)
|
|
315
|
+
if (!a || !a.hasAttribute("link"))
|
|
310
316
|
return;
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
const target = svg ? a.target.baseVal : a.target;
|
|
314
|
-
if (target || (!href && !a.hasAttribute("state")))
|
|
317
|
+
const href = a.href;
|
|
318
|
+
if (a.target || (!href && !a.hasAttribute("state")))
|
|
315
319
|
return;
|
|
316
320
|
const rel = (a.getAttribute("rel") || "").split(/\s+/);
|
|
317
321
|
if (a.hasAttribute("download") || (rel && rel.includes("external")))
|
|
318
322
|
return;
|
|
319
|
-
const url =
|
|
323
|
+
const url = new URL(href);
|
|
320
324
|
const pathname = urlDecode(url.pathname);
|
|
321
325
|
if (url.origin !== window.location.origin ||
|
|
322
326
|
(basePath && pathname && !pathname.toLowerCase().startsWith(basePath.toLowerCase())))
|
|
@@ -331,6 +335,8 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
331
335
|
state: state && JSON.parse(state)
|
|
332
336
|
});
|
|
333
337
|
}
|
|
338
|
+
// ensure delegated events run first
|
|
339
|
+
delegateEvents(["click"]);
|
|
334
340
|
document.addEventListener("click", handleAnchorClick);
|
|
335
341
|
onCleanup(() => document.removeEventListener("click", handleAnchorClick));
|
|
336
342
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -33,13 +33,13 @@ export interface RouterIntegration {
|
|
|
33
33
|
signal: LocationChangeSignal;
|
|
34
34
|
utils?: Partial<RouterUtils>;
|
|
35
35
|
}
|
|
36
|
-
export interface RouteDataFuncArgs {
|
|
37
|
-
data:
|
|
36
|
+
export interface RouteDataFuncArgs<T = unknown> {
|
|
37
|
+
data: T extends RouteDataFunc ? ReturnType<T> : T;
|
|
38
38
|
params: Params;
|
|
39
39
|
location: Location;
|
|
40
40
|
navigate: Navigator;
|
|
41
41
|
}
|
|
42
|
-
export declare type RouteDataFunc<T = unknown> = (args: RouteDataFuncArgs) =>
|
|
42
|
+
export declare type RouteDataFunc<T = unknown, R = unknown> = (args: RouteDataFuncArgs<T>) => R;
|
|
43
43
|
export declare type RouteDefinition = {
|
|
44
44
|
path: string | string[];
|
|
45
45
|
data?: RouteDataFunc;
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"Ryan Turnquist"
|
|
7
7
|
],
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.5.0",
|
|
10
10
|
"homepage": "https://github.com/solidjs/solid-router#readme",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
@@ -38,23 +38,24 @@
|
|
|
38
38
|
"pretty": "prettier --write \"{src,test}/**/*.{ts,tsx}\""
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@babel/core": "^7.
|
|
42
|
-
"@babel/preset-typescript": "^7.
|
|
43
|
-
"@rollup/plugin-babel": "5.3.
|
|
44
|
-
"@rollup/plugin-node-resolve": "13.0
|
|
45
|
-
"@types/jest": "^
|
|
46
|
-
"@types/node": "^
|
|
47
|
-
"babel-preset-solid": "^1.
|
|
48
|
-
"jest": "^
|
|
49
|
-
"
|
|
50
|
-
"
|
|
41
|
+
"@babel/core": "^7.18.13",
|
|
42
|
+
"@babel/preset-typescript": "^7.18.6",
|
|
43
|
+
"@rollup/plugin-babel": "5.3.1",
|
|
44
|
+
"@rollup/plugin-node-resolve": "13.3.0",
|
|
45
|
+
"@types/jest": "^29.0.0",
|
|
46
|
+
"@types/node": "^18.7.14",
|
|
47
|
+
"babel-preset-solid": "^1.5.3",
|
|
48
|
+
"jest": "^29.0.1",
|
|
49
|
+
"jest-environment-jsdom": "^29.1.2",
|
|
50
|
+
"prettier": "^2.7.1",
|
|
51
|
+
"rollup": "^2.79.0",
|
|
51
52
|
"rollup-plugin-terser": "^7.0.2",
|
|
52
53
|
"solid-jest": "^0.2.0",
|
|
53
|
-
"solid-js": "^1.
|
|
54
|
-
"typescript": "^4.
|
|
54
|
+
"solid-js": "^1.5.3",
|
|
55
|
+
"typescript": "^4.8.2"
|
|
55
56
|
},
|
|
56
57
|
"peerDependencies": {
|
|
57
|
-
"solid-js": "^1.3
|
|
58
|
+
"solid-js": "^1.5.3"
|
|
58
59
|
},
|
|
59
60
|
"jest": {
|
|
60
61
|
"preset": "solid-jest/preset/browser"
|