toiljs 0.0.15 → 0.0.16

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.
Files changed (217) hide show
  1. package/.babelrc +13 -13
  2. package/.gitattributes +2 -2
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -90
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  7. package/.github/PULL_REQUEST_TEMPLATE.md +43 -43
  8. package/.github/changelog-config.json +45 -45
  9. package/.github/dependabot.yml +27 -27
  10. package/.github/workflows/ci.yml +191 -191
  11. package/.prettierrc.json +11 -11
  12. package/.vscode/settings.json +9 -9
  13. package/CHANGELOG.md +5 -5
  14. package/LICENSE +187 -187
  15. package/README.md +339 -315
  16. package/as-pect.asconfig.json +34 -34
  17. package/as-pect.config.js +65 -65
  18. package/assets/logo.svg +36 -36
  19. package/build/backend/.tsbuildinfo +1 -1
  20. package/build/cli/.tsbuildinfo +1 -1
  21. package/build/cli/index.js +0 -0
  22. package/build/client/.tsbuildinfo +1 -1
  23. package/build/client/dev/devtools.d.ts +6 -0
  24. package/build/client/dev/devtools.js +442 -0
  25. package/build/client/dev/error-overlay.d.ts +9 -0
  26. package/build/client/dev/error-overlay.js +19 -4
  27. package/build/client/navigation/prefetch.d.ts +1 -0
  28. package/build/client/navigation/prefetch.js +35 -0
  29. package/build/client/routing/Router.js +1 -1
  30. package/build/client/routing/hooks.js +6 -2
  31. package/build/client/routing/loader.d.ts +23 -0
  32. package/build/client/routing/loader.js +53 -7
  33. package/build/client/routing/mount.js +4 -3
  34. package/build/compiler/.tsbuildinfo +1 -1
  35. package/build/compiler/config.d.ts +16 -0
  36. package/build/compiler/config.js +7 -0
  37. package/build/compiler/docs.js +16 -16
  38. package/build/compiler/index.d.ts +2 -2
  39. package/build/compiler/index.js +1 -1
  40. package/build/compiler/plugin.js +156 -0
  41. package/build/compiler/prerender.d.ts +1 -0
  42. package/build/compiler/prerender.js +1 -1
  43. package/build/compiler/seo.d.ts +1 -1
  44. package/build/compiler/seo.js +5 -4
  45. package/build/compiler/ssg.js +32 -1
  46. package/build/io/.tsbuildinfo +1 -1
  47. package/build/logger/.tsbuildinfo +1 -1
  48. package/build/shared/.tsbuildinfo +1 -1
  49. package/eslint.config.js +48 -48
  50. package/examples/basic/client/404.tsx +11 -11
  51. package/examples/basic/client/components/.gitkeep +1 -1
  52. package/examples/basic/client/global-error.tsx +13 -13
  53. package/examples/basic/client/layout.tsx +25 -25
  54. package/examples/basic/client/public/images/.gitkeep +1 -1
  55. package/examples/basic/client/public/images/logo.svg +36 -36
  56. package/examples/basic/client/public/robots.txt +2 -2
  57. package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
  58. package/examples/basic/client/routes/features/error/error.tsx +16 -16
  59. package/examples/basic/client/routes/features/template/b.tsx +14 -14
  60. package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
  61. package/examples/basic/client/routes/gallery/layout.tsx +13 -13
  62. package/examples/basic/client/routes/io.tsx +24 -24
  63. package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
  64. package/examples/basic/client/routes/search.tsx +61 -61
  65. package/examples/basic/client/toil.tsx +5 -5
  66. package/package.json +155 -148
  67. package/presets/eslint.js +88 -88
  68. package/presets/no-uint8array-tostring.js +200 -200
  69. package/presets/prettier.json +18 -18
  70. package/presets/tsconfig.json +37 -37
  71. package/src/backend/index.ts +160 -160
  72. package/src/cli/proc.ts +50 -50
  73. package/src/cli/updates.ts +69 -69
  74. package/src/cli/validate.ts +31 -31
  75. package/src/client/channel/channel.ts +146 -146
  76. package/src/client/components/Form.tsx +65 -65
  77. package/src/client/components/Script.tsx +113 -113
  78. package/src/client/components/Slot.tsx +21 -21
  79. package/src/client/dev/devtools.tsx +973 -0
  80. package/src/client/dev/error-overlay.tsx +30 -4
  81. package/src/client/head/head.ts +167 -167
  82. package/src/client/head/metadata.ts +112 -112
  83. package/src/client/index.ts +89 -89
  84. package/src/client/navigation/NavLink.tsx +86 -86
  85. package/src/client/navigation/navigation.ts +235 -235
  86. package/src/client/navigation/prefetch.ts +169 -130
  87. package/src/client/navigation/scroll.ts +53 -53
  88. package/src/client/routing/Router.tsx +8 -2
  89. package/src/client/routing/action.ts +122 -122
  90. package/src/client/routing/error-boundary.tsx +43 -43
  91. package/src/client/routing/hooks.ts +21 -6
  92. package/src/client/routing/loader.ts +325 -235
  93. package/src/client/routing/match.ts +47 -47
  94. package/src/client/routing/mount.tsx +54 -52
  95. package/src/client/routing/params-context.ts +10 -10
  96. package/src/client/routing/slot-context.ts +7 -7
  97. package/src/client/search/search.ts +189 -189
  98. package/src/client/search/use-page-search.ts +73 -73
  99. package/src/client/types.ts +73 -73
  100. package/src/compiler/config.ts +219 -182
  101. package/src/compiler/docs.ts +228 -228
  102. package/src/compiler/generate.ts +394 -394
  103. package/src/compiler/index.ts +64 -57
  104. package/src/compiler/pages.ts +70 -70
  105. package/src/compiler/plugin.ts +170 -2
  106. package/src/compiler/prerender.ts +156 -156
  107. package/src/compiler/seo.ts +397 -390
  108. package/src/compiler/ssg.ts +162 -126
  109. package/src/io/BinaryReader.ts +340 -340
  110. package/src/io/BinaryWriter.ts +385 -385
  111. package/src/io/FastMap.ts +127 -127
  112. package/src/io/index.ts +11 -11
  113. package/src/io/lengths.ts +14 -14
  114. package/src/io/types.ts +18 -18
  115. package/src/logger/index.ts +22 -22
  116. package/src/server/index.ts +10 -10
  117. package/src/server/main.ts +13 -13
  118. package/src/server/tsconfig.json +4 -4
  119. package/src/shared/index.ts +10 -10
  120. package/std/client/index.d.ts +15 -15
  121. package/std/client/package.json +3 -3
  122. package/test/assembly/example.spec.ts +7 -7
  123. package/test/channel.test.ts +21 -21
  124. package/test/dom/Link.test.tsx +47 -47
  125. package/test/dom/NavLink.test.tsx +37 -37
  126. package/test/dom/error-overlay.test.tsx +44 -44
  127. package/test/dom/loader.test.tsx +121 -121
  128. package/test/dom/navigation.test.ts +59 -59
  129. package/test/dom/revalidate.test.tsx +38 -38
  130. package/test/dom/route-head.test.tsx +78 -78
  131. package/test/dom/router-loading.test.tsx +44 -44
  132. package/test/dom/scroll.test.ts +56 -56
  133. package/test/dom/use-metadata.test.tsx +58 -58
  134. package/test/io.test.ts +93 -93
  135. package/test/navlink.test.ts +28 -28
  136. package/test/placeholder.test.ts +9 -9
  137. package/test/routes.test.ts +76 -76
  138. package/test/seo.test.ts +175 -164
  139. package/test/slot-layouts.test.ts +69 -69
  140. package/test/ssg.test.ts +36 -36
  141. package/test/update.test.ts +44 -44
  142. package/test/validate.test.ts +42 -42
  143. package/toil-routes.d.ts +7 -0
  144. package/toilconfig.json +30 -30
  145. package/tsconfig.backend.json +13 -13
  146. package/tsconfig.base.json +35 -35
  147. package/tsconfig.cli.json +13 -13
  148. package/tsconfig.client.json +14 -14
  149. package/tsconfig.compiler.json +13 -13
  150. package/tsconfig.io.json +12 -12
  151. package/tsconfig.json +22 -22
  152. package/tsconfig.logger.json +12 -12
  153. package/tsconfig.server.json +10 -10
  154. package/tsconfig.shared.json +12 -12
  155. package/vitest.config.ts +26 -26
  156. package/.idea/codeStyles/Project.xml +0 -54
  157. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  158. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  159. package/.idea/modules.xml +0 -8
  160. package/.idea/prettier.xml +0 -7
  161. package/.idea/toiljs.iml +0 -8
  162. package/.idea/vcs.xml +0 -6
  163. package/.toil/entry.tsx +0 -9
  164. package/.toil/index.html +0 -12
  165. package/.toil/routes.ts +0 -9
  166. package/build/cli/configure.d.ts +0 -16
  167. package/build/cli/configure.js +0 -272
  168. package/build/cli/create.d.ts +0 -16
  169. package/build/cli/create.js +0 -420
  170. package/build/cli/diagnostics.d.ts +0 -55
  171. package/build/cli/diagnostics.js +0 -333
  172. package/build/cli/doctor.d.ts +0 -6
  173. package/build/cli/doctor.js +0 -249
  174. package/build/cli/features.d.ts +0 -25
  175. package/build/cli/features.js +0 -107
  176. package/build/cli/index.d.ts +0 -2
  177. package/build/cli/proc.d.ts +0 -6
  178. package/build/cli/proc.js +0 -31
  179. package/build/cli/ui.d.ts +0 -9
  180. package/build/cli/ui.js +0 -75
  181. package/build/cli/update.d.ts +0 -7
  182. package/build/cli/update.js +0 -117
  183. package/build/cli/updates.d.ts +0 -10
  184. package/build/cli/updates.js +0 -45
  185. package/build/cli/validate.d.ts +0 -4
  186. package/build/cli/validate.js +0 -19
  187. package/build/client/Link.d.ts +0 -8
  188. package/build/client/Link.js +0 -44
  189. package/build/client/NavLink.d.ts +0 -14
  190. package/build/client/NavLink.js +0 -37
  191. package/build/client/Router.d.ts +0 -7
  192. package/build/client/Router.js +0 -55
  193. package/build/client/channel.d.ts +0 -23
  194. package/build/client/channel.js +0 -94
  195. package/build/client/error-boundary.d.ts +0 -16
  196. package/build/client/error-boundary.js +0 -19
  197. package/build/client/head.d.ts +0 -26
  198. package/build/client/head.js +0 -87
  199. package/build/client/hooks.d.ts +0 -17
  200. package/build/client/hooks.js +0 -48
  201. package/build/client/lazy.d.ts +0 -16
  202. package/build/client/lazy.js +0 -53
  203. package/build/client/match.d.ts +0 -2
  204. package/build/client/match.js +0 -32
  205. package/build/client/mount.d.ts +0 -2
  206. package/build/client/mount.js +0 -13
  207. package/build/client/navigation.d.ts +0 -13
  208. package/build/client/navigation.js +0 -97
  209. package/build/client/params-context.d.ts +0 -2
  210. package/build/client/params-context.js +0 -2
  211. package/build/client/prefetch.d.ts +0 -11
  212. package/build/client/prefetch.js +0 -100
  213. package/build/client/runtime.d.ts +0 -31
  214. package/build/client/runtime.js +0 -112
  215. package/build/client/scroll.d.ts +0 -8
  216. package/build/client/scroll.js +0 -36
  217. package/toil-env.d.ts +0 -16
@@ -1,89 +1,89 @@
1
- /**
2
- * toiljs client runtime, published as `toiljs/client`. Re-exports the router (mount/Router/Link),
3
- * navigation hooks, prefetching, and the route types consumed by the compiler-generated entry.
4
- * Zero imports needed in user route files beyond this package.
5
- *
6
- * Internals are split by concern: route `types`, history-based `navigation`, the params
7
- * `params-context` + `hooks`, `lazy` component resolution, the `Link`/`Router` components,
8
- * `mount`, `match` (pure matcher), `prefetch` (link prefetcher), and `channel` (WebSocket helper).
9
- */
10
-
11
- export { mount } from './routing/mount.js';
12
- export { Router } from './routing/Router.js';
13
- export { Link } from './navigation/Link.js';
14
- export type { LinkProps } from './navigation/Link.js';
15
- export { NavLink, matchActive } from './navigation/NavLink.js';
16
- export type { NavLinkProps, NavLinkState } from './navigation/NavLink.js';
17
- export {
18
- navigate,
19
- back,
20
- forward,
21
- refresh,
22
- setViewTransitions,
23
- setTransitions,
24
- href,
25
- } from './navigation/navigation.js';
26
- export type { NavigateOptions } from './navigation/navigation.js';
27
- export {
28
- useParams,
29
- useNavigate,
30
- useLocation,
31
- usePathname,
32
- useSearchParams,
33
- useRouter,
34
- useNavigationPending,
35
- } from './routing/hooks.js';
36
- export type { RouterInstance } from './routing/hooks.js';
37
- export { useLoaderData, revalidate, invalidateLoaderData } from './routing/loader.js';
38
- export type {
39
- LoaderArgs,
40
- LoaderFunction,
41
- LoaderData,
42
- Revalidate,
43
- StaticParams,
44
- GenerateStaticParams,
45
- } from './routing/loader.js';
46
- export { useAction } from './routing/action.js';
47
- export type {
48
- UseActionOptions,
49
- ActionState,
50
- ActionHandle,
51
- RevalidateTarget,
52
- } from './routing/action.js';
53
- export { prefetch } from './navigation/prefetch.js';
54
- export type {
55
- RouteDef,
56
- LayoutLoader,
57
- LayoutComponentLoader,
58
- NotFoundLoader,
59
- RouteErrorProps,
60
- Register,
61
- RoutePath,
62
- Href,
63
- } from './types.js';
64
- export { matchRoute } from './routing/match.js';
65
- export type { RouteParams } from './routing/match.js';
66
- export { connectChannel, useChannel, resolveChannelUrl } from './channel/channel.js';
67
- export type { Channel, ChannelOptions, ChannelHook, ChannelData } from './channel/channel.js';
68
- export { useHead, useTitle, Head, mergeHead } from './head/head.js';
69
- export type { HeadSpec, MetaTag, LinkTag, ResolvedHead } from './head/head.js';
70
- export { resolveMetadata, useMetadata, Metadata } from './head/metadata.js';
71
- export type { GenerateMetadata, GenerateMetadataArgs, OpenGraph } from './head/metadata.js';
72
- export { searchPages, registerPages, getPages, pagePath } from './search/search.js';
73
- export type {
74
- PageMeta,
75
- PageSearchResult,
76
- PageSearchOptions,
77
- SearchField,
78
- SearchHints,
79
- } from './search/search.js';
80
- export { usePageSearch } from './search/use-page-search.js';
81
- export type { PageSearch } from './search/use-page-search.js';
82
- export { Image } from './components/Image.js';
83
- export type { ImageProps } from './components/Image.js';
84
- export { Script } from './components/Script.js';
85
- export type { ScriptProps, ScriptStrategy } from './components/Script.js';
86
- export { Form } from './components/Form.js';
87
- export type { FormProps } from './components/Form.js';
88
- export { Slot } from './components/Slot.js';
89
- export type { SlotProps } from './components/Slot.js';
1
+ /**
2
+ * toiljs client runtime, published as `toiljs/client`. Re-exports the router (mount/Router/Link),
3
+ * navigation hooks, prefetching, and the route types consumed by the compiler-generated entry.
4
+ * Zero imports needed in user route files beyond this package.
5
+ *
6
+ * Internals are split by concern: route `types`, history-based `navigation`, the params
7
+ * `params-context` + `hooks`, `lazy` component resolution, the `Link`/`Router` components,
8
+ * `mount`, `match` (pure matcher), `prefetch` (link prefetcher), and `channel` (WebSocket helper).
9
+ */
10
+
11
+ export { mount } from './routing/mount.js';
12
+ export { Router } from './routing/Router.js';
13
+ export { Link } from './navigation/Link.js';
14
+ export type { LinkProps } from './navigation/Link.js';
15
+ export { NavLink, matchActive } from './navigation/NavLink.js';
16
+ export type { NavLinkProps, NavLinkState } from './navigation/NavLink.js';
17
+ export {
18
+ navigate,
19
+ back,
20
+ forward,
21
+ refresh,
22
+ setViewTransitions,
23
+ setTransitions,
24
+ href,
25
+ } from './navigation/navigation.js';
26
+ export type { NavigateOptions } from './navigation/navigation.js';
27
+ export {
28
+ useParams,
29
+ useNavigate,
30
+ useLocation,
31
+ usePathname,
32
+ useSearchParams,
33
+ useRouter,
34
+ useNavigationPending,
35
+ } from './routing/hooks.js';
36
+ export type { RouterInstance } from './routing/hooks.js';
37
+ export { useLoaderData, revalidate, invalidateLoaderData } from './routing/loader.js';
38
+ export type {
39
+ LoaderArgs,
40
+ LoaderFunction,
41
+ LoaderData,
42
+ Revalidate,
43
+ StaticParams,
44
+ GenerateStaticParams,
45
+ } from './routing/loader.js';
46
+ export { useAction } from './routing/action.js';
47
+ export type {
48
+ UseActionOptions,
49
+ ActionState,
50
+ ActionHandle,
51
+ RevalidateTarget,
52
+ } from './routing/action.js';
53
+ export { prefetch } from './navigation/prefetch.js';
54
+ export type {
55
+ RouteDef,
56
+ LayoutLoader,
57
+ LayoutComponentLoader,
58
+ NotFoundLoader,
59
+ RouteErrorProps,
60
+ Register,
61
+ RoutePath,
62
+ Href,
63
+ } from './types.js';
64
+ export { matchRoute } from './routing/match.js';
65
+ export type { RouteParams } from './routing/match.js';
66
+ export { connectChannel, useChannel, resolveChannelUrl } from './channel/channel.js';
67
+ export type { Channel, ChannelOptions, ChannelHook, ChannelData } from './channel/channel.js';
68
+ export { useHead, useTitle, Head, mergeHead } from './head/head.js';
69
+ export type { HeadSpec, MetaTag, LinkTag, ResolvedHead } from './head/head.js';
70
+ export { resolveMetadata, useMetadata, Metadata } from './head/metadata.js';
71
+ export type { GenerateMetadata, GenerateMetadataArgs, OpenGraph } from './head/metadata.js';
72
+ export { searchPages, registerPages, getPages, pagePath } from './search/search.js';
73
+ export type {
74
+ PageMeta,
75
+ PageSearchResult,
76
+ PageSearchOptions,
77
+ SearchField,
78
+ SearchHints,
79
+ } from './search/search.js';
80
+ export { usePageSearch } from './search/use-page-search.js';
81
+ export type { PageSearch } from './search/use-page-search.js';
82
+ export { Image } from './components/Image.js';
83
+ export type { ImageProps } from './components/Image.js';
84
+ export { Script } from './components/Script.js';
85
+ export type { ScriptProps, ScriptStrategy } from './components/Script.js';
86
+ export { Form } from './components/Form.js';
87
+ export type { FormProps } from './components/Form.js';
88
+ export { Slot } from './components/Slot.js';
89
+ export type { SlotProps } from './components/Slot.js';
@@ -1,86 +1,86 @@
1
- import type { CSSProperties, ReactNode } from 'react';
2
-
3
- import { useLocation } from '../routing/hooks.js';
4
- import { Link, type LinkProps } from './Link.js';
5
-
6
- /** State passed to `NavLink`'s function-form `className` / `style` / `children`. */
7
- export interface NavLinkState {
8
- readonly isActive: boolean;
9
- }
10
-
11
- /**
12
- * Props for {@link NavLink}: all {@link LinkProps}, but `className` / `style` / `children` may also
13
- * be functions of the active state.
14
- */
15
- export interface NavLinkProps extends Omit<LinkProps, 'className' | 'style' | 'children'> {
16
- className?: string | ((state: NavLinkState) => string | undefined);
17
- style?: CSSProperties | ((state: NavLinkState) => CSSProperties | undefined);
18
- children?: ReactNode | ((state: NavLinkState) => ReactNode);
19
- /** Match `href` exactly; without it, sub-paths are also active. Default `false`. */
20
- end?: boolean;
21
- /** Class added when active (used with a string `className`). Default `"active"`. */
22
- activeClassName?: string;
23
- }
24
-
25
- function normalizePath(p: string): string {
26
- return p.length > 1 ? p.replace(/\/+$/, '') : p;
27
- }
28
-
29
- /**
30
- * Whether a link to `linkPath` is active for `currentPath`. Exact when `end`; otherwise a parent
31
- * path is active for its sub-paths (and `/` is active everywhere, matching React Router).
32
- */
33
- export function matchActive(linkPath: string, currentPath: string, end: boolean): boolean {
34
- const link = normalizePath(linkPath);
35
- const current = normalizePath(currentPath);
36
- if (current === link) return true;
37
- if (end) return false;
38
- if (link === '/') return true;
39
- return current.startsWith(link + '/');
40
- }
41
-
42
- /**
43
- * A {@link Link} that knows whether it points at the current location. Applies an active class
44
- * (default `"active"`) and `aria-current="page"` when active; `className` / `style` / `children`
45
- * may be functions of `{ isActive }`. Inherits Link's full anchor API and prefetching.
46
- */
47
- export function NavLink(props: NavLinkProps): ReactNode {
48
- const {
49
- href,
50
- className,
51
- style,
52
- children,
53
- end = false,
54
- activeClassName = 'active',
55
- ...rest
56
- } = props;
57
- const pathname = useLocation();
58
-
59
- let linkPath = href;
60
- try {
61
- linkPath = new URL(href, window.location.href).pathname;
62
- } catch {
63
- linkPath = href;
64
- }
65
- const isActive = matchActive(linkPath, pathname, end);
66
- const state: NavLinkState = { isActive };
67
-
68
- const resolvedClassName =
69
- typeof className === 'function'
70
- ? className(state)
71
- : [className, isActive ? activeClassName : undefined].filter(Boolean).join(' ') ||
72
- undefined;
73
- const resolvedStyle = typeof style === 'function' ? style(state) : style;
74
- const resolvedChildren = typeof children === 'function' ? children(state) : children;
75
-
76
- return (
77
- <Link
78
- {...rest}
79
- href={href}
80
- className={resolvedClassName}
81
- style={resolvedStyle}
82
- aria-current={isActive ? 'page' : undefined}>
83
- {resolvedChildren}
84
- </Link>
85
- );
86
- }
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+
3
+ import { useLocation } from '../routing/hooks.js';
4
+ import { Link, type LinkProps } from './Link.js';
5
+
6
+ /** State passed to `NavLink`'s function-form `className` / `style` / `children`. */
7
+ export interface NavLinkState {
8
+ readonly isActive: boolean;
9
+ }
10
+
11
+ /**
12
+ * Props for {@link NavLink}: all {@link LinkProps}, but `className` / `style` / `children` may also
13
+ * be functions of the active state.
14
+ */
15
+ export interface NavLinkProps extends Omit<LinkProps, 'className' | 'style' | 'children'> {
16
+ className?: string | ((state: NavLinkState) => string | undefined);
17
+ style?: CSSProperties | ((state: NavLinkState) => CSSProperties | undefined);
18
+ children?: ReactNode | ((state: NavLinkState) => ReactNode);
19
+ /** Match `href` exactly; without it, sub-paths are also active. Default `false`. */
20
+ end?: boolean;
21
+ /** Class added when active (used with a string `className`). Default `"active"`. */
22
+ activeClassName?: string;
23
+ }
24
+
25
+ function normalizePath(p: string): string {
26
+ return p.length > 1 ? p.replace(/\/+$/, '') : p;
27
+ }
28
+
29
+ /**
30
+ * Whether a link to `linkPath` is active for `currentPath`. Exact when `end`; otherwise a parent
31
+ * path is active for its sub-paths (and `/` is active everywhere, matching React Router).
32
+ */
33
+ export function matchActive(linkPath: string, currentPath: string, end: boolean): boolean {
34
+ const link = normalizePath(linkPath);
35
+ const current = normalizePath(currentPath);
36
+ if (current === link) return true;
37
+ if (end) return false;
38
+ if (link === '/') return true;
39
+ return current.startsWith(link + '/');
40
+ }
41
+
42
+ /**
43
+ * A {@link Link} that knows whether it points at the current location. Applies an active class
44
+ * (default `"active"`) and `aria-current="page"` when active; `className` / `style` / `children`
45
+ * may be functions of `{ isActive }`. Inherits Link's full anchor API and prefetching.
46
+ */
47
+ export function NavLink(props: NavLinkProps): ReactNode {
48
+ const {
49
+ href,
50
+ className,
51
+ style,
52
+ children,
53
+ end = false,
54
+ activeClassName = 'active',
55
+ ...rest
56
+ } = props;
57
+ const pathname = useLocation();
58
+
59
+ let linkPath = href;
60
+ try {
61
+ linkPath = new URL(href, window.location.href).pathname;
62
+ } catch {
63
+ linkPath = href;
64
+ }
65
+ const isActive = matchActive(linkPath, pathname, end);
66
+ const state: NavLinkState = { isActive };
67
+
68
+ const resolvedClassName =
69
+ typeof className === 'function'
70
+ ? className(state)
71
+ : [className, isActive ? activeClassName : undefined].filter(Boolean).join(' ') ||
72
+ undefined;
73
+ const resolvedStyle = typeof style === 'function' ? style(state) : style;
74
+ const resolvedChildren = typeof children === 'function' ? children(state) : children;
75
+
76
+ return (
77
+ <Link
78
+ {...rest}
79
+ href={href}
80
+ className={resolvedClassName}
81
+ style={resolvedStyle}
82
+ aria-current={isActive ? 'page' : undefined}>
83
+ {resolvedChildren}
84
+ </Link>
85
+ );
86
+ }