UNPKG

next

Version:

The React Framework

25 lines 6.61 kB
"use strict";var _interopRequireWildcard=require("@babel/runtime/helpers/interopRequireWildcard");exports.__esModule=true;exports.default=void 0;var _react=_interopRequireWildcard(require("react"));var _router=require("../next-server/lib/router/router");var _router2=require("./router");var _useIntersection=require("./use-intersection");const prefetched={};function prefetch(router,href,as,options){if(typeof window==='undefined'||!router)return;if(!(0,_router.isLocalURL)(href))return;// Prefetch the JSON page if asked (only in the client) // We need to handle a prefetch error here since we may be // loading with priority which can reject but we don't // want to force navigation since this is only a prefetch router.prefetch(href,as,options).catch(err=>{if(process.env.NODE_ENV!=='production'){// rethrow to show invalid URL errors throw err;}});const curLocale=options&&typeof options.locale!=='undefined'?options.locale:router&&router.locale;// Join on an invalid URI character prefetched[href+'%'+as+(curLocale?'%'+curLocale:'')]=true;}function isModifiedEvent(event){const{target}=event.currentTarget;return target&&target!=='_self'||event.metaKey||event.ctrlKey||event.shiftKey||event.altKey||// triggers resource download event.nativeEvent&&event.nativeEvent.which===2;}function linkClicked(e,router,href,as,replace,shallow,scroll,locale){const{nodeName}=e.currentTarget;if(nodeName==='A'&&(isModifiedEvent(e)||!(0,_router.isLocalURL)(href))){// ignore click for browser’s default behavior return;}e.preventDefault();// avoid scroll for urls with anchor refs if(scroll==null){scroll=as.indexOf('#')<0;}// replace state instead of push if prop is present router[replace?'replace':'push'](href,as,{shallow,locale,scroll}).then(success=>{if(!success)return;if(scroll){// FIXME: proper route announcing at Router level, not Link: document.body.focus();}});}function Link(props){if(process.env.NODE_ENV!=='production'){function createPropError(args){return new Error(`Failed prop type: The prop \`${args.key}\` expects a ${args.expected} in \`<Link>\`, but got \`${args.actual}\` instead.`+(typeof window!=='undefined'?"\nOpen your browser's console to view the Component stack trace.":''));}// TypeScript trick for type-guarding: const requiredPropsGuard={href:true};const requiredProps=Object.keys(requiredPropsGuard);requiredProps.forEach(key=>{if(key==='href'){if(props[key]==null||typeof props[key]!=='string'&&typeof props[key]!=='object'){throw createPropError({key,expected:'`string` or `object`',actual:props[key]===null?'null':typeof props[key]});}}else{// TypeScript trick for type-guarding: // eslint-disable-next-line @typescript-eslint/no-unused-vars const _=key;}});// TypeScript trick for type-guarding: const optionalPropsGuard={as:true,replace:true,scroll:true,shallow:true,passHref:true,prefetch:true,locale:true};const optionalProps=Object.keys(optionalPropsGuard);optionalProps.forEach(key=>{const valType=typeof props[key];if(key==='as'){if(props[key]&&valType!=='string'&&valType!=='object'){throw createPropError({key,expected:'`string` or `object`',actual:valType});}}else if(key==='locale'){if(props[key]&&valType!=='string'){throw createPropError({key,expected:'`string`',actual:valType});}}else if(key==='replace'||key==='scroll'||key==='shallow'||key==='passHref'||key==='prefetch'){if(props[key]!=null&&valType!=='boolean'){throw createPropError({key,expected:'`boolean`',actual:valType});}}else{// TypeScript trick for type-guarding: // eslint-disable-next-line @typescript-eslint/no-unused-vars const _=key;}});// This hook is in a conditional but that is ok because `process.env.NODE_ENV` never changes // eslint-disable-next-line react-hooks/rules-of-hooks const hasWarned=_react.default.useRef(false);if(props.prefetch&&!hasWarned.current){hasWarned.current=true;console.warn('Next.js auto-prefetches automatically based on viewport. The prefetch attribute is no longer needed. More: https://err.sh/vercel/next.js/prefetch-true-deprecated');}}const p=props.prefetch!==false;const router=(0,_router2.useRouter)();const pathname=router&&router.pathname||'/';const{href,as}=_react.default.useMemo(()=>{const[resolvedHref,resolvedAs]=(0,_router.resolveHref)(pathname,props.href,true);return{href:resolvedHref,as:props.as?(0,_router.resolveHref)(pathname,props.as):resolvedAs||resolvedHref};},[pathname,props.href,props.as]);let{children,replace,shallow,scroll,locale}=props;// Deprecated. Warning shown by propType check. If the children provided is a string (<Link>example</Link>) we wrap it in an <a> tag if(typeof children==='string'){children=/*#__PURE__*/_react.default.createElement("a",null,children);}// This will return the first child, if multiple are provided it will throw an error const child=_react.Children.only(children);const childRef=child&&typeof child==='object'&&child.ref;const[setIntersectionRef,isVisible]=(0,_useIntersection.useIntersection)({rootMargin:'200px'});const setRef=_react.default.useCallback(el=>{setIntersectionRef(el);if(childRef){if(typeof childRef==='function')childRef(el);else if(typeof childRef==='object'){childRef.current=el;}}},[childRef,setIntersectionRef]);(0,_react.useEffect)(()=>{const shouldPrefetch=isVisible&&p&&(0,_router.isLocalURL)(href);const curLocale=typeof locale!=='undefined'?locale:router&&router.locale;const isPrefetched=prefetched[href+'%'+as+(curLocale?'%'+curLocale:'')];if(shouldPrefetch&&!isPrefetched){prefetch(router,href,as,{locale:curLocale});}},[as,href,isVisible,locale,p,router]);const childProps={ref:setRef,onClick:e=>{if(child.props&&typeof child.props.onClick==='function'){child.props.onClick(e);}if(!e.defaultPrevented){linkClicked(e,router,href,as,replace,shallow,scroll,locale);}}};childProps.onMouseEnter=e=>{if(!(0,_router.isLocalURL)(href))return;if(child.props&&typeof child.props.onMouseEnter==='function'){child.props.onMouseEnter(e);}prefetch(router,href,as,{priority:true});};// If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is // defined, we specify the current 'href', so that repetition is not needed by the user if(props.passHref||child.type==='a'&&!('href'in child.props)){const curLocale=typeof locale!=='undefined'?locale:router&&router.locale;const localeDomain=(0,_router.getDomainLocale)(as,curLocale,router&&router.locales,router&&router.domainLocales);childProps.href=localeDomain||(0,_router.addBasePath)((0,_router.addLocale)(as,curLocale,router&&router.defaultLocale));}return/*#__PURE__*/_react.default.cloneElement(child,childProps);}var _default=Link;exports.default=_default; //# sourceMappingURL=link.js.map