@next-box/link-extra 0.0.20 → 0.1.1

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/README.md CHANGED
@@ -1,8 +1,142 @@
1
1
  # @next-box/link-extra
2
2
 
3
- A collection of link components for use primarily with Next.js.
3
+ A configurable link component for React applications, primarily designed for Next.js.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/%40next-box%2Flink-extra.svg)](https://badge.fury.io/js/%40next-box%2Flink-extra)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
 
8
- The use of React server components has flipped the traditional UX pattern of navigating to a page and waiting for the content to load on its head. Now, the potential delay is prior to the redirection, while the server render is happening. This transition can sometimes be handled by the use of the `loading.tsx` file, but not always.
8
+ Next.js is a powerful framework for building modern React applications, particularly with its support for React Server Components and server-side rendering. However, these features can introduce some differences in navigation behaviour compared with traditional client-side applications.
9
+
10
+ Client-side navigation can sometimes feel unresponsive when the destination requires server-side work, with the browser waiting for the new route to begin rendering before the UI changes. This has been discussed in the Next.js community, including [Slow route navigation](https://github.com/vercel/next.js/discussions/65150) and [How to indicate loading during pagination](https://github.com/vercel/next.js/discussions/55481).
11
+
12
+ Next.js also maintains a client-side Router Cache to improve navigation performance. While this is useful for many applications, there are cases where an application needs to ensure that navigation retrieves the latest version of a route. The ability to opt out of this client-side caching has been discussed in [Opt-out of client cache](https://github.com/vercel/next.js/discussions/54162), and the distinction between the Router Cache and server-side caching is discussed in [Deep Dive: Caching and Revalidating](https://github.com/vercel/next.js/discussions/54075).
13
+
14
+ Finally, applications often have their own link components and design systems. Integrating these with Next.js `Link` can be awkward, particularly when an application needs the `href` applied to its own anchor element rather than having Next.js render the anchor itself. This has been discussed in the Next.js community, including [Add back `passHref` to the new next/link component](https://github.com/vercel/next.js/discussions/49508) and [Remove `legacyBehavior` from Link component on Next.js 15](https://github.com/vercel/next.js/discussions/67987).
15
+
16
+ `@next-box/link-extra` provides a wrapper around the Next.js `Link` component that addresses these concerns while retaining Next.js client-side navigation.
17
+
18
+ ## What it provides
19
+
20
+ ### Loading feedback
21
+
22
+ A navigation can take some time to begin rendering, particularly when the destination requires server-side work. `@next-box/link-extra` can display a custom loading component if navigation has not completed within a configurable timeout.
23
+
24
+ If the route transition completes before the timeout, no loading indicator is displayed. If it takes longer, the loading component is rendered automatically.
25
+
26
+ ### Router cache control
27
+
28
+ `@next-box/link-extra` provides the `disableRouterCache` prop for cases where an application needs to bypass the Next.js client-side Router Cache.
29
+
30
+ When enabled, the link adds a cache-busting query parameter to the destination URL. This is enabled by default.
31
+
32
+ ### Custom link components
33
+
34
+ The library separates the Next.js navigation link from the component used to render the actual link.
35
+
36
+ This allows applications to provide their own link component for styling and design-system requirements while retaining Next.js navigation behaviour.
37
+
38
+ ## Installation
39
+
40
+ ```shell
41
+ npm add @next-box/link-extra
42
+ ```
43
+
44
+ ## Usage
45
+
46
+ ### Create a link provider
47
+
48
+ `LinkProvider` supplies the Next.js link, your own link component, and the loading component used by `Link`.
49
+
50
+ It also receives the current pathname so that it can detect when a navigation has completed.
51
+
52
+ ```tsx
53
+ import Link from 'next/link';
54
+ import { usePathname } from 'next/navigation';
55
+ import {
56
+ LinkProvider,
57
+ } from '@next-box/link-extra';
58
+
59
+ const LinkProviderWrapper = ({
60
+ children,
61
+ }: {
62
+ children: ReactNode;
63
+ }) => {
64
+ const pathname = usePathname();
65
+
66
+ return (
67
+ <LinkProvider
68
+ LoadingComponent={Loading}
69
+ NextLink={Link}
70
+ OwnLink={YourLink}
71
+ pathname={pathname}
72
+ >
73
+ {children}
74
+ </LinkProvider>
75
+ );
76
+ };
77
+ ```
78
+
79
+ For Next.js applications using the App Router, the provider should be placed in a client component because it uses React context and client-side navigation state.
80
+
81
+ ### Render a link
82
+
83
+ Once the provider has been configured, use the `Link` component in place of your normal Next.js link.
84
+
85
+ ```tsx
86
+ import { Link } from '@next-box/link-extra';
87
+
88
+ const Component = () => {
89
+ return (
90
+ <Link href="/dashboard">
91
+ Dashboard
92
+ </Link>
93
+ );
94
+ };
95
+ ```
96
+
97
+ ### Disable Router Cache
98
+
99
+ Router cache busting is enabled by default.
100
+
101
+ To allow Next.js to use its normal Router Cache behaviour for an individual link, set `disableRouterCache` to `false`:
102
+
103
+ ```tsx
104
+ <Link
105
+ href="/dashboard"
106
+ disableRouterCache={false}
107
+ >
108
+ Dashboard
109
+ </Link>
110
+ ```
111
+
112
+ ### Configure loading behaviour
113
+
114
+ The loading timeout defaults to `500ms`. This can be changed through `LinkProvider`:
115
+
116
+ ```tsx
117
+ <LinkProvider
118
+ LoadingComponent={Loading}
119
+ NextLink={Link}
120
+ OwnLink={YourLink}
121
+ pathname={pathname}
122
+ loadingTimeout={1000}
123
+ >
124
+ {children}
125
+ </LinkProvider>
126
+ ```
127
+
128
+ The loading component is only rendered when a link navigation remains in progress beyond the configured timeout.
129
+
130
+ ### Prevent loading for a link
131
+
132
+ The loading state is only triggered when the link represents navigation to a different URL and the click has not been prevented.
133
+
134
+ This means links that point to the current location, or clicks where `event.preventDefault()` has been called, do not trigger the loading indicator.
135
+
136
+ ## Changelog
137
+
138
+ See the [changelog](../../CHANGELOG.md) for features, fixes, and other changes included in each major, minor, and patch release.
139
+
140
+ ## License
141
+
142
+ `@next-box/link-extra` is [MIT Licensed](LICENSE).
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("next/link.js"),r=require("react");require("core-js/modules/web.url.parse.js");var n=require("nanoid");const i=r.createContext({NextLink:t,OwnLink:()=>{},setLinkClicked:()=>{}});let a;const o=e=>{if(!globalThis.location)return!1;const t=URL.parse(e,globalThis.location.origin);if(!t)return!1;const{pathname:r,search:n}=t,i=new URLSearchParams(n);i.has("y")&&i.delete("y");const a=new URLSearchParams(globalThis.location.search);return a.has("y")&&a.delete("y"),`${r}?${i.toString()}`==`${globalThis.location.pathname}?${a.toString()}`},s=e=>{if(!globalThis.location)return e;const t=URL.parse(e,globalThis.location.origin);if(!t)return e;const r=new URLSearchParams(globalThis.location.search),i=r.get("y");i&&r.delete("y");const{pathname:a,search:o}=t,s=new URLSearchParams(o);return`${a}?${o}`==`${globalThis.location.pathname}?${r.toString()}`?s.set("y",i??n.nanoid()):s.set("y",n.nanoid()),`${a}?${s.toString()}`},l=()=>r.useContext(i);exports.Link=({children:t,disableRouterCache:r=!0,href:n="#",onClick:i,prefetch:a=!1,scroll:c=!1,...h})=>{const{NextLink:u,OwnLink:d,setLinkClicked:L}=l();return r&&(n=s(n)),e.jsx(u,{href:n,legacyBehavior:!0,passHref:!0,prefetch:a,scroll:c,children:e.jsx(d,{onClick:e=>{i&&i(e),o(n)||e.defaultPrevented||L(!0)},...h,children:t})})},exports.LinkContext=i,exports.LinkProvider=({LoadingComponent:t,NextLink:n,OwnLink:o,children:s,loadingTimeout:l=500,pathname:c})=>{const[h,u]=r.useState(!1),[d,L]=r.useState(!1);return r.useEffect(()=>(h&&(a=setTimeout(()=>{L(!0)},l)),()=>{clearTimeout(a)}),[h]),r.useEffect(()=>{h&&(u(!1),L(!1),globalThis.scroll(0,0)),a&&clearTimeout(a)},[c]),e.jsx(i.Provider,{value:{NextLink:n,OwnLink:o,setLinkClicked:e=>{u(e)}},children:e.jsxs(e.Fragment,{children:[s,d?e.jsx(t,{}):void 0]})})},exports.addCacheBusterQueryParam=s,exports.doUrlAndLocationMatch=o,exports.useLinkExtra=l;
1
+ "use strict";var e=require("react/jsx-runtime"),r=require("react"),n=require("nanoid");const t=r.createContext({}),a=e=>{if(!globalThis.location)return!1;const r=URL.parse(e,location.origin);if(!r)return!1;const{pathname:n,search:t}=r,a=new URLSearchParams(t);a.has("y")&&a.delete("y");const o=new URLSearchParams(location.search);return o.has("y")&&o.delete("y"),`${n}?${a.toString()}`==`${location.pathname}?${o.toString()}`},o=e=>{if(!globalThis.location)return e;const r=URL.parse(e,location.origin);if(!r)return e;const t=new URLSearchParams(location.search),a=t.get("y");a&&t.delete("y");const{pathname:o,search:i}=r,c=new URLSearchParams(i);return`${o}?${i}`==`${location.pathname}?${t.toString()}`?c.set("y",a??n.nanoid()):c.set("y",n.nanoid()),`${o}?${c.toString()}`},i=()=>r.use(t);exports.Link=({children:r,disableRouterCache:n=!0,href:t="#",onClick:c,prefetch:s=!1,scroll:l=!1,...u})=>{const{NextLink:h,OwnLink:d,onLinkClicked:L}=i();return n&&(t=o(t)),e.jsx(h,{href:t,legacyBehavior:!0,passHref:!0,prefetch:s,scroll:l,children:e.jsx(d,{onClick:e=>{c&&c(e),a(t)||e.defaultPrevented||L()},...u,children:r})})},exports.LinkContext=t,exports.LinkProvider=({LoadingComponent:n,NextLink:a,OwnLink:o,children:i,loadingTimeout:c=500,pathname:s})=>{const l=r.useRef(null),[u,h]=r.useState(!1),d=r.useCallback(()=>{l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{h(!0)},c)},[c]);return r.useEffect(()=>{l.current&&clearTimeout(l.current),h(!1),scroll(0,0)},[s]),e.jsx(t,{value:{NextLink:a,OwnLink:o,onLinkClicked:()=>{d()}},children:e.jsxs(e.Fragment,{children:[i,u?e.jsx(n,{}):void 0]})})},exports.addCacheBusterQueryParam=o,exports.shouldUrlAndLocationMatch=a,exports.useLinkExtra=i;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../link-extra/src//LinkProvider.tsx","../link-extra/src//helpers.ts","../link-extra/src//useLinkExtra.ts","../link-extra/src//Link.tsx"],"sourcesContent":["import Link from 'next/link.js';\nimport { type ComponentType, type ReactNode, createContext, useEffect, useState } from 'react';\nimport { type LinkContextData, type OwnLinkProps } from '#types.js';\n\n// Needs to return explicit value\n// eslint-disable-next-line unicorn/no-useless-undefined\nconst NoopComponent = () => undefined;\n// This is a noop\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nconst noop = () => {};\n\nexport const LinkContext = createContext<LinkContextData>({\n NextLink: Link,\n OwnLink: NoopComponent,\n setLinkClicked: noop,\n});\n\nexport type LinkProviderProps = {\n LoadingComponent: ComponentType;\n NextLink: typeof Link;\n OwnLink: ComponentType<OwnLinkProps>;\n children: ReactNode | ReactNode[];\n loadingTimeout?: number;\n pathname: string;\n};\n\nlet timeoutId: NodeJS.Timeout | undefined;\n\nexport const LinkProvider = ({\n LoadingComponent,\n NextLink,\n OwnLink,\n children,\n loadingTimeout = 500,\n pathname,\n}: LinkProviderProps) => {\n const [linkClicked, setLinkClicked] = useState<boolean>(false);\n const [showLoading, setShowLoading] = useState<boolean>(false);\n\n useEffect(() => {\n if (linkClicked) {\n timeoutId = setTimeout(() => {\n setShowLoading(true);\n }, loadingTimeout);\n }\n\n return () => {\n clearTimeout(timeoutId);\n };\n // We only want to re-execute when linkClicked changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [linkClicked]);\n\n useEffect(() => {\n if (linkClicked) {\n setLinkClicked(false);\n setShowLoading(false);\n globalThis.scroll(0, 0);\n }\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // We only want to re-execute when pathname changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pathname]);\n\n return (\n <LinkContext.Provider\n value={{\n NextLink,\n OwnLink,\n setLinkClicked: clicked => {\n setLinkClicked(clicked);\n },\n }}\n >\n <>\n {children}\n {showLoading ? <LoadingComponent /> : undefined}\n </>\n </LinkContext.Provider>\n );\n};\n","import { nanoid } from 'nanoid';\n\nexport const doUrlAndLocationMatch = (url: string) => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return false;\n }\n\n const parsedUrl = URL.parse(url, globalThis.location.origin);\n\n if (!parsedUrl) {\n return false;\n }\n\n const { pathname, search } = parsedUrl;\n const urlSearchParams = new URLSearchParams(search);\n\n if (urlSearchParams.has('y')) {\n urlSearchParams.delete('y');\n }\n\n const locationSearchParams = new URLSearchParams(globalThis.location.search);\n\n if (locationSearchParams.has('y')) {\n locationSearchParams.delete('y');\n }\n\n return (\n `${pathname}?${urlSearchParams.toString()}` === `${globalThis.location.pathname}?${locationSearchParams.toString()}`\n );\n};\n\nexport const addCacheBusterQueryParam = (url: string): string => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return url;\n }\n\n const parsedUrl = URL.parse(url, globalThis.location.origin);\n\n if (!parsedUrl) {\n return url;\n }\n\n const locationSearchParams = new URLSearchParams(globalThis.location.search);\n const locationCacheBusterSearchParam = locationSearchParams.get('y');\n\n if (locationCacheBusterSearchParam) {\n locationSearchParams.delete('y');\n }\n\n const { pathname, search } = parsedUrl;\n const searchParams = new URLSearchParams(search);\n\n if (`${pathname}?${search}` === `${globalThis.location.pathname}?${locationSearchParams.toString()}`) {\n searchParams.set('y', locationCacheBusterSearchParam ?? nanoid());\n } else {\n searchParams.set('y', nanoid());\n }\n\n return `${pathname}?${searchParams.toString()}`;\n};\n","import { useContext } from 'react';\nimport { type LinkContextData } from '#types.ts';\nimport { LinkContext } from './LinkProvider.tsx';\n\nexport const useLinkExtra = (): LinkContextData => {\n return useContext(LinkContext);\n};\n","import { type AnchorHTMLAttributes, type ReactNode } from 'react';\nimport { addCacheBusterQueryParam, doUrlAndLocationMatch } from '#helpers.ts';\nimport { useLinkExtra } from './useLinkExtra.ts';\n\nexport type LinkProps<T extends object> = {\n children: ReactNode;\n disableRouterCache?: boolean;\n href?: string;\n prefetch?: boolean;\n scroll?: boolean;\n} & AnchorHTMLAttributes<HTMLAnchorElement> &\n T;\n\nexport const Link = <T extends object>({\n children,\n disableRouterCache = true,\n href = '#',\n onClick,\n prefetch = false,\n scroll = false,\n ...otherProps\n}: LinkProps<T>) => {\n const { NextLink, OwnLink, setLinkClicked } = useLinkExtra();\n\n if (disableRouterCache) {\n href = addCacheBusterQueryParam(href);\n }\n\n return (\n // @ts-expect-error Next.js types wrong for nodenext\n <NextLink href={href} legacyBehavior passHref prefetch={prefetch} scroll={scroll}>\n <OwnLink\n onClick={event => {\n if (onClick) {\n onClick(event);\n }\n\n if (!doUrlAndLocationMatch(href) && !event.defaultPrevented) {\n setLinkClicked(true);\n }\n }}\n {...otherProps}\n >\n {children}\n </OwnLink>\n </NextLink>\n );\n};\n"],"names":["LinkContext","createContext","NextLink","Link","OwnLink","setLinkClicked","timeoutId","doUrlAndLocationMatch","url","globalThis","location","parsedUrl","URL","parse","origin","pathname","search","urlSearchParams","URLSearchParams","has","delete","locationSearchParams","toString","addCacheBusterQueryParam","locationCacheBusterSearchParam","get","searchParams","set","nanoid","useLinkExtra","useContext","children","disableRouterCache","href","onClick","prefetch","scroll","otherProps","_jsx","legacyBehavior","passHref","event","defaultPrevented","LoadingComponent","loadingTimeout","linkClicked","useState","showLoading","setShowLoading","useEffect","setTimeout","clearTimeout","Provider","value","clicked","_jsxs","_Fragment","undefined"],"mappings":"iKAMA,MAKaA,EAAcC,EAAAA,cAA+B,CACxDC,SAAUC,EACVC,QAPoB,OAQpBC,eALW,SAiBb,IAAIC,QCxBSC,EAAyBC,IAGpC,IAAKC,WAAWC,SACd,OAAO,EAGT,MAAMC,EAAYC,IAAIC,MAAML,EAAKC,WAAWC,SAASI,QAErD,IAAKH,EACH,OAAO,EAGT,MAAMI,SAAEA,EAAQC,OAAEA,GAAWL,EACvBM,EAAkB,IAAIC,gBAAgBF,GAExCC,EAAgBE,IAAI,MACtBF,EAAgBG,OAAO,KAGzB,MAAMC,EAAuB,IAAIH,gBAAgBT,WAAWC,SAASM,QAMrE,OAJIK,EAAqBF,IAAI,MAC3BE,EAAqBD,OAAO,KAI5B,GAAGL,KAAYE,EAAgBK,cAAiB,GAAGb,WAAWC,SAASK,YAAYM,EAAqBC,cAI/FC,EAA4Bf,IAGvC,IAAKC,WAAWC,SACd,OAAOF,EAGT,MAAMG,EAAYC,IAAIC,MAAML,EAAKC,WAAWC,SAASI,QAErD,IAAKH,EACH,OAAOH,EAGT,MAAMa,EAAuB,IAAIH,gBAAgBT,WAAWC,SAASM,QAC/DQ,EAAiCH,EAAqBI,IAAI,KAE5DD,GACFH,EAAqBD,OAAO,KAG9B,MAAML,SAAEA,EAAQC,OAAEA,GAAWL,EACvBe,EAAe,IAAIR,gBAAgBF,GAQzC,MANI,GAAGD,KAAYC,KAAa,GAAGP,WAAWC,SAASK,YAAYM,EAAqBC,aACtFI,EAAaC,IAAI,IAAKH,GAAkCI,EAAAA,UAExDF,EAAaC,IAAI,IAAKC,EAAAA,UAGjB,GAAGb,KAAYW,EAAaJ,cC1DxBO,EAAe,IACnBC,EAAAA,WAAW9B,gBCQA,EAClB+B,WACAC,sBAAqB,EACrBC,OAAO,IACPC,UACAC,YAAW,EACXC,UAAS,KACNC,MAEH,MAAMnC,SAAEA,EAAQE,QAAEA,EAAOC,eAAEA,GAAmBwB,IAM9C,OAJIG,IACFC,EAAOV,EAAyBU,IAKhCK,EAAAA,IAACpC,EAAAA,CAAS+B,KAAMA,EAAMM,gBAAc,EAACC,UAAQ,EAACL,SAAUA,EAAUC,OAAQA,EACxEL,SAAAO,EAAAA,IAAClC,EAAAA,CACC8B,QAASO,IACHP,GACFA,EAAQO,GAGLlC,EAAsB0B,IAAUQ,EAAMC,kBACzCrC,GAAe,OAGfgC,EAEHN,SAAAA,kDHfmB,EAC1BY,mBACAzC,WACAE,UACA2B,WACAa,iBAAiB,IACjB7B,eAEA,MAAO8B,EAAaxC,GAAkByC,EAAAA,UAAkB,IACjDC,EAAaC,GAAkBF,EAAAA,UAAkB,GA+BxD,OA7BAG,EAAAA,UAAU,KACJJ,IACFvC,EAAY4C,WAAW,KACrBF,GAAe,IACdJ,IAGE,KACLO,aAAa7C,KAId,CAACuC,IAEJI,EAAAA,UAAU,KACJJ,IACFxC,GAAe,GACf2C,GAAe,GACfvC,WAAW2B,OAAO,EAAG,IAGnB9B,GACF6C,aAAa7C,IAKd,CAACS,IAGFuB,EAAAA,IAACtC,EAAYoD,SAAQ,CACnBC,MAAO,CACLnD,WACAE,UACAC,eAAgBiD,IACdjD,EAAeiD,cAInBC,EAAAA,KAAAC,WAAA,WACGzB,EACAgB,EAAcT,EAAAA,IAACK,EAAAA,CAAAA,QAAsBc"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/LinkProvider.tsx","../../src/helpers.ts","../../src/useLinkExtra.ts","../../src/Link.tsx"],"sourcesContent":["import type Link from 'next/link.js';\nimport {\n type ComponentType,\n type FC,\n type ReactNode,\n createContext,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { type LinkContextData, type NextLinkComponent, type OwnLinkProps } from '#types.js';\n\n// Context requires an initial value, but this is set in the provider so casting\n// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\nexport const LinkContext = createContext<LinkContextData>({} as LinkContextData);\n\nexport type LinkProviderProps = {\n LoadingComponent: ComponentType;\n NextLink: typeof Link;\n OwnLink: ComponentType<OwnLinkProps>;\n children: ReactNode | ReactNode[];\n loadingTimeout?: number;\n pathname: string;\n};\n\nexport const LinkProvider: FC<LinkProviderProps> = ({\n LoadingComponent,\n NextLink,\n OwnLink,\n children,\n loadingTimeout = 500,\n pathname,\n}) => {\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [showLoading, setShowLoading] = useState<boolean>(false);\n\n const onLinkClicked = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n timeoutRef.current = setTimeout(() => {\n setShowLoading(true);\n }, loadingTimeout);\n }, [loadingTimeout]);\n\n useEffect(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n // This is setting state based on pathname change\n // eslint-disable-next-line react-hooks/set-state-in-effect, @eslint-react/set-state-in-effect\n setShowLoading(false);\n scroll(0, 0);\n }, [pathname]);\n\n return (\n <LinkContext\n value={{\n // Casting due to issues marrying up prop type and context type\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n NextLink: NextLink as unknown as NextLinkComponent,\n OwnLink,\n onLinkClicked: () => {\n onLinkClicked();\n },\n }}\n >\n <>\n {children}\n {showLoading ? <LoadingComponent /> : undefined}\n </>\n </LinkContext>\n );\n};\n","import { nanoid } from 'nanoid';\n\nexport const shouldUrlAndLocationMatch = (url: string): boolean => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return false;\n }\n\n const parsedUrl = URL.parse(url, location.origin);\n\n if (!parsedUrl) {\n return false;\n }\n\n const { pathname, search } = parsedUrl;\n const urlSearchParams = new URLSearchParams(search);\n\n if (urlSearchParams.has('y')) {\n urlSearchParams.delete('y');\n }\n\n const locationSearchParams = new URLSearchParams(location.search);\n\n if (locationSearchParams.has('y')) {\n locationSearchParams.delete('y');\n }\n\n return `${pathname}?${urlSearchParams.toString()}` === `${location.pathname}?${locationSearchParams.toString()}`;\n};\n\nexport const addCacheBusterQueryParam = (url: string): string => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return url;\n }\n\n const parsedUrl = URL.parse(url, location.origin);\n\n if (!parsedUrl) {\n return url;\n }\n\n const locationSearchParams = new URLSearchParams(location.search);\n const locationCacheBusterSearchParam = locationSearchParams.get('y');\n\n if (locationCacheBusterSearchParam) {\n locationSearchParams.delete('y');\n }\n\n const { pathname, search } = parsedUrl;\n const searchParams = new URLSearchParams(search);\n\n if (`${pathname}?${search}` === `${location.pathname}?${locationSearchParams.toString()}`) {\n searchParams.set('y', locationCacheBusterSearchParam ?? nanoid());\n } else {\n searchParams.set('y', nanoid());\n }\n\n return `${pathname}?${searchParams.toString()}`;\n};\n","import { use } from 'react';\nimport { type LinkContextData } from '#types.ts';\nimport { LinkContext } from './LinkProvider.tsx';\n\nexport const useLinkExtra = (): LinkContextData => {\n return use(LinkContext);\n};\n","import { type AnchorHTMLAttributes, type JSX, type ReactNode } from 'react';\nimport { addCacheBusterQueryParam, shouldUrlAndLocationMatch } from '#helpers.ts';\nimport { useLinkExtra } from './useLinkExtra.ts';\n\nexport type LinkProps<T extends object> = {\n children: ReactNode;\n disableRouterCache?: boolean;\n href?: string;\n prefetch?: boolean;\n scroll?: boolean;\n} & AnchorHTMLAttributes<HTMLAnchorElement> &\n T;\n\nexport const Link = <T extends object>({\n children,\n disableRouterCache = true,\n href = '#',\n onClick,\n prefetch = false,\n scroll = false,\n ...otherProps\n}: LinkProps<T>): JSX.Element => {\n // This and the two other disables below are false positives\n // eslint-disable-next-line @eslint-react/static-components\n const { NextLink, OwnLink, onLinkClicked } = useLinkExtra();\n\n if (disableRouterCache) {\n href = addCacheBusterQueryParam(href);\n }\n\n return (\n // This needs to remain: https://github.com/vercel/next.js/discussions/76329\n // eslint-disable-next-line @typescript-eslint/no-deprecated, @eslint-react/static-components\n <NextLink href={href} legacyBehavior passHref prefetch={prefetch} scroll={scroll}>\n <OwnLink // eslint-disable-line @eslint-react/static-components\n onClick={event => {\n if (onClick) {\n onClick(event);\n }\n\n if (!shouldUrlAndLocationMatch(href) && !event.defaultPrevented) {\n onLinkClicked();\n }\n }}\n {...otherProps}\n >\n {children}\n </OwnLink>\n </NextLink>\n );\n};\n"],"names":["LinkContext","createContext","shouldUrlAndLocationMatch","url","globalThis","location","parsedUrl","URL","parse","origin","pathname","search","urlSearchParams","URLSearchParams","has","delete","locationSearchParams","toString","addCacheBusterQueryParam","locationCacheBusterSearchParam","get","searchParams","set","nanoid","useLinkExtra","use","children","disableRouterCache","href","onClick","prefetch","scroll","otherProps","NextLink","OwnLink","onLinkClicked","_jsx","legacyBehavior","passHref","event","defaultPrevented","LoadingComponent","loadingTimeout","timeoutRef","useRef","showLoading","setShowLoading","useState","useCallback","current","clearTimeout","setTimeout","useEffect","value","_jsxs","_Fragment","undefined"],"mappings":"uFAeO,MAAMA,EAAcC,EAAAA,cAA+B,CAAA,GCb7CC,EAA6BC,IAGxC,IAAKC,WAAWC,SACd,OAAO,EAGT,MAAMC,EAAYC,IAAIC,MAAML,EAAKE,SAASI,QAE1C,IAAKH,EACH,OAAO,EAGT,MAAMI,SAAEA,EAAQC,OAAEA,GAAWL,EACvBM,EAAkB,IAAIC,gBAAgBF,GAExCC,EAAgBE,IAAI,MACtBF,EAAgBG,OAAO,KAGzB,MAAMC,EAAuB,IAAIH,gBAAgBR,SAASM,QAM1D,OAJIK,EAAqBF,IAAI,MAC3BE,EAAqBD,OAAO,KAGvB,GAAGL,KAAYE,EAAgBK,cAAiB,GAAGZ,SAASK,YAAYM,EAAqBC,cAGzFC,EAA4Bf,IAGvC,IAAKC,WAAWC,SACd,OAAOF,EAGT,MAAMG,EAAYC,IAAIC,MAAML,EAAKE,SAASI,QAE1C,IAAKH,EACH,OAAOH,EAGT,MAAMa,EAAuB,IAAIH,gBAAgBR,SAASM,QACpDQ,EAAiCH,EAAqBI,IAAI,KAE5DD,GACFH,EAAqBD,OAAO,KAG9B,MAAML,SAAEA,EAAQC,OAAEA,GAAWL,EACvBe,EAAe,IAAIR,gBAAgBF,GAQzC,MANI,GAAGD,KAAYC,KAAa,GAAGN,SAASK,YAAYM,EAAqBC,aAC3EI,EAAaC,IAAI,IAAKH,GAAkCI,EAAAA,UAExDF,EAAaC,IAAI,IAAKC,EAAAA,UAGjB,GAAGb,KAAYW,EAAaJ,cCxDxBO,EAAe,IACnBC,EAAAA,IAAIzB,gBCQO,EAClB0B,WACAC,sBAAqB,EACrBC,OAAO,IACPC,UACAC,YAAW,EACXC,UAAS,KACNC,MAIH,MAAMC,SAAEA,EAAQC,QAAEA,EAAOC,cAAEA,GAAkBX,IAM7C,OAJIG,IACFC,EAAOV,EAAyBU,IAMhCQ,EAAAA,IAACH,EAAAA,CAASL,KAAMA,EAAMS,gBAAc,EAACC,UAAQ,EAACR,SAAUA,EAAUC,OAAQA,WACxEK,EAAAA,IAACF,GACCL,QAASU,IACHV,GACFA,EAAQU,GAGLrC,EAA0B0B,IAAUW,EAAMC,kBAC7CL,QAGAH,EAEHN,SAAAA,kDHpB0C,EACjDe,mBACAR,WACAC,UACAR,WACAgB,iBAAiB,IACjBhC,eAEA,MAAMiC,EAAaC,EAAAA,OAA6C,OACzDC,EAAaC,GAAkBC,EAAAA,UAAkB,GAElDZ,EAAgBa,EAAAA,YAAY,KAC5BL,EAAWM,SACbC,aAAaP,EAAWM,SAG1BN,EAAWM,QAAUE,WAAW,KAC9BL,GAAe,IACdJ,IACF,CAACA,IAaJ,OAXAU,EAAAA,UAAU,KACJT,EAAWM,SACbC,aAAaP,EAAWM,SAK1BH,GAAe,GACff,OAAO,EAAG,IACT,CAACrB,IAGF0B,EAAAA,IAACpC,EAAAA,CACCqD,MAAO,CAGLpB,SAAUA,EACVC,UACAC,cAAe,KACbA,eAIJmB,EAAAA,KAAAC,WAAA,WACG7B,EACAmB,EAAcT,EAAAA,IAACK,EAAAA,CAAAA,QAAsBe"}
@@ -1,2 +1,2 @@
1
- import{jsx as e,jsxs as n,Fragment as t}from"react/jsx-runtime";import r from"next/link.js";import{createContext as o,useState as i,useEffect as a,useContext as l}from"react";import"core-js/modules/web.url.parse.js";import{nanoid as c}from"nanoid";const s=o({NextLink:r,OwnLink:()=>{},setLinkClicked:()=>{}});let h;const m=({LoadingComponent:r,NextLink:o,OwnLink:l,children:c,loadingTimeout:m=500,pathname:d})=>{const[g,p]=i(!1),[u,L]=i(!1);return a(()=>(g&&(h=setTimeout(()=>{L(!0)},m)),()=>{clearTimeout(h)}),[g]),a(()=>{g&&(p(!1),L(!1),globalThis.scroll(0,0)),h&&clearTimeout(h)},[d]),e(s.Provider,{value:{NextLink:o,OwnLink:l,setLinkClicked:e=>{p(e)}},children:n(t,{children:[c,u?e(r,{}):void 0]})})},d=e=>{if(!globalThis.location)return!1;const n=URL.parse(e,globalThis.location.origin);if(!n)return!1;const{pathname:t,search:r}=n,o=new URLSearchParams(r);o.has("y")&&o.delete("y");const i=new URLSearchParams(globalThis.location.search);return i.has("y")&&i.delete("y"),`${t}?${o.toString()}`==`${globalThis.location.pathname}?${i.toString()}`},g=e=>{if(!globalThis.location)return e;const n=URL.parse(e,globalThis.location.origin);if(!n)return e;const t=new URLSearchParams(globalThis.location.search),r=t.get("y");r&&t.delete("y");const{pathname:o,search:i}=n,a=new URLSearchParams(i);return`${o}?${i}`==`${globalThis.location.pathname}?${t.toString()}`?a.set("y",r??c()):a.set("y",c()),`${o}?${a.toString()}`},p=()=>l(s),u=({children:n,disableRouterCache:t=!0,href:r="#",onClick:o,prefetch:i=!1,scroll:a=!1,...l})=>{const{NextLink:c,OwnLink:s,setLinkClicked:h}=p();return t&&(r=g(r)),e(c,{href:r,legacyBehavior:!0,passHref:!0,prefetch:i,scroll:a,children:e(s,{onClick:e=>{o&&o(e),d(r)||e.defaultPrevented||h(!0)},...l,children:n})})};export{u as Link,s as LinkContext,m as LinkProvider,g as addCacheBusterQueryParam,d as doUrlAndLocationMatch,p as useLinkExtra};
1
+ import{jsx as e,jsxs as n,Fragment as r}from"react/jsx-runtime";import{createContext as t,useRef as o,useState as a,useCallback as i,useEffect as c,use as l}from"react";import{nanoid as s}from"nanoid";const h=t({}),u=({LoadingComponent:t,NextLink:l,OwnLink:s,children:u,loadingTimeout:m=500,pathname:d})=>{const p=o(null),[L,f]=a(!1),g=i(()=>{p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{f(!0)},m)},[m]);return c(()=>{p.current&&clearTimeout(p.current),f(!1),scroll(0,0)},[d]),e(h,{value:{NextLink:l,OwnLink:s,onLinkClicked:()=>{g()}},children:n(r,{children:[u,L?e(t,{}):void 0]})})},m=e=>{if(!globalThis.location)return!1;const n=URL.parse(e,location.origin);if(!n)return!1;const{pathname:r,search:t}=n,o=new URLSearchParams(t);o.has("y")&&o.delete("y");const a=new URLSearchParams(location.search);return a.has("y")&&a.delete("y"),`${r}?${o.toString()}`==`${location.pathname}?${a.toString()}`},d=e=>{if(!globalThis.location)return e;const n=URL.parse(e,location.origin);if(!n)return e;const r=new URLSearchParams(location.search),t=r.get("y");t&&r.delete("y");const{pathname:o,search:a}=n,i=new URLSearchParams(a);return`${o}?${a}`==`${location.pathname}?${r.toString()}`?i.set("y",t??s()):i.set("y",s()),`${o}?${i.toString()}`},p=()=>l(h),L=({children:n,disableRouterCache:r=!0,href:t="#",onClick:o,prefetch:a=!1,scroll:i=!1,...c})=>{const{NextLink:l,OwnLink:s,onLinkClicked:h}=p();return r&&(t=d(t)),e(l,{href:t,legacyBehavior:!0,passHref:!0,prefetch:a,scroll:i,children:e(s,{onClick:e=>{o&&o(e),m(t)||e.defaultPrevented||h()},...c,children:n})})};export{L as Link,h as LinkContext,u as LinkProvider,d as addCacheBusterQueryParam,m as shouldUrlAndLocationMatch,p as useLinkExtra};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../link-extra/src//LinkProvider.tsx","../link-extra/src//helpers.ts","../link-extra/src//useLinkExtra.ts","../link-extra/src//Link.tsx"],"sourcesContent":["import Link from 'next/link.js';\nimport { type ComponentType, type ReactNode, createContext, useEffect, useState } from 'react';\nimport { type LinkContextData, type OwnLinkProps } from '#types.js';\n\n// Needs to return explicit value\n// eslint-disable-next-line unicorn/no-useless-undefined\nconst NoopComponent = () => undefined;\n// This is a noop\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nconst noop = () => {};\n\nexport const LinkContext = createContext<LinkContextData>({\n NextLink: Link,\n OwnLink: NoopComponent,\n setLinkClicked: noop,\n});\n\nexport type LinkProviderProps = {\n LoadingComponent: ComponentType;\n NextLink: typeof Link;\n OwnLink: ComponentType<OwnLinkProps>;\n children: ReactNode | ReactNode[];\n loadingTimeout?: number;\n pathname: string;\n};\n\nlet timeoutId: NodeJS.Timeout | undefined;\n\nexport const LinkProvider = ({\n LoadingComponent,\n NextLink,\n OwnLink,\n children,\n loadingTimeout = 500,\n pathname,\n}: LinkProviderProps) => {\n const [linkClicked, setLinkClicked] = useState<boolean>(false);\n const [showLoading, setShowLoading] = useState<boolean>(false);\n\n useEffect(() => {\n if (linkClicked) {\n timeoutId = setTimeout(() => {\n setShowLoading(true);\n }, loadingTimeout);\n }\n\n return () => {\n clearTimeout(timeoutId);\n };\n // We only want to re-execute when linkClicked changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [linkClicked]);\n\n useEffect(() => {\n if (linkClicked) {\n setLinkClicked(false);\n setShowLoading(false);\n globalThis.scroll(0, 0);\n }\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // We only want to re-execute when pathname changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pathname]);\n\n return (\n <LinkContext.Provider\n value={{\n NextLink,\n OwnLink,\n setLinkClicked: clicked => {\n setLinkClicked(clicked);\n },\n }}\n >\n <>\n {children}\n {showLoading ? <LoadingComponent /> : undefined}\n </>\n </LinkContext.Provider>\n );\n};\n","import { nanoid } from 'nanoid';\n\nexport const doUrlAndLocationMatch = (url: string) => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return false;\n }\n\n const parsedUrl = URL.parse(url, globalThis.location.origin);\n\n if (!parsedUrl) {\n return false;\n }\n\n const { pathname, search } = parsedUrl;\n const urlSearchParams = new URLSearchParams(search);\n\n if (urlSearchParams.has('y')) {\n urlSearchParams.delete('y');\n }\n\n const locationSearchParams = new URLSearchParams(globalThis.location.search);\n\n if (locationSearchParams.has('y')) {\n locationSearchParams.delete('y');\n }\n\n return (\n `${pathname}?${urlSearchParams.toString()}` === `${globalThis.location.pathname}?${locationSearchParams.toString()}`\n );\n};\n\nexport const addCacheBusterQueryParam = (url: string): string => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return url;\n }\n\n const parsedUrl = URL.parse(url, globalThis.location.origin);\n\n if (!parsedUrl) {\n return url;\n }\n\n const locationSearchParams = new URLSearchParams(globalThis.location.search);\n const locationCacheBusterSearchParam = locationSearchParams.get('y');\n\n if (locationCacheBusterSearchParam) {\n locationSearchParams.delete('y');\n }\n\n const { pathname, search } = parsedUrl;\n const searchParams = new URLSearchParams(search);\n\n if (`${pathname}?${search}` === `${globalThis.location.pathname}?${locationSearchParams.toString()}`) {\n searchParams.set('y', locationCacheBusterSearchParam ?? nanoid());\n } else {\n searchParams.set('y', nanoid());\n }\n\n return `${pathname}?${searchParams.toString()}`;\n};\n","import { useContext } from 'react';\nimport { type LinkContextData } from '#types.ts';\nimport { LinkContext } from './LinkProvider.tsx';\n\nexport const useLinkExtra = (): LinkContextData => {\n return useContext(LinkContext);\n};\n","import { type AnchorHTMLAttributes, type ReactNode } from 'react';\nimport { addCacheBusterQueryParam, doUrlAndLocationMatch } from '#helpers.ts';\nimport { useLinkExtra } from './useLinkExtra.ts';\n\nexport type LinkProps<T extends object> = {\n children: ReactNode;\n disableRouterCache?: boolean;\n href?: string;\n prefetch?: boolean;\n scroll?: boolean;\n} & AnchorHTMLAttributes<HTMLAnchorElement> &\n T;\n\nexport const Link = <T extends object>({\n children,\n disableRouterCache = true,\n href = '#',\n onClick,\n prefetch = false,\n scroll = false,\n ...otherProps\n}: LinkProps<T>) => {\n const { NextLink, OwnLink, setLinkClicked } = useLinkExtra();\n\n if (disableRouterCache) {\n href = addCacheBusterQueryParam(href);\n }\n\n return (\n // @ts-expect-error Next.js types wrong for nodenext\n <NextLink href={href} legacyBehavior passHref prefetch={prefetch} scroll={scroll}>\n <OwnLink\n onClick={event => {\n if (onClick) {\n onClick(event);\n }\n\n if (!doUrlAndLocationMatch(href) && !event.defaultPrevented) {\n setLinkClicked(true);\n }\n }}\n {...otherProps}\n >\n {children}\n </OwnLink>\n </NextLink>\n );\n};\n"],"names":["LinkContext","createContext","NextLink","Link","OwnLink","setLinkClicked","timeoutId","LinkProvider","LoadingComponent","children","loadingTimeout","pathname","linkClicked","useState","showLoading","setShowLoading","useEffect","setTimeout","clearTimeout","globalThis","scroll","_jsx","Provider","value","clicked","_jsxs","_Fragment","undefined","doUrlAndLocationMatch","url","location","parsedUrl","URL","parse","origin","search","urlSearchParams","URLSearchParams","has","delete","locationSearchParams","toString","addCacheBusterQueryParam","locationCacheBusterSearchParam","get","searchParams","set","nanoid","useLinkExtra","useContext","disableRouterCache","href","onClick","prefetch","otherProps","legacyBehavior","passHref","event","defaultPrevented"],"mappings":"wPAMA,MAKaA,EAAcC,EAA+B,CACxDC,SAAUC,EACVC,QAPoB,OAQpBC,eALW,SAiBb,IAAIC,QAESC,EAAe,EAC1BC,mBACAN,WACAE,UACAK,WACAC,iBAAiB,IACjBC,eAEA,MAAOC,EAAaP,GAAkBQ,GAAkB,IACjDC,EAAaC,GAAkBF,GAAkB,GA+BxD,OA7BAG,EAAU,KACJJ,IACFN,EAAYW,WAAW,KACrBF,GAAe,IACdL,IAGE,KACLQ,aAAaZ,KAId,CAACM,IAEJI,EAAU,KACJJ,IACFP,GAAe,GACfU,GAAe,GACfI,WAAWC,OAAO,EAAG,IAGnBd,GACFY,aAAaZ,IAKd,CAACK,IAGFU,EAACrB,EAAYsB,SAAQ,CACnBC,MAAO,CACLrB,WACAE,UACAC,eAAgBmB,IACdnB,EAAemB,cAInBC,EAAAC,EAAA,WACGjB,EACAK,EAAcO,EAACb,EAAAA,CAAAA,QAAsBmB,QC9EjCC,EAAyBC,IAGpC,IAAKV,WAAWW,SACd,OAAO,EAGT,MAAMC,EAAYC,IAAIC,MAAMJ,EAAKV,WAAWW,SAASI,QAErD,IAAKH,EACH,OAAO,EAGT,MAAMpB,SAAEA,EAAQwB,OAAEA,GAAWJ,EACvBK,EAAkB,IAAIC,gBAAgBF,GAExCC,EAAgBE,IAAI,MACtBF,EAAgBG,OAAO,KAGzB,MAAMC,EAAuB,IAAIH,gBAAgBlB,WAAWW,SAASK,QAMrE,OAJIK,EAAqBF,IAAI,MAC3BE,EAAqBD,OAAO,KAI5B,GAAG5B,KAAYyB,EAAgBK,cAAiB,GAAGtB,WAAWW,SAASnB,YAAY6B,EAAqBC,cAI/FC,EAA4Bb,IAGvC,IAAKV,WAAWW,SACd,OAAOD,EAGT,MAAME,EAAYC,IAAIC,MAAMJ,EAAKV,WAAWW,SAASI,QAErD,IAAKH,EACH,OAAOF,EAGT,MAAMW,EAAuB,IAAIH,gBAAgBlB,WAAWW,SAASK,QAC/DQ,EAAiCH,EAAqBI,IAAI,KAE5DD,GACFH,EAAqBD,OAAO,KAG9B,MAAM5B,SAAEA,EAAQwB,OAAEA,GAAWJ,EACvBc,EAAe,IAAIR,gBAAgBF,GAQzC,MANI,GAAGxB,KAAYwB,KAAa,GAAGhB,WAAWW,SAASnB,YAAY6B,EAAqBC,aACtFI,EAAaC,IAAI,IAAKH,GAAkCI,KAExDF,EAAaC,IAAI,IAAKC,KAGjB,GAAGpC,KAAYkC,EAAaJ,cC1DxBO,EAAe,IACnBC,EAAWjD,GCQPG,EAAO,EAClBM,WACAyC,sBAAqB,EACrBC,OAAO,IACPC,UACAC,YAAW,EACXjC,UAAS,KACNkC,MAEH,MAAMpD,SAAEA,EAAQE,QAAEA,EAAOC,eAAEA,GAAmB2C,IAM9C,OAJIE,IACFC,EAAOT,EAAyBS,IAKhC9B,EAACnB,EAAAA,CAASiD,KAAMA,EAAMI,gBAAc,EAACC,UAAQ,EAACH,SAAUA,EAAUjC,OAAQA,EACxEX,SAAAY,EAACjB,EAAAA,CACCgD,QAASK,IACHL,GACFA,EAAQK,GAGL7B,EAAsBuB,IAAUM,EAAMC,kBACzCrD,GAAe,OAGfiD,EAEH7C,SAAAA"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/LinkProvider.tsx","../../src/helpers.ts","../../src/useLinkExtra.ts","../../src/Link.tsx"],"sourcesContent":["import type Link from 'next/link.js';\nimport {\n type ComponentType,\n type FC,\n type ReactNode,\n createContext,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { type LinkContextData, type NextLinkComponent, type OwnLinkProps } from '#types.js';\n\n// Context requires an initial value, but this is set in the provider so casting\n// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\nexport const LinkContext = createContext<LinkContextData>({} as LinkContextData);\n\nexport type LinkProviderProps = {\n LoadingComponent: ComponentType;\n NextLink: typeof Link;\n OwnLink: ComponentType<OwnLinkProps>;\n children: ReactNode | ReactNode[];\n loadingTimeout?: number;\n pathname: string;\n};\n\nexport const LinkProvider: FC<LinkProviderProps> = ({\n LoadingComponent,\n NextLink,\n OwnLink,\n children,\n loadingTimeout = 500,\n pathname,\n}) => {\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [showLoading, setShowLoading] = useState<boolean>(false);\n\n const onLinkClicked = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n timeoutRef.current = setTimeout(() => {\n setShowLoading(true);\n }, loadingTimeout);\n }, [loadingTimeout]);\n\n useEffect(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n // This is setting state based on pathname change\n // eslint-disable-next-line react-hooks/set-state-in-effect, @eslint-react/set-state-in-effect\n setShowLoading(false);\n scroll(0, 0);\n }, [pathname]);\n\n return (\n <LinkContext\n value={{\n // Casting due to issues marrying up prop type and context type\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n NextLink: NextLink as unknown as NextLinkComponent,\n OwnLink,\n onLinkClicked: () => {\n onLinkClicked();\n },\n }}\n >\n <>\n {children}\n {showLoading ? <LoadingComponent /> : undefined}\n </>\n </LinkContext>\n );\n};\n","import { nanoid } from 'nanoid';\n\nexport const shouldUrlAndLocationMatch = (url: string): boolean => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return false;\n }\n\n const parsedUrl = URL.parse(url, location.origin);\n\n if (!parsedUrl) {\n return false;\n }\n\n const { pathname, search } = parsedUrl;\n const urlSearchParams = new URLSearchParams(search);\n\n if (urlSearchParams.has('y')) {\n urlSearchParams.delete('y');\n }\n\n const locationSearchParams = new URLSearchParams(location.search);\n\n if (locationSearchParams.has('y')) {\n locationSearchParams.delete('y');\n }\n\n return `${pathname}?${urlSearchParams.toString()}` === `${location.pathname}?${locationSearchParams.toString()}`;\n};\n\nexport const addCacheBusterQueryParam = (url: string): string => {\n // It is possible for this to be undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!globalThis.location) {\n return url;\n }\n\n const parsedUrl = URL.parse(url, location.origin);\n\n if (!parsedUrl) {\n return url;\n }\n\n const locationSearchParams = new URLSearchParams(location.search);\n const locationCacheBusterSearchParam = locationSearchParams.get('y');\n\n if (locationCacheBusterSearchParam) {\n locationSearchParams.delete('y');\n }\n\n const { pathname, search } = parsedUrl;\n const searchParams = new URLSearchParams(search);\n\n if (`${pathname}?${search}` === `${location.pathname}?${locationSearchParams.toString()}`) {\n searchParams.set('y', locationCacheBusterSearchParam ?? nanoid());\n } else {\n searchParams.set('y', nanoid());\n }\n\n return `${pathname}?${searchParams.toString()}`;\n};\n","import { use } from 'react';\nimport { type LinkContextData } from '#types.ts';\nimport { LinkContext } from './LinkProvider.tsx';\n\nexport const useLinkExtra = (): LinkContextData => {\n return use(LinkContext);\n};\n","import { type AnchorHTMLAttributes, type JSX, type ReactNode } from 'react';\nimport { addCacheBusterQueryParam, shouldUrlAndLocationMatch } from '#helpers.ts';\nimport { useLinkExtra } from './useLinkExtra.ts';\n\nexport type LinkProps<T extends object> = {\n children: ReactNode;\n disableRouterCache?: boolean;\n href?: string;\n prefetch?: boolean;\n scroll?: boolean;\n} & AnchorHTMLAttributes<HTMLAnchorElement> &\n T;\n\nexport const Link = <T extends object>({\n children,\n disableRouterCache = true,\n href = '#',\n onClick,\n prefetch = false,\n scroll = false,\n ...otherProps\n}: LinkProps<T>): JSX.Element => {\n // This and the two other disables below are false positives\n // eslint-disable-next-line @eslint-react/static-components\n const { NextLink, OwnLink, onLinkClicked } = useLinkExtra();\n\n if (disableRouterCache) {\n href = addCacheBusterQueryParam(href);\n }\n\n return (\n // This needs to remain: https://github.com/vercel/next.js/discussions/76329\n // eslint-disable-next-line @typescript-eslint/no-deprecated, @eslint-react/static-components\n <NextLink href={href} legacyBehavior passHref prefetch={prefetch} scroll={scroll}>\n <OwnLink // eslint-disable-line @eslint-react/static-components\n onClick={event => {\n if (onClick) {\n onClick(event);\n }\n\n if (!shouldUrlAndLocationMatch(href) && !event.defaultPrevented) {\n onLinkClicked();\n }\n }}\n {...otherProps}\n >\n {children}\n </OwnLink>\n </NextLink>\n );\n};\n"],"names":["LinkContext","createContext","LinkProvider","LoadingComponent","NextLink","OwnLink","children","loadingTimeout","pathname","timeoutRef","useRef","showLoading","setShowLoading","useState","onLinkClicked","useCallback","current","clearTimeout","setTimeout","useEffect","scroll","_jsx","value","_jsxs","_Fragment","undefined","shouldUrlAndLocationMatch","url","globalThis","location","parsedUrl","URL","parse","origin","search","urlSearchParams","URLSearchParams","has","delete","locationSearchParams","toString","addCacheBusterQueryParam","locationCacheBusterSearchParam","get","searchParams","set","nanoid","useLinkExtra","use","Link","disableRouterCache","href","onClick","prefetch","otherProps","legacyBehavior","passHref","event","defaultPrevented"],"mappings":"yMAeO,MAAMA,EAAcC,EAA+B,CAAA,GAW7CC,EAAsC,EACjDC,mBACAC,WACAC,UACAC,WACAC,iBAAiB,IACjBC,eAEA,MAAMC,EAAaC,EAA6C,OACzDC,EAAaC,GAAkBC,GAAkB,GAElDC,EAAgBC,EAAY,KAC5BN,EAAWO,SACbC,aAAaR,EAAWO,SAG1BP,EAAWO,QAAUE,WAAW,KAC9BN,GAAe,IACdL,IACF,CAACA,IAaJ,OAXAY,EAAU,KACJV,EAAWO,SACbC,aAAaR,EAAWO,SAK1BJ,GAAe,GACfQ,OAAO,EAAG,IACT,CAACZ,IAGFa,EAACrB,EAAAA,CACCsB,MAAO,CAGLlB,SAAUA,EACVC,UACAS,cAAe,KACbA,eAIJS,EAAAC,EAAA,WACGlB,EACAK,EAAcU,EAAClB,EAAAA,CAAAA,QAAsBsB,QCtEjCC,EAA6BC,IAGxC,IAAKC,WAAWC,SACd,OAAO,EAGT,MAAMC,EAAYC,IAAIC,MAAML,EAAKE,SAASI,QAE1C,IAAKH,EACH,OAAO,EAGT,MAAMtB,SAAEA,EAAQ0B,OAAEA,GAAWJ,EACvBK,EAAkB,IAAIC,gBAAgBF,GAExCC,EAAgBE,IAAI,MACtBF,EAAgBG,OAAO,KAGzB,MAAMC,EAAuB,IAAIH,gBAAgBP,SAASK,QAM1D,OAJIK,EAAqBF,IAAI,MAC3BE,EAAqBD,OAAO,KAGvB,GAAG9B,KAAY2B,EAAgBK,cAAiB,GAAGX,SAASrB,YAAY+B,EAAqBC,cAGzFC,EAA4Bd,IAGvC,IAAKC,WAAWC,SACd,OAAOF,EAGT,MAAMG,EAAYC,IAAIC,MAAML,EAAKE,SAASI,QAE1C,IAAKH,EACH,OAAOH,EAGT,MAAMY,EAAuB,IAAIH,gBAAgBP,SAASK,QACpDQ,EAAiCH,EAAqBI,IAAI,KAE5DD,GACFH,EAAqBD,OAAO,KAG9B,MAAM9B,SAAEA,EAAQ0B,OAAEA,GAAWJ,EACvBc,EAAe,IAAIR,gBAAgBF,GAQzC,MANI,GAAG1B,KAAY0B,KAAa,GAAGL,SAASrB,YAAY+B,EAAqBC,aAC3EI,EAAaC,IAAI,IAAKH,GAAkCI,KAExDF,EAAaC,IAAI,IAAKC,KAGjB,GAAGtC,KAAYoC,EAAaJ,cCxDxBO,EAAe,IACnBC,EAAIhD,GCQAiD,EAAO,EAClB3C,WACA4C,sBAAqB,EACrBC,OAAO,IACPC,UACAC,YAAW,EACXjC,UAAS,KACNkC,MAIH,MAAMlD,SAAEA,EAAQC,QAAEA,EAAOS,cAAEA,GAAkBiC,IAM7C,OAJIG,IACFC,EAAOV,EAAyBU,IAMhC9B,EAACjB,EAAAA,CAAS+C,KAAMA,EAAMI,gBAAc,EAACC,UAAQ,EAACH,SAAUA,EAAUjC,OAAQA,WACxEC,EAAChB,GACC+C,QAASK,IACHL,GACFA,EAAQK,GAGL/B,EAA0ByB,IAAUM,EAAMC,kBAC7C5C,QAGAwC,EAEHhD,SAAAA"}
@@ -1,46 +1,46 @@
1
1
  -----------------------------
2
2
  Rollup File Analysis
3
3
  -----------------------------
4
- bundle size: 4.581 KB
5
- original size: 5.51 KB
6
- code reduction: 16.86 %
4
+ bundle size: 4.759 KB
5
+ original size: 5.717 KB
6
+ code reduction: 16.76 %
7
7
  module count: 5
8
8
 
9
- ███████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
10
- file: /src/LinkProvider.tsx
11
- bundle space: 39.66 %
12
- rendered size: 1.817 KB
13
- original size: 2.107 KB
14
- code reduction: 13.76 %
9
+ ██████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
10
+ file: /src/helpers.ts
11
+ bundle space: 36.81 %
12
+ rendered size: 1.752 KB
13
+ original size: 1.739 KB
14
+ code reduction: 0 %
15
15
  dependents: 2
16
- - /src/useLinkExtra.ts
16
+ - /src/Link.tsx
17
17
  - /src/index.ts
18
18
 
19
- ███████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
20
- file: /src/helpers.ts
21
- bundle space: 39.29 %
22
- rendered size: 1.8 KB
23
- original size: 1.802 KB
24
- code reduction: 0.11 %
19
+ █████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
20
+ file: /src/LinkProvider.tsx
21
+ bundle space: 35.91 %
22
+ rendered size: 1.709 KB
23
+ original size: 2.064 KB
24
+ code reduction: 17.2 %
25
25
  dependents: 2
26
- - /src/Link.tsx
26
+ - /src/useLinkExtra.ts
27
27
  - /src/index.ts
28
28
 
29
- █████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
29
+ ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
30
30
  file: /src/Link.tsx
31
- bundle space: 19.62 %
32
- rendered size: 899 Bytes
33
- original size: 1.217 KB
34
- code reduction: 26.13 %
31
+ bundle space: 25.93 %
32
+ rendered size: 1.234 KB
33
+ original size: 1.544 KB
34
+ code reduction: 20.08 %
35
35
  dependents: 1
36
36
  - /src/index.ts
37
37
 
38
38
  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
39
39
  file: /src/useLinkExtra.ts
40
- bundle space: 1.42 %
41
- rendered size: 65 Bytes
42
- original size: 227 Bytes
43
- code reduction: 71.37 %
40
+ bundle space: 1.34 %
41
+ rendered size: 64 Bytes
42
+ original size: 213 Bytes
43
+ code reduction: 69.95 %
44
44
  dependents: 2
45
45
  - /src/Link.tsx
46
46
  - /src/index.ts
@@ -1,4 +1,4 @@
1
- import { type AnchorHTMLAttributes, type ReactNode } from 'react';
1
+ import { type AnchorHTMLAttributes, type JSX, type ReactNode } from 'react';
2
2
  export type LinkProps<T extends object> = {
3
3
  children: ReactNode;
4
4
  disableRouterCache?: boolean;
@@ -6,5 +6,5 @@ export type LinkProps<T extends object> = {
6
6
  prefetch?: boolean;
7
7
  scroll?: boolean;
8
8
  } & AnchorHTMLAttributes<HTMLAnchorElement> & T;
9
- export declare const Link: <T extends object>({ children, disableRouterCache, href, onClick, prefetch, scroll, ...otherProps }: LinkProps<T>) => import("react/jsx-runtime").JSX.Element;
9
+ export declare const Link: <T extends object>({ children, disableRouterCache, href, onClick, prefetch, scroll, ...otherProps }: LinkProps<T>) => JSX.Element;
10
10
  //# sourceMappingURL=Link.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Link.d.cts","sourceRoot":"","sources":["../../../src/Link.ctsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,GACzC,CAAC,CAAC;AAEJ,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,kFAQpC,SAAS,CAAC,CAAC,CAAC,4CA0Bd,CAAC"}
1
+ {"version":3,"file":"Link.d.cts","sourceRoot":"","sources":["../../../src/Link.ctsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI5E,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,GACzC,CAAC,CAAC;AAEJ,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,kFAQpC,SAAS,CAAC,CAAC,CAAC,KAAG,GAAG,CAAC,OA6BrB,CAAC"}
@@ -1,5 +1,5 @@
1
- import Link from 'next/link.js';
2
- import { type ComponentType, type ReactNode } from 'react';
1
+ import type Link from 'next/link.js';
2
+ import { type ComponentType, type FC, type ReactNode } from 'react';
3
3
  import { type LinkContextData, type OwnLinkProps } from '#types.js';
4
4
  export declare const LinkContext: import("react").Context<LinkContextData>;
5
5
  export type LinkProviderProps = {
@@ -10,5 +10,5 @@ export type LinkProviderProps = {
10
10
  loadingTimeout?: number;
11
11
  pathname: string;
12
12
  };
13
- export declare const LinkProvider: ({ LoadingComponent, NextLink, OwnLink, children, loadingTimeout, pathname, }: LinkProviderProps) => import("react/jsx-runtime").JSX.Element;
13
+ export declare const LinkProvider: FC<LinkProviderProps>;
14
14
  //# sourceMappingURL=LinkProvider.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinkProvider.d.cts","sourceRoot":"","sources":["../../../src/LinkProvider.ctsx"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,cAAc,CAAC;AAChC,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAsC,MAAM,OAAO,CAAC;AAC/F,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AASpE,eAAO,MAAM,WAAW,0CAItB,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gBAAgB,EAAE,aAAa,CAAC;IAChC,QAAQ,EAAE,OAAO,IAAI,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,eAAO,MAAM,YAAY,GAAI,8EAO1B,iBAAiB,4CAiDnB,CAAC"}
1
+ {"version":3,"file":"LinkProvider.d.cts","sourceRoot":"","sources":["../../../src/LinkProvider.ctsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,cAAc,CAAC;AACrC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,EAAE,EACP,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,eAAe,EAA0B,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAI5F,eAAO,MAAM,WAAW,0CAAwD,CAAC;AAEjF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gBAAgB,EAAE,aAAa,CAAC;IAChC,QAAQ,EAAE,OAAO,IAAI,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAkD9C,CAAC"}
@@ -1,3 +1,3 @@
1
- export declare const doUrlAndLocationMatch: (url: string) => boolean;
1
+ export declare const shouldUrlAndLocationMatch: (url: string) => boolean;
2
2
  export declare const addCacheBusterQueryParam: (url: string) => string;
3
3
  //# sourceMappingURL=helpers.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.cts","sourceRoot":"","sources":["../../../src/helpers.cts"],"names":[],"mappings":"AAEA,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,YA6BhD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,KAAG,MA8BtD,CAAC"}
1
+ {"version":3,"file":"helpers.d.cts","sourceRoot":"","sources":["../../../src/helpers.cts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,GAAI,KAAK,MAAM,KAAG,OA2BvD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,KAAG,MA8BtD,CAAC"}
@@ -1,9 +1,12 @@
1
- import type NextLink from 'next/link.js';
2
- import { type AnchorHTMLAttributes, type ComponentType } from 'react';
1
+ import { type LinkProps } from 'next/link.js';
2
+ import { type AnchorHTMLAttributes, type ComponentType, type ReactNode } from 'react';
3
3
  export type OwnLinkProps = Record<string, any> & AnchorHTMLAttributes<HTMLAnchorElement>;
4
+ export type NextLinkComponent = ComponentType<LinkProps & {
5
+ children: ReactNode;
6
+ }>;
4
7
  export type LinkContextData = {
5
- NextLink: typeof NextLink;
8
+ NextLink: NextLinkComponent;
6
9
  OwnLink: ComponentType<AnchorHTMLAttributes<HTMLAnchorElement>>;
7
- setLinkClicked: (clicked: true) => void;
10
+ onLinkClicked: () => void;
8
11
  };
9
12
  //# sourceMappingURL=types.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../../../src/types.cts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAItE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAEzF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,OAAO,EAAE,aAAa,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAChE,cAAc,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;CACzC,CAAC"}
1
+ {"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../../../src/types.cts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAItF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAEzF,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAC3C,SAAS,GAAG;IACV,QAAQ,EAAE,SAAS,CAAC;CACrB,CACF,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,EAAE,aAAa,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAChE,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type AnchorHTMLAttributes, type ReactNode } from 'react';
1
+ import { type AnchorHTMLAttributes, type JSX, type ReactNode } from 'react';
2
2
  export type LinkProps<T extends object> = {
3
3
  children: ReactNode;
4
4
  disableRouterCache?: boolean;
@@ -6,5 +6,5 @@ export type LinkProps<T extends object> = {
6
6
  prefetch?: boolean;
7
7
  scroll?: boolean;
8
8
  } & AnchorHTMLAttributes<HTMLAnchorElement> & T;
9
- export declare const Link: <T extends object>({ children, disableRouterCache, href, onClick, prefetch, scroll, ...otherProps }: LinkProps<T>) => import("react/jsx-runtime").JSX.Element;
9
+ export declare const Link: <T extends object>({ children, disableRouterCache, href, onClick, prefetch, scroll, ...otherProps }: LinkProps<T>) => JSX.Element;
10
10
  //# sourceMappingURL=Link.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,GACzC,CAAC,CAAC;AAEJ,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,kFAQpC,SAAS,CAAC,CAAC,CAAC,4CA0Bd,CAAC"}
1
+ {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI5E,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,GACzC,CAAC,CAAC;AAEJ,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,kFAQpC,SAAS,CAAC,CAAC,CAAC,KAAG,GAAG,CAAC,OA6BrB,CAAC"}
@@ -1,5 +1,5 @@
1
- import Link from 'next/link.js';
2
- import { type ComponentType, type ReactNode } from 'react';
1
+ import type Link from 'next/link.js';
2
+ import { type ComponentType, type FC, type ReactNode } from 'react';
3
3
  import { type LinkContextData, type OwnLinkProps } from '#types.js';
4
4
  export declare const LinkContext: import("react").Context<LinkContextData>;
5
5
  export type LinkProviderProps = {
@@ -10,5 +10,5 @@ export type LinkProviderProps = {
10
10
  loadingTimeout?: number;
11
11
  pathname: string;
12
12
  };
13
- export declare const LinkProvider: ({ LoadingComponent, NextLink, OwnLink, children, loadingTimeout, pathname, }: LinkProviderProps) => import("react/jsx-runtime").JSX.Element;
13
+ export declare const LinkProvider: FC<LinkProviderProps>;
14
14
  //# sourceMappingURL=LinkProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinkProvider.d.ts","sourceRoot":"","sources":["../../../src/LinkProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,cAAc,CAAC;AAChC,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAsC,MAAM,OAAO,CAAC;AAC/F,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AASpE,eAAO,MAAM,WAAW,0CAItB,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gBAAgB,EAAE,aAAa,CAAC;IAChC,QAAQ,EAAE,OAAO,IAAI,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,eAAO,MAAM,YAAY,GAAI,8EAO1B,iBAAiB,4CAiDnB,CAAC"}
1
+ {"version":3,"file":"LinkProvider.d.ts","sourceRoot":"","sources":["../../../src/LinkProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,cAAc,CAAC;AACrC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,EAAE,EACP,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,eAAe,EAA0B,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAI5F,eAAO,MAAM,WAAW,0CAAwD,CAAC;AAEjF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gBAAgB,EAAE,aAAa,CAAC;IAChC,QAAQ,EAAE,OAAO,IAAI,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAkD9C,CAAC"}
@@ -1,3 +1,3 @@
1
- export declare const doUrlAndLocationMatch: (url: string) => boolean;
1
+ export declare const shouldUrlAndLocationMatch: (url: string) => boolean;
2
2
  export declare const addCacheBusterQueryParam: (url: string) => string;
3
3
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/helpers.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,YA6BhD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,KAAG,MA8BtD,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/helpers.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,GAAI,KAAK,MAAM,KAAG,OA2BvD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,KAAG,MA8BtD,CAAC"}
@@ -1,9 +1,12 @@
1
- import type NextLink from 'next/link.js';
2
- import { type AnchorHTMLAttributes, type ComponentType } from 'react';
1
+ import { type LinkProps } from 'next/link.js';
2
+ import { type AnchorHTMLAttributes, type ComponentType, type ReactNode } from 'react';
3
3
  export type OwnLinkProps = Record<string, any> & AnchorHTMLAttributes<HTMLAnchorElement>;
4
+ export type NextLinkComponent = ComponentType<LinkProps & {
5
+ children: ReactNode;
6
+ }>;
4
7
  export type LinkContextData = {
5
- NextLink: typeof NextLink;
8
+ NextLink: NextLinkComponent;
6
9
  OwnLink: ComponentType<AnchorHTMLAttributes<HTMLAnchorElement>>;
7
- setLinkClicked: (clicked: true) => void;
10
+ onLinkClicked: () => void;
8
11
  };
9
12
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAItE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAEzF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,OAAO,EAAE,aAAa,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAChE,cAAc,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC;CACzC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAItF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAEzF,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAC3C,SAAS,GAAG;IACV,QAAQ,EAAE,SAAS,CAAC;CACrB,CACF,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,EAAE,aAAa,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAChE,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC"}