@shuvi/router-react 0.0.1-rc.7 → 1.0.0-rc.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/esm/Link.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import * as React from 'react';
2
+ import { State, PathRecord } from '@shuvi/router';
3
+ /**
4
+ * The public API for rendering a history-aware `<a>`.
5
+ * ```ts
6
+ * // jump to `/about`
7
+ * <Link to="/about">About</Link>
8
+ * // jump with query
9
+ * <Link to="/about?sort=name">About</Link>
10
+ * // with some state
11
+ * <Link to="/about" state={{fromDashboard: true}}>About</Link>
12
+ * // props `to` could be a object
13
+ * <Link to={{
14
+ * pathname: "/about",
15
+ * search: "?sort=name",
16
+ * hash: "#the-hash",
17
+ * }}>About</Link>
18
+ * // props target '_self' | '_blank', default is '_self'
19
+ * <Link to="/about" target="_self">About</Link>
20
+ * // overrides default redirect mode by `replace`
21
+ * <Link to="/about" replace>About</Link>
22
+ * // if `onClick` function, run it first
23
+ * <Link to="/about" onClick={fn}>About</Link>
24
+ * // other props will be delivered to `<a>`
25
+ * <Link to="/about" a='a' b='b'>About</Link> => <{...rest} a>
26
+ * ```
27
+ */
28
+ export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
29
+ export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
30
+ replace?: boolean;
31
+ state?: State;
32
+ to: PathRecord;
33
+ prefetch?: boolean;
34
+ onMouseEnter?: (e: any) => void;
35
+ }
package/esm/Link.js ADDED
@@ -0,0 +1,91 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import * as React from 'react';
13
+ import * as PropTypes from 'prop-types';
14
+ import { useHref, useNavigate, useResolvedPath } from '.';
15
+ import { pathToString } from '@shuvi/router';
16
+ import { __DEV__ } from './constants';
17
+ import { useCurrentRoute } from './hooks';
18
+ function isModifiedEvent(event) {
19
+ return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
20
+ }
21
+ /**
22
+ * The public API for rendering a history-aware `<a>`.
23
+ * ```ts
24
+ * // jump to `/about`
25
+ * <Link to="/about">About</Link>
26
+ * // jump with query
27
+ * <Link to="/about?sort=name">About</Link>
28
+ * // with some state
29
+ * <Link to="/about" state={{fromDashboard: true}}>About</Link>
30
+ * // props `to` could be a object
31
+ * <Link to={{
32
+ * pathname: "/about",
33
+ * search: "?sort=name",
34
+ * hash: "#the-hash",
35
+ * }}>About</Link>
36
+ * // props target '_self' | '_blank', default is '_self'
37
+ * <Link to="/about" target="_self">About</Link>
38
+ * // overrides default redirect mode by `replace`
39
+ * <Link to="/about" replace>About</Link>
40
+ * // if `onClick` function, run it first
41
+ * <Link to="/about" onClick={fn}>About</Link>
42
+ * // other props will be delivered to `<a>`
43
+ * <Link to="/about" a='a' b='b'>About</Link> => <{...rest} a>
44
+ * ```
45
+ */
46
+ export const Link = React.forwardRef(function LinkWithRef(_a, ref) {
47
+ var { onClick, replace: replaceProp = false, state, target, to } = _a, rest = __rest(_a, ["onClick", "replace", "state", "target", "to"]);
48
+ let href = useHref(to);
49
+ let navigate = useNavigate();
50
+ const location = useCurrentRoute();
51
+ let path = useResolvedPath(to);
52
+ function handleClick(event) {
53
+ if (onClick)
54
+ onClick(event);
55
+ if (!event.defaultPrevented && // onClick prevented default
56
+ event.button === 0 && // Ignore everything but left clicks
57
+ (!target || target === '_self') && // Let browser handle "target=_blank" etc.
58
+ !isModifiedEvent(event) // Ignore clicks with modifier keys
59
+ ) {
60
+ event.preventDefault();
61
+ // If the URL hasn't changed, a regular <a> will do a replace instead of
62
+ // a push, so do the same here.
63
+ let replace = !!replaceProp ||
64
+ (location && pathToString(location)) === pathToString(path);
65
+ navigate(to, { replace, state });
66
+ }
67
+ }
68
+ return (
69
+ // @ts-ignore
70
+ React.createElement("a", Object.assign({}, rest, { href: href, onClick: handleClick, ref: ref, target: target })));
71
+ });
72
+ if (__DEV__) {
73
+ Link.displayName = 'Link';
74
+ Link.propTypes = {
75
+ onClick: PropTypes.func,
76
+ replace: PropTypes.bool,
77
+ state: PropTypes.object,
78
+ target: PropTypes.string,
79
+ prefetch: PropTypes.bool,
80
+ onMouseEnter: PropTypes.func,
81
+ // @ts-ignore proptypes's bug?
82
+ to: PropTypes.oneOfType([
83
+ PropTypes.string,
84
+ PropTypes.shape({
85
+ pathname: PropTypes.string,
86
+ search: PropTypes.string,
87
+ hash: PropTypes.string
88
+ })
89
+ ]).isRequired
90
+ };
91
+ }
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ import * as PropTypes from 'prop-types';
3
+ import { IMemoryRouterProps } from './types';
4
+ /**
5
+ * a <Router> that stores all entries in memory.
6
+ */
7
+ export declare function MemoryRouter({ basename, children, routes, initialEntries, initialIndex }: IMemoryRouterProps): React.ReactElement;
8
+ export declare namespace MemoryRouter {
9
+ var displayName: string;
10
+ var propTypes: {
11
+ children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
12
+ routes: PropTypes.Requireable<(object | null | undefined)[]>;
13
+ initialEntries: PropTypes.Requireable<(string | PropTypes.InferProps<{
14
+ pathname: PropTypes.Requireable<string>;
15
+ search: PropTypes.Requireable<string>;
16
+ hash: PropTypes.Requireable<string>;
17
+ state: PropTypes.Requireable<object>;
18
+ key: PropTypes.Requireable<string>;
19
+ }> | null | undefined)[]>;
20
+ initialIndex: PropTypes.Requireable<number>;
21
+ };
22
+ }
@@ -0,0 +1,37 @@
1
+ import * as React from 'react';
2
+ import * as PropTypes from 'prop-types';
3
+ import { createMemoryHistory, createRouter } from '@shuvi/router';
4
+ import { Router } from './Router';
5
+ import { __DEV__ } from './constants';
6
+ /**
7
+ * a <Router> that stores all entries in memory.
8
+ */
9
+ export function MemoryRouter({ basename, children, routes, initialEntries, initialIndex }) {
10
+ let routerRef = React.useRef();
11
+ if (routerRef.current == null) {
12
+ routerRef.current = createRouter({
13
+ basename,
14
+ routes: routes || [],
15
+ history: createMemoryHistory({ initialEntries, initialIndex })
16
+ }).init();
17
+ }
18
+ return React.createElement(Router, { children: children, router: routerRef.current });
19
+ }
20
+ if (__DEV__) {
21
+ MemoryRouter.displayName = 'MemoryRouter';
22
+ MemoryRouter.propTypes = {
23
+ children: PropTypes.node,
24
+ routes: PropTypes.arrayOf(PropTypes.object),
25
+ initialEntries: PropTypes.arrayOf(PropTypes.oneOfType([
26
+ PropTypes.string,
27
+ PropTypes.shape({
28
+ pathname: PropTypes.string,
29
+ search: PropTypes.string,
30
+ hash: PropTypes.string,
31
+ state: PropTypes.object,
32
+ key: PropTypes.string
33
+ })
34
+ ])),
35
+ initialIndex: PropTypes.number
36
+ };
37
+ }
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ import * as PropTypes from 'prop-types';
3
+ import { IRouterProps } from './types';
4
+ /**
5
+ * Provides location context for the rest of the app.
6
+ *
7
+ * Note: You usually won't render a <Router> directly. Instead, you'll render a
8
+ * router that is more specific to your environment such as a <BrowserRouter>
9
+ * in web browsers or a <StaticRouter> for server rendering.
10
+ */
11
+ export declare function Router({ children, static: staticProp, router }: IRouterProps): React.ReactElement;
12
+ export declare namespace Router {
13
+ var displayName: string;
14
+ var propTypes: {
15
+ children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
16
+ router: PropTypes.Requireable<object>;
17
+ static: PropTypes.Requireable<boolean>;
18
+ };
19
+ }
package/esm/Router.js ADDED
@@ -0,0 +1,46 @@
1
+ import * as React from 'react';
2
+ import { useRef, useReducer } from 'react';
3
+ import * as PropTypes from 'prop-types';
4
+ import invariant from '@shuvi/utils/lib/invariant';
5
+ import { RouterContext, RouteContext } from './contexts';
6
+ import { useInRouterContext } from './hooks';
7
+ import { __DEV__ } from './constants';
8
+ import { useIsomorphicEffect } from './utils';
9
+ /**
10
+ * Provides location context for the rest of the app.
11
+ *
12
+ * Note: You usually won't render a <Router> directly. Instead, you'll render a
13
+ * router that is more specific to your environment such as a <BrowserRouter>
14
+ * in web browsers or a <StaticRouter> for server rendering.
15
+ */
16
+ export function Router({ children = null, static: staticProp = false, router }) {
17
+ invariant(!useInRouterContext(), `You cannot render a <Router> inside another <Router>.` +
18
+ ` You never need more than one.`);
19
+ const contextVal = React.useMemo(() => {
20
+ return {
21
+ static: staticProp,
22
+ router: router
23
+ };
24
+ }, [staticProp, router]);
25
+ const unmount = useRef(false);
26
+ const forceupdate = useReducer(s => s * -1, 1)[1];
27
+ useIsomorphicEffect(() => () => (unmount.current = true), []);
28
+ useIsomorphicEffect(() => {
29
+ router.listen(() => {
30
+ if (unmount.current) {
31
+ return;
32
+ }
33
+ forceupdate();
34
+ });
35
+ }, [router]);
36
+ return (React.createElement(RouterContext.Provider, { value: contextVal },
37
+ React.createElement(RouteContext.Provider, { children: children, value: router.current })));
38
+ }
39
+ if (__DEV__) {
40
+ Router.displayName = 'Router';
41
+ Router.propTypes = {
42
+ children: PropTypes.node,
43
+ router: PropTypes.object,
44
+ static: PropTypes.bool
45
+ };
46
+ }
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ export declare function RouterView(): React.ReactElement | null;
3
+ export declare namespace RouterView {
4
+ var displayName: string;
5
+ }
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ import { joinPaths } from '@shuvi/router';
3
+ import { useCurrentRoute } from './hooks';
4
+ import { __DEV__ } from './constants';
5
+ import { MatchedRouteContext } from './contexts';
6
+ import { warningOnce, readOnly } from './utils';
7
+ const defaultElement = React.createElement(RouterView, null);
8
+ function MatchedRoute({ match, depth, parentPathname, parentParams }) {
9
+ const { route, params, pathname } = match;
10
+ const element = React.useMemo(() => route.component
11
+ ? React.createElement(route.component, route.props)
12
+ : defaultElement, [route.component, route.props, defaultElement]);
13
+ return (React.createElement(MatchedRouteContext.Provider, { children: element, value: {
14
+ depth: depth + 1,
15
+ params: readOnly(Object.assign(Object.assign({}, parentParams), params)),
16
+ pathname: joinPaths([parentPathname, pathname]),
17
+ route
18
+ } }));
19
+ }
20
+ export function RouterView() {
21
+ let { depth, pathname: parentPathname, params: parentParams } = React.useContext(MatchedRouteContext);
22
+ const { matches } = useCurrentRoute();
23
+ if (!matches.length) {
24
+ return null;
25
+ }
26
+ // Otherwise render an element.
27
+ const matched = matches[depth];
28
+ if (!matched) {
29
+ if (__DEV__) {
30
+ warningOnce(parentPathname, false, `Use <RouterView/> under path "${parentPathname}", but it has no children routes.` +
31
+ `\n\n` +
32
+ `Please remove the <RouterView/>.`);
33
+ }
34
+ return null;
35
+ }
36
+ return (React.createElement(MatchedRoute, { match: matched, depth: depth, parentPathname: parentPathname, parentParams: parentParams }));
37
+ }
38
+ if (__DEV__) {
39
+ RouterView.displayName = 'RouterView';
40
+ }
@@ -0,0 +1 @@
1
+ export declare const __DEV__: boolean;
@@ -0,0 +1 @@
1
+ export const __DEV__ = process.env.NODE_ENV !== 'production';
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import { IRoute } from '@shuvi/router';
3
+ import { IRouterContextObject, IRouteContextObject } from './types';
4
+ export declare const RouterContext: React.Context<IRouterContextObject>;
5
+ export declare const RouteContext: React.Context<IRoute<{
6
+ caseSensitive?: boolean | undefined;
7
+ children?: any[] | undefined;
8
+ component?: any;
9
+ redirect?: string | undefined;
10
+ props?: import("@shuvi/router").IRouteComponentProps | undefined;
11
+ path: string;
12
+ filepath?: string | undefined;
13
+ id?: string | undefined;
14
+ __componentSourceWithAffix__?: string | undefined;
15
+ __resolveWeak__?: (() => any) | undefined;
16
+ }>>;
17
+ export declare const MatchedRouteContext: React.Context<IRouteContextObject<{}>>;
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import { readOnly } from './utils';
3
+ import { __DEV__ } from './constants';
4
+ export const RouterContext = React.createContext(null);
5
+ if (__DEV__) {
6
+ RouterContext.displayName = 'Router';
7
+ }
8
+ export const RouteContext = React.createContext(null);
9
+ if (__DEV__) {
10
+ RouterContext.displayName = 'Route';
11
+ }
12
+ export const MatchedRouteContext = React.createContext({
13
+ depth: 0,
14
+ params: readOnly({}),
15
+ pathname: '',
16
+ route: null
17
+ });
18
+ if (__DEV__) {
19
+ MatchedRouteContext.displayName = 'MatchedRoute';
20
+ }
package/esm/hooks.d.ts ADDED
@@ -0,0 +1,57 @@
1
+ import { IParams, IPathMatch, Blocker, Path, PathRecord, IRouter, IPathPattern } from '@shuvi/router';
2
+ import { INavigateFunction, IRouteContextObject } from './types';
3
+ /**
4
+ * is just point `router.current` object
5
+ */
6
+ export declare function useCurrentRoute(): import("@shuvi/router").IRoute<{
7
+ caseSensitive?: boolean | undefined;
8
+ children?: any[] | undefined;
9
+ component?: any;
10
+ redirect?: string | undefined;
11
+ props?: import("@shuvi/router").IRouteComponentProps | undefined;
12
+ path: string;
13
+ filepath?: string | undefined;
14
+ id?: string | undefined;
15
+ __componentSourceWithAffix__?: string | undefined;
16
+ __resolveWeak__?: (() => any) | undefined;
17
+ }>;
18
+ /**
19
+ * Blocks all navigation attempts. This is useful for preventing the page from
20
+ * changing until some condition is met, like saving form data.
21
+ */
22
+ export declare function useBlocker(blocker: Blocker, when?: boolean): void;
23
+ /**
24
+ * Returns the full href for the given "to" value. This is useful for building
25
+ * custom links that are also accessible and preserve right-click behavior.
26
+ */
27
+ export declare function useHref(to: PathRecord): string;
28
+ /**
29
+ * Returns true if this component is a descendant of a <Router>.
30
+ */
31
+ export declare function useInRouterContext(): boolean;
32
+ /**
33
+ * Returns true if the URL for the given "to" value matches the current URL.
34
+ * This is useful for components that need to know "active" state, e.g.
35
+ * <NavLink>.
36
+ */
37
+ export declare function useMatch(pattern: IPathPattern): IPathMatch | null;
38
+ /**
39
+ * Returns an imperative method for changing the location. Used by <Link>s, but
40
+ * may also be used by other elements to change the location.
41
+ */
42
+ export declare function useNavigate(): INavigateFunction;
43
+ /**
44
+ * Returns an object of key/value pairs of the dynamic params from the current
45
+ * URL that were matched by the route path.
46
+ */
47
+ export declare function useParams(): IParams;
48
+ /**
49
+ * Resolves the pathname of the given `to` value against the current location.
50
+ */
51
+ export declare function useResolvedPath(to: PathRecord): Path;
52
+ /**
53
+ * Returns the current router object
54
+ * two parts, one is router behavior(browser history mode, hash history mode), another is router content
55
+ */
56
+ export declare function useRouter(): IRouter;
57
+ export declare function useMatchedRoute<ExtendedTypes = {}>(): IRouteContextObject<ExtendedTypes>;
package/esm/hooks.js ADDED
@@ -0,0 +1,116 @@
1
+ import * as React from 'react';
2
+ import { useContext } from 'react';
3
+ import { matchPathname } from '@shuvi/router';
4
+ import invariant from '@shuvi/utils/lib/invariant';
5
+ import { RouterContext, RouteContext, MatchedRouteContext } from './contexts';
6
+ import { warning } from './utils';
7
+ /**
8
+ * is just point `router.current` object
9
+ */
10
+ export function useCurrentRoute() {
11
+ return useContext(RouteContext);
12
+ }
13
+ /**
14
+ * Blocks all navigation attempts. This is useful for preventing the page from
15
+ * changing until some condition is met, like saving form data.
16
+ */
17
+ export function useBlocker(blocker, when = true) {
18
+ invariant(useInRouterContext(), `useBlocker() may be used only in the context of a <Router> component.`);
19
+ const { router } = useContext(RouterContext);
20
+ React.useEffect(() => {
21
+ if (!when)
22
+ return;
23
+ let unblock = router.block((tx) => {
24
+ let autoUnblockingTx = Object.assign(Object.assign({}, tx), { retry() {
25
+ // Automatically unblock the transition so it can play all the way
26
+ // through before retrying it. TODO: Figure out how to re-enable
27
+ // this block if the transition is cancelled for some reason.
28
+ unblock();
29
+ tx.retry();
30
+ } });
31
+ blocker(autoUnblockingTx);
32
+ });
33
+ return unblock;
34
+ }, [router, blocker, when]);
35
+ }
36
+ /**
37
+ * Returns the full href for the given "to" value. This is useful for building
38
+ * custom links that are also accessible and preserve right-click behavior.
39
+ */
40
+ export function useHref(to) {
41
+ invariant(useInRouterContext(), `useHref() may be used only in the context of a <Router> component.`);
42
+ const { router } = useContext(RouterContext);
43
+ const path = useResolvedPath(to);
44
+ return router.resolve(path).href;
45
+ }
46
+ /**
47
+ * Returns true if this component is a descendant of a <Router>.
48
+ */
49
+ export function useInRouterContext() {
50
+ return useContext(RouterContext) != null;
51
+ }
52
+ /**
53
+ * Returns true if the URL for the given "to" value matches the current URL.
54
+ * This is useful for components that need to know "active" state, e.g.
55
+ * <NavLink>.
56
+ */
57
+ export function useMatch(pattern) {
58
+ invariant(useInRouterContext(), `useMatch() may be used only in the context of a <Router> component.`);
59
+ const { pathname } = useCurrentRoute();
60
+ return matchPathname(pattern, pathname);
61
+ }
62
+ /**
63
+ * Returns an imperative method for changing the location. Used by <Link>s, but
64
+ * may also be used by other elements to change the location.
65
+ */
66
+ export function useNavigate() {
67
+ invariant(useInRouterContext(), `useNavigate() may be used only in the context of a <Router> component.`);
68
+ const { router } = useContext(RouterContext);
69
+ const { pathname } = useContext(MatchedRouteContext);
70
+ const activeRef = React.useRef(false);
71
+ React.useEffect(() => {
72
+ activeRef.current = true;
73
+ });
74
+ let navigate = React.useCallback((to, options = {}) => {
75
+ if (activeRef.current) {
76
+ if (typeof to === 'number') {
77
+ router.go(to);
78
+ }
79
+ else {
80
+ let { path } = router.resolve(to, pathname);
81
+ (!!options.replace ? router.replace : router.push).call(router, path, options.state);
82
+ }
83
+ }
84
+ else {
85
+ warning(false, `You should call navigate() in a useEffect, not when ` +
86
+ `your component is first rendered.`);
87
+ }
88
+ }, [router, pathname]);
89
+ return navigate;
90
+ }
91
+ /**
92
+ * Returns an object of key/value pairs of the dynamic params from the current
93
+ * URL that were matched by the route path.
94
+ */
95
+ export function useParams() {
96
+ return useContext(MatchedRouteContext).params;
97
+ }
98
+ /**
99
+ * Resolves the pathname of the given `to` value against the current location.
100
+ */
101
+ export function useResolvedPath(to) {
102
+ const { router } = useContext(RouterContext);
103
+ const { pathname } = useContext(MatchedRouteContext);
104
+ return React.useMemo(() => router.resolve(to, pathname).path, [to, pathname]);
105
+ }
106
+ /**
107
+ * Returns the current router object
108
+ * two parts, one is router behavior(browser history mode, hash history mode), another is router content
109
+ */
110
+ export function useRouter() {
111
+ invariant(useInRouterContext(), `useRouter() may be used only in the context of a <Router> component.`);
112
+ return useContext(RouterContext).router;
113
+ }
114
+ export function useMatchedRoute() {
115
+ return useContext(MatchedRouteContext);
116
+ }
package/esm/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export { generatePath, useIsomorphicEffect } from './utils';
2
+ export { MemoryRouter } from './MemoryRouter';
3
+ export { RouterView } from './RouterView';
4
+ export { Router } from './Router';
5
+ export { Link, LinkProps } from './Link';
6
+ export * from './hooks';
7
+ export * from './contexts';
8
+ export * from './types';
9
+ export * from '@shuvi/router';
package/esm/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { generatePath, useIsomorphicEffect } from './utils';
2
+ export { MemoryRouter } from './MemoryRouter';
3
+ export { RouterView } from './RouterView';
4
+ export { Router } from './Router';
5
+ export { Link } from './Link';
6
+ export * from './hooks';
7
+ export * from './contexts';
8
+ export * from './types';
9
+ export * from '@shuvi/router';
package/esm/types.d.ts ADDED
@@ -0,0 +1,47 @@
1
+ /// <reference types="react" />
2
+ import { IParams, InitialEntry, State, PathRecord, IRouteRecord as IOriginalRouteRecord, IRouter } from '@shuvi/router';
3
+ export declare type IReactRouteRecord<T = {}> = IOriginalRouteRecord<React.ReactNode, T>;
4
+ export declare type IReactPartialRouteRecord = Partial<IReactRouteRecord>;
5
+ export interface IRouterContextObject {
6
+ static: boolean;
7
+ router: IRouter;
8
+ }
9
+ export interface IRouteContextObject<ExtendedTypes = {}> {
10
+ depth: number;
11
+ params: IParams;
12
+ pathname: string;
13
+ route: IReactRouteRecord<ExtendedTypes> | null;
14
+ }
15
+ export interface IMemoryRouterProps {
16
+ basename?: string;
17
+ children?: React.ReactNode;
18
+ routes?: IReactRouteRecord[];
19
+ initialEntries?: InitialEntry[];
20
+ initialIndex?: number;
21
+ }
22
+ export interface INavigateProps {
23
+ to: PathRecord;
24
+ replace?: boolean;
25
+ state?: State;
26
+ }
27
+ export interface IOutletProps {
28
+ }
29
+ export interface IRouterProps {
30
+ children?: React.ReactNode;
31
+ static?: boolean;
32
+ router: IRouter;
33
+ }
34
+ export interface IRoutesProps {
35
+ basename?: string;
36
+ children?: React.ReactNode;
37
+ }
38
+ /**
39
+ * The interface for the navigate() function returned from useNavigate().
40
+ */
41
+ export interface INavigateFunction {
42
+ (to: PathRecord, options?: {
43
+ replace?: boolean;
44
+ state?: State;
45
+ }): void;
46
+ (delta: number): void;
47
+ }
package/esm/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/esm/utils.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { IParams } from '@shuvi/router';
2
+ export declare function useIsomorphicEffect(cb: any, deps: any): void;
3
+ export declare const readOnly: <T extends unknown>(obj: T) => T;
4
+ export declare function warning(cond: boolean, message: string): void;
5
+ export declare function warningOnce(key: string, cond: boolean, message: string): void;
6
+ /**
7
+ * Returns a path with params interpolated.
8
+ */
9
+ export declare function generatePath(path: string, params?: IParams): string;
package/esm/utils.js ADDED
@@ -0,0 +1,42 @@
1
+ import { matchStringify } from '@shuvi/router';
2
+ import { useLayoutEffect, useEffect } from 'react';
3
+ import { __DEV__ } from './constants';
4
+ export function useIsomorphicEffect(cb, deps) {
5
+ if (typeof window !== 'undefined') {
6
+ useLayoutEffect(cb, deps);
7
+ }
8
+ else {
9
+ useEffect(cb, deps);
10
+ }
11
+ }
12
+ export const readOnly = __DEV__
13
+ ? obj => Object.freeze(obj)
14
+ : obj => obj;
15
+ export function warning(cond, message) {
16
+ if (!cond) {
17
+ if (typeof console !== 'undefined')
18
+ console.warn(message);
19
+ try {
20
+ // Welcome to debugging React Router!
21
+ //
22
+ // This error is thrown as a convenience so you can more easily
23
+ // find the source for a warning that appears in the console by
24
+ // enabling "pause on exceptions" in your JavaScript debugger.
25
+ throw new Error(message);
26
+ }
27
+ catch (e) { }
28
+ }
29
+ }
30
+ const alreadyWarned = {};
31
+ export function warningOnce(key, cond, message) {
32
+ if (!cond && !alreadyWarned[key]) {
33
+ alreadyWarned[key] = true;
34
+ warning(false, message);
35
+ }
36
+ }
37
+ /**
38
+ * Returns a path with params interpolated.
39
+ */
40
+ export function generatePath(path, params = {}) {
41
+ return matchStringify(path, params);
42
+ }