UNPKG

@tanstack/solid-router

Version:

Modern and scalable routing for Solid applications

316 lines (315 loc) 10.9 kB
const require_runtime = require("./_virtual/_rolldown/runtime.cjs"); const require_ClientOnly = require("./ClientOnly.cjs"); const require_useRouter = require("./useRouter.cjs"); const require_useRouterState = require("./useRouterState.cjs"); const require_utils = require("./utils.cjs"); let _tanstack_router_core = require("@tanstack/router-core"); let solid_js_web = require("solid-js/web"); let solid_js = require("solid-js"); solid_js = require_runtime.__toESM(solid_js); let _solid_primitives_refs = require("@solid-primitives/refs"); let _tanstack_router_core_isServer = require("@tanstack/router-core/isServer"); //#region src/link.tsx var _tmpl$ = /* @__PURE__ */ (0, solid_js_web.template)(`<svg><a>`); var timeoutMap = /* @__PURE__ */ new WeakMap(); function useLinkProps(options) { const router = require_useRouter.useRouter(); const [isTransitioning, setIsTransitioning] = solid_js.createSignal(false); const shouldHydrateHash = !_tanstack_router_core_isServer.isServer && !!router.options.ssr; const hasHydrated = require_ClientOnly.useHydrated(); let hasRenderFetched = false; const [local, rest] = solid_js.splitProps(solid_js.mergeProps({ activeProps: () => ({ class: "active" }), inactiveProps: () => ({}) }, options), [ "activeProps", "inactiveProps", "activeOptions", "to", "preload", "preloadDelay", "hashScrollIntoView", "replace", "startTransition", "resetScroll", "viewTransition", "target", "disabled", "style", "class", "onClick", "onBlur", "onFocus", "onMouseEnter", "onMouseLeave", "onMouseOver", "onMouseOut", "onTouchStart", "ignoreBlocker" ]); const [_, propsSafeToSpread] = solid_js.splitProps(rest, [ "params", "search", "hash", "state", "mask", "reloadDocument", "unsafeRelative" ]); const currentLocation = require_useRouterState.useRouterState({ select: (s) => s.location }); const buildLocationKey = require_useRouterState.useRouterState({ select: (s) => { const leaf = s.matches[s.matches.length - 1]; return { search: leaf?.search, hash: s.location.hash, path: leaf?.pathname }; } }); const from = options.from; const _options = () => { return { ...options, from }; }; const next = solid_js.createMemo(() => { buildLocationKey(); return router.buildLocation(_options()); }); const hrefOption = solid_js.createMemo(() => { if (_options().disabled) return void 0; const location = next().maskedLocation ?? next(); const publicHref = location.publicHref; if (location.external) return { href: publicHref, external: true }; return { href: router.history.createHref(publicHref) || "/", external: false }; }); const externalLink = solid_js.createMemo(() => { const _href = hrefOption(); if (_href?.external) { if ((0, _tanstack_router_core.isDangerousProtocol)(_href.href, router.protocolAllowlist)) { if (process.env.NODE_ENV !== "production") console.warn(`Blocked Link with dangerous protocol: ${_href.href}`); return; } return _href.href; } const to = _options().to; if (typeof to === "string" && to.charCodeAt(0) === 47 && to.charCodeAt(1) !== 47) return void 0; try { new URL(to); if ((0, _tanstack_router_core.isDangerousProtocol)(to, router.protocolAllowlist)) { if (process.env.NODE_ENV !== "production") console.warn(`Blocked Link with dangerous protocol: ${to}`); return; } return to; } catch {} }); const preload = solid_js.createMemo(() => { if (_options().reloadDocument || externalLink()) return false; return local.preload ?? router.options.defaultPreload; }); const preloadDelay = () => local.preloadDelay ?? router.options.defaultPreloadDelay ?? 0; const isActive = solid_js.createMemo(() => { if (externalLink()) return false; if (local.activeOptions?.exact) { if (!(0, _tanstack_router_core.exactPathTest)(currentLocation().pathname, next().pathname, router.basepath)) return false; } else { const currentPathSplit = (0, _tanstack_router_core.removeTrailingSlash)(currentLocation().pathname, router.basepath).split("/"); if (!((0, _tanstack_router_core.removeTrailingSlash)(next()?.pathname, router.basepath)?.split("/"))?.every((d, i) => d === currentPathSplit[i])) return false; } if (local.activeOptions?.includeSearch ?? true) { if (!(0, _tanstack_router_core.deepEqual)(currentLocation().search, next().search, { partial: !local.activeOptions?.exact, ignoreUndefined: !local.activeOptions?.explicitUndefined })) return false; } if (local.activeOptions?.includeHash) return (shouldHydrateHash && !hasHydrated() ? "" : currentLocation().hash) === next().hash; return true; }); const doPreload = () => router.preloadRoute(_options()).catch((err) => { console.warn(err); console.warn(_tanstack_router_core.preloadWarning); }); const preloadViewportIoCallback = (entry) => { if (entry?.isIntersecting) doPreload(); }; const [ref, setRef] = solid_js.createSignal(null); require_utils.useIntersectionObserver(ref, preloadViewportIoCallback, { rootMargin: "100px" }, { disabled: !!local.disabled || !(preload() === "viewport") }); solid_js.createEffect(() => { if (hasRenderFetched) return; if (!local.disabled && preload() === "render") { doPreload(); hasRenderFetched = true; } }); if (externalLink()) return solid_js.mergeProps(propsSafeToSpread, { ref: (0, _solid_primitives_refs.mergeRefs)(setRef, _options().ref), href: externalLink() }, solid_js.splitProps(local, [ "target", "disabled", "style", "class", "onClick", "onBlur", "onFocus", "onMouseEnter", "onMouseLeave", "onMouseOut", "onMouseOver", "onTouchStart" ])[0]); const handleClick = (e) => { const elementTarget = e.currentTarget.getAttribute("target"); const effectiveTarget = local.target !== void 0 ? local.target : elementTarget; if (!local.disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!effectiveTarget || effectiveTarget === "_self") && e.button === 0) { e.preventDefault(); setIsTransitioning(true); const unsub = router.subscribe("onResolved", () => { unsub(); setIsTransitioning(false); }); router.navigate({ ..._options(), replace: local.replace, resetScroll: local.resetScroll, hashScrollIntoView: local.hashScrollIntoView, startTransition: local.startTransition, viewTransition: local.viewTransition, ignoreBlocker: local.ignoreBlocker }); } }; const enqueueIntentPreload = (e) => { if (local.disabled || preload() !== "intent") return; if (!preloadDelay()) { doPreload(); return; } const eventTarget = e.currentTarget || e.target; if (!eventTarget || timeoutMap.has(eventTarget)) return; timeoutMap.set(eventTarget, setTimeout(() => { timeoutMap.delete(eventTarget); doPreload(); }, preloadDelay())); }; const handleTouchStart = (_) => { if (local.disabled || preload() !== "intent") return; doPreload(); }; const handleLeave = (e) => { if (local.disabled) return; const eventTarget = e.currentTarget || e.target; if (eventTarget) { const id = timeoutMap.get(eventTarget); clearTimeout(id); timeoutMap.delete(eventTarget); } }; /** Call a JSX.EventHandlerUnion with the event. */ function callHandler(event, handler) { if (handler) if (typeof handler === "function") handler(event); else handler[0](handler[1], event); return event.defaultPrevented; } function composeEventHandlers(handlers) { return (event) => { for (const handler of handlers) callHandler(event, handler); }; } const resolvedActiveProps = () => isActive() ? (0, _tanstack_router_core.functionalUpdate)(local.activeProps, {}) ?? {} : {}; const resolvedInactiveProps = () => isActive() ? {} : (0, _tanstack_router_core.functionalUpdate)(local.inactiveProps, {}); const resolvedClassName = () => [ local.class, resolvedActiveProps().class, resolvedInactiveProps().class ].filter(Boolean).join(" "); const resolvedStyle = () => ({ ...local.style, ...resolvedActiveProps().style, ...resolvedInactiveProps().style }); return solid_js.mergeProps(propsSafeToSpread, resolvedActiveProps, resolvedInactiveProps, () => { return { href: hrefOption()?.href, ref: (0, _solid_primitives_refs.mergeRefs)(setRef, _options().ref), onClick: composeEventHandlers([local.onClick, handleClick]), onBlur: composeEventHandlers([local.onBlur, handleLeave]), onFocus: composeEventHandlers([local.onFocus, enqueueIntentPreload]), onMouseEnter: composeEventHandlers([local.onMouseEnter, enqueueIntentPreload]), onMouseOver: composeEventHandlers([local.onMouseOver, enqueueIntentPreload]), onMouseLeave: composeEventHandlers([local.onMouseLeave, handleLeave]), onMouseOut: composeEventHandlers([local.onMouseOut, handleLeave]), onTouchStart: composeEventHandlers([local.onTouchStart, handleTouchStart]), disabled: !!local.disabled, target: local.target, ...(() => { const s = resolvedStyle(); return Object.keys(s).length ? { style: s } : {}; })(), ...(() => { const c = resolvedClassName(); return c ? { class: c } : {}; })(), ...local.disabled && { role: "link", "aria-disabled": true }, ...isActive() && { "data-status": "active", "aria-current": "page" }, ...isTransitioning() && { "data-transitioning": "transitioning" } }; }); } function createLink(Comp) { return (props) => (0, solid_js_web.createComponent)(Link, (0, solid_js_web.mergeProps)(props, { _asChild: Comp })); } var Link = (props) => { const [local, rest] = solid_js.splitProps(props, ["_asChild", "children"]); const [_, linkProps] = solid_js.splitProps(useLinkProps(rest), ["type"]); const children = solid_js.createMemo(() => { const ch = local.children; if (typeof ch === "function") return ch({ get isActive() { return linkProps["data-status"] === "active"; }, get isTransitioning() { return linkProps["data-transitioning"] === "transitioning"; } }); return ch; }); if (local._asChild === "svg") { const [_, svgLinkProps] = solid_js.splitProps(linkProps, ["class"]); return (() => { var _el$ = _tmpl$(), _el$2 = _el$.firstChild; (0, solid_js_web.spread)(_el$2, svgLinkProps, false, true); (0, solid_js_web.insert)(_el$2, children); return _el$; })(); } return (0, solid_js_web.createComponent)(solid_js_web.Dynamic, (0, solid_js_web.mergeProps)({ get component() { return (0, solid_js_web.memo)(() => !!local._asChild)() ? local._asChild : "a"; } }, linkProps, { get children() { return children(); } })); }; function isCtrlEvent(e) { return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey); } var linkOptions = (options) => { return options; }; //#endregion exports.Link = Link; exports.createLink = createLink; exports.linkOptions = linkOptions; exports.useLinkProps = useLinkProps; //# sourceMappingURL=link.cjs.map