@solidjs/router
Advanced tools
Comparing version 0.4.3 to 0.5.0
@@ -9,2 +9,3 @@ import type { Component, JSX } from "solid-js"; | ||
replace?: boolean; | ||
link?: boolean; | ||
} | ||
@@ -31,3 +32,3 @@ } | ||
export declare const Routes: (props: RoutesProps) => JSX.Element; | ||
export declare const useRoutes: (routes: RouteDefinition | RouteDefinition[], base?: string | undefined) => () => JSX.Element; | ||
export declare const useRoutes: (routes: RouteDefinition | RouteDefinition[], base?: string) => () => JSX.Element; | ||
export declare type RouteProps = { | ||
@@ -47,3 +48,3 @@ path: string | string[]; | ||
export declare const Outlet: () => JSX.Element; | ||
export interface LinkProps extends Omit<JSX.AnchorHTMLAttributes<HTMLAnchorElement>, "state"> { | ||
export interface AnchorProps extends Omit<JSX.AnchorHTMLAttributes<HTMLAnchorElement>, "state"> { | ||
href: string; | ||
@@ -53,5 +54,2 @@ replace?: boolean; | ||
state?: unknown; | ||
} | ||
export declare function Link(props: LinkProps): JSX.Element; | ||
export interface NavLinkProps extends LinkProps { | ||
inactiveClass?: string; | ||
@@ -61,3 +59,4 @@ activeClass?: string; | ||
} | ||
export declare function NavLink(props: NavLinkProps): JSX.Element; | ||
export declare function A(props: AnchorProps): JSX.Element; | ||
export { A as Link, A as NavLink, AnchorProps as LinkProps, AnchorProps as NavLinkProps }; | ||
export interface NavigateProps { | ||
@@ -64,0 +63,0 @@ href: ((args: { |
@@ -57,3 +57,3 @@ /*@refresh skip*/ | ||
return (<Show when={routeStates() && root}> | ||
{route => <RouteContextObj.Provider value={route}>{route.outlet()}</RouteContextObj.Provider>} | ||
{((route) => (<RouteContextObj.Provider value={route}>{route.outlet()}</RouteContextObj.Provider>))} | ||
</Show>); | ||
@@ -75,26 +75,15 @@ }; | ||
return (<Show when={route.child}> | ||
{child => <RouteContextObj.Provider value={child}>{child.outlet()}</RouteContextObj.Provider>} | ||
{((child) => (<RouteContextObj.Provider value={child}>{child.outlet()}</RouteContextObj.Provider>))} | ||
</Show>); | ||
}; | ||
function LinkBase(props) { | ||
const [, rest] = splitProps(props, ["children", "to", "href", "state"]); | ||
const href = useHref(() => props.to); | ||
return (<a {...rest} href={href() || props.href} state={JSON.stringify(props.state)}> | ||
{props.children} | ||
</a>); | ||
} | ||
export function Link(props) { | ||
export function A(props) { | ||
props = mergeProps({ inactiveClass: "inactive", activeClass: "active" }, props); | ||
const [, rest] = splitProps(props, ["href", "state", "activeClass", "inactiveClass", "end"]); | ||
const to = useResolvedPath(() => props.href); | ||
return <LinkBase {...props} to={to()}/>; | ||
} | ||
export function NavLink(props) { | ||
props = mergeProps({ inactiveClass: "inactive", activeClass: "active" }, props); | ||
const [, rest] = splitProps(props, ["activeClass", "inactiveClass", "end"]); | ||
const href = useHref(to); | ||
const location = useLocation(); | ||
const to = useResolvedPath(() => props.href); | ||
const isActive = createMemo(() => { | ||
const to_ = to(); | ||
if (to_ === undefined) { | ||
if (to_ === undefined) | ||
return false; | ||
} | ||
const path = to_.split(/[?#]/, 1)[0].toLowerCase(); | ||
@@ -104,4 +93,10 @@ const loc = location.pathname.toLowerCase(); | ||
}); | ||
return (<LinkBase {...rest} to={to()} classList={{ [props.inactiveClass]: !isActive(), [props.activeClass]: isActive(), ...rest.classList }} aria-current={isActive() ? "page" : undefined}/>); | ||
return (<a link {...rest} href={href() || props.href} state={JSON.stringify(props.state)} classList={{ | ||
[props.inactiveClass]: !isActive(), | ||
[props.activeClass]: isActive(), | ||
...rest.classList | ||
}} aria-current={isActive() ? "page" : undefined}/>); | ||
} | ||
// deprecated alias exports | ||
export { A as Link, A as NavLink }; | ||
export function Navigate(props) { | ||
@@ -108,0 +103,0 @@ const navigate = useNavigate(); |
@@ -1,3 +0,3 @@ | ||
import { isServer, delegateEvents, createComponent as createComponent$1, mergeProps as mergeProps$1, spread, insert, effect, setAttribute, template } from 'solid-js/web'; | ||
import { createSignal, onCleanup, runWithOwner, createMemo, getOwner, createContext, useContext, untrack, useTransition, on, resetErrorBoundaries, createRenderEffect, createComponent, children, createRoot, Show, mergeProps, splitProps } from 'solid-js'; | ||
import { isServer, delegateEvents, createComponent as createComponent$1, spread, effect, setAttribute, classList, template } from 'solid-js/web'; | ||
import { createSignal, onCleanup, getOwner, runWithOwner, createMemo, createContext, useContext, untrack, createRenderEffect, createComponent, on, startTransition, resetErrorBoundaries, children, createRoot, Show, mergeProps, splitProps } from 'solid-js'; | ||
@@ -310,6 +310,5 @@ function bindEvent(target, type, handler) { | ||
const searchString = untrack(() => mergeSearchString(location.search, params)); | ||
navigate(searchString, { | ||
navigate(location.pathname + searchString, { | ||
scroll: false, | ||
...options, | ||
resolve: true | ||
...options | ||
}); | ||
@@ -489,3 +488,14 @@ }; | ||
const [isRouting, start] = useTransition(); | ||
const [isRouting, setIsRouting] = createSignal(false); | ||
const start = async callback => { | ||
setIsRouting(true); | ||
try { | ||
await startTransition(callback); | ||
} finally { | ||
setIsRouting(false); | ||
} | ||
}; | ||
const [reference, setReference] = createSignal(source().value); | ||
@@ -629,17 +639,11 @@ const [state, setState] = createSignal(source().state); | ||
if (!isServer) { | ||
function isSvg(el) { | ||
return el.namespaceURI === "http://www.w3.org/2000/svg"; | ||
} | ||
function handleAnchorClick(evt) { | ||
if (evt.defaultPrevented || evt.button !== 0 || evt.metaKey || evt.altKey || evt.ctrlKey || evt.shiftKey) return; | ||
const a = evt.composedPath().find(el => el instanceof Node && el.nodeName.toUpperCase() === "A"); | ||
if (!a) return; | ||
const svg = isSvg(a); | ||
const href = svg ? a.href.baseVal : a.href; | ||
const target = svg ? a.target.baseVal : a.target; | ||
if (target || !href && !a.hasAttribute("state")) return; | ||
if (!a || !a.hasAttribute("link")) return; | ||
const href = a.href; | ||
if (a.target || !href && !a.hasAttribute("state")) return; | ||
const rel = (a.getAttribute("rel") || "").split(/\s+/); | ||
if (a.hasAttribute("download") || rel && rel.includes("external")) return; | ||
const url = svg ? new URL(href, document.baseURI) : new URL(href); | ||
const url = new URL(href); | ||
const pathname = urlDecode(url.pathname); | ||
@@ -725,3 +729,3 @@ if (url.origin !== window.location.origin || basePath && pathname && !pathname.toLowerCase().startsWith(basePath.toLowerCase())) return; | ||
const _tmpl$ = /*#__PURE__*/template(`<a></a>`, 2); | ||
const _tmpl$ = /*#__PURE__*/template(`<a link></a>`, 2); | ||
const Router = props => { | ||
@@ -850,39 +854,3 @@ const { | ||
}; | ||
function LinkBase(props) { | ||
const [, rest] = splitProps(props, ["children", "to", "href", "state"]); | ||
const href = useHref(() => props.to); | ||
return (() => { | ||
const _el$ = _tmpl$.cloneNode(true); | ||
spread(_el$, rest, false, true); | ||
insert(_el$, () => props.children); | ||
effect(_p$ => { | ||
const _v$ = href() || props.href, | ||
_v$2 = JSON.stringify(props.state); | ||
_v$ !== _p$._v$ && setAttribute(_el$, "href", _p$._v$ = _v$); | ||
_v$2 !== _p$._v$2 && setAttribute(_el$, "state", _p$._v$2 = _v$2); | ||
return _p$; | ||
}, { | ||
_v$: undefined, | ||
_v$2: undefined | ||
}); | ||
return _el$; | ||
})(); | ||
} | ||
function Link(props) { | ||
const to = useResolvedPath(() => props.href); | ||
return createComponent$1(LinkBase, mergeProps$1(props, { | ||
get to() { | ||
return to(); | ||
} | ||
})); | ||
} | ||
function NavLink(props) { | ||
function A(props) { | ||
props = mergeProps({ | ||
@@ -892,12 +860,9 @@ inactiveClass: "inactive", | ||
}, props); | ||
const [, rest] = splitProps(props, ["activeClass", "inactiveClass", "end"]); | ||
const [, rest] = splitProps(props, ["href", "state", "activeClass", "inactiveClass", "end"]); | ||
const to = useResolvedPath(() => props.href); | ||
const href = useHref(to); | ||
const location = useLocation(); | ||
const to = useResolvedPath(() => props.href); | ||
const isActive = createMemo(() => { | ||
const to_ = to(); | ||
if (to_ === undefined) { | ||
return false; | ||
} | ||
if (to_ === undefined) return false; | ||
const path = to_.split(/[?#]/, 1)[0].toLowerCase(); | ||
@@ -907,21 +872,32 @@ const loc = location.pathname.toLowerCase(); | ||
}); | ||
return createComponent$1(LinkBase, mergeProps$1(rest, { | ||
get to() { | ||
return to(); | ||
}, | ||
return (() => { | ||
const _el$ = _tmpl$.cloneNode(true); | ||
get classList() { | ||
return { | ||
spread(_el$, rest, false, false); | ||
effect(_p$ => { | ||
const _v$ = href() || props.href, | ||
_v$2 = JSON.stringify(props.state), | ||
_v$3 = { | ||
[props.inactiveClass]: !isActive(), | ||
[props.activeClass]: isActive(), | ||
...rest.classList | ||
}; | ||
}, | ||
}, | ||
_v$4 = isActive() ? "page" : undefined; | ||
get ["aria-current"]() { | ||
return isActive() ? "page" : undefined; | ||
} | ||
_v$ !== _p$._v$ && setAttribute(_el$, "href", _p$._v$ = _v$); | ||
_v$2 !== _p$._v$2 && setAttribute(_el$, "state", _p$._v$2 = _v$2); | ||
_p$._v$3 = classList(_el$, _v$3, _p$._v$3); | ||
_v$4 !== _p$._v$4 && setAttribute(_el$, "aria-current", _p$._v$4 = _v$4); | ||
return _p$; | ||
}, { | ||
_v$: undefined, | ||
_v$2: undefined, | ||
_v$3: undefined, | ||
_v$4: undefined | ||
}); | ||
})); | ||
} | ||
return _el$; | ||
})(); | ||
} // deprecated alias exports | ||
function Navigate(props) { | ||
@@ -945,2 +921,2 @@ const navigate = useNavigate(); | ||
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 }; | ||
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 }; |
@@ -16,3 +16,3 @@ import type { Component, Accessor } from "solid-js"; | ||
export declare const useRouteData: <T>() => MaybeReturnType<T>; | ||
export declare const useSearchParams: <T extends Params>() => [T, (params: SetParams, options?: Partial<NavigateOptions<unknown>> | undefined) => void]; | ||
export declare const useSearchParams: <T extends Params>() => [T, (params: SetParams, options?: Partial<NavigateOptions>) => void]; | ||
export declare function createRoutes(routeDef: RouteDefinition, base?: string, fallback?: Component): Route[]; | ||
@@ -19,0 +19,0 @@ export declare function createBranch(routes: Route[], index?: number): Branch; |
@@ -1,2 +0,2 @@ | ||
import { createComponent, createContext, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack, useContext, useTransition, resetErrorBoundaries } from "solid-js"; | ||
import { createComponent, createContext, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack, useContext, startTransition, resetErrorBoundaries } from "solid-js"; | ||
import { isServer, delegateEvents } from "solid-js/web"; | ||
@@ -37,3 +37,3 @@ import { normalizeIntegration } from "./integration"; | ||
const searchString = untrack(() => mergeSearchString(location.search, params)); | ||
navigate(searchString, { scroll: false, ...options, resolve: true }); | ||
navigate(location.pathname + searchString, { scroll: false, ...options }); | ||
}; | ||
@@ -183,3 +183,12 @@ return [location.query, setSearchParams]; | ||
} | ||
const [isRouting, start] = useTransition(); | ||
const [isRouting, setIsRouting] = createSignal(false); | ||
const start = async (callback) => { | ||
setIsRouting(true); | ||
try { | ||
await startTransition(callback); | ||
} | ||
finally { | ||
setIsRouting(false); | ||
} | ||
}; | ||
const [reference, setReference] = createSignal(source().value); | ||
@@ -297,5 +306,2 @@ const [state, setState] = createSignal(source().state); | ||
if (!isServer) { | ||
function isSvg(el) { | ||
return el.namespaceURI === "http://www.w3.org/2000/svg"; | ||
} | ||
function handleAnchorClick(evt) { | ||
@@ -312,8 +318,6 @@ if (evt.defaultPrevented || | ||
.find(el => el instanceof Node && el.nodeName.toUpperCase() === "A"); | ||
if (!a) | ||
if (!a || !a.hasAttribute("link")) | ||
return; | ||
const svg = isSvg(a); | ||
const href = svg ? a.href.baseVal : a.href; | ||
const target = svg ? a.target.baseVal : a.target; | ||
if (target || (!href && !a.hasAttribute("state"))) | ||
const href = a.href; | ||
if (a.target || (!href && !a.hasAttribute("state"))) | ||
return; | ||
@@ -323,3 +327,3 @@ const rel = (a.getAttribute("rel") || "").split(/\s+/); | ||
return; | ||
const url = svg ? new URL(href, document.baseURI) : new URL(href); | ||
const url = new URL(href); | ||
const pathname = urlDecode(url.pathname); | ||
@@ -326,0 +330,0 @@ if (url.origin !== window.location.origin || |
@@ -9,3 +9,3 @@ { | ||
"license": "MIT", | ||
"version": "0.4.3", | ||
"version": "0.5.0", | ||
"homepage": "https://github.com/solidjs/solid-router#readme", | ||
@@ -42,19 +42,20 @@ "repository": { | ||
"devDependencies": { | ||
"@babel/core": "^7.15.8", | ||
"@babel/preset-typescript": "^7.15.0", | ||
"@rollup/plugin-babel": "5.3.0", | ||
"@rollup/plugin-node-resolve": "13.0.5", | ||
"@types/jest": "^27.0.2", | ||
"@types/node": "^16.10.3", | ||
"babel-preset-solid": "^1.4.4", | ||
"jest": "^27.2.5", | ||
"prettier": "^2.5.1", | ||
"rollup": "^2.52.1", | ||
"@babel/core": "^7.18.13", | ||
"@babel/preset-typescript": "^7.18.6", | ||
"@rollup/plugin-babel": "5.3.1", | ||
"@rollup/plugin-node-resolve": "13.3.0", | ||
"@types/jest": "^29.0.0", | ||
"@types/node": "^18.7.14", | ||
"babel-preset-solid": "^1.5.3", | ||
"jest": "^29.0.1", | ||
"jest-environment-jsdom": "^29.1.2", | ||
"prettier": "^2.7.1", | ||
"rollup": "^2.79.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"solid-jest": "^0.2.0", | ||
"solid-js": "^1.4.4", | ||
"typescript": "^4.5.4" | ||
"solid-js": "^1.5.3", | ||
"typescript": "^4.8.2" | ||
}, | ||
"peerDependencies": { | ||
"solid-js": "^1.3.5" | ||
"solid-js": "^1.5.3" | ||
}, | ||
@@ -61,0 +62,0 @@ "jest": { |
@@ -101,3 +101,3 @@ <p> | ||
This way, the `Users` and `Home` components will only be loaded if you're navigating to `/users` or `/home`, respectively. | ||
This way, the `Users` and `Home` components will only be loaded if you're navigating to `/users` or `/`, respectively. | ||
@@ -124,7 +124,7 @@ ```jsx | ||
Use the `Link` component to create an anchor tag that takes you to a route: | ||
Use the `A` component to create an anchor tag that takes you to a route: | ||
```jsx | ||
import { lazy } from "solid-js"; | ||
import { Routes, Route, Link } from "@solidjs/router" | ||
import { Routes, Route, A } from "@solidjs/router" | ||
const Users = lazy(() => import("./pages/Users")); | ||
@@ -137,4 +137,4 @@ const Home = lazy(() => import("./pages/Home")); | ||
<nav> | ||
<Link href="/about">About</Link> | ||
<Link href="/">Home</Link> | ||
<A href="/about">About</A> | ||
<A href="/">Home</A> | ||
</nav> | ||
@@ -150,5 +150,4 @@ <Routes> | ||
If you use `NavLink` instead of `Link`, the anchor tag will have 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. | ||
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. | ||
Both of these components have these props: | ||
@@ -160,9 +159,3 @@ | prop | type | description | | ||
| 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.) | | ||
| state | unknown | [Push this value](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) to the history stack when navigating | | ||
`NavLink` additionally has: | ||
| prop | type | description | | ||
|----------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| state | unknown | [Push this value](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) to the history stack when navigating | | | ||
| inactiveClass | string | The class to show when the link is inactive (when the current location doesn't match the link) | | ||
@@ -172,9 +165,4 @@ | activeClass | string | The class to show when the link is active | | ||
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. | ||
### The Navigate Component | ||
Solid Router provides a `Navigate` component that works similarly to `Link` and `NavLink`, 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: | ||
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: | ||
@@ -189,5 +177,3 @@ ```jsx | ||
//Navigating to /redirect will redirect you to the result of getPath | ||
<Route path="/redirect"> | ||
<Navigate href={getPath}/> | ||
</Route> | ||
<Route path="/redirect" element={<Navigate href={getPath}/>}/> | ||
``` | ||
@@ -208,3 +194,3 @@ | ||
return <> | ||
<h1>My Site with Lots of Pages<h1/> | ||
<h1>My Site with Lots of Pages</h1> | ||
<Routes> | ||
@@ -235,3 +221,3 @@ <Route path="/users" component={Users} /> | ||
return <a href={userData.twitter}>{userData.name}</a> | ||
return <A href={userData.twitter}>{userData.name}</A> | ||
} | ||
@@ -285,5 +271,5 @@ ``` | ||
import { Route } from "@solidjs/router"; | ||
import { fetchUser } ... | ||
import { fetchUser } ... | ||
const User = lazy(() => import("/pages/users/[id].js")); | ||
const User = lazy(() => import("./pages/users/[id].js")); | ||
@@ -374,3 +360,3 @@ //Data function | ||
<Outlet/> | ||
<Link href="/">Back Home</Link> | ||
<A href="/">Back Home</A> | ||
</div> | ||
@@ -415,3 +401,3 @@ } | ||
import { render } from "solid-js/web"; | ||
import { Router, useRoutes, Link } from "@solidjs/router"; | ||
import { Router, useRoutes, A } from "@solidjs/router"; | ||
@@ -447,8 +433,8 @@ const routes = [ | ||
<h1>Awesome Site</h1> | ||
<Link class="nav" href="/"> | ||
<A class="nav" href="/"> | ||
Home | ||
</Link> | ||
<Link class="nav" href="/users"> | ||
</A> | ||
<A class="nav" href="/users"> | ||
Users | ||
</Link> | ||
</A> | ||
<Routes /> | ||
@@ -455,0 +441,0 @@ </> |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83144
15
1753
541