@tanstack/vue-router 1.140.1 → 1.141.0

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 (150) hide show
  1. package/dist/esm/Asset.js +122 -8
  2. package/dist/esm/Asset.js.map +1 -1
  3. package/dist/esm/Body.d.ts +4 -0
  4. package/dist/esm/Body.js +26 -0
  5. package/dist/esm/Body.js.map +1 -0
  6. package/dist/esm/CatchBoundary.d.ts +1 -1
  7. package/dist/esm/CatchBoundary.js +8 -8
  8. package/dist/esm/CatchBoundary.js.map +1 -1
  9. package/dist/esm/Html.d.ts +4 -0
  10. package/dist/esm/Html.js +63 -0
  11. package/dist/esm/Html.js.map +1 -0
  12. package/dist/esm/Match.js +87 -49
  13. package/dist/esm/Match.js.map +1 -1
  14. package/dist/esm/Matches.js +3 -2
  15. package/dist/esm/Matches.js.map +1 -1
  16. package/dist/esm/RouterProvider.js +3 -0
  17. package/dist/esm/RouterProvider.js.map +1 -1
  18. package/dist/esm/ScriptOnce.d.ts +12 -5
  19. package/dist/esm/ScriptOnce.js +35 -15
  20. package/dist/esm/ScriptOnce.js.map +1 -1
  21. package/dist/esm/Scripts.d.ts +2 -1
  22. package/dist/esm/Scripts.js +101 -35
  23. package/dist/esm/Scripts.js.map +1 -1
  24. package/dist/esm/Transitioner.d.ts +16 -0
  25. package/dist/esm/Transitioner.js +136 -133
  26. package/dist/esm/Transitioner.js.map +1 -1
  27. package/dist/esm/awaited.d.ts +20 -5
  28. package/dist/esm/awaited.js +17 -20
  29. package/dist/esm/awaited.js.map +1 -1
  30. package/dist/esm/index.d.ts +2 -0
  31. package/dist/esm/index.js +4 -0
  32. package/dist/esm/index.js.map +1 -1
  33. package/dist/esm/lazyRouteComponent.js +2 -2
  34. package/dist/esm/lazyRouteComponent.js.map +1 -1
  35. package/dist/esm/link.js +27 -35
  36. package/dist/esm/link.js.map +1 -1
  37. package/dist/esm/scroll-restoration.d.ts +8 -1
  38. package/dist/esm/scroll-restoration.js +44 -12
  39. package/dist/esm/scroll-restoration.js.map +1 -1
  40. package/dist/esm/ssr/RouterClient.d.ts +15 -0
  41. package/dist/esm/ssr/RouterClient.js +46 -0
  42. package/dist/esm/ssr/RouterClient.js.map +1 -0
  43. package/dist/esm/ssr/RouterServer.d.ts +15 -0
  44. package/dist/esm/ssr/RouterServer.js +37 -0
  45. package/dist/esm/ssr/RouterServer.js.map +1 -0
  46. package/dist/esm/ssr/client.d.ts +1 -0
  47. package/dist/esm/ssr/client.js +5 -0
  48. package/dist/esm/ssr/client.js.map +1 -0
  49. package/dist/esm/ssr/defaultRenderHandler.d.ts +1 -0
  50. package/dist/esm/ssr/defaultRenderHandler.js +15 -0
  51. package/dist/esm/ssr/defaultRenderHandler.js.map +1 -0
  52. package/dist/esm/ssr/defaultStreamHandler.d.ts +1 -0
  53. package/dist/esm/ssr/defaultStreamHandler.js +17 -0
  54. package/dist/esm/ssr/defaultStreamHandler.js.map +1 -0
  55. package/dist/esm/ssr/renderRouterToStream.d.ts +8 -0
  56. package/dist/esm/ssr/renderRouterToStream.js +70 -0
  57. package/dist/esm/ssr/renderRouterToStream.js.map +1 -0
  58. package/dist/esm/ssr/renderRouterToString.d.ts +7 -0
  59. package/dist/esm/ssr/renderRouterToString.js +33 -0
  60. package/dist/esm/ssr/renderRouterToString.js.map +1 -0
  61. package/dist/esm/ssr/server.d.ts +6 -0
  62. package/dist/esm/ssr/server.js +14 -0
  63. package/dist/esm/ssr/server.js.map +1 -0
  64. package/dist/source/Asset.jsx +119 -7
  65. package/dist/source/Asset.jsx.map +1 -1
  66. package/dist/source/Body.d.ts +4 -0
  67. package/dist/source/Body.jsx +15 -0
  68. package/dist/source/Body.jsx.map +1 -0
  69. package/dist/source/CatchBoundary.d.ts +1 -1
  70. package/dist/source/CatchBoundary.jsx +10 -23
  71. package/dist/source/CatchBoundary.jsx.map +1 -1
  72. package/dist/source/Html.d.ts +4 -0
  73. package/dist/source/Html.jsx +56 -0
  74. package/dist/source/Html.jsx.map +1 -0
  75. package/dist/source/Match.jsx +119 -54
  76. package/dist/source/Match.jsx.map +1 -1
  77. package/dist/source/Matches.jsx +15 -3
  78. package/dist/source/Matches.jsx.map +1 -1
  79. package/dist/source/RouterProvider.jsx +5 -0
  80. package/dist/source/RouterProvider.jsx.map +1 -1
  81. package/dist/source/ScriptOnce.d.ts +12 -5
  82. package/dist/source/ScriptOnce.jsx +27 -16
  83. package/dist/source/ScriptOnce.jsx.map +1 -1
  84. package/dist/source/Scripts.d.ts +2 -1
  85. package/dist/source/Scripts.jsx +100 -42
  86. package/dist/source/Scripts.jsx.map +1 -1
  87. package/dist/source/Transitioner.d.ts +16 -0
  88. package/dist/source/Transitioner.jsx +180 -160
  89. package/dist/source/Transitioner.jsx.map +1 -1
  90. package/dist/source/awaited.d.ts +20 -5
  91. package/dist/source/awaited.jsx +18 -25
  92. package/dist/source/awaited.jsx.map +1 -1
  93. package/dist/source/index.d.ts +2 -0
  94. package/dist/source/index.jsx +2 -0
  95. package/dist/source/index.jsx.map +1 -1
  96. package/dist/source/lazyRouteComponent.jsx +4 -2
  97. package/dist/source/lazyRouteComponent.jsx.map +1 -1
  98. package/dist/source/link.jsx +37 -51
  99. package/dist/source/link.jsx.map +1 -1
  100. package/dist/source/scroll-restoration.d.ts +8 -1
  101. package/dist/source/scroll-restoration.jsx +55 -12
  102. package/dist/source/scroll-restoration.jsx.map +1 -1
  103. package/dist/source/ssr/RouterClient.d.ts +15 -0
  104. package/dist/source/ssr/RouterClient.jsx +48 -0
  105. package/dist/source/ssr/RouterClient.jsx.map +1 -0
  106. package/dist/source/ssr/RouterServer.d.ts +15 -0
  107. package/dist/source/ssr/RouterServer.jsx +40 -0
  108. package/dist/source/ssr/RouterServer.jsx.map +1 -0
  109. package/dist/source/ssr/client.d.ts +1 -0
  110. package/dist/source/ssr/client.js +2 -0
  111. package/dist/source/ssr/client.js.map +1 -0
  112. package/dist/source/ssr/defaultRenderHandler.d.ts +1 -0
  113. package/dist/source/ssr/defaultRenderHandler.jsx +9 -0
  114. package/dist/source/ssr/defaultRenderHandler.jsx.map +1 -0
  115. package/dist/source/ssr/defaultStreamHandler.d.ts +1 -0
  116. package/dist/source/ssr/defaultStreamHandler.jsx +10 -0
  117. package/dist/source/ssr/defaultStreamHandler.jsx.map +1 -0
  118. package/dist/source/ssr/renderRouterToStream.d.ts +8 -0
  119. package/dist/source/ssr/renderRouterToStream.jsx +55 -0
  120. package/dist/source/ssr/renderRouterToStream.jsx.map +1 -0
  121. package/dist/source/ssr/renderRouterToString.d.ts +7 -0
  122. package/dist/source/ssr/renderRouterToString.jsx +26 -0
  123. package/dist/source/ssr/renderRouterToString.jsx.map +1 -0
  124. package/dist/source/ssr/server.d.ts +6 -0
  125. package/dist/source/ssr/server.js +7 -0
  126. package/dist/source/ssr/server.js.map +1 -0
  127. package/package.json +16 -3
  128. package/src/Asset.tsx +157 -7
  129. package/src/Body.tsx +26 -0
  130. package/src/CatchBoundary.tsx +11 -25
  131. package/src/Html.tsx +65 -0
  132. package/src/Match.tsx +135 -58
  133. package/src/Matches.tsx +16 -4
  134. package/src/RouterProvider.tsx +6 -0
  135. package/src/ScriptOnce.tsx +43 -28
  136. package/src/Scripts.tsx +121 -56
  137. package/src/Transitioner.tsx +197 -176
  138. package/src/awaited.tsx +17 -28
  139. package/src/index.tsx +2 -0
  140. package/src/lazyRouteComponent.tsx +4 -2
  141. package/src/link.tsx +42 -47
  142. package/src/scroll-restoration.tsx +69 -21
  143. package/src/ssr/RouterClient.tsx +58 -0
  144. package/src/ssr/RouterServer.tsx +51 -0
  145. package/src/ssr/client.ts +1 -0
  146. package/src/ssr/defaultRenderHandler.tsx +12 -0
  147. package/src/ssr/defaultStreamHandler.tsx +13 -0
  148. package/src/ssr/renderRouterToStream.tsx +85 -0
  149. package/src/ssr/renderRouterToString.tsx +37 -0
  150. package/src/ssr/server.ts +6 -0
package/dist/esm/Asset.js CHANGED
@@ -1,4 +1,119 @@
1
+ import * as Vue from "vue";
1
2
  import { createVNode, mergeProps } from "vue";
3
+ import { useRouter } from "./useRouter.js";
4
+ const Title = Vue.defineComponent({
5
+ name: "Title",
6
+ props: {
7
+ children: {
8
+ type: String,
9
+ default: ""
10
+ }
11
+ },
12
+ setup(props) {
13
+ const router = useRouter();
14
+ if (!router.isServer) {
15
+ Vue.onMounted(() => {
16
+ if (props.children) {
17
+ document.title = props.children;
18
+ }
19
+ });
20
+ Vue.watch(() => props.children, (newTitle) => {
21
+ if (newTitle) {
22
+ document.title = newTitle;
23
+ }
24
+ });
25
+ }
26
+ return () => Vue.h("title", {}, props.children);
27
+ }
28
+ });
29
+ const Script = Vue.defineComponent({
30
+ name: "Script",
31
+ props: {
32
+ attrs: {
33
+ type: Object,
34
+ default: () => ({})
35
+ },
36
+ children: {
37
+ type: String,
38
+ default: void 0
39
+ }
40
+ },
41
+ setup(props) {
42
+ const router = useRouter();
43
+ if (!router.isServer) {
44
+ Vue.onMounted(() => {
45
+ const attrs = props.attrs;
46
+ const children = props.children;
47
+ if (attrs?.src) {
48
+ const normSrc = (() => {
49
+ try {
50
+ const base = document.baseURI || window.location.href;
51
+ return new URL(attrs.src, base).href;
52
+ } catch {
53
+ return attrs.src;
54
+ }
55
+ })();
56
+ const existingScript = Array.from(document.querySelectorAll("script[src]")).find((el) => el.src === normSrc);
57
+ if (existingScript) {
58
+ return;
59
+ }
60
+ const script = document.createElement("script");
61
+ for (const [key, value] of Object.entries(attrs)) {
62
+ if (value !== void 0 && value !== false) {
63
+ script.setAttribute(key, typeof value === "boolean" ? "" : String(value));
64
+ }
65
+ }
66
+ document.head.appendChild(script);
67
+ } else if (typeof children === "string") {
68
+ const typeAttr = typeof attrs?.type === "string" ? attrs.type : "text/javascript";
69
+ const nonceAttr = typeof attrs?.nonce === "string" ? attrs.nonce : void 0;
70
+ const existingScript = Array.from(document.querySelectorAll("script:not([src])")).find((el) => {
71
+ if (!(el instanceof HTMLScriptElement)) return false;
72
+ const sType = el.getAttribute("type") ?? "text/javascript";
73
+ const sNonce = el.getAttribute("nonce") ?? void 0;
74
+ return el.textContent === children && sType === typeAttr && sNonce === nonceAttr;
75
+ });
76
+ if (existingScript) {
77
+ return;
78
+ }
79
+ const script = document.createElement("script");
80
+ script.textContent = children;
81
+ if (attrs) {
82
+ for (const [key, value] of Object.entries(attrs)) {
83
+ if (value !== void 0 && value !== false) {
84
+ script.setAttribute(key, typeof value === "boolean" ? "" : String(value));
85
+ }
86
+ }
87
+ }
88
+ document.head.appendChild(script);
89
+ }
90
+ });
91
+ }
92
+ return () => {
93
+ if (!router.isServer) {
94
+ const {
95
+ src: _src,
96
+ ...rest
97
+ } = props.attrs || {};
98
+ return Vue.h("script", {
99
+ ...rest,
100
+ "data-allow-mismatch": true,
101
+ innerHTML: ""
102
+ });
103
+ }
104
+ if (props.attrs?.src && typeof props.attrs.src === "string") {
105
+ return Vue.h("script", props.attrs);
106
+ }
107
+ if (typeof props.children === "string") {
108
+ return Vue.h("script", {
109
+ ...props.attrs,
110
+ innerHTML: props.children
111
+ });
112
+ }
113
+ return null;
114
+ };
115
+ }
116
+ });
2
117
  function Asset({
3
118
  tag,
4
119
  attrs,
@@ -6,7 +121,9 @@ function Asset({
6
121
  }) {
7
122
  switch (tag) {
8
123
  case "title":
9
- return createVNode("title", attrs, [children]);
124
+ return Vue.h(Title, {
125
+ children
126
+ });
10
127
  case "meta":
11
128
  return createVNode("meta", attrs, null);
12
129
  case "link":
@@ -16,13 +133,10 @@ function Asset({
16
133
  "innerHTML": children
17
134
  }), null);
18
135
  case "script":
19
- if (attrs && attrs.src) {
20
- return createVNode("script", attrs, null);
21
- }
22
- if (typeof children === "string") return createVNode("script", mergeProps(attrs, {
23
- "innerHTML": children
24
- }), null);
25
- return null;
136
+ return Vue.h(Script, {
137
+ attrs,
138
+ children
139
+ });
26
140
  default:
27
141
  return null;
28
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Asset.js","sources":["../../src/Asset.tsx"],"sourcesContent":["import type { RouterManagedTag } from '@tanstack/router-core'\n\nexport function Asset({ tag, attrs, children }: RouterManagedTag): any {\n switch (tag) {\n case 'title':\n return <title {...attrs}>{children}</title>\n case 'meta':\n return <meta {...attrs} />\n case 'link':\n return <link {...attrs} />\n case 'style':\n return <style {...attrs} innerHTML={children} />\n case 'script':\n if ((attrs as any) && (attrs as any).src) {\n return <script {...attrs} />\n }\n if (typeof children === 'string')\n return <script {...attrs} innerHTML={children} />\n return null\n default:\n return null\n }\n}\n"],"names":["Asset","tag","attrs","children","_createVNode","_mergeProps","src"],"mappings":";AAEO,SAASA,MAAM;AAAA,EAAEC;AAAAA,EAAKC;AAAAA,EAAOC;AAA2B,GAAQ;AACrE,UAAQF,KAAG;AAAA,IACT,KAAK;AACH,aAAAG,YAAA,SAAkBF,OAAK,CAAGC,QAAQ,CAAA;AAAA,IACpC,KAAK;AACH,aAAAC,oBAAiBF,OAAK,IAAA;AAAA,IACxB,KAAK;AACH,aAAAE,oBAAiBF,OAAK,IAAA;AAAA,IACxB,KAAK;AACH,aAAAE,YAAA,SAAAC,WAAkBH,OAAK;AAAA,QAAA,aAAaC;AAAAA,MAAQ,CAAA,GAAA,IAAA;AAAA,IAC9C,KAAK;AACH,UAAKD,SAAkBA,MAAcI,KAAK;AACxC,eAAAF,sBAAmBF,OAAK,IAAA;AAAA,MAC1B;AACA,UAAI,OAAOC,aAAa,SACtB,QAAAC,YAAA,UAAAC,WAAmBH,OAAK;AAAA,QAAA,aAAaC;AAAAA,MAAQ,CAAA,GAAA,IAAA;AAC/C,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;"}
1
+ {"version":3,"file":"Asset.js","sources":["../../src/Asset.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { useRouter } from './useRouter'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\ninterface ScriptAttrs {\n [key: string]: string | boolean | undefined\n src?: string\n}\n\nconst Title = Vue.defineComponent({\n name: 'Title',\n props: {\n children: {\n type: String,\n default: '',\n },\n },\n setup(props) {\n const router = useRouter()\n\n if (!router.isServer) {\n Vue.onMounted(() => {\n if (props.children) {\n document.title = props.children\n }\n })\n\n Vue.watch(\n () => props.children,\n (newTitle) => {\n if (newTitle) {\n document.title = newTitle\n }\n },\n )\n }\n\n return () => Vue.h('title', {}, props.children)\n },\n})\n\nconst Script = Vue.defineComponent({\n name: 'Script',\n props: {\n attrs: {\n type: Object as Vue.PropType<ScriptAttrs>,\n default: () => ({}),\n },\n children: {\n type: String,\n default: undefined,\n },\n },\n setup(props) {\n const router = useRouter()\n\n if (!router.isServer) {\n Vue.onMounted(() => {\n const attrs = props.attrs\n const children = props.children\n\n if (attrs?.src) {\n const normSrc = (() => {\n try {\n const base = document.baseURI || window.location.href\n return new URL(attrs.src, base).href\n } catch {\n return attrs.src\n }\n })()\n const existingScript = Array.from(\n document.querySelectorAll('script[src]'),\n ).find((el) => (el as HTMLScriptElement).src === normSrc)\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n\n for (const [key, value] of Object.entries(attrs)) {\n if (value !== undefined && value !== false) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n\n document.head.appendChild(script)\n } else if (typeof children === 'string') {\n const typeAttr =\n typeof attrs?.type === 'string' ? attrs.type : 'text/javascript'\n const nonceAttr =\n typeof attrs?.nonce === 'string' ? attrs.nonce : undefined\n const existingScript = Array.from(\n document.querySelectorAll('script:not([src])'),\n ).find((el) => {\n if (!(el instanceof HTMLScriptElement)) return false\n const sType = el.getAttribute('type') ?? 'text/javascript'\n const sNonce = el.getAttribute('nonce') ?? undefined\n return (\n el.textContent === children &&\n sType === typeAttr &&\n sNonce === nonceAttr\n )\n })\n\n if (existingScript) {\n return\n }\n\n const script = document.createElement('script')\n script.textContent = children\n\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (value !== undefined && value !== false) {\n script.setAttribute(\n key,\n typeof value === 'boolean' ? '' : String(value),\n )\n }\n }\n }\n\n document.head.appendChild(script)\n }\n })\n }\n\n return () => {\n if (!router.isServer) {\n const { src: _src, ...rest } = props.attrs || {}\n return Vue.h('script', {\n ...rest,\n 'data-allow-mismatch': true,\n innerHTML: '',\n })\n }\n\n if (props.attrs?.src && typeof props.attrs.src === 'string') {\n return Vue.h('script', props.attrs)\n }\n\n if (typeof props.children === 'string') {\n return Vue.h('script', {\n ...props.attrs,\n innerHTML: props.children,\n })\n }\n\n return null\n }\n },\n})\n\nexport function Asset({ tag, attrs, children }: RouterManagedTag): any {\n switch (tag) {\n case 'title':\n return Vue.h(Title, { children: children })\n case 'meta':\n return <meta {...attrs} />\n case 'link':\n return <link {...attrs} />\n case 'style':\n return <style {...attrs} innerHTML={children} />\n case 'script':\n return Vue.h(Script, { attrs, children: children })\n default:\n return null\n }\n}\n"],"names":["Title","Vue","defineComponent","name","props","children","type","String","default","setup","router","useRouter","isServer","onMounted","document","title","watch","newTitle","h","Script","attrs","Object","undefined","src","normSrc","base","baseURI","window","location","href","URL","existingScript","Array","from","querySelectorAll","find","el","script","createElement","key","value","entries","setAttribute","head","appendChild","typeAttr","nonceAttr","nonce","HTMLScriptElement","sType","getAttribute","sNonce","textContent","_src","rest","innerHTML","Asset","tag","_createVNode","_mergeProps"],"mappings":";;;AASA,MAAMA,QAAQC,IAAIC,gBAAgB;AAAA,EAChCC,MAAM;AAAA,EACNC,OAAO;AAAA,IACLC,UAAU;AAAA,MACRC,MAAMC;AAAAA,MACNC,SAAS;AAAA,IACX;AAAA;EAEFC,MAAML,OAAO;AACX,UAAMM,SAASC,UAAS;AAExB,QAAI,CAACD,OAAOE,UAAU;AACpBX,UAAIY,UAAU,MAAM;AAClB,YAAIT,MAAMC,UAAU;AAClBS,mBAASC,QAAQX,MAAMC;AAAAA,QACzB;AAAA,MACF,CAAC;AAEDJ,UAAIe,MACF,MAAMZ,MAAMC,UACXY,cAAa;AACZ,YAAIA,UAAU;AACZH,mBAASC,QAAQE;AAAAA,QACnB;AAAA,MACF,CACF;AAAA,IACF;AAEA,WAAO,MAAMhB,IAAIiB,EAAE,SAAS,CAAA,GAAId,MAAMC,QAAQ;AAAA,EAChD;AACF,CAAC;AAED,MAAMc,SAASlB,IAAIC,gBAAgB;AAAA,EACjCC,MAAM;AAAA,EACNC,OAAO;AAAA,IACLgB,OAAO;AAAA,MACLd,MAAMe;AAAAA,MACNb,SAASA,OAAO,CAAA;AAAA;IAElBH,UAAU;AAAA,MACRC,MAAMC;AAAAA,MACNC,SAASc;AAAAA,IACX;AAAA;EAEFb,MAAML,OAAO;AACX,UAAMM,SAASC,UAAS;AAExB,QAAI,CAACD,OAAOE,UAAU;AACpBX,UAAIY,UAAU,MAAM;AAClB,cAAMO,QAAQhB,MAAMgB;AACpB,cAAMf,WAAWD,MAAMC;AAEvB,YAAIe,OAAOG,KAAK;AACd,gBAAMC,WAAW,MAAM;AACrB,gBAAI;AACF,oBAAMC,OAAOX,SAASY,WAAWC,OAAOC,SAASC;AACjD,qBAAO,IAAIC,IAAIV,MAAMG,KAAKE,IAAI,EAAEI;AAAAA,YAClC,QAAQ;AACN,qBAAOT,MAAMG;AAAAA,YACf;AAAA,UACF,GAAC;AACD,gBAAMQ,iBAAiBC,MAAMC,KAC3BnB,SAASoB,iBAAiB,aAAa,CACzC,EAAEC,KAAMC,QAAQA,GAAyBb,QAAQC,OAAO;AAExD,cAAIO,gBAAgB;AAClB;AAAA,UACF;AAEA,gBAAMM,SAASvB,SAASwB,cAAc,QAAQ;AAE9C,qBAAW,CAACC,KAAKC,KAAK,KAAKnB,OAAOoB,QAAQrB,KAAK,GAAG;AAChD,gBAAIoB,UAAUlB,UAAakB,UAAU,OAAO;AAC1CH,qBAAOK,aACLH,KACA,OAAOC,UAAU,YAAY,KAAKjC,OAAOiC,KAAK,CAChD;AAAA,YACF;AAAA,UACF;AAEA1B,mBAAS6B,KAAKC,YAAYP,MAAM;AAAA,QAClC,WAAW,OAAOhC,aAAa,UAAU;AACvC,gBAAMwC,WACJ,OAAOzB,OAAOd,SAAS,WAAWc,MAAMd,OAAO;AACjD,gBAAMwC,YACJ,OAAO1B,OAAO2B,UAAU,WAAW3B,MAAM2B,QAAQzB;AACnD,gBAAMS,iBAAiBC,MAAMC,KAC3BnB,SAASoB,iBAAiB,mBAAmB,CAC/C,EAAEC,KAAMC,QAAO;AACb,gBAAI,EAAEA,cAAcY,mBAAoB,QAAO;AAC/C,kBAAMC,QAAQb,GAAGc,aAAa,MAAM,KAAK;AACzC,kBAAMC,SAASf,GAAGc,aAAa,OAAO,KAAK5B;AAC3C,mBACEc,GAAGgB,gBAAgB/C,YACnB4C,UAAUJ,YACVM,WAAWL;AAAAA,UAEf,CAAC;AAED,cAAIf,gBAAgB;AAClB;AAAA,UACF;AAEA,gBAAMM,SAASvB,SAASwB,cAAc,QAAQ;AAC9CD,iBAAOe,cAAc/C;AAErB,cAAIe,OAAO;AACT,uBAAW,CAACmB,KAAKC,KAAK,KAAKnB,OAAOoB,QAAQrB,KAAK,GAAG;AAChD,kBAAIoB,UAAUlB,UAAakB,UAAU,OAAO;AAC1CH,uBAAOK,aACLH,KACA,OAAOC,UAAU,YAAY,KAAKjC,OAAOiC,KAAK,CAChD;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA1B,mBAAS6B,KAAKC,YAAYP,MAAM;AAAA,QAClC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,MAAM;AACX,UAAI,CAAC3B,OAAOE,UAAU;AACpB,cAAM;AAAA,UAAEW,KAAK8B;AAAAA,UAAM,GAAGC;AAAAA,QAAK,IAAIlD,MAAMgB,SAAS,CAAA;AAC9C,eAAOnB,IAAIiB,EAAE,UAAU;AAAA,UACrB,GAAGoC;AAAAA,UACH,uBAAuB;AAAA,UACvBC,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAEA,UAAInD,MAAMgB,OAAOG,OAAO,OAAOnB,MAAMgB,MAAMG,QAAQ,UAAU;AAC3D,eAAOtB,IAAIiB,EAAE,UAAUd,MAAMgB,KAAK;AAAA,MACpC;AAEA,UAAI,OAAOhB,MAAMC,aAAa,UAAU;AACtC,eAAOJ,IAAIiB,EAAE,UAAU;AAAA,UACrB,GAAGd,MAAMgB;AAAAA,UACTmC,WAAWnD,MAAMC;AAAAA,QACnB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF,CAAC;AAEM,SAASmD,MAAM;AAAA,EAAEC;AAAAA,EAAKrC;AAAAA,EAAOf;AAA2B,GAAQ;AACrE,UAAQoD,KAAG;AAAA,IACT,KAAK;AACH,aAAOxD,IAAIiB,EAAElB,OAAO;AAAA,QAAEK;AAAAA,MAAmB,CAAC;AAAA,IAC5C,KAAK;AACH,aAAAqD,oBAAiBtC,OAAK,IAAA;AAAA,IACxB,KAAK;AACH,aAAAsC,oBAAiBtC,OAAK,IAAA;AAAA,IACxB,KAAK;AACH,aAAAsC,YAAA,SAAAC,WAAkBvC,OAAK;AAAA,QAAA,aAAaf;AAAAA,MAAQ,CAAA,GAAA,IAAA;AAAA,IAC9C,KAAK;AACH,aAAOJ,IAAIiB,EAAEC,QAAQ;AAAA,QAAEC;AAAAA,QAAOf;AAAAA,MAAmB,CAAC;AAAA,IACpD;AACE,aAAO;AAAA,EACX;AACF;"}
@@ -0,0 +1,4 @@
1
+ import * as Vue from 'vue';
2
+ export declare const Body: Vue.DefineComponent<{}, () => Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
3
+ [key: string]: any;
4
+ }>, {}, {}, {}, Vue.ComponentOptionsMixin, Vue.ComponentOptionsMixin, {}, string, Vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, Vue.ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,26 @@
1
+ import * as Vue from "vue";
2
+ const Body = Vue.defineComponent({
3
+ name: "Body",
4
+ setup(_, {
5
+ slots
6
+ }) {
7
+ const isServer = typeof window === "undefined";
8
+ return () => {
9
+ const children = slots.default?.();
10
+ if (isServer) {
11
+ return Vue.h("body", {}, Vue.h("div", {
12
+ id: "__app"
13
+ }, Vue.h("div", {
14
+ "data-allow-mismatch": ""
15
+ }, children)));
16
+ }
17
+ return Vue.h("div", {
18
+ "data-allow-mismatch": ""
19
+ }, children);
20
+ };
21
+ }
22
+ });
23
+ export {
24
+ Body
25
+ };
26
+ //# sourceMappingURL=Body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Body.js","sources":["../../src/Body.tsx"],"sourcesContent":["import * as Vue from 'vue'\n\nexport const Body = Vue.defineComponent({\n name: 'Body',\n setup(_, { slots }) {\n const isServer = typeof window === 'undefined'\n\n return () => {\n const children = slots.default?.()\n\n if (isServer) {\n return Vue.h(\n 'body',\n {},\n Vue.h(\n 'div',\n { id: '__app' },\n Vue.h('div', { 'data-allow-mismatch': '' }, children),\n ),\n )\n }\n\n return Vue.h('div', { 'data-allow-mismatch': '' }, children)\n }\n },\n})\n"],"names":["Body","Vue","defineComponent","name","setup","_","slots","isServer","window","children","default","h","id"],"mappings":";MAEaA,OAAOC,IAAIC,gBAAgB;AAAA,EACtCC,MAAM;AAAA,EACNC,MAAMC,GAAG;AAAA,IAAEC;AAAAA,EAAM,GAAG;AAClB,UAAMC,WAAW,OAAOC,WAAW;AAEnC,WAAO,MAAM;AACX,YAAMC,WAAWH,MAAMI,UAAO;AAE9B,UAAIH,UAAU;AACZ,eAAON,IAAIU,EACT,QACA,CAAA,GACAV,IAAIU,EACF,OACA;AAAA,UAAEC,IAAI;AAAA,QAAQ,GACdX,IAAIU,EAAE,OAAO;AAAA,UAAE,uBAAuB;AAAA,QAAG,GAAGF,QAAQ,CACtD,CACF;AAAA,MACF;AAEA,aAAOR,IAAIU,EAAE,OAAO;AAAA,QAAE,uBAAuB;AAAA,SAAMF,QAAQ;AAAA,IAC7D;AAAA,EACF;AACF,CAAC;"}
@@ -3,7 +3,7 @@ import * as Vue from 'vue';
3
3
  export declare function CatchBoundary(props: {
4
4
  getResetKey: () => number | string;
5
5
  children: Vue.VNode;
6
- errorComponent?: ErrorRouteComponent;
6
+ errorComponent?: ErrorRouteComponent | Vue.Component;
7
7
  onCatch?: (error: Error) => void;
8
8
  }): Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
9
9
  [key: string]: any;
@@ -32,12 +32,14 @@ const VueErrorBoundary = Vue.defineComponent({
32
32
  });
33
33
  return () => {
34
34
  if (error.value && slots.fallback) {
35
- return slots.fallback({
35
+ const fallbackContent = slots.fallback({
36
36
  error: error.value,
37
37
  reset
38
38
  });
39
+ return Array.isArray(fallbackContent) && fallbackContent.length === 1 ? fallbackContent[0] : fallbackContent;
39
40
  }
40
- return slots.default && slots.default();
41
+ const defaultContent = slots.default && slots.default();
42
+ return Array.isArray(defaultContent) && defaultContent.length === 1 ? defaultContent[0] : defaultContent;
41
43
  };
42
44
  }
43
45
  });
@@ -48,7 +50,6 @@ function CatchBoundary(props) {
48
50
  setup() {
49
51
  const resetKey = Vue.computed(() => props.getResetKey());
50
52
  return () => {
51
- const defaultErrorComponent = ErrorComponent;
52
53
  return Vue.h(VueErrorBoundary, {
53
54
  resetKey: resetKey.value,
54
55
  onError: props.onCatch
@@ -63,12 +64,11 @@ function CatchBoundary(props) {
63
64
  error,
64
65
  reset
65
66
  });
66
- } else {
67
- return Vue.h(defaultErrorComponent, {
68
- error,
69
- reset
70
- });
71
67
  }
68
+ return Vue.h(ErrorComponent, {
69
+ error,
70
+ reset
71
+ });
72
72
  }
73
73
  });
74
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CatchBoundary.js","sources":["../../src/CatchBoundary.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport type { ErrorRouteComponent } from './route'\n\n// Define the error component props interface\ninterface ErrorComponentProps {\n error: Error\n reset: () => void\n}\n\n// Create a Vue error boundary component\nconst VueErrorBoundary = Vue.defineComponent({\n name: 'VueErrorBoundary',\n props: {\n onError: Function,\n resetKey: [String, Number],\n },\n emits: ['catch'],\n setup(props, { slots }) {\n const error = Vue.ref<Error | null>(null)\n const resetFn = Vue.ref<(() => void) | null>(null)\n\n const reset = () => {\n error.value = null\n }\n\n // Watch for changes in the reset key\n Vue.watch(\n () => props.resetKey,\n (newKey, oldKey) => {\n if (newKey !== oldKey && error.value) {\n reset()\n }\n },\n )\n\n // Capture errors from child components\n Vue.onErrorCaptured((err: Error) => {\n // If the error is a Promise (thrown for Suspense), don't treat it as an error\n // Just ignore it - Suspense will handle it\n if (\n err instanceof Promise ||\n (err && typeof (err as any).then === 'function')\n ) {\n return false // Prevent from propagating as an error, but don't set error state\n }\n\n error.value = err\n resetFn.value = reset\n\n // Call the onError callback if provided\n if (props.onError) {\n props.onError(err)\n }\n\n // Prevent the error from propagating further\n return false\n })\n\n return () => {\n // If there's an error, render the fallback\n if (error.value && slots.fallback) {\n return slots.fallback({\n error: error.value,\n reset,\n })\n }\n\n // Otherwise render the default slot\n return slots.default && slots.default()\n }\n },\n})\n\n// Main CatchBoundary component\nexport function CatchBoundary(props: {\n getResetKey: () => number | string\n children: Vue.VNode\n errorComponent?: ErrorRouteComponent\n onCatch?: (error: Error) => void\n}) {\n // Create a component to use in the template\n const CatchBoundaryWrapper = Vue.defineComponent({\n name: 'CatchBoundaryWrapper',\n inheritAttrs: false,\n setup() {\n const resetKey = Vue.computed(() => props.getResetKey())\n\n return () => {\n // Always use our default component as a safe fallback\n const defaultErrorComponent = ErrorComponent\n\n return Vue.h(\n VueErrorBoundary,\n {\n resetKey: resetKey.value,\n onError: props.onCatch,\n },\n {\n default: () => props.children,\n fallback: ({ error, reset }: ErrorComponentProps) => {\n // Safely render the error component - either the provided one or the default\n if (props.errorComponent) {\n // Use the provided error component\n return Vue.h(props.errorComponent, { error, reset })\n } else {\n // Use the default error component\n return Vue.h(defaultErrorComponent, { error, reset })\n }\n },\n },\n )\n }\n },\n })\n\n return Vue.h(CatchBoundaryWrapper)\n}\n\n// Error component\nexport const ErrorComponent = Vue.defineComponent({\n name: 'ErrorComponent',\n props: {\n error: Object,\n reset: Function,\n },\n setup(props) {\n const show = Vue.ref(process.env.NODE_ENV !== 'production')\n\n const toggleShow = () => {\n show.value = !show.value\n }\n\n return () =>\n Vue.h('div', { style: { padding: '.5rem', maxWidth: '100%' } }, [\n Vue.h(\n 'div',\n { style: { display: 'flex', alignItems: 'center', gap: '.5rem' } },\n [\n Vue.h(\n 'strong',\n { style: { fontSize: '1rem' } },\n 'Something went wrong!',\n ),\n Vue.h(\n 'button',\n {\n style: {\n appearance: 'none',\n fontSize: '.6em',\n border: '1px solid currentColor',\n padding: '.1rem .2rem',\n fontWeight: 'bold',\n borderRadius: '.25rem',\n },\n onClick: toggleShow,\n },\n show.value ? 'Hide Error' : 'Show Error',\n ),\n ],\n ),\n Vue.h('div', { style: { height: '.25rem' } }),\n show.value\n ? Vue.h('div', {}, [\n Vue.h(\n 'pre',\n {\n style: {\n fontSize: '.7em',\n border: '1px solid red',\n borderRadius: '.25rem',\n padding: '.3rem',\n color: 'red',\n overflow: 'auto',\n },\n },\n [\n props.error?.message\n ? Vue.h('code', {}, props.error.message)\n : null,\n ],\n ),\n ])\n : null,\n ])\n },\n})\n"],"names":["VueErrorBoundary","Vue","defineComponent","name","props","onError","Function","resetKey","String","Number","emits","setup","slots","error","ref","resetFn","reset","value","watch","newKey","oldKey","onErrorCaptured","err","Promise","then","fallback","default","CatchBoundary","CatchBoundaryWrapper","inheritAttrs","computed","getResetKey","defaultErrorComponent","ErrorComponent","h","onCatch","children","errorComponent","Object","show","process","env","NODE_ENV","toggleShow","style","padding","maxWidth","display","alignItems","gap","fontSize","appearance","border","fontWeight","borderRadius","onClick","height","color","overflow","message"],"mappings":"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"}
1
+ {"version":3,"file":"CatchBoundary.js","sources":["../../src/CatchBoundary.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport type { ErrorRouteComponent } from './route'\n\ninterface ErrorComponentProps {\n error: Error\n reset: () => void\n}\n\nconst VueErrorBoundary = Vue.defineComponent({\n name: 'VueErrorBoundary',\n props: {\n onError: Function,\n resetKey: [String, Number],\n },\n emits: ['catch'],\n setup(props, { slots }) {\n const error = Vue.ref<Error | null>(null)\n const resetFn = Vue.ref<(() => void) | null>(null)\n\n const reset = () => {\n error.value = null\n }\n\n Vue.watch(\n () => props.resetKey,\n (newKey, oldKey) => {\n if (newKey !== oldKey && error.value) {\n reset()\n }\n },\n )\n\n Vue.onErrorCaptured((err: Error) => {\n if (\n err instanceof Promise ||\n (err && typeof (err as any).then === 'function')\n ) {\n return false\n }\n\n error.value = err\n resetFn.value = reset\n\n if (props.onError) {\n props.onError(err)\n }\n\n return false\n })\n\n return () => {\n if (error.value && slots.fallback) {\n const fallbackContent = slots.fallback({\n error: error.value,\n reset,\n })\n return Array.isArray(fallbackContent) && fallbackContent.length === 1\n ? fallbackContent[0]\n : fallbackContent\n }\n\n const defaultContent = slots.default && slots.default()\n return Array.isArray(defaultContent) && defaultContent.length === 1\n ? defaultContent[0]\n : defaultContent\n }\n },\n})\n\nexport function CatchBoundary(props: {\n getResetKey: () => number | string\n children: Vue.VNode\n errorComponent?: ErrorRouteComponent | Vue.Component\n onCatch?: (error: Error) => void\n}) {\n const CatchBoundaryWrapper = Vue.defineComponent({\n name: 'CatchBoundaryWrapper',\n inheritAttrs: false,\n setup() {\n const resetKey = Vue.computed(() => props.getResetKey())\n\n return () => {\n return Vue.h(\n VueErrorBoundary,\n {\n resetKey: resetKey.value,\n onError: props.onCatch,\n },\n {\n default: () => props.children,\n fallback: ({ error, reset }: ErrorComponentProps) => {\n if (props.errorComponent) {\n return Vue.h(props.errorComponent, { error, reset })\n }\n return Vue.h(ErrorComponent, { error, reset })\n },\n },\n )\n }\n },\n })\n\n return Vue.h(CatchBoundaryWrapper)\n}\n\nexport const ErrorComponent = Vue.defineComponent({\n name: 'ErrorComponent',\n props: {\n error: Object,\n reset: Function,\n },\n setup(props) {\n const show = Vue.ref(process.env.NODE_ENV !== 'production')\n\n const toggleShow = () => {\n show.value = !show.value\n }\n\n return () =>\n Vue.h('div', { style: { padding: '.5rem', maxWidth: '100%' } }, [\n Vue.h(\n 'div',\n { style: { display: 'flex', alignItems: 'center', gap: '.5rem' } },\n [\n Vue.h(\n 'strong',\n { style: { fontSize: '1rem' } },\n 'Something went wrong!',\n ),\n Vue.h(\n 'button',\n {\n style: {\n appearance: 'none',\n fontSize: '.6em',\n border: '1px solid currentColor',\n padding: '.1rem .2rem',\n fontWeight: 'bold',\n borderRadius: '.25rem',\n },\n onClick: toggleShow,\n },\n show.value ? 'Hide Error' : 'Show Error',\n ),\n ],\n ),\n Vue.h('div', { style: { height: '.25rem' } }),\n show.value\n ? Vue.h('div', {}, [\n Vue.h(\n 'pre',\n {\n style: {\n fontSize: '.7em',\n border: '1px solid red',\n borderRadius: '.25rem',\n padding: '.3rem',\n color: 'red',\n overflow: 'auto',\n },\n },\n [\n props.error?.message\n ? Vue.h('code', {}, props.error.message)\n : null,\n ],\n ),\n ])\n : null,\n ])\n },\n})\n"],"names":["VueErrorBoundary","Vue","defineComponent","name","props","onError","Function","resetKey","String","Number","emits","setup","slots","error","ref","resetFn","reset","value","watch","newKey","oldKey","onErrorCaptured","err","Promise","then","fallback","fallbackContent","Array","isArray","length","defaultContent","default","CatchBoundary","CatchBoundaryWrapper","inheritAttrs","computed","getResetKey","h","onCatch","children","errorComponent","ErrorComponent","Object","show","process","env","NODE_ENV","toggleShow","style","padding","maxWidth","display","alignItems","gap","fontSize","appearance","border","fontWeight","borderRadius","onClick","height","color","overflow","message"],"mappings":";AAQA,MAAMA,mBAAmBC,IAAIC,gBAAgB;AAAA,EAC3CC,MAAM;AAAA,EACNC,OAAO;AAAA,IACLC,SAASC;AAAAA,IACTC,UAAU,CAACC,QAAQC,MAAM;AAAA;EAE3BC,OAAO,CAAC,OAAO;AAAA,EACfC,MAAMP,OAAO;AAAA,IAAEQ;AAAAA,EAAM,GAAG;AACtB,UAAMC,QAAQZ,IAAIa,IAAkB,IAAI;AACxC,UAAMC,UAAUd,IAAIa,IAAyB,IAAI;AAEjD,UAAME,QAAQA,MAAM;AAClBH,YAAMI,QAAQ;AAAA,IAChB;AAEAhB,QAAIiB,MACF,MAAMd,MAAMG,UACZ,CAACY,QAAQC,WAAW;AAClB,UAAID,WAAWC,UAAUP,MAAMI,OAAO;AACpCD,cAAK;AAAA,MACP;AAAA,IACF,CACF;AAEAf,QAAIoB,gBAAiBC,SAAe;AAClC,UACEA,eAAeC,WACdD,OAAO,OAAQA,IAAYE,SAAS,YACrC;AACA,eAAO;AAAA,MACT;AAEAX,YAAMI,QAAQK;AACdP,cAAQE,QAAQD;AAEhB,UAAIZ,MAAMC,SAAS;AACjBD,cAAMC,QAAQiB,GAAG;AAAA,MACnB;AAEA,aAAO;AAAA,IACT,CAAC;AAED,WAAO,MAAM;AACX,UAAIT,MAAMI,SAASL,MAAMa,UAAU;AACjC,cAAMC,kBAAkBd,MAAMa,SAAS;AAAA,UACrCZ,OAAOA,MAAMI;AAAAA,UACbD;AAAAA,QACF,CAAC;AACD,eAAOW,MAAMC,QAAQF,eAAe,KAAKA,gBAAgBG,WAAW,IAChEH,gBAAgB,CAAC,IACjBA;AAAAA,MACN;AAEA,YAAMI,iBAAiBlB,MAAMmB,WAAWnB,MAAMmB,QAAO;AACrD,aAAOJ,MAAMC,QAAQE,cAAc,KAAKA,eAAeD,WAAW,IAC9DC,eAAe,CAAC,IAChBA;AAAAA,IACN;AAAA,EACF;AACF,CAAC;AAEM,SAASE,cAAc5B,OAK3B;AACD,QAAM6B,uBAAuBhC,IAAIC,gBAAgB;AAAA,IAC/CC,MAAM;AAAA,IACN+B,cAAc;AAAA,IACdvB,QAAQ;AACN,YAAMJ,WAAWN,IAAIkC,SAAS,MAAM/B,MAAMgC,YAAW,CAAE;AAEvD,aAAO,MAAM;AACX,eAAOnC,IAAIoC,EACTrC,kBACA;AAAA,UACEO,UAAUA,SAASU;AAAAA,UACnBZ,SAASD,MAAMkC;AAAAA,QACjB,GACA;AAAA,UACEP,SAASA,MAAM3B,MAAMmC;AAAAA,UACrBd,UAAUA,CAAC;AAAA,YAAEZ;AAAAA,YAAOG;AAAAA,UAA2B,MAAM;AACnD,gBAAIZ,MAAMoC,gBAAgB;AACxB,qBAAOvC,IAAIoC,EAAEjC,MAAMoC,gBAAgB;AAAA,gBAAE3B;AAAAA,gBAAOG;AAAAA,cAAM,CAAC;AAAA,YACrD;AACA,mBAAOf,IAAIoC,EAAEI,gBAAgB;AAAA,cAAE5B;AAAAA,cAAOG;AAAAA,YAAM,CAAC;AAAA,UAC/C;AAAA,QACF,CACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAOf,IAAIoC,EAAEJ,oBAAoB;AACnC;MAEaQ,iBAAiBxC,IAAIC,gBAAgB;AAAA,EAChDC,MAAM;AAAA,EACNC,OAAO;AAAA,IACLS,OAAO6B;AAAAA,IACP1B,OAAOV;AAAAA;EAETK,MAAMP,OAAO;AACX,UAAMuC,OAAO1C,IAAIa,IAAI8B,QAAQC,IAAIC,aAAa,YAAY;AAE1D,UAAMC,aAAaA,MAAM;AACvBJ,WAAK1B,QAAQ,CAAC0B,KAAK1B;AAAAA,IACrB;AAEA,WAAO,MACLhB,IAAIoC,EAAE,OAAO;AAAA,MAAEW,OAAO;AAAA,QAAEC,SAAS;AAAA,QAASC,UAAU;AAAA,MAAO;AAAA,IAAE,GAAG,CAC9DjD,IAAIoC,EACF,OACA;AAAA,MAAEW,OAAO;AAAA,QAAEG,SAAS;AAAA,QAAQC,YAAY;AAAA,QAAUC,KAAK;AAAA,MAAQ;AAAA,IAAE,GACjE,CACEpD,IAAIoC,EACF,UACA;AAAA,MAAEW,OAAO;AAAA,QAAEM,UAAU;AAAA,MAAO;AAAA,OAC5B,uBACF,GACArD,IAAIoC,EACF,UACA;AAAA,MACEW,OAAO;AAAA,QACLO,YAAY;AAAA,QACZD,UAAU;AAAA,QACVE,QAAQ;AAAA,QACRP,SAAS;AAAA,QACTQ,YAAY;AAAA,QACZC,cAAc;AAAA;MAEhBC,SAASZ;AAAAA,IACX,GACAJ,KAAK1B,QAAQ,eAAe,YAC9B,CAAC,CAEL,GACAhB,IAAIoC,EAAE,OAAO;AAAA,MAAEW,OAAO;AAAA,QAAEY,QAAQ;AAAA,MAAS;AAAA,KAAG,GAC5CjB,KAAK1B,QACDhB,IAAIoC,EAAE,OAAO,CAAA,GAAI,CACfpC,IAAIoC,EACF,OACA;AAAA,MACEW,OAAO;AAAA,QACLM,UAAU;AAAA,QACVE,QAAQ;AAAA,QACRE,cAAc;AAAA,QACdT,SAAS;AAAA,QACTY,OAAO;AAAA,QACPC,UAAU;AAAA,MACZ;AAAA,IACF,GACA,CACE1D,MAAMS,OAAOkD,UACT9D,IAAIoC,EAAE,QAAQ,CAAA,GAAIjC,MAAMS,MAAMkD,OAAO,IACrC,IAAI,CAEZ,CAAC,CACF,IACD,IAAI,CACT;AAAA,EACL;AACF,CAAC;"}
@@ -0,0 +1,4 @@
1
+ import * as Vue from 'vue';
2
+ export declare const Html: Vue.DefineComponent<{}, () => Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
3
+ [key: string]: any;
4
+ }> | undefined, {}, {}, {}, Vue.ComponentOptionsMixin, Vue.ComponentOptionsMixin, {}, string, Vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, Vue.ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,63 @@
1
+ import * as Vue from "vue";
2
+ import { Body } from "./Body.js";
3
+ const Html = Vue.defineComponent({
4
+ name: "Html",
5
+ setup(_, {
6
+ slots
7
+ }) {
8
+ const isServer = typeof window === "undefined";
9
+ const hydrated = Vue.ref(false);
10
+ if (!isServer) {
11
+ Vue.onMounted(() => {
12
+ hydrated.value = true;
13
+ });
14
+ }
15
+ return () => {
16
+ if (isServer) {
17
+ return Vue.h("html", {}, slots.default?.());
18
+ }
19
+ const children = slots.default?.() || [];
20
+ const flatChildren = Array.isArray(children) ? children : [children];
21
+ let bodyVnode = null;
22
+ const headChildren = [];
23
+ for (const child of flatChildren) {
24
+ if (typeof child === "object" && child !== null) {
25
+ const vnode = child;
26
+ if (vnode.type === "head") {
27
+ if (vnode.children) {
28
+ if (Array.isArray(vnode.children)) {
29
+ for (const c of vnode.children) {
30
+ if (typeof c === "object" && c !== null && "type" in c) {
31
+ headChildren.push(c);
32
+ }
33
+ }
34
+ }
35
+ }
36
+ continue;
37
+ }
38
+ if (vnode.type === Body) {
39
+ bodyVnode = vnode;
40
+ continue;
41
+ }
42
+ if (!bodyVnode) {
43
+ bodyVnode = vnode;
44
+ }
45
+ }
46
+ }
47
+ const result = [];
48
+ if (bodyVnode) {
49
+ result.push(bodyVnode);
50
+ }
51
+ if (hydrated.value && headChildren.length > 0) {
52
+ result.push(Vue.h(Vue.Teleport, {
53
+ to: "head"
54
+ }, headChildren));
55
+ }
56
+ return result.length === 1 ? result[0] : Vue.h(Vue.Fragment, result);
57
+ };
58
+ }
59
+ });
60
+ export {
61
+ Html
62
+ };
63
+ //# sourceMappingURL=Html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Html.js","sources":["../../src/Html.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { Body } from './Body'\n\nexport const Html = Vue.defineComponent({\n name: 'Html',\n setup(_, { slots }) {\n const isServer = typeof window === 'undefined'\n\n const hydrated = Vue.ref(false)\n\n if (!isServer) {\n Vue.onMounted(() => {\n hydrated.value = true\n })\n }\n\n return () => {\n if (isServer) {\n return Vue.h('html', {}, slots.default?.())\n }\n\n const children = slots.default?.() || []\n const flatChildren = Array.isArray(children) ? children : [children]\n let bodyVnode: Vue.VNode | null = null\n const headChildren: Array<Vue.VNode> = []\n\n for (const child of flatChildren) {\n if (typeof child === 'object' && child !== null) {\n const vnode = child\n if (vnode.type === 'head') {\n if (vnode.children) {\n if (Array.isArray(vnode.children)) {\n for (const c of vnode.children) {\n if (typeof c === 'object' && c !== null && 'type' in c) {\n headChildren.push(c as Vue.VNode)\n }\n }\n }\n }\n continue\n }\n if (vnode.type === Body) {\n bodyVnode = vnode\n continue\n }\n if (!bodyVnode) {\n bodyVnode = vnode\n }\n }\n }\n\n const result: Array<Vue.VNode> = []\n\n if (bodyVnode) {\n result.push(bodyVnode)\n }\n\n if (hydrated.value && headChildren.length > 0) {\n result.push(Vue.h(Vue.Teleport, { to: 'head' }, headChildren))\n }\n\n return result.length === 1 ? result[0] : Vue.h(Vue.Fragment, result)\n }\n },\n})\n"],"names":["Html","Vue","defineComponent","name","setup","_","slots","isServer","window","hydrated","ref","onMounted","value","h","default","children","flatChildren","Array","isArray","bodyVnode","headChildren","child","vnode","type","c","push","Body","result","length","Teleport","to","Fragment"],"mappings":";;MAGaA,OAAOC,IAAIC,gBAAgB;AAAA,EACtCC,MAAM;AAAA,EACNC,MAAMC,GAAG;AAAA,IAAEC;AAAAA,EAAM,GAAG;AAClB,UAAMC,WAAW,OAAOC,WAAW;AAEnC,UAAMC,WAAWR,IAAIS,IAAI,KAAK;AAE9B,QAAI,CAACH,UAAU;AACbN,UAAIU,UAAU,MAAM;AAClBF,iBAASG,QAAQ;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,WAAO,MAAM;AACX,UAAIL,UAAU;AACZ,eAAON,IAAIY,EAAE,QAAQ,CAAA,GAAIP,MAAMQ,WAAW;AAAA,MAC5C;AAEA,YAAMC,WAAWT,MAAMQ,UAAO,KAAQ,CAAA;AACtC,YAAME,eAAeC,MAAMC,QAAQH,QAAQ,IAAIA,WAAW,CAACA,QAAQ;AACnE,UAAII,YAA8B;AAClC,YAAMC,eAAiC,CAAA;AAEvC,iBAAWC,SAASL,cAAc;AAChC,YAAI,OAAOK,UAAU,YAAYA,UAAU,MAAM;AAC/C,gBAAMC,QAAQD;AACd,cAAIC,MAAMC,SAAS,QAAQ;AACzB,gBAAID,MAAMP,UAAU;AAClB,kBAAIE,MAAMC,QAAQI,MAAMP,QAAQ,GAAG;AACjC,2BAAWS,KAAKF,MAAMP,UAAU;AAC9B,sBAAI,OAAOS,MAAM,YAAYA,MAAM,QAAQ,UAAUA,GAAG;AACtDJ,iCAAaK,KAAKD,CAAc;AAAA,kBAClC;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AACA;AAAA,UACF;AACA,cAAIF,MAAMC,SAASG,MAAM;AACvBP,wBAAYG;AACZ;AAAA,UACF;AACA,cAAI,CAACH,WAAW;AACdA,wBAAYG;AAAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,YAAMK,SAA2B,CAAA;AAEjC,UAAIR,WAAW;AACbQ,eAAOF,KAAKN,SAAS;AAAA,MACvB;AAEA,UAAIV,SAASG,SAASQ,aAAaQ,SAAS,GAAG;AAC7CD,eAAOF,KAAKxB,IAAIY,EAAEZ,IAAI4B,UAAU;AAAA,UAAEC,IAAI;AAAA,WAAUV,YAAY,CAAC;AAAA,MAC/D;AAEA,aAAOO,OAAOC,WAAW,IAAID,OAAO,CAAC,IAAI1B,IAAIY,EAAEZ,IAAI8B,UAAUJ,MAAM;AAAA,IACrE;AAAA,EACF;AACF,CAAC;"}
package/dist/esm/Match.js CHANGED
@@ -19,13 +19,33 @@ const Match = Vue.defineComponent({
19
19
  },
20
20
  setup(props) {
21
21
  const router = useRouter();
22
- const routeId = useRouterState({
22
+ let lastKnownRouteId = null;
23
+ const matchData = useRouterState({
23
24
  select: (s) => {
24
- return s.matches.find((d) => d.id === props.matchId)?.routeId;
25
+ let match = s.matches.find((d) => d.id === props.matchId);
26
+ let matchIndex = match ? s.matches.findIndex((d) => d.id === props.matchId) : -1;
27
+ if (match) {
28
+ lastKnownRouteId = match.routeId;
29
+ } else if (lastKnownRouteId) {
30
+ match = s.matches.find((d) => d.routeId === lastKnownRouteId);
31
+ matchIndex = match ? s.matches.findIndex((d) => d.routeId === lastKnownRouteId) : -1;
32
+ }
33
+ if (!match) {
34
+ return null;
35
+ }
36
+ const routeId = match.routeId;
37
+ const parentRouteId = matchIndex > 0 ? s.matches[matchIndex - 1]?.routeId : null;
38
+ return {
39
+ matchId: match.id,
40
+ // Return the actual matchId (may differ from props.matchId)
41
+ routeId,
42
+ parentRouteId,
43
+ loadedAt: s.loadedAt
44
+ };
25
45
  }
26
46
  });
27
- invariant(routeId.value, `Could not find routeId for matchId "${props.matchId}". Please file an issue!`);
28
- const route = Vue.computed(() => router.routesById[routeId.value]);
47
+ invariant(matchData.value, `Could not find routeId for matchId "${props.matchId}". Please file an issue!`);
48
+ const route = Vue.computed(() => matchData.value ? router.routesById[matchData.value.routeId] : null);
29
49
  const PendingComponent = Vue.computed(() => route.value?.options?.pendingComponent ?? router?.options?.defaultPendingComponent);
30
50
  const routeErrorComponent = Vue.computed(() => route.value?.options?.errorComponent ?? router?.options?.defaultErrorComponent);
31
51
  const routeOnCatch = Vue.computed(() => route.value?.options?.onCatch ?? router?.options?.defaultOnCatch);
@@ -33,30 +53,22 @@ const Match = Vue.defineComponent({
33
53
  // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component
34
54
  route.value?.options?.notFoundComponent ?? router?.options?.notFoundRoute?.options?.component
35
55
  ) : route.value?.options?.notFoundComponent);
36
- const resetKey = useRouterState({
37
- select: (s) => s.loadedAt
38
- });
39
- const parentRouteId = useRouterState({
40
- select: (s) => {
41
- const index = s.matches.findIndex((d) => d.id === props.matchId);
42
- return s.matches[index - 1]?.routeId;
43
- }
44
- });
45
- const matchIdRef = Vue.ref(props.matchId);
46
- Vue.watch(() => props.matchId, (newMatchId) => {
47
- matchIdRef.value = newMatchId;
56
+ const matchIdRef = Vue.ref(matchData.value?.matchId ?? props.matchId);
57
+ Vue.watch([() => props.matchId, () => matchData.value?.matchId], ([propsMatchId, dataMatchId]) => {
58
+ matchIdRef.value = dataMatchId ?? propsMatchId;
48
59
  }, {
49
60
  immediate: true
50
61
  });
51
62
  Vue.provide(matchContext, matchIdRef);
52
63
  return () => {
64
+ const actualMatchId = matchData.value?.matchId ?? props.matchId;
53
65
  let content = Vue.h(MatchInner, {
54
- matchId: props.matchId
66
+ matchId: actualMatchId
55
67
  });
56
68
  if (routeNotFoundComponent.value) {
57
69
  content = Vue.h(CatchNotFound, {
58
70
  fallback: (error) => {
59
- if (!routeNotFoundComponent.value || error.routeId && error.routeId !== routeId.value || !error.routeId && route.value && !route.value.isRoot) throw error;
71
+ if (!routeNotFoundComponent.value || error.routeId && error.routeId !== matchData.value?.routeId || !error.routeId && route.value && !route.value.isRoot) throw error;
60
72
  return Vue.h(routeNotFoundComponent.value, error);
61
73
  },
62
74
  children: content
@@ -64,11 +76,11 @@ const Match = Vue.defineComponent({
64
76
  }
65
77
  if (routeErrorComponent.value) {
66
78
  content = CatchBoundary({
67
- getResetKey: () => resetKey.value,
79
+ getResetKey: () => matchData.value?.loadedAt ?? 0,
68
80
  errorComponent: routeErrorComponent.value || ErrorComponent,
69
81
  onCatch: (error) => {
70
82
  if (isNotFound(error)) throw error;
71
- warning(false, `Error in route match: ${props.matchId}`);
83
+ warning(false, `Error in route match: ${actualMatchId}`);
72
84
  routeOnCatch.value?.(error);
73
85
  },
74
86
  children: content
@@ -82,7 +94,10 @@ const Match = Vue.defineComponent({
82
94
  default: () => content
83
95
  });
84
96
  }
85
- const withScrollRestoration = [content, parentRouteId.value === rootRouteId && router.options.scrollRestoration ? Vue.h(Vue.Fragment, null, [Vue.h(OnRendered), Vue.h(ScrollRestoration)]) : null].filter(Boolean);
97
+ const withScrollRestoration = [content, matchData.value?.parentRouteId === rootRouteId && router.options.scrollRestoration ? Vue.h(Vue.Fragment, null, [Vue.h(OnRendered), Vue.h(ScrollRestoration)]) : null].filter(Boolean);
98
+ if (withScrollRestoration.length === 1) {
99
+ return withScrollRestoration[0];
100
+ }
86
101
  return Vue.h(Vue.Fragment, null, withScrollRestoration);
87
102
  };
88
103
  }
@@ -117,47 +132,52 @@ const MatchInner = Vue.defineComponent({
117
132
  },
118
133
  setup(props) {
119
134
  const router = useRouter();
120
- const matchState = useRouterState({
135
+ let lastKnownRouteId = null;
136
+ const combinedState = useRouterState({
121
137
  select: (s) => {
122
- const match2 = s.matches.find((d) => d.id === props.matchId);
138
+ let match2 = s.matches.find((d) => d.id === props.matchId);
139
+ if (match2) {
140
+ lastKnownRouteId = match2.routeId;
141
+ } else if (lastKnownRouteId) {
142
+ const sameRouteMatch = s.matches.find((d) => d.routeId === lastKnownRouteId);
143
+ if (sameRouteMatch) {
144
+ match2 = sameRouteMatch;
145
+ }
146
+ }
123
147
  if (!match2) {
124
148
  return null;
125
149
  }
126
150
  const routeId = match2.routeId;
127
151
  const remountFn = router.routesById[routeId].options.remountDeps ?? router.options.defaultRemountDeps;
128
- const remountDeps = remountFn?.({
129
- routeId,
130
- loaderDeps: match2.loaderDeps,
131
- params: match2._strictParams,
132
- search: match2._strictSearch
133
- });
134
- const key = remountDeps ? JSON.stringify(remountDeps) : void 0;
152
+ let remountKey2;
153
+ if (remountFn) {
154
+ const remountDeps = remountFn({
155
+ routeId,
156
+ loaderDeps: match2.loaderDeps,
157
+ params: match2._strictParams,
158
+ search: match2._strictSearch
159
+ });
160
+ remountKey2 = remountDeps ? JSON.stringify(remountDeps) : void 0;
161
+ }
135
162
  return {
136
- key,
137
163
  routeId,
138
164
  match: {
139
165
  id: match2.id,
140
166
  status: match2.status,
141
167
  error: match2.error
142
- }
168
+ },
169
+ remountKey: remountKey2
143
170
  };
144
171
  }
145
172
  });
146
173
  const route = Vue.computed(() => {
147
- if (!matchState.value) return null;
148
- return router.routesById[matchState.value.routeId];
149
- });
150
- const match = Vue.computed(() => matchState.value?.match);
151
- const out = Vue.computed(() => {
152
- if (!route.value) return null;
153
- const Comp = route.value.options.component ?? router.options.defaultComponent;
154
- if (Comp) {
155
- return Vue.h(Comp);
156
- }
157
- return Vue.h(Outlet);
174
+ if (!combinedState.value) return null;
175
+ return router.routesById[combinedState.value.routeId];
158
176
  });
177
+ const match = Vue.computed(() => combinedState.value?.match);
178
+ const remountKey = Vue.computed(() => combinedState.value?.remountKey);
159
179
  return () => {
160
- if (!matchState.value || !match.value || !route.value) {
180
+ if (!combinedState.value || !match.value || !route.value) {
161
181
  return null;
162
182
  }
163
183
  if (match.value.status === "notFound") {
@@ -202,7 +222,16 @@ const MatchInner = Vue.defineComponent({
202
222
  }
203
223
  return null;
204
224
  }
205
- return out.value;
225
+ const Comp = route.value.options.component ?? router.options.defaultComponent;
226
+ const key = remountKey.value;
227
+ if (Comp) {
228
+ return Vue.h(Comp, key !== void 0 ? {
229
+ key
230
+ } : void 0);
231
+ }
232
+ return Vue.h(Outlet, key !== void 0 ? {
233
+ key
234
+ } : void 0);
206
235
  };
207
236
  }
208
237
  });
@@ -226,22 +255,31 @@ const Outlet = Vue.defineComponent({
226
255
  return parentMatch.globalNotFound;
227
256
  }
228
257
  });
229
- const childMatchId = useRouterState({
258
+ const childMatchData = useRouterState({
230
259
  select: (s) => {
231
260
  const matches = s.matches;
232
261
  const index = matches.findIndex((d) => d.id === safeMatchId.value);
233
- return matches[index + 1]?.id;
262
+ const child = matches[index + 1];
263
+ if (!child) return null;
264
+ return {
265
+ id: child.id,
266
+ // Key based on routeId + params only (not loaderDeps)
267
+ // This ensures component recreates when params change,
268
+ // but NOT when only loaderDeps change
269
+ paramsKey: child.routeId + JSON.stringify(child._strictParams)
270
+ };
234
271
  }
235
272
  });
236
273
  return () => {
237
274
  if (parentGlobalNotFound.value) {
238
275
  return renderRouteNotFound(router, route.value, void 0);
239
276
  }
240
- if (!childMatchId.value) {
277
+ if (!childMatchData.value) {
241
278
  return null;
242
279
  }
243
280
  const nextMatch = Vue.h(Match, {
244
- matchId: childMatchId.value
281
+ matchId: childMatchData.value.id,
282
+ key: childMatchData.value.paramsKey
245
283
  });
246
284
  if (safeMatchId.value === rootRouteId) {
247
285
  return Vue.h(Vue.Suspense, {