UNPKG

react-router-lite

Version:
137 lines (136 loc) 5.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Link = exports.Redirect = exports.Switch = exports.Route = exports.Match = exports.useMatch = exports.Router = exports.context = exports.go = void 0; const tslib_1 = require("tslib"); const React = tslib_1.__importStar(require("react")); const go_1 = require("./go"); Object.defineProperty(exports, "go", { enumerable: true, get: function () { return go_1.go; } }); const h = React.createElement; const defaultGo = go_1.go; exports.context = React.createContext(null); const Router = (props) => { const { route, fullRoute, parent, go, children } = props; const value = { fullRoute: fullRoute || route, route, go, parent, }; return h(exports.context.Provider, { value }, children); }; exports.Router = Router; // -------------------------------------------------------------------- <Match> const createMatcher = (match, exact) => { if (typeof match === 'function') return match; const regex = typeof match === 'string' ? new RegExp(`^(${match}${exact ? '$' : ''})`) : match; return (route) => route.match(regex); }; const useMatch = (match, exact) => { if (process.env.NODE_ENV !== 'production') { if (typeof match !== 'string') { if (exact) { // tslint:disable-next-line console.warn('You are using useMatch(!string, true) with non-string match prop, ' + 'exact prop works only with string match prop.'); } } } const { fullRoute, route, parent } = React.useContext(exports.context); const mather = React.useMemo(() => createMatcher(match, exact), [match, exact]); const matches = mather(route); return { fullRoute, route, parent, matches, }; }; exports.useMatch = useMatch; const Match = (props) => { const { match = '', exact = false, truncate, children, render = children } = props; const data = (0, exports.useMatch)(match, exact); const { route, matches } = data; let element = (typeof render === 'function' ? render(data) : render) || null; if (matches && truncate) { element = h(exports.Router, { fullRoute: route, route: route.substring(matches[0].length), parent: data, children: element, }); } return element instanceof Array ? h(React.Fragment, null, element) : element; }; exports.Match = Match; // -------------------------------------------------------------------- <Route> const Route = ({ children, render = children, ...rest }) => h(exports.Match, { ...rest, render: (data) => (data.matches ? (typeof render === 'function' ? render(data) : render || null) : null), }); exports.Route = Route; const Switch = ({ children }) => { const { route } = React.useContext(exports.context); for (const element of children) { if (process.env.NODE_ENV !== 'production') { if (typeof element !== 'object' || element.type !== exports.Route) { throw new TypeError('All <Switch> children must be <Route> elements.'); } } const { match, exact } = element.props; if (createMatcher(match, exact)(route)) return element; } return null; }; exports.Switch = Switch; // ----------------------------------------------------------------- <Redirect> const isBrowser = typeof window !== 'undefined'; const useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect; const Redirect = ({ to, ...params }) => { const go = React.useContext(exports.context).go || defaultGo; useIsomorphicLayoutEffect(() => { go(to, params); }, []); return null; }; exports.Redirect = Redirect; // --------------------------------------------------------------------- <Link> const isModifiedEvent = (event) => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); const EXTERNAL_REGEX = /(^https?:)?\/\/.+/; const isExternal = (to) => EXTERNAL_REGEX.test(to); exports.Link = React.forwardRef((props, ref) => { const { replace, state, to = '', a, comp = a ? 'a' : 'button', onClick: originalClick, target, external, ...rest } = props; const go = React.useContext(exports.context)?.go || defaultGo; const onClick = React.useCallback((event) => { if (!event.defaultPrevented && // onClick prevented default event.button === 0 && // ignore everything but left clicks !target && // let browser handle "target=*" !isModifiedEvent(event) // ignore clicks with modifier keys ) { if (!(external || isExternal(to))) { event.preventDefault(); go(to, { replace, state: state ? state(props) : undefined, }); } if (originalClick) originalClick(event); } }, [originalClick, replace, target, state]); const attr = { ...rest, ref, onClick, }; if (comp === 'a') { attr.href = to; attr.target = target; if (external || isExternal(to)) { attr.target = '_blank'; attr.rel = 'noopener noreferrer'; } } return h(comp, attr); });