123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- "client";
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _interop_require_default = require("@swc/helpers/lib/_interop_require_default.js").default;
- var _object_without_properties_loose = require("@swc/helpers/lib/_object_without_properties_loose.js").default;
- var _react = _interop_require_default(require("react"));
- var _router = require("../shared/lib/router/router");
- var _addLocale = require("./add-locale");
- var _routerContext = require("../shared/lib/router-context");
- var _appRouterContext = require("../shared/lib/app-router-context");
- var _useIntersection = require("./use-intersection");
- var _getDomainLocale = require("./get-domain-locale");
- var _addBasePath = require("./add-base-path");
- 'client';
- 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
- Promise.resolve(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 || event.nativeEvent && event.nativeEvent.which === 2;
- }
- function linkClicked(e, router, href, as, replace, shallow, scroll, locale, isAppRouter, prefetchEnabled) {
- const { nodeName } = e.currentTarget;
- // anchors inside an svg have a lowercase nodeName
- const isAnchorNodeName = nodeName.toUpperCase() === 'A';
- if (isAnchorNodeName && (isModifiedEvent(e) || !(0, _router).isLocalURL(href))) {
- // ignore click for browser’s default behavior
- return;
- }
- e.preventDefault();
- const navigate = ()=>{
- // If the router is an NextRouter instance it will have `beforePopState`
- if ('beforePopState' in router) {
- router[replace ? 'replace' : 'push'](href, as, {
- shallow,
- locale,
- scroll
- });
- } else {
- // If `beforePopState` doesn't exist on the router it's the AppRouter.
- const method = replace ? 'replace' : 'push';
- router[method](href, {
- forceOptimisticNavigation: !prefetchEnabled
- });
- }
- };
- if (isAppRouter) {
- // @ts-expect-error startTransition exists.
- _react.default.startTransition(navigate);
- } else {
- navigate();
- }
- }
- const Link = /*#__PURE__*/ _react.default.forwardRef(function LinkComponent(props, forwardedRef) {
- 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,
- onClick: true,
- onMouseEnter: true,
- onTouchStart: true,
- legacyBehavior: 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 === 'onClick' || key === 'onMouseEnter' || key === 'onTouchStart') {
- if (props[key] && valType !== 'function') {
- throw createPropError({
- key,
- expected: '`function`',
- actual: valType
- });
- }
- } else if (key === 'replace' || key === 'scroll' || key === 'shallow' || key === 'passHref' || key === 'prefetch' || key === 'legacyBehavior') {
- 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://nextjs.org/docs/messages/prefetch-true-deprecated');
- }
- }
- let children;
- const { href: hrefProp , as: asProp , children: childrenProp , prefetch: prefetchProp , passHref , replace , shallow , scroll , locale , onClick , onMouseEnter , onTouchStart , legacyBehavior =Boolean(process.env.__NEXT_NEW_LINK_BEHAVIOR) !== true } = props, restProps = _object_without_properties_loose(props, [
- "href",
- "as",
- "children",
- "prefetch",
- "passHref",
- "replace",
- "shallow",
- "scroll",
- "locale",
- "onClick",
- "onMouseEnter",
- "onTouchStart",
- "legacyBehavior"
- ]);
- children = childrenProp;
- if (legacyBehavior && (typeof children === 'string' || typeof children === 'number')) {
- children = /*#__PURE__*/ _react.default.createElement("a", null, children);
- }
- const p = prefetchProp !== false;
- let router = _react.default.useContext(_routerContext.RouterContext);
- // TODO-APP: type error. Remove `as any`
- const appRouter = _react.default.useContext(_appRouterContext.AppRouterContext);
- if (appRouter) {
- router = appRouter;
- }
- const { href , as } = _react.default.useMemo(()=>{
- const [resolvedHref, resolvedAs] = (0, _router).resolveHref(router, hrefProp, true);
- return {
- href: resolvedHref,
- as: asProp ? (0, _router).resolveHref(router, asProp) : resolvedAs || resolvedHref
- };
- }, [
- router,
- hrefProp,
- asProp
- ]);
- const previousHref = _react.default.useRef(href);
- const previousAs = _react.default.useRef(as);
- // This will return the first child, if multiple are provided it will throw an error
- let child;
- if (legacyBehavior) {
- if (process.env.NODE_ENV === 'development') {
- if (onClick) {
- console.warn(`"onClick" was passed to <Link> with \`href\` of \`${hrefProp}\` but "legacyBehavior" was set. The legacy behavior requires onClick be set on the child of next/link`);
- }
- if (onMouseEnter) {
- console.warn(`"onMouseEnter" was passed to <Link> with \`href\` of \`${hrefProp}\` but "legacyBehavior" was set. The legacy behavior requires onMouseEnter be set on the child of next/link`);
- }
- try {
- child = _react.default.Children.only(children);
- } catch (err) {
- if (!children) {
- throw new Error(`No children were passed to <Link> with \`href\` of \`${hrefProp}\` but one child is required https://nextjs.org/docs/messages/link-no-children`);
- }
- throw new Error(`Multiple children were passed to <Link> with \`href\` of \`${hrefProp}\` but only one child is supported https://nextjs.org/docs/messages/link-multiple-children` + (typeof window !== 'undefined' ? " \nOpen your browser's console to view the Component stack trace." : ''));
- }
- } else {
- child = _react.default.Children.only(children);
- }
- }
- const childRef = legacyBehavior ? child && typeof child === 'object' && child.ref : forwardedRef;
- const [setIntersectionRef, isVisible, resetVisible] = (0, _useIntersection).useIntersection({
- rootMargin: '200px'
- });
- const setRef = _react.default.useCallback((el)=>{
- // Before the link getting observed, check if visible state need to be reset
- if (previousAs.current !== as || previousHref.current !== href) {
- resetVisible();
- previousAs.current = as;
- previousHref.current = href;
- }
- setIntersectionRef(el);
- if (childRef) {
- if (typeof childRef === 'function') childRef(el);
- else if (typeof childRef === 'object') {
- childRef.current = el;
- }
- }
- }, [
- as,
- childRef,
- href,
- resetVisible,
- setIntersectionRef
- ]);
- _react.default.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 (process.env.NODE_ENV !== 'production') {
- if (!e) {
- throw new Error(`Component rendered inside next/link has to pass click event to "onClick" prop.`);
- }
- }
- if (!legacyBehavior && typeof onClick === 'function') {
- onClick(e);
- }
- if (legacyBehavior && child.props && typeof child.props.onClick === 'function') {
- child.props.onClick(e);
- }
- if (!e.defaultPrevented) {
- linkClicked(e, router, href, as, replace, shallow, scroll, locale, Boolean(appRouter), p);
- }
- },
- onMouseEnter: (e)=>{
- if (!legacyBehavior && typeof onMouseEnter === 'function') {
- onMouseEnter(e);
- }
- if (legacyBehavior && child.props && typeof child.props.onMouseEnter === 'function') {
- child.props.onMouseEnter(e);
- }
- // Check for not prefetch disabled in page using appRouter
- if (!(!p && appRouter)) {
- if ((0, _router).isLocalURL(href)) {
- prefetch(router, href, as, {
- priority: true
- });
- }
- }
- },
- onTouchStart: (e)=>{
- if (!legacyBehavior && typeof onTouchStart === 'function') {
- onTouchStart(e);
- }
- if (legacyBehavior && child.props && typeof child.props.onTouchStart === 'function') {
- child.props.onTouchStart(e);
- }
- // Check for not prefetch disabled in page using appRouter
- if (!(!p && appRouter)) {
- if ((0, _router).isLocalURL(href)) {
- 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 (!legacyBehavior || passHref || child.type === 'a' && !('href' in child.props)) {
- const curLocale = typeof locale !== 'undefined' ? locale : router && router.locale;
- // we only render domain locales if we are currently on a domain locale
- // so that locale links are still visitable in development/preview envs
- const localeDomain = router && router.isLocaleDomain && (0, _getDomainLocale).getDomainLocale(as, curLocale, router.locales, router.domainLocales);
- childProps.href = localeDomain || (0, _addBasePath).addBasePath((0, _addLocale).addLocale(as, curLocale, router && router.defaultLocale));
- }
- return legacyBehavior ? /*#__PURE__*/ _react.default.cloneElement(child, childProps) : /*#__PURE__*/ _react.default.createElement("a", Object.assign({}, restProps, childProps), children);
- });
- var _default = Link;
- exports.default = _default;
- if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
- Object.defineProperty(exports.default, '__esModule', { value: true });
- Object.assign(exports.default, exports);
- module.exports = exports.default;
- }
- //# sourceMappingURL=link.js.map
|