@bleedingdev/modern-js-renderer-solid 0.0.0-bootstrap → 3.9.3-ultramodern.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.
Files changed (296) hide show
  1. package/dist/esm/actions.js +283 -0
  2. package/dist/esm/application-router.js +25 -0
  3. package/dist/esm/client.js +49 -0
  4. package/dist/esm/entry-application.js +60 -0
  5. package/dist/esm/entry-client.js +23 -0
  6. package/dist/esm/federation-context.js +25 -0
  7. package/dist/esm/federation-ssr.js +84 -0
  8. package/dist/esm/federation.js +83 -0
  9. package/dist/esm/i18n/I18nProvider.js +33 -0
  10. package/dist/esm/i18n/LocalizedLink.js +74 -0
  11. package/dist/esm/i18n/context.js +3 -0
  12. package/dist/esm/i18n/index.js +8 -0
  13. package/dist/esm/i18n/languageSync.js +50 -0
  14. package/dist/esm/i18n/types.js +0 -0
  15. package/dist/esm/i18n/useI18n.js +74 -0
  16. package/dist/esm/index.js +58 -0
  17. package/dist/esm/manifest.js +150 -0
  18. package/dist/esm/route-completion.js +150 -0
  19. package/dist/esm/route-data-error.js +108 -0
  20. package/dist/esm/router-binding/Asset.js +201 -0
  21. package/dist/esm/router-binding/CatchBoundary.js +94 -0
  22. package/dist/esm/router-binding/ClientOnly.js +26 -0
  23. package/dist/esm/router-binding/HeadContent.js +8 -0
  24. package/dist/esm/router-binding/LICENSE +21 -0
  25. package/dist/esm/router-binding/Match.js +319 -0
  26. package/dist/esm/router-binding/Matches.js +117 -0
  27. package/dist/esm/router-binding/PROVENANCE.json +94 -0
  28. package/dist/esm/router-binding/RouterProvider.js +51 -0
  29. package/dist/esm/router-binding/SafeFragment.js +5 -0
  30. package/dist/esm/router-binding/ScriptOnce.js +15 -0
  31. package/dist/esm/router-binding/Scripts.js +30 -0
  32. package/dist/esm/router-binding/ScrollRestoration.js +16 -0
  33. package/dist/esm/router-binding/Transitioner.js +103 -0
  34. package/dist/esm/router-binding/awaited.js +48 -0
  35. package/dist/esm/router-binding/fileRoute.js +83 -0
  36. package/dist/esm/router-binding/flightData.js +23 -0
  37. package/dist/esm/router-binding/headContentUtils.js +162 -0
  38. package/dist/esm/router-binding/history.js +0 -0
  39. package/dist/esm/router-binding/index.js +35 -0
  40. package/dist/esm/router-binding/lazyRouteComponent.js +30 -0
  41. package/dist/esm/router-binding/link.js +389 -0
  42. package/dist/esm/router-binding/matchContext.js +7 -0
  43. package/dist/esm/router-binding/nonRouteComponentContext.js +13 -0
  44. package/dist/esm/router-binding/not-found.js +35 -0
  45. package/dist/esm/router-binding/publicMatchData.js +447 -0
  46. package/dist/esm/router-binding/registryTransfer.js +210 -0
  47. package/dist/esm/router-binding/renderRouteNotFound.js +23 -0
  48. package/dist/esm/router-binding/route.js +143 -0
  49. package/dist/esm/router-binding/router.js +13 -0
  50. package/dist/esm/router-binding/routerContext.js +3 -0
  51. package/dist/esm/router-binding/routerStores.js +50 -0
  52. package/dist/esm/router-binding/scroll-restoration.js +13 -0
  53. package/dist/esm/router-binding/typePrimitives.js +0 -0
  54. package/dist/esm/router-binding/useBlocker.js +152 -0
  55. package/dist/esm/router-binding/useCanGoBack.js +7 -0
  56. package/dist/esm/router-binding/useLoaderData.js +9 -0
  57. package/dist/esm/router-binding/useLoaderDeps.js +8 -0
  58. package/dist/esm/router-binding/useLocation.js +14 -0
  59. package/dist/esm/router-binding/useMatch.js +28 -0
  60. package/dist/esm/router-binding/useNavigate.js +19 -0
  61. package/dist/esm/router-binding/useParams.js +13 -0
  62. package/dist/esm/router-binding/useRouteContext.js +8 -0
  63. package/dist/esm/router-binding/useRouter.js +10 -0
  64. package/dist/esm/router-binding/useRouterState.js +19 -0
  65. package/dist/esm/router-binding/useSearch.js +13 -0
  66. package/dist/esm/router-binding/utils.js +23 -0
  67. package/dist/esm/router.js +187 -0
  68. package/dist/esm-node/actions.js +263 -0
  69. package/dist/esm-node/application-router.js +25 -0
  70. package/dist/esm-node/client.js +49 -0
  71. package/dist/esm-node/entry-application.js +110 -0
  72. package/dist/esm-node/entry-client.js +23 -0
  73. package/dist/esm-node/entry-server.js +47 -0
  74. package/dist/esm-node/federation-context.js +25 -0
  75. package/dist/esm-node/federation-ssr.js +84 -0
  76. package/dist/esm-node/federation.js +83 -0
  77. package/dist/esm-node/i18n/I18nProvider.js +42 -0
  78. package/dist/esm-node/i18n/LocalizedLink.js +142 -0
  79. package/dist/esm-node/i18n/context.js +3 -0
  80. package/dist/esm-node/i18n/index.js +8 -0
  81. package/dist/esm-node/i18n/languageSync.js +50 -0
  82. package/dist/esm-node/i18n/types.js +1 -0
  83. package/dist/esm-node/i18n/useI18n.js +74 -0
  84. package/dist/esm-node/index.js +58 -0
  85. package/dist/esm-node/manifest.js +150 -0
  86. package/dist/esm-node/native-promise-serialization.js +113 -0
  87. package/dist/esm-node/plugin/compiler.js +209 -0
  88. package/dist/esm-node/plugin/create.js +235 -0
  89. package/dist/esm-node/plugin/index.js +73 -0
  90. package/dist/esm-node/plugin/profile.js +52 -0
  91. package/dist/esm-node/route-completion.js +160 -0
  92. package/dist/esm-node/route-data-error.js +108 -0
  93. package/dist/esm-node/router-binding/Asset.js +171 -0
  94. package/dist/esm-node/router-binding/CatchBoundary.js +136 -0
  95. package/dist/esm-node/router-binding/ClientOnly.js +46 -0
  96. package/dist/esm-node/router-binding/HeadContent.js +8 -0
  97. package/dist/esm-node/router-binding/LICENSE +21 -0
  98. package/dist/esm-node/router-binding/Match.js +660 -0
  99. package/dist/esm-node/router-binding/Matches.js +161 -0
  100. package/dist/esm-node/router-binding/PROVENANCE.json +94 -0
  101. package/dist/esm-node/router-binding/RouterProvider.js +87 -0
  102. package/dist/esm-node/router-binding/SafeFragment.js +5 -0
  103. package/dist/esm-node/router-binding/ScriptOnce.js +16 -0
  104. package/dist/esm-node/router-binding/Scripts.js +49 -0
  105. package/dist/esm-node/router-binding/ScrollRestoration.js +16 -0
  106. package/dist/esm-node/router-binding/Transitioner.js +103 -0
  107. package/dist/esm-node/router-binding/awaited.js +75 -0
  108. package/dist/esm-node/router-binding/fileRoute.js +83 -0
  109. package/dist/esm-node/router-binding/flightData.js +23 -0
  110. package/dist/esm-node/router-binding/headContentUtils.js +162 -0
  111. package/dist/esm-node/router-binding/history.js +1 -0
  112. package/dist/esm-node/router-binding/index.js +35 -0
  113. package/dist/esm-node/router-binding/lazyRouteComponent.js +30 -0
  114. package/dist/esm-node/router-binding/link.js +399 -0
  115. package/dist/esm-node/router-binding/matchContext.js +7 -0
  116. package/dist/esm-node/router-binding/nonRouteComponentContext.js +22 -0
  117. package/dist/esm-node/router-binding/not-found.js +49 -0
  118. package/dist/esm-node/router-binding/publicMatchData.js +447 -0
  119. package/dist/esm-node/router-binding/registryTransfer.js +210 -0
  120. package/dist/esm-node/router-binding/renderRouteNotFound.js +22 -0
  121. package/dist/esm-node/router-binding/route.js +162 -0
  122. package/dist/esm-node/router-binding/router.js +13 -0
  123. package/dist/esm-node/router-binding/routerContext.js +3 -0
  124. package/dist/esm-node/router-binding/routerStores.js +50 -0
  125. package/dist/esm-node/router-binding/scroll-restoration.js +12 -0
  126. package/dist/esm-node/router-binding/typePrimitives.js +1 -0
  127. package/dist/esm-node/router-binding/useBlocker.js +152 -0
  128. package/dist/esm-node/router-binding/useCanGoBack.js +7 -0
  129. package/dist/esm-node/router-binding/useLoaderData.js +9 -0
  130. package/dist/esm-node/router-binding/useLoaderDeps.js +8 -0
  131. package/dist/esm-node/router-binding/useLocation.js +14 -0
  132. package/dist/esm-node/router-binding/useMatch.js +28 -0
  133. package/dist/esm-node/router-binding/useNavigate.js +19 -0
  134. package/dist/esm-node/router-binding/useParams.js +13 -0
  135. package/dist/esm-node/router-binding/useRouteContext.js +8 -0
  136. package/dist/esm-node/router-binding/useRouter.js +10 -0
  137. package/dist/esm-node/router-binding/useRouterState.js +19 -0
  138. package/dist/esm-node/router-binding/useSearch.js +13 -0
  139. package/dist/esm-node/router-binding/utils.js +23 -0
  140. package/dist/esm-node/router.js +187 -0
  141. package/dist/esm-node/server.js +396 -0
  142. package/dist/types/actions.d.ts +45 -0
  143. package/dist/types/application-router.d.ts +5 -0
  144. package/dist/types/client.d.ts +23 -0
  145. package/dist/types/entry-application.d.ts +10 -0
  146. package/dist/types/entry-client.d.ts +5 -0
  147. package/dist/types/entry-server.d.ts +5 -0
  148. package/dist/types/federation-context.d.ts +16 -0
  149. package/dist/types/federation-ssr.d.ts +21 -0
  150. package/dist/types/federation.d.ts +30 -0
  151. package/dist/types/i18n/I18nProvider.d.ts +21 -0
  152. package/dist/types/i18n/LocalizedLink.d.ts +43 -0
  153. package/dist/types/i18n/context.d.ts +11 -0
  154. package/dist/types/i18n/index.d.ts +9 -0
  155. package/dist/types/i18n/languageSync.d.ts +31 -0
  156. package/dist/types/i18n/types.d.ts +33 -0
  157. package/dist/types/i18n/useI18n.d.ts +24 -0
  158. package/dist/types/index.d.ts +41 -0
  159. package/dist/types/manifest.d.ts +55 -0
  160. package/dist/types/native-promise-serialization.d.ts +9 -0
  161. package/dist/types/plugin/compiler.d.ts +6 -0
  162. package/dist/types/plugin/create.d.ts +21 -0
  163. package/dist/types/plugin/index.d.ts +3 -0
  164. package/dist/types/plugin/lazy-modules.d.cts +15 -0
  165. package/dist/types/plugin/preserve-import-loader.d.cts +3 -0
  166. package/dist/types/plugin/profile.d.ts +2 -0
  167. package/dist/types/plugin/solid-loader.d.cts +2 -0
  168. package/dist/types/plugin/svg-component-template.d.cts +6 -0
  169. package/dist/types/route-completion.d.ts +21 -0
  170. package/dist/types/route-data-error.d.ts +17 -0
  171. package/dist/types/router-binding/Asset.d.ts +3 -0
  172. package/dist/types/router-binding/CatchBoundary.d.ts +13 -0
  173. package/dist/types/router-binding/ClientOnly.d.ts +31 -0
  174. package/dist/types/router-binding/HeadContent.d.ts +13 -0
  175. package/dist/types/router-binding/Match.d.ts +6 -0
  176. package/dist/types/router-binding/Matches.d.ts +26 -0
  177. package/dist/types/router-binding/RouterProvider.d.ts +10 -0
  178. package/dist/types/router-binding/SafeFragment.d.ts +2 -0
  179. package/dist/types/router-binding/ScriptOnce.d.ts +6 -0
  180. package/dist/types/router-binding/Scripts.d.ts +2 -0
  181. package/dist/types/router-binding/ScrollRestoration.d.ts +14 -0
  182. package/dist/types/router-binding/Transitioner.d.ts +2 -0
  183. package/dist/types/router-binding/awaited.d.ts +11 -0
  184. package/dist/types/router-binding/fileRoute.d.ts +54 -0
  185. package/dist/types/router-binding/flightData.d.ts +38 -0
  186. package/dist/types/router-binding/headContentUtils.d.ts +15 -0
  187. package/dist/types/router-binding/history.d.ts +8 -0
  188. package/dist/types/router-binding/index.d.ts +45 -0
  189. package/dist/types/router-binding/lazyRouteComponent.d.ts +2 -0
  190. package/dist/types/router-binding/link.d.ts +43 -0
  191. package/dist/types/router-binding/matchContext.d.ts +7 -0
  192. package/dist/types/router-binding/nonRouteComponentContext.d.ts +5 -0
  193. package/dist/types/router-binding/not-found.d.ts +11 -0
  194. package/dist/types/router-binding/publicMatchData.d.ts +19 -0
  195. package/dist/types/router-binding/registryTransfer.d.ts +47 -0
  196. package/dist/types/router-binding/renderRouteNotFound.d.ts +11 -0
  197. package/dist/types/router-binding/route.d.ts +105 -0
  198. package/dist/types/router-binding/router.d.ts +70 -0
  199. package/dist/types/router-binding/routerContext.d.ts +3 -0
  200. package/dist/types/router-binding/routerStores.d.ts +2 -0
  201. package/dist/types/router-binding/scroll-restoration.d.ts +2 -0
  202. package/dist/types/router-binding/typePrimitives.d.ts +10 -0
  203. package/dist/types/router-binding/useBlocker.d.ts +70 -0
  204. package/dist/types/router-binding/useCanGoBack.d.ts +2 -0
  205. package/dist/types/router-binding/useLoaderData.d.ts +8 -0
  206. package/dist/types/router-binding/useLoaderDeps.d.ts +8 -0
  207. package/dist/types/router-binding/useLocation.d.ts +7 -0
  208. package/dist/types/router-binding/useMatch.d.ts +10 -0
  209. package/dist/types/router-binding/useNavigate.d.ts +5 -0
  210. package/dist/types/router-binding/useParams.d.ts +9 -0
  211. package/dist/types/router-binding/useRouteContext.d.ts +4 -0
  212. package/dist/types/router-binding/useRouter.d.ts +4 -0
  213. package/dist/types/router-binding/useRouterState.d.ts +8 -0
  214. package/dist/types/router-binding/useSearch.d.ts +9 -0
  215. package/dist/types/router-binding/utils.d.ts +25 -0
  216. package/dist/types/router.d.ts +31 -0
  217. package/dist/types/server.d.ts +47 -0
  218. package/package.json +118 -4
  219. package/src/actions.tsx +437 -0
  220. package/src/application-router.tsx +41 -0
  221. package/src/client.ts +106 -0
  222. package/src/entry-application.tsx +73 -0
  223. package/src/entry-client.tsx +48 -0
  224. package/src/entry-server.tsx +85 -0
  225. package/src/federation-context.ts +47 -0
  226. package/src/federation-ssr.ts +117 -0
  227. package/src/federation.tsx +193 -0
  228. package/src/i18n/I18nProvider.tsx +54 -0
  229. package/src/i18n/LocalizedLink.tsx +122 -0
  230. package/src/i18n/context.ts +13 -0
  231. package/src/i18n/index.ts +35 -0
  232. package/src/i18n/languageSync.ts +113 -0
  233. package/src/i18n/types.ts +35 -0
  234. package/src/i18n/useI18n.ts +121 -0
  235. package/src/index.ts +41 -0
  236. package/src/manifest.ts +337 -0
  237. package/src/native-promise-serialization.ts +167 -0
  238. package/src/plugin/compiler.ts +320 -0
  239. package/src/plugin/create.ts +270 -0
  240. package/src/plugin/index.ts +72 -0
  241. package/src/plugin/lazy-modules.cjs +146 -0
  242. package/src/plugin/preserve-import-loader.cjs +46 -0
  243. package/src/plugin/profile.ts +42 -0
  244. package/src/plugin/solid-loader.cjs +83 -0
  245. package/src/plugin/svg-component-template.cjs +19 -0
  246. package/src/route-completion.tsx +222 -0
  247. package/src/route-data-error.ts +175 -0
  248. package/src/router-binding/Asset.tsx +283 -0
  249. package/src/router-binding/CatchBoundary.tsx +130 -0
  250. package/src/router-binding/ClientOnly.tsx +76 -0
  251. package/src/router-binding/HeadContent.tsx +23 -0
  252. package/src/router-binding/LICENSE +21 -0
  253. package/src/router-binding/Match.tsx +397 -0
  254. package/src/router-binding/Matches.tsx +242 -0
  255. package/src/router-binding/PROVENANCE.json +94 -0
  256. package/src/router-binding/RouterProvider.tsx +129 -0
  257. package/src/router-binding/SafeFragment.tsx +5 -0
  258. package/src/router-binding/ScriptOnce.tsx +23 -0
  259. package/src/router-binding/Scripts.tsx +44 -0
  260. package/src/router-binding/ScrollRestoration.tsx +49 -0
  261. package/src/router-binding/Transitioner.tsx +172 -0
  262. package/src/router-binding/awaited.tsx +71 -0
  263. package/src/router-binding/fileRoute.ts +268 -0
  264. package/src/router-binding/flightData.ts +90 -0
  265. package/src/router-binding/headContentUtils.tsx +290 -0
  266. package/src/router-binding/history.ts +9 -0
  267. package/src/router-binding/index.tsx +318 -0
  268. package/src/router-binding/lazyRouteComponent.tsx +70 -0
  269. package/src/router-binding/link.tsx +865 -0
  270. package/src/router-binding/matchContext.tsx +15 -0
  271. package/src/router-binding/nonRouteComponentContext.tsx +23 -0
  272. package/src/router-binding/not-found.tsx +65 -0
  273. package/src/router-binding/publicMatchData.ts +674 -0
  274. package/src/router-binding/registryTransfer.ts +383 -0
  275. package/src/router-binding/renderRouteNotFound.tsx +53 -0
  276. package/src/router-binding/route.tsx +665 -0
  277. package/src/router-binding/router.ts +121 -0
  278. package/src/router-binding/routerContext.tsx +6 -0
  279. package/src/router-binding/routerStores.ts +85 -0
  280. package/src/router-binding/scroll-restoration.tsx +15 -0
  281. package/src/router-binding/typePrimitives.ts +74 -0
  282. package/src/router-binding/useBlocker.tsx +359 -0
  283. package/src/router-binding/useCanGoBack.ts +9 -0
  284. package/src/router-binding/useLoaderData.tsx +50 -0
  285. package/src/router-binding/useLoaderDeps.tsx +46 -0
  286. package/src/router-binding/useLocation.tsx +43 -0
  287. package/src/router-binding/useMatch.tsx +111 -0
  288. package/src/router-binding/useNavigate.tsx +43 -0
  289. package/src/router-binding/useParams.tsx +72 -0
  290. package/src/router-binding/useRouteContext.ts +30 -0
  291. package/src/router-binding/useRouter.tsx +17 -0
  292. package/src/router-binding/useRouterState.tsx +50 -0
  293. package/src/router-binding/useSearch.tsx +72 -0
  294. package/src/router-binding/utils.ts +59 -0
  295. package/src/router.ts +376 -0
  296. package/src/server.ts +645 -0
@@ -0,0 +1,865 @@
1
+ import type { ComponentProps, JSX, ValidComponent } from '@solidjs/web';
2
+ import { Dynamic } from '@solidjs/web';
3
+ import type {
4
+ AnyRouter,
5
+ Constrain,
6
+ LinkOptions,
7
+ ParsedLocation,
8
+ RegisteredRouter,
9
+ RoutePaths,
10
+ } from '@tanstack/router-core';
11
+ import {
12
+ deepEqual,
13
+ exactPathTest,
14
+ functionalUpdate,
15
+ getUrlScheme,
16
+ hasKeys,
17
+ isDangerousProtocol,
18
+ preloadWarning,
19
+ removeTrailingSlash,
20
+ } from '@tanstack/router-core';
21
+ import { isServer } from '@tanstack/router-core/isServer';
22
+ import * as Solid from 'solid-js';
23
+
24
+ import { useHydrated } from './ClientOnly';
25
+ import type {
26
+ ValidateLinkOptions,
27
+ ValidateLinkOptionsArray,
28
+ } from './typePrimitives';
29
+ import { useRouter } from './useRouter';
30
+ import { useIntersectionObserver } from './utils';
31
+
32
+ function mergeRefs<T>(...refs: Array<unknown>): (el: T) => void {
33
+ const setRef = (ref: unknown, el: T) => {
34
+ if (typeof ref === 'function') {
35
+ ref(el);
36
+ } else if (Array.isArray(ref)) {
37
+ for (const nestedRef of ref) {
38
+ setRef(nestedRef, el);
39
+ }
40
+ }
41
+ };
42
+
43
+ return (el: T) => {
44
+ for (const ref of refs) {
45
+ setRef(ref, el);
46
+ }
47
+ };
48
+ }
49
+
50
+ function splitProps<T extends Record<string, any>, TKey extends keyof T>(
51
+ props: T,
52
+ keys: ReadonlyArray<TKey>,
53
+ ): [Pick<T, TKey>, Omit<T, TKey>] {
54
+ const _local = {} as Pick<T, TKey>;
55
+ const _rest = {} as Omit<T, TKey>;
56
+
57
+ // A safe way to polyfill splitProps if native getter copy is too complex
58
+ // is just to return [props, Solid.omit(props, keys)] but it modifies typing.
59
+ // Actually, Solid.omit exists!
60
+ // Note: Solid.omit uses rest params (...keys), so we must spread the array.
61
+ return [props as any, Solid.omit(props, ...(keys as any)) as any];
62
+ }
63
+ const timeoutMap = new WeakMap<object, ReturnType<typeof setTimeout>>();
64
+ const cancelPreload = (eventTarget: object) => {
65
+ clearTimeout(timeoutMap.get(eventTarget));
66
+ timeoutMap.delete(eventTarget);
67
+ };
68
+
69
+ export function useLinkProps<
70
+ TRouter extends AnyRouter = RegisteredRouter,
71
+ TFrom extends RoutePaths<TRouter['routeTree']> | string = string,
72
+ TTo extends string = '',
73
+ TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,
74
+ TMaskTo extends string = '',
75
+ >(
76
+ options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
77
+ ): ComponentProps<'a'> {
78
+ const router = useRouter();
79
+ const shouldHydrateHash = !isServer && !!router.options.ssr;
80
+ const hasHydrated = useHydrated();
81
+
82
+ let hasRenderFetched = false;
83
+
84
+ // Defaults are resolved through accessors at the use sites instead of
85
+ // merging them into the props. Every merge/omit proxy layered here gets
86
+ // re-enumerated by spread() on each navigation, and V8 dispatches proxy
87
+ // traps in native runtime code — keeping this path proxy-free is what
88
+ // keeps Link updates cheap.
89
+ const local = options;
90
+ const activeProps = () => local.activeProps ?? STATIC_ACTIVE_PROPS_GET;
91
+ const inactiveProps = () => local.inactiveProps ?? STATIC_INACTIVE_PROPS_GET;
92
+
93
+ const propsSafeToSpread = Solid.omit(
94
+ options as Record<string, any>,
95
+ 'activeProps',
96
+ 'inactiveProps',
97
+ 'activeOptions',
98
+ 'to',
99
+ 'preload',
100
+ 'preloadDelay',
101
+ 'preloadIntentProximity',
102
+ 'hashScrollIntoView',
103
+ 'replace',
104
+ 'startTransition',
105
+ 'resetScroll',
106
+ 'viewTransition',
107
+ 'target',
108
+ 'disabled',
109
+ 'style',
110
+ 'class',
111
+ 'onClick',
112
+ 'onBlur',
113
+ 'onFocus',
114
+ 'onMouseEnter',
115
+ 'onMouseLeave',
116
+ 'onMouseOver',
117
+ 'onMouseOut',
118
+ 'onTouchStart',
119
+ 'ignoreBlocker',
120
+ 'params',
121
+ 'search',
122
+ 'hash',
123
+ 'state',
124
+ 'mask',
125
+ 'reloadDocument',
126
+ 'unsafeRelative',
127
+ 'from',
128
+ );
129
+
130
+ const currentLocation = Solid.createMemo(() => router.stores.location.get(), {
131
+ equals: (prev, next) => prev.href === next.href,
132
+ });
133
+
134
+ const _options = () => options;
135
+
136
+ const next = Solid.createMemo(
137
+ () => {
138
+ // Rebuild when inherited search/hash or the current route context changes.
139
+ const _fromLocation = currentLocation();
140
+ const options = { _fromLocation, ..._options() } as any;
141
+ // untrack because router-core will also access stores, which are signals in solid
142
+ return Solid.untrack(() => router.buildLocation(options));
143
+ },
144
+ {
145
+ lazy: true,
146
+ // Navigations usually leave most links' built locations unchanged;
147
+ // comparing hrefs lets downstream memos (href, isActive) skip work.
148
+ equals: (prev, next) =>
149
+ prev.href === next.href &&
150
+ prev.external === next.external &&
151
+ prev.maskedLocation?.href === next.maskedLocation?.href,
152
+ },
153
+ );
154
+
155
+ // A `to` with a URL scheme skips route resolution: the URL itself when the
156
+ // router allows its protocol, `null` when it is blocked, `undefined` for a
157
+ // route path. Read through the accessor so a reactive `to` can move between
158
+ // the three states after setup.
159
+ const directExternalLink = Solid.createMemo(
160
+ () => resolveExternalLink(_options().to, router.protocolAllowlist),
161
+ { lazy: true },
162
+ );
163
+
164
+ // The rendered href. `undefined` means disabled or blocked; neither renders
165
+ // an href, so the browser cannot follow it either.
166
+ const hrefOption = Solid.createMemo(
167
+ () => {
168
+ if (_options().disabled) return undefined;
169
+ const direct = directExternalLink();
170
+ if (direct !== undefined) return direct ?? undefined;
171
+ return getHrefOption(next(), router);
172
+ },
173
+ { lazy: true },
174
+ );
175
+
176
+ const externalLink = Solid.createMemo(
177
+ () => {
178
+ const direct = directExternalLink();
179
+ if (direct !== undefined) return direct ?? undefined;
180
+ const href = hrefOption();
181
+ return href && getUrlScheme(href) ? href : undefined;
182
+ },
183
+ { lazy: true },
184
+ );
185
+
186
+ // Disabled and blocked links render without an href, do not preload and do
187
+ // not navigate. Enabled external links stay plain anchors.
188
+ const linkDisabled = Solid.createMemo(
189
+ () => !!local.disabled || (!externalLink() && hrefOption() === undefined),
190
+ { lazy: true },
191
+ );
192
+ const blockedLink = () => linkDisabled() && !local.disabled;
193
+
194
+ const preload = Solid.createMemo(
195
+ () => {
196
+ if (_options().reloadDocument || externalLink() || linkDisabled()) {
197
+ return false;
198
+ }
199
+ return local.preload ?? router.options.defaultPreload;
200
+ },
201
+ { lazy: true },
202
+ );
203
+ const preloadDelay = () =>
204
+ local.preloadDelay ?? router.options.defaultPreloadDelay ?? 0;
205
+
206
+ const isActive = Solid.createMemo(
207
+ () => {
208
+ if (externalLink() || blockedLink()) return false;
209
+ const activeOptions = local.activeOptions;
210
+ const current = currentLocation();
211
+ const nextLocation = next();
212
+
213
+ if (activeOptions?.exact) {
214
+ const testExact = exactPathTest(
215
+ current.pathname,
216
+ nextLocation.pathname,
217
+ router.basepath,
218
+ );
219
+ if (!testExact) {
220
+ return false;
221
+ }
222
+ } else {
223
+ const currentPath = removeTrailingSlash(
224
+ current.pathname,
225
+ router.basepath,
226
+ );
227
+ const nextPath = removeTrailingSlash(
228
+ nextLocation.pathname,
229
+ router.basepath,
230
+ );
231
+
232
+ const pathIsFuzzyEqual =
233
+ currentPath.startsWith(nextPath) &&
234
+ (currentPath.length === nextPath.length ||
235
+ currentPath[nextPath.length] === '/');
236
+ if (!pathIsFuzzyEqual) {
237
+ return false;
238
+ }
239
+ }
240
+
241
+ if (activeOptions?.includeSearch ?? true) {
242
+ const searchTest = deepEqual(
243
+ current.search,
244
+ nextLocation.search,
245
+ !activeOptions?.exact,
246
+ activeOptions?.explicitUndefined,
247
+ );
248
+ if (!searchTest) {
249
+ return false;
250
+ }
251
+ }
252
+
253
+ if (activeOptions?.includeHash) {
254
+ const currentHash =
255
+ shouldHydrateHash && !hasHydrated() ? '' : current.hash;
256
+ return currentHash === nextLocation.hash;
257
+ }
258
+ return true;
259
+ },
260
+ { lazy: true },
261
+ );
262
+
263
+ const doPreload = () =>
264
+ router
265
+ .preloadRoute({ ...options, _builtLocation: next() } as any)
266
+ .catch((err: any) => {
267
+ console.warn(err);
268
+ console.warn(preloadWarning);
269
+ });
270
+
271
+ const [ref, setRefSignal] = Solid.createSignal<Element | null>(null);
272
+
273
+ const setRef = (el: Element | null) => {
274
+ Solid.runWithOwner(null, () => {
275
+ setRefSignal(el);
276
+ });
277
+ };
278
+
279
+ const enqueuePreload = (
280
+ e?: MouseEvent | FocusEvent | IntersectionObserverEntry,
281
+ ) => {
282
+ if (!e) {
283
+ cancelPreload(ref);
284
+ return;
285
+ }
286
+
287
+ if (
288
+ !(
289
+ (e as IntersectionObserverEntry).isIntersecting ??
290
+ preload() === 'intent'
291
+ )
292
+ ) {
293
+ if ((e as IntersectionObserverEntry).isIntersecting === false) {
294
+ cancelPreload(ref);
295
+ }
296
+ return;
297
+ }
298
+
299
+ if (!preloadDelay()) {
300
+ doPreload();
301
+ return;
302
+ }
303
+
304
+ if (!timeoutMap.has(ref)) {
305
+ timeoutMap.set(
306
+ ref,
307
+ setTimeout(() => {
308
+ timeoutMap.delete(ref);
309
+ doPreload();
310
+ }, preloadDelay()),
311
+ );
312
+ }
313
+ };
314
+
315
+ useIntersectionObserver(ref, enqueuePreload, () => preload() !== 'viewport');
316
+
317
+ Solid.createEffect(preload, preloadValue => {
318
+ if (hasRenderFetched) {
319
+ return;
320
+ }
321
+ if (preloadValue === 'render') {
322
+ Solid.untrack(() => doPreload());
323
+ hasRenderFetched = true;
324
+ }
325
+ });
326
+
327
+ // External and internal links share one props object whose getters follow
328
+ // `externalLink()`, so a reactive `to` can switch between the two kinds.
329
+
330
+ // The click handler
331
+ const handleClick = (e: MouseEvent) => {
332
+ // The browser follows external hrefs; blocked links have none to follow.
333
+ if (externalLink() || linkDisabled()) return;
334
+ const element = e.currentTarget as HTMLAnchorElement | SVGAElement;
335
+ // A download link fetches its resource; the browser handles that click.
336
+ if (element.hasAttribute('download')) return;
337
+ // Check actual element's target attribute as fallback
338
+ const elementTarget = element.getAttribute('target');
339
+ const effectiveTarget = resolvedTarget() ?? elementTarget;
340
+
341
+ if (
342
+ !isCtrlEvent(e) &&
343
+ !e.defaultPrevented &&
344
+ (!effectiveTarget || effectiveTarget === '_self') &&
345
+ e.button === 0
346
+ ) {
347
+ e.preventDefault();
348
+
349
+ // All is well? Navigate!
350
+ // N.B. we don't call `router.commitLocation(next) here because we want to run `validateSearch` before committing
351
+ router.navigate({
352
+ ...options,
353
+ replace: local.replace,
354
+ resetScroll: local.resetScroll,
355
+ hashScrollIntoView: local.hashScrollIntoView,
356
+ startTransition: local.startTransition,
357
+ viewTransition: local.viewTransition,
358
+ ignoreBlocker: local.ignoreBlocker,
359
+ });
360
+ }
361
+ };
362
+
363
+ const handleTouchStart = () => {
364
+ if (preload() !== 'intent') return;
365
+ doPreload();
366
+ };
367
+
368
+ const handleLeave = () => {
369
+ if (preload() === 'intent') {
370
+ cancelPreload(ref);
371
+ }
372
+ };
373
+
374
+ const simpleStyling = Solid.createMemo(
375
+ () =>
376
+ activeProps() === STATIC_ACTIVE_PROPS_GET &&
377
+ inactiveProps() === STATIC_INACTIVE_PROPS_GET &&
378
+ local.class === undefined &&
379
+ local.style === undefined,
380
+ { lazy: true },
381
+ );
382
+
383
+ // activeProps/inactiveProps may supply event handlers too. Each runs after
384
+ // the caller's own and, like it, can prevent the Link's behavior.
385
+ const stateHandler =
386
+ (key: string) => (): JSX.EventHandlerUnion<any, any> | undefined =>
387
+ (resolvedStateProps() as Record<string, any>)[key];
388
+ const handlers = (key: keyof typeof local & string) => [
389
+ () => local[key] as JSX.EventHandlerUnion<any, any> | undefined,
390
+ stateHandler(key),
391
+ ];
392
+ const onClick = createComposedHandler(handlers('onClick'), handleClick);
393
+ const onBlur = createComposedHandler(handlers('onBlur'), handleLeave);
394
+ const onFocus = createComposedHandler(handlers('onFocus'), enqueuePreload);
395
+ const onMouseEnter = createComposedHandler(
396
+ handlers('onMouseEnter'),
397
+ enqueuePreload,
398
+ );
399
+ const onMouseOver = createComposedHandler(
400
+ handlers('onMouseOver'),
401
+ enqueuePreload,
402
+ );
403
+ const onMouseLeave = createComposedHandler(
404
+ handlers('onMouseLeave'),
405
+ handleLeave,
406
+ );
407
+ const onMouseOut = createComposedHandler(handlers('onMouseOut'), handleLeave);
408
+ const onTouchStart = createComposedHandler(
409
+ handlers('onTouchStart'),
410
+ handleTouchStart,
411
+ );
412
+
413
+ type ResolvedLinkStateProps = Omit<ComponentProps<'a'>, 'style'> & {
414
+ style?: JSX.CSSProperties;
415
+ };
416
+
417
+ // External links keep the caller's props as given, without state props.
418
+ const resolvedStateProps = Solid.createMemo(
419
+ (): ResolvedLinkStateProps => {
420
+ const stateProps: ResolvedLinkStateProps = externalLink()
421
+ ? EMPTY_OBJECT
422
+ : ((isActive()
423
+ ? functionalUpdate(activeProps() as any, {})
424
+ : functionalUpdate(inactiveProps(), {})) ?? EMPTY_OBJECT);
425
+ if (process.env.NODE_ENV !== 'production')
426
+ warnUnknownStateKeys(stateProps, extraStateKeys);
427
+ return stateProps;
428
+ },
429
+ { lazy: true },
430
+ );
431
+
432
+ // State props override the base props, target included: a `_blank` from
433
+ // activeProps opens a new browsing context instead of navigating in place.
434
+ const resolvedTarget = () => {
435
+ const target = (resolvedStateProps() as { target?: string }).target;
436
+ return target !== undefined ? target : local.target;
437
+ };
438
+ const stateOrBase = (key: string): unknown => {
439
+ const state = (resolvedStateProps() as Record<string, unknown>)[key];
440
+ return state !== undefined
441
+ ? state
442
+ : (propsSafeToSpread as Record<string, unknown>)[key];
443
+ };
444
+
445
+ const resolvedClass = Solid.createMemo(
446
+ () => {
447
+ if (simpleStyling()) return isActive() ? 'active' : undefined;
448
+ return (
449
+ [local.class, resolvedStateProps().class].filter(Boolean).join(' ') ||
450
+ undefined
451
+ );
452
+ },
453
+ { lazy: true },
454
+ );
455
+
456
+ const resolvedStyle = Solid.createMemo(
457
+ () => {
458
+ if (simpleStyling()) return local.style;
459
+ const style = { ...local.style, ...resolvedStateProps().style };
460
+ return hasKeys(style) ? style : undefined;
461
+ },
462
+ { lazy: true },
463
+ );
464
+
465
+ // The returned object must be a plain object with a stable key set so the
466
+ // consuming spread() never enumerates through proxy traps. Reactivity lives
467
+ // in the property getters; values that no longer apply resolve to undefined,
468
+ // which spread()/assign() treats as attribute removal. Keys returned by
469
+ // activeProps/inactiveProps are discovered once at setup: their values stay
470
+ // reactive, but a key first returned later is not applied, and development
471
+ // builds warn about it.
472
+ const extraStateKeys = new Set<string>();
473
+ Solid.untrack(() => {
474
+ for (const stateProps of [
475
+ functionalUpdate(activeProps() as any, {}),
476
+ functionalUpdate(inactiveProps(), {}),
477
+ ]) {
478
+ if (stateProps) {
479
+ for (const key of Object.keys(stateProps)) {
480
+ if (key !== 'class' && key !== 'style') extraStateKeys.add(key);
481
+ }
482
+ }
483
+ }
484
+ });
485
+
486
+ const composedRef = mergeRefs(setRef, (el: Element) => {
487
+ const r = _options().ref as any;
488
+ if (typeof r === 'function') r(el);
489
+ });
490
+
491
+ const linkProps: Record<string, any> = {};
492
+ for (const key of Object.keys(propsSafeToSpread)) {
493
+ Object.defineProperty(
494
+ linkProps,
495
+ key,
496
+ Object.getOwnPropertyDescriptor(propsSafeToSpread, key)!,
497
+ );
498
+ }
499
+ for (const key of extraStateKeys) {
500
+ Object.defineProperty(linkProps, key, {
501
+ get: () => (resolvedStateProps() as Record<string, any>)[key],
502
+ enumerable: true,
503
+ configurable: true,
504
+ });
505
+ }
506
+
507
+ const defineGetters = (getters: Record<string, () => any>) => {
508
+ for (const key of Object.keys(getters)) {
509
+ Object.defineProperty(linkProps, key, {
510
+ get: getters[key],
511
+ enumerable: true,
512
+ configurable: true,
513
+ });
514
+ }
515
+ };
516
+
517
+ // The Link owns ref and onClick. Define them over any getter a state prop
518
+ // installed above; a plain assignment to a getter-only key throws.
519
+ for (const [key, value] of [
520
+ ['ref', composedRef],
521
+ ['onClick', onClick],
522
+ ] as const)
523
+ Object.defineProperty(linkProps, key, {
524
+ value,
525
+ writable: true,
526
+ enumerable: true,
527
+ configurable: true,
528
+ });
529
+
530
+ // Intent preloading is the only thing these handlers do, and each of them
531
+ // already bails at a `preload() !== 'intent'` gate. Handing them out anyway
532
+ // is not free: Solid does not delegate mouseenter/mouseleave/focus/blur, so
533
+ // every anchor installs four real listeners that exist only to return. On a
534
+ // list view — a table of rows, a calendar of spans — that is four listeners
535
+ // per row for no behaviour at all.
536
+ //
537
+ // So when intent preloading is off, the property resolves to whatever the
538
+ // user passed (or undefined), and spread()/assign() installs nothing. The
539
+ // getters keep this reactive: flipping `preload` back to 'intent' re-runs
540
+ // the consuming spread, which attaches the composed handler then.
541
+ // Without intent preloading only the caller's and state handlers remain, so
542
+ // nothing is installed unless one of them exists.
543
+ const onIntent = (composed: (event: any) => void, key: string) => {
544
+ const passthrough = createComposedHandler(handlers(key as never));
545
+ return () =>
546
+ preload() === 'intent'
547
+ ? composed
548
+ : (local as Record<string, unknown>)[key] || stateHandler(key)()
549
+ ? passthrough
550
+ : undefined;
551
+ };
552
+
553
+ defineGetters({
554
+ onBlur: onIntent(onBlur, 'onBlur'),
555
+ onFocus: onIntent(onFocus, 'onFocus'),
556
+ onMouseEnter: onIntent(onMouseEnter, 'onMouseEnter'),
557
+ onMouseOver: onIntent(onMouseOver, 'onMouseOver'),
558
+ onMouseLeave: onIntent(onMouseLeave, 'onMouseLeave'),
559
+ onMouseOut: onIntent(onMouseOut, 'onMouseOut'),
560
+ onTouchStart: onIntent(onTouchStart, 'onTouchStart'),
561
+ });
562
+
563
+ defineGetters({
564
+ href: hrefOption,
565
+ disabled: () => !!local.disabled || linkDisabled(),
566
+ target: resolvedTarget,
567
+ // The Link owns these only while disabled or active, as upstream Links
568
+ // do; otherwise a value from the state props, then the base props, wins.
569
+ role: () => (linkDisabled() ? 'link' : stateOrBase('role')),
570
+ 'aria-disabled': () =>
571
+ linkDisabled() ? 'true' : stateOrBase('aria-disabled'),
572
+ 'data-status': () => (isActive() ? 'active' : stateOrBase('data-status')),
573
+ 'aria-current': () => (isActive() ? 'page' : stateOrBase('aria-current')),
574
+ class: resolvedClass,
575
+ style: resolvedStyle,
576
+ });
577
+
578
+ return linkProps as any;
579
+ }
580
+
581
+ const STATIC_ACTIVE_PROPS = { class: 'active' };
582
+ const STATIC_ACTIVE_PROPS_GET = () => STATIC_ACTIVE_PROPS;
583
+ const EMPTY_OBJECT = {};
584
+ const STATIC_INACTIVE_PROPS_GET = () => EMPTY_OBJECT;
585
+
586
+ /** Call a JSX.EventHandlerUnion with the event. */
587
+ function callHandler<T, TEvent extends Event>(
588
+ event: TEvent & { currentTarget: T; target: Element },
589
+ handler: JSX.EventHandlerUnion<T, TEvent>,
590
+ ) {
591
+ if (typeof handler === 'function') {
592
+ handler(event);
593
+ } else {
594
+ handler[0](handler[1], event);
595
+ }
596
+ return event.defaultPrevented;
597
+ }
598
+
599
+ /** Run each handler in order; one that prevents default skips the rest. */
600
+ function createComposedHandler<T, TEvent extends Event>(
601
+ getHandlers: readonly (() => JSX.EventHandlerUnion<T, TEvent> | undefined)[],
602
+ fallback?: (event: TEvent) => void,
603
+ ) {
604
+ return (event: TEvent & { currentTarget: T; target: Element }) => {
605
+ for (const getHandler of getHandlers) {
606
+ const handler = getHandler();
607
+ if (handler && callHandler(event, handler)) return;
608
+ }
609
+ fallback?.(event);
610
+ };
611
+ }
612
+
613
+ export type UseLinkPropsOptions<
614
+ TRouter extends AnyRouter = RegisteredRouter,
615
+ TFrom extends RoutePaths<TRouter['routeTree']> | string = string,
616
+ TTo extends string | undefined = '.',
617
+ TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,
618
+ TMaskTo extends string = '.',
619
+ > = ActiveLinkOptions<'a', TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &
620
+ Omit<ComponentProps<'a'>, 'style'> & { style?: JSX.CSSProperties };
621
+
622
+ export type ActiveLinkOptions<
623
+ TComp = 'a',
624
+ TRouter extends AnyRouter = RegisteredRouter,
625
+ TFrom extends string = string,
626
+ TTo extends string | undefined = '.',
627
+ TMaskFrom extends string = TFrom,
628
+ TMaskTo extends string = '.',
629
+ > = LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &
630
+ ActiveLinkOptionProps<TComp>;
631
+
632
+ type ActiveLinkProps<TComp> = Partial<
633
+ LinkComponentSolidProps<TComp> & {
634
+ [key: `data-${string}`]: unknown;
635
+ }
636
+ >;
637
+
638
+ export interface ActiveLinkOptionProps<TComp = 'a'> {
639
+ /**
640
+ * A function that returns additional props for the `active` state of this link.
641
+ * These props override other props passed to the link (`style`'s are merged, `class`'s are concatenated)
642
+ */
643
+ activeProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>);
644
+ /**
645
+ * A function that returns additional props for the `inactive` state of this link.
646
+ * These props override other props passed to the link (`style`'s are merged, `class`'s are concatenated)
647
+ */
648
+ inactiveProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>);
649
+ }
650
+
651
+ export type LinkProps<
652
+ TComp = 'a',
653
+ TRouter extends AnyRouter = RegisteredRouter,
654
+ TFrom extends string = string,
655
+ TTo extends string | undefined = '.',
656
+ TMaskFrom extends string = TFrom,
657
+ TMaskTo extends string = '.',
658
+ > = ActiveLinkOptions<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &
659
+ LinkPropsChildren;
660
+
661
+ export interface LinkPropsChildren {
662
+ // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
663
+ children?: JSX.Element | ((state: { isActive: boolean }) => JSX.Element);
664
+ }
665
+
666
+ type LinkComponentSolidProps<TComp> = TComp extends ValidComponent
667
+ ? Omit<ComponentProps<TComp>, keyof CreateLinkProps>
668
+ : never;
669
+
670
+ export type LinkComponentProps<
671
+ TComp = 'a',
672
+ TRouter extends AnyRouter = RegisteredRouter,
673
+ TFrom extends string = string,
674
+ TTo extends string | undefined = '.',
675
+ TMaskFrom extends string = TFrom,
676
+ TMaskTo extends string = '.',
677
+ > = LinkComponentSolidProps<TComp> &
678
+ LinkProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
679
+
680
+ export type CreateLinkProps = LinkProps<
681
+ any,
682
+ any,
683
+ string,
684
+ string,
685
+ string,
686
+ string
687
+ >;
688
+
689
+ export type LinkComponent<
690
+ in out TComp,
691
+ in out TDefaultFrom extends string = string,
692
+ > = <
693
+ TRouter extends AnyRouter = RegisteredRouter,
694
+ const TFrom extends string = TDefaultFrom,
695
+ const TTo extends string | undefined = undefined,
696
+ const TMaskFrom extends string = TFrom,
697
+ const TMaskTo extends string = '',
698
+ >(
699
+ props: LinkComponentProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
700
+ ) => JSX.Element;
701
+
702
+ export interface LinkComponentRoute<
703
+ in out TDefaultFrom extends string = string,
704
+ > {
705
+ defaultFrom: TDefaultFrom;
706
+ <
707
+ TRouter extends AnyRouter = RegisteredRouter,
708
+ const TTo extends string | undefined = undefined,
709
+ const TMaskTo extends string = '',
710
+ >(
711
+ props: LinkComponentProps<
712
+ 'a',
713
+ TRouter,
714
+ this['defaultFrom'],
715
+ TTo,
716
+ this['defaultFrom'],
717
+ TMaskTo
718
+ >,
719
+ ): JSX.Element;
720
+ }
721
+
722
+ export function createLink<const TComp>(
723
+ Comp: Constrain<TComp, any, (props: CreateLinkProps) => JSX.Element>,
724
+ ): LinkComponent<TComp> {
725
+ return props => <Link {...props} _asChild={Comp} />;
726
+ }
727
+
728
+ export const Link: LinkComponent<'a'> = props => {
729
+ const [local, rest] = splitProps(props as typeof props & { _asChild: any }, [
730
+ '_asChild',
731
+ 'children',
732
+ ]);
733
+ const [_, linkProps] = splitProps(useLinkProps(rest as unknown as any), [
734
+ 'type',
735
+ ]);
736
+
737
+ // Resolve children once using Solid.children to avoid
738
+ // re-accessing the children getter (which in Solid 2.0 would
739
+ // re-invoke createComponent each time for JSX children).
740
+ const resolvedChildren = Solid.children(() => local.children as JSX.Element);
741
+ const children = () => {
742
+ const ch = resolvedChildren();
743
+ if (typeof ch === 'function') {
744
+ return (ch as Function)({
745
+ get isActive() {
746
+ return (linkProps as any)['data-status'] === 'active';
747
+ },
748
+ });
749
+ }
750
+
751
+ return ch;
752
+ };
753
+
754
+ if (local._asChild === 'svg') {
755
+ const [_, svgLinkProps] = splitProps(linkProps as any, ['class']);
756
+ return (
757
+ <svg>
758
+ <a {...svgLinkProps}>{children()}</a>
759
+ </svg>
760
+ );
761
+ }
762
+
763
+ if (!local._asChild) {
764
+ return <a {...linkProps}>{children()}</a>;
765
+ }
766
+
767
+ return (
768
+ <Dynamic component={local._asChild as ValidComponent} {...linkProps}>
769
+ {children()}
770
+ </Dynamic>
771
+ );
772
+ };
773
+
774
+ function isCtrlEvent(e: MouseEvent) {
775
+ return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
776
+ }
777
+
778
+ const warnedStateKeys = new Set<string>();
779
+
780
+ function warnUnknownStateKeys(
781
+ stateProps: object,
782
+ knownKeys: ReadonlySet<string>,
783
+ ) {
784
+ for (const key of Object.keys(stateProps)) {
785
+ if (
786
+ key === 'class' ||
787
+ key === 'style' ||
788
+ knownKeys.has(key) ||
789
+ warnedStateKeys.has(key)
790
+ )
791
+ continue;
792
+ warnedStateKeys.add(key);
793
+ console.warn(
794
+ `Link activeProps/inactiveProps returned "${key}" after the Link was created; return every key from the start (use undefined for "unset") so it can be applied.`,
795
+ );
796
+ }
797
+ }
798
+
799
+ function warnBlockedLink(href: string) {
800
+ if (process.env.NODE_ENV !== 'production') {
801
+ console.warn(`Blocked Link with dangerous protocol: ${href}`);
802
+ }
803
+ }
804
+
805
+ /**
806
+ * Classifies a `to` by URL scheme, as upstream router Links do: the URL when
807
+ * the router's protocol allowlist admits it, `null` when it is blocked, and
808
+ * `undefined` for a route path that still needs route resolution.
809
+ */
810
+ function resolveExternalLink(
811
+ to: unknown,
812
+ protocolAllowlist: AnyRouter['protocolAllowlist'],
813
+ ): string | null | undefined {
814
+ const scheme = typeof to === 'string' ? getUrlScheme(to) : undefined;
815
+ if (!scheme) return undefined;
816
+ if (!protocolAllowlist.has(scheme)) {
817
+ warnBlockedLink(to as string);
818
+ return null;
819
+ }
820
+ return to as string;
821
+ }
822
+
823
+ /**
824
+ * The display href of a built location. publicHref is the full URL when a
825
+ * rewrite changed the origin and the origin-stripped path otherwise, so no URL
826
+ * is constructed in the hot path. A rewritten or history-formatted href with a
827
+ * disallowed protocol resolves to `undefined` and the link renders blocked.
828
+ */
829
+ function getHrefOption(
830
+ next: ParsedLocation,
831
+ router: AnyRouter,
832
+ ): string | undefined {
833
+ const location = next.maskedLocation ?? next;
834
+ const href = location.external
835
+ ? location.publicHref
836
+ : router.history.createHref(location.publicHref) || '/';
837
+ if (
838
+ (location.external || href !== location.publicHref) &&
839
+ isDangerousProtocol(href, router.protocolAllowlist)
840
+ ) {
841
+ warnBlockedLink(href);
842
+ return undefined;
843
+ }
844
+ return href;
845
+ }
846
+
847
+ export type LinkOptionsFnOptions<
848
+ TOptions,
849
+ TComp,
850
+ TRouter extends AnyRouter = RegisteredRouter,
851
+ > =
852
+ TOptions extends ReadonlyArray<any>
853
+ ? ValidateLinkOptionsArray<TRouter, TOptions, string, TComp>
854
+ : ValidateLinkOptions<TRouter, TOptions, string, TComp>;
855
+
856
+ export type LinkOptionsFn<TComp> = <
857
+ const TOptions,
858
+ TRouter extends AnyRouter = RegisteredRouter,
859
+ >(
860
+ options: LinkOptionsFnOptions<TOptions, TComp, TRouter>,
861
+ ) => TOptions;
862
+
863
+ export const linkOptions: LinkOptionsFn<'a'> = options => {
864
+ return options as any;
865
+ };