+21
-15
| import { useBrowserLocation, useSearch as useSearch$1 } from './use-browser-location.js'; | ||
| import { createContext, forwardRef, useEvent, isValidElement, createElement, cloneElement, useContext, useRef, useIsomorphicLayoutEffect, Fragment } from './react-deps.js'; | ||
| import { createContext, forwardRef, useEvent, isValidElement, cloneElement, createElement, useContext, useRef, useIsomorphicLayoutEffect, Fragment } from './react-deps.js'; | ||
@@ -242,5 +242,16 @@ /** | ||
| const { to, href = to, children, onClick } = props; | ||
| const { | ||
| to, | ||
| href: _href = to, | ||
| onClick: _onClick, | ||
| asChild, | ||
| children, | ||
| /* eslint-disable no-unused-vars */ | ||
| replace /* ignore nav props */, | ||
| state /* ignore nav props */, | ||
| /* eslint-enable no-unused-vars */ | ||
| ...restProps | ||
| } = props; | ||
| const handleClick = useEvent((event) => { | ||
| const onClick = useEvent((event) => { | ||
| // ignores the navigation when clicked using right mouse button or | ||
@@ -257,20 +268,15 @@ // by holding a special modifier key: ctrl, command, win, alt, shift | ||
| onClick && onClick(event); | ||
| _onClick && _onClick(event); // TODO: is it safe to use _onClick?.(event) | ||
| if (!event.defaultPrevented) { | ||
| event.preventDefault(); | ||
| navigate(to || href, props); | ||
| navigate(_href, props); | ||
| } | ||
| }); | ||
| // wraps children in `a` if needed | ||
| const extraProps = { | ||
| // handle nested routers and absolute paths | ||
| href: href[0] === "~" ? href.slice(1) : router.base + href, | ||
| onClick: handleClick, | ||
| to: null, | ||
| ref, | ||
| }; | ||
| const jsx = isValidElement(children) ? children : createElement("a", props); | ||
| // handle nested routers and absolute paths | ||
| const href = _href[0] === "~" ? _href.slice(1) : router.base + _href; | ||
| return cloneElement(jsx, extraProps); | ||
| return asChild && isValidElement(children) | ||
| ? cloneElement(children, { href, onClick }) | ||
| : createElement("a", { ...restProps, href, onClick, children, ref }); | ||
| }); | ||
@@ -277,0 +283,0 @@ |
| import { useSyncExternalStore } from './react-deps.js'; | ||
| // fortunately `hashchange` is a native event, so there is no need to | ||
| // patch `history` object (unlike `pushState/replaceState` events) | ||
| // array of callback subscribed to hash updates | ||
| const listeners = { | ||
| v: [], | ||
| }; | ||
| const onHashChange = () => listeners.v.forEach((cb) => cb()); | ||
| // we subscribe to `hashchange` only once when needed to guarantee that | ||
| // all listeners are called synchronously | ||
| const subscribeToHashUpdates = (callback) => { | ||
| addEventListener("hashchange", callback); | ||
| return () => removeEventListener("hashchange", callback); | ||
| if (listeners.v.push(callback) === 1) | ||
| addEventListener("hashchange", onHashChange); | ||
| return () => { | ||
| listeners.v = listeners.v.filter((i) => i !== callback); | ||
| if (!listeners.v.length) removeEventListener("hashchange", onHashChange); | ||
| }; | ||
| }; | ||
@@ -14,8 +26,13 @@ | ||
| const navigate = (to, { state = null } = {}) => { | ||
| history.pushState( | ||
| // calling `replaceState` allows us to set the history | ||
| // state without creating an extra entry | ||
| history.replaceState( | ||
| state, | ||
| "", | ||
| // keep the current pathname, current query string, but replace the hash | ||
| // (leading '#' and '/' are optional, see above) | ||
| location.pathname + location.search + `#/${to.replace(/^#?\/?/, "")}` | ||
| location.pathname + | ||
| location.search + | ||
| // update location hash, this will cause `hashchange` event to fire | ||
| // normalise the value before updating, so it's always preceeded with "#/" | ||
| (location.hash = `#/${to.replace(/^#?\/?/, "")}`) | ||
| ); | ||
@@ -22,0 +39,0 @@ }; |
+2
-2
| { | ||
| "name": "wouter", | ||
| "version": "3.0.0-dev.f5441c6", | ||
| "version": "3.0.0-rc.1", | ||
| "description": "Minimalist-friendly ~1.5KB router for React", | ||
@@ -40,3 +40,3 @@ "type": "module", | ||
| "typesVersions": { | ||
| "*": { | ||
| ">=4.1": { | ||
| "types/index.d.ts": [ | ||
@@ -43,0 +43,0 @@ "types/index.d.ts" |
+27
-31
@@ -8,8 +8,7 @@ // Minimum TypeScript Version: 4.1 | ||
| FunctionComponent, | ||
| PropsWithChildren, | ||
| RefAttributes, | ||
| ComponentType, | ||
| ReactNode, | ||
| ReactElement, | ||
| ReactChild, | ||
| ReactPortal, | ||
| MouseEventHandler, | ||
| } from "react"; | ||
@@ -23,24 +22,16 @@ | ||
| BaseSearchHook, | ||
| } from "./location-hook"; | ||
| import { BrowserLocationHook, BrowserSearchHook } from "./use-browser-location"; | ||
| } from "./location-hook.js"; | ||
| import { | ||
| BrowserLocationHook, | ||
| BrowserSearchHook, | ||
| } from "./use-browser-location.js"; | ||
| import { RouterObject, RouterOptions } from "./router"; | ||
| import { RouterObject, RouterOptions } from "./router.js"; | ||
| // re-export some types from these modules | ||
| export { Path, BaseLocationHook, BaseSearchHook } from "./location-hook"; | ||
| export * from "./router"; | ||
| export { Path, BaseLocationHook, BaseSearchHook } from "./location-hook.js"; | ||
| export * from "./router.js"; | ||
| import { RouteParams } from "./regexparam"; | ||
| import { RouteParams } from "./regexparam.js"; | ||
| // React <18 only: fixes incorrect `ReactNode` declaration that had `{}` in the union. | ||
| // This issue has been fixed in React 18 type declaration. | ||
| // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210 | ||
| type ReactNode = | ||
| | ReactChild | ||
| | Iterable<ReactNode> | ||
| | ReactPortal | ||
| | boolean | ||
| | null | ||
| | undefined; | ||
| /** | ||
@@ -91,3 +82,3 @@ * Route patterns and parameters | ||
| RoutePath extends Path = Path | ||
| >(props: RouteProps<T, RoutePath>): ReactElement | null; | ||
| >(props: RouteProps<T, RoutePath>): ReturnType<FunctionComponent>; | ||
@@ -103,8 +94,2 @@ /* | ||
| export type LinkProps<H extends BaseLocationHook = BrowserLocationHook> = Omit< | ||
| AnchorHTMLAttributes<HTMLAnchorElement>, | ||
| "href" | ||
| > & | ||
| NavigationalProps<H>; | ||
| export type RedirectProps<H extends BaseLocationHook = BrowserLocationHook> = | ||
@@ -116,10 +101,21 @@ NavigationalProps<H> & { | ||
| export function Redirect<H extends BaseLocationHook = BrowserLocationHook>( | ||
| props: PropsWithChildren<RedirectProps<H>>, | ||
| props: RedirectProps<H>, | ||
| context?: any | ||
| ): ReactElement<any, any> | null; | ||
| ): null; | ||
| type AsChildProps<ComponentProps, DefaultElementProps> = | ||
| | ({ asChild?: false } & DefaultElementProps) | ||
| | ({ asChild: true } & ComponentProps); | ||
| export type LinkProps<H extends BaseLocationHook = BrowserLocationHook> = | ||
| NavigationalProps<H> & | ||
| AsChildProps< | ||
| { children: ReactElement; onClick?: MouseEventHandler }, | ||
| AnchorHTMLAttributes<HTMLAnchorElement> & RefAttributes<HTMLAnchorElement> | ||
| >; | ||
| export function Link<H extends BaseLocationHook = BrowserLocationHook>( | ||
| props: PropsWithChildren<LinkProps<H>> & RefAttributes<HTMLAnchorElement>, | ||
| props: LinkProps<H>, | ||
| context?: any | ||
| ): ReactElement<any, any> | null; | ||
| ): ReturnType<FunctionComponent>; | ||
@@ -126,0 +122,0 @@ /* |
@@ -1,2 +0,2 @@ | ||
| import { BaseLocationHook, Path } from "./location-hook"; | ||
| import { BaseLocationHook, Path } from "./location-hook.js"; | ||
@@ -3,0 +3,0 @@ type Navigate<S = any> = ( |
@@ -6,3 +6,3 @@ import { | ||
| BaseSearchHook, | ||
| } from "./location-hook"; | ||
| } from "./location-hook.js"; | ||
@@ -9,0 +9,0 @@ export type Parser = (route: Path) => { pattern: RegExp; keys: string[] }; |
@@ -1,2 +0,2 @@ | ||
| import { Path, SearchString } from "./location-hook"; | ||
| import { Path, SearchString } from "./location-hook.js"; | ||
@@ -3,0 +3,0 @@ type Primitive = string | number | bigint | boolean | null | undefined | symbol; |
@@ -1,2 +0,2 @@ | ||
| import { Path } from "./location-hook"; | ||
| import { Path } from "./location-hook.js"; | ||
@@ -3,0 +3,0 @@ export function navigate<S = any>(to: Path, options?: { state: S }): void; |
27205
2.11%736
2.22%