@real-router/vue 0.13.0 → 0.15.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.
- package/README.md +29 -3
- package/dist/cjs/createHttpStatusSink-XDu5aGhc.d.ts.map +1 -1
- package/dist/cjs/index.d.ts +95 -30
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/ssr.d.ts +17 -18
- package/dist/cjs/ssr.d.ts.map +1 -1
- package/dist/cjs/ssr.js.map +1 -1
- package/dist/cjs/useRoute-BT3SkdOc.js.map +1 -1
- package/dist/esm/createHttpStatusSink-DduXvbGr.d.mts.map +1 -1
- package/dist/esm/index.d.mts +95 -30
- package/dist/esm/index.d.mts.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/ssr.d.mts +17 -18
- package/dist/esm/ssr.d.mts.map +1 -1
- package/dist/esm/ssr.mjs.map +1 -1
- package/dist/esm/useRoute-2ocUdDHc.mjs.map +1 -1
- package/package.json +4 -4
- package/src/RouterProvider.ts +28 -1
- package/src/components/Link.ts +1 -1
package/dist/cjs/ssr.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { n as createHttpStatusSink, t as HttpStatusSink } from "./createHttpStatusSink-XDu5aGhc.js";
|
|
2
|
-
import * as _$vue from "vue";
|
|
3
2
|
import { PropType } from "vue";
|
|
4
3
|
|
|
5
4
|
//#region src/components/ClientOnly.d.ts
|
|
6
|
-
declare const ClientOnly:
|
|
5
|
+
declare const ClientOnly: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
7
6
|
[key: string]: any;
|
|
8
|
-
}>[] | undefined, {}, {}, {},
|
|
7
|
+
}>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
9
8
|
type ClientOnlyProps = InstanceType<typeof ClientOnly>["$props"];
|
|
10
9
|
//#endregion
|
|
11
10
|
//#region src/components/ServerOnly.d.ts
|
|
12
|
-
declare const ServerOnly:
|
|
11
|
+
declare const ServerOnly: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
13
12
|
[key: string]: any;
|
|
14
|
-
}>[] | undefined, {}, {}, {},
|
|
13
|
+
}>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
15
14
|
type ServerOnlyProps = InstanceType<typeof ServerOnly>["$props"];
|
|
16
15
|
//#endregion
|
|
17
16
|
//#region src/components/Await.d.ts
|
|
@@ -44,19 +43,19 @@ type ServerOnlyProps = InstanceType<typeof ServerOnly>["$props"];
|
|
|
44
43
|
* until resolution. Rejection bubbles to the nearest `onErrorCaptured`
|
|
45
44
|
* handler.
|
|
46
45
|
*/
|
|
47
|
-
declare const Await:
|
|
46
|
+
declare const Await: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
48
47
|
/** Deferred key declared in the loader's `defer({ deferred: { <name>: ... } })`. */name: {
|
|
49
48
|
type: StringConstructor;
|
|
50
49
|
required: true;
|
|
51
50
|
};
|
|
52
|
-
}>, () =>
|
|
51
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
53
52
|
[key: string]: any;
|
|
54
|
-
}>[] | undefined, {}, {}, {},
|
|
53
|
+
}>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
55
54
|
/** Deferred key declared in the loader's `defer({ deferred: { <name>: ... } })`. */name: {
|
|
56
55
|
type: StringConstructor;
|
|
57
56
|
required: true;
|
|
58
57
|
};
|
|
59
|
-
}>> & Readonly<{}>, {}, {}, {}, {}, string,
|
|
58
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
60
59
|
type AwaitProps = InstanceType<typeof Await>["$props"];
|
|
61
60
|
//#endregion
|
|
62
61
|
//#region src/components/Streamed.d.ts
|
|
@@ -73,9 +72,9 @@ type AwaitProps = InstanceType<typeof Await>["$props"];
|
|
|
73
72
|
* `async setup()` inside. This matches Vue 3's stable streaming behaviour
|
|
74
73
|
* (vs React 19 / Solid which support OOO resolution).
|
|
75
74
|
*/
|
|
76
|
-
declare const Streamed:
|
|
75
|
+
declare const Streamed: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
77
76
|
[key: string]: any;
|
|
78
|
-
}>, {}, {}, {},
|
|
77
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
79
78
|
type StreamedProps = InstanceType<typeof Streamed>["$props"];
|
|
80
79
|
//#endregion
|
|
81
80
|
//#region src/components/HttpStatusCode.d.ts
|
|
@@ -126,33 +125,33 @@ type StreamedProps = InstanceType<typeof Streamed>["$props"];
|
|
|
126
125
|
* 5xx / dropped connection, not silent corruption. Pass a real HTTP status
|
|
127
126
|
* integer (commonly 4xx/5xx; 100-999 is what Node accepts).
|
|
128
127
|
*/
|
|
129
|
-
declare const HttpStatusCode:
|
|
128
|
+
declare const HttpStatusCode: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
130
129
|
/** HTTP status to apply to the response. Common values: 404, 410, 451, 503. */code: {
|
|
131
130
|
type: NumberConstructor;
|
|
132
131
|
required: true;
|
|
133
132
|
};
|
|
134
|
-
}>, () => null, {}, {}, {},
|
|
133
|
+
}>, () => null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
135
134
|
/** HTTP status to apply to the response. Common values: 404, 410, 451, 503. */code: {
|
|
136
135
|
type: NumberConstructor;
|
|
137
136
|
required: true;
|
|
138
137
|
};
|
|
139
|
-
}>> & Readonly<{}>, {}, {}, {}, {}, string,
|
|
138
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
140
139
|
type HttpStatusCodeProps = InstanceType<typeof HttpStatusCode>["$props"];
|
|
141
140
|
//#endregion
|
|
142
141
|
//#region src/components/HttpStatusProvider.d.ts
|
|
143
|
-
declare const HttpStatusProvider:
|
|
142
|
+
declare const HttpStatusProvider: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
144
143
|
sink: {
|
|
145
144
|
type: PropType<HttpStatusSink>;
|
|
146
145
|
required: true;
|
|
147
146
|
};
|
|
148
|
-
}>, () =>
|
|
147
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
149
148
|
[key: string]: any;
|
|
150
|
-
}>[] | undefined, {}, {}, {},
|
|
149
|
+
}>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
151
150
|
sink: {
|
|
152
151
|
type: PropType<HttpStatusSink>;
|
|
153
152
|
required: true;
|
|
154
153
|
};
|
|
155
|
-
}>> & Readonly<{}>, {}, {}, {}, {}, string,
|
|
154
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
156
155
|
type HttpStatusProviderProps = InstanceType<typeof HttpStatusProvider>["$props"];
|
|
157
156
|
//#endregion
|
|
158
157
|
//#region src/composables/useDeferred.d.ts
|
package/dist/cjs/ssr.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr.d.ts","names":[],"sources":["../../src/components/ClientOnly.ts","../../src/components/ServerOnly.ts","../../src/components/Await.ts","../../src/components/Streamed.ts","../../src/components/HttpStatusCode.ts","../../src/components/HttpStatusProvider.ts","../../src/composables/useDeferred.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ssr.d.ts","names":[],"sources":["../../src/components/ClientOnly.ts","../../src/components/ServerOnly.ts","../../src/components/Await.ts","../../src/components/Streamed.ts","../../src/components/HttpStatusCode.ts","../../src/components/HttpStatusProvider.ts","../../src/composables/useDeferred.ts"],"mappings":";;;;cAEa,UAAA,gBAAU,eAAA,yBAAA,KAAA,eAAA,YAAA,gBAAA,eAAA;EAAA;+IAWrB,QAAA,OAAA,QAAA;KAEU,eAAA,GAAkB,YAAY,QAAQ,UAAA;;;cCbrC,UAAA,gBAAU,eAAA,yBAAA,KAAA,eAAA,YAAA,gBAAA,eAAA;EAAA;+IAWrB,QAAA,OAAA,QAAA;KAEU,eAAA,GAAkB,YAAY,QAAQ,UAAA;;;;;;;ADblD;;;;;;;;;;;;;;;;;AAaA;;;;AAA4D;;;;cEkB/C,KAAA,gBAAK,eAAA,eAAA,gBAAA;EDpBhB;;;;;;;;;;;;KCiCU,UAAA,GAAa,YAAY,QAAQ,KAAA;;;;;;;AF5C7C;;;;;;;;;cGaa,QAAA,gBAAQ,eAAA,yBAAA,KAAA,eAAA,YAAA,gBAAA,eAAA;EAAA;iIAanB,QAAA,OAAA,QAAA;KAEU,aAAA,GAAgB,YAAY,QAAQ,QAAA;;;;;;;AH5BhD;;;;;;;;;;;;;;;;;AAaA;;;;AAA4D;;;;ACb5D;;;;;;;;;;;;;;;;;AAaA;cGyCa,cAAA,gBAAc,eAAA,eAAA,gBAAA;;;;;0CAjDA,qBAAA,gBAAA,qBAAA,4BAAA,WAAA,EAAA,QAAA,eAAA,gBAAA;EF0Bd;;;;;KEwCD,mBAAA,GAAsB,YAAY,QAAQ,cAAA;;;cClEzC,kBAAA,gBAAkB,eAAA,eAAA,gBAAA;;UAGH,QAAA,CAAS,cAAA;;;;;;;UAAT,QAAA,CAAS,cAAA;;;;KASzB,uBAAA,GAA0B,YAAY,QACzC,kBAAA;;;;;;;ALlBT;;;;;;;;;;;;;;;iBM4BgB,WAAA,aAAA,CAAyB,GAAA,WAAc,OAAO,CAAC,CAAA"}
|
package/dist/cjs/ssr.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr.js","names":["useRoute","Suspense","HTTP_STATUS_KEY","HTTP_STATUS_KEY"],"sources":["../../src/components/ClientOnly.ts","../../src/components/ServerOnly.ts","../../src/composables/useDeferred.ts","../../src/components/Await.ts","../../src/components/Streamed.ts","../../src/components/HttpStatusCode.ts","../../src/components/HttpStatusProvider.ts","../../src/utils/createHttpStatusSink.ts"],"sourcesContent":["import { defineComponent, onMounted, ref } from \"vue\";\n\nexport const ClientOnly = defineComponent({\n name: \"ClientOnly\",\n setup(_, { slots }) {\n const mounted = ref(false);\n\n onMounted(() => {\n mounted.value = true;\n });\n\n return () => (mounted.value ? slots.default?.() : slots.fallback?.());\n },\n});\n\nexport type ClientOnlyProps = InstanceType<typeof ClientOnly>[\"$props\"];\n","import { defineComponent, onMounted, ref } from \"vue\";\n\nexport const ServerOnly = defineComponent({\n name: \"ServerOnly\",\n setup(_, { slots }) {\n const mounted = ref(false);\n\n onMounted(() => {\n mounted.value = true;\n });\n\n return () => (mounted.value ? slots.fallback?.() : slots.default?.());\n },\n});\n\nexport type ServerOnlyProps = InstanceType<typeof ServerOnly>[\"$props\"];\n","import { useRoute } from \"./useRoute\";\n\ninterface DeferredContext {\n ssrDataDeferred?: Record<string, Promise<unknown>>;\n}\n\nconst NEVER_PROMISE = new Promise<never>(() => {\n // Intentionally never resolves — surfaces a forever-pending Suspense boundary\n // when a key is requested that the loader never declared.\n});\n\n/**\n * Read a deferred promise published by `defer({ deferred: { <key>: Promise } })`\n * inside an SSR data loader. Returns the Promise for use inside `async setup()`\n * (Vue's native Suspense pattern) or paired with `<Await name=\"key\">`.\n *\n * ```ts\n * // Vue async setup pattern\n * export default defineComponent({\n * async setup() {\n * const reviews = await useDeferred<Review[]>(\"reviews\");\n * return () => h(\"div\", reviews.map(...));\n * },\n * });\n * ```\n *\n * Returns a forever-pending promise when the key is missing — surfaces\n * loader/consumer key drift as a visible Suspense fallback rather than a\n * silent runtime error.\n */\nexport function useDeferred<T = unknown>(key: string): Promise<T> {\n const { route } = useRoute();\n const context = route.value.context as DeferredContext;\n const deferred = context.ssrDataDeferred;\n\n return (deferred?.[key] ?? NEVER_PROMISE) as Promise<T>;\n}\n","import { defineComponent } from \"vue\";\n\nimport { useDeferred } from \"../composables/useDeferred\";\n\n/**\n * Reads `useDeferred(name)` and hands the resolved value to the `default`\n * scoped slot via Vue's native `async setup()` Suspense pattern. Wrap in\n * `<Streamed>` (or Vue's `<Suspense>`).\n *\n * ```vue-html\n * <Streamed>\n * <Await name=\"reviews\" v-slot=\"{ value }\">\n * <ReviewList :items=\"value\" />\n * </Await>\n * <template #fallback>\n * <Spinner />\n * </template>\n * </Streamed>\n * ```\n *\n * Or with the render function:\n *\n * ```ts\n * h(Await, { name: \"reviews\" }, {\n * default: ({ value }: { value: Review[] }) => h(ReviewList, { items: value }),\n * });\n * ```\n *\n * Implementation: `async setup()` awaits the deferred promise. Vue's\n * `<Suspense>` boundary catches the pending promise and shows the fallback\n * until resolution. Rejection bubbles to the nearest `onErrorCaptured`\n * handler.\n */\nexport const Await = defineComponent({\n name: \"Await\",\n props: {\n /** Deferred key declared in the loader's `defer({ deferred: { <name>: ... } })`. */\n name: { type: String, required: true },\n },\n async setup(props, { slots }) {\n const value = await useDeferred(props.name);\n\n return () => slots.default?.({ value });\n },\n});\n\nexport type AwaitProps = InstanceType<typeof Await>[\"$props\"];\n","import { defineComponent, h, Suspense } from \"vue\";\n\n/**\n * Cross-adapter alias for Vue's native `<Suspense>`. Symmetric naming with\n * the React/Preact/Solid/Svelte/Angular `<Streamed>` components.\n *\n * Slots:\n * - `default` — content (may contain `<Await>` or `async setup()` children).\n * - `fallback` — shown while any descendant suspends.\n *\n * Vue's `<Suspense>` is **blocking** under SSR (no out-of-order placeholder\n * resolution) — render of HTML after `<Streamed>` waits for every\n * `async setup()` inside. This matches Vue 3's stable streaming behaviour\n * (vs React 19 / Solid which support OOO resolution).\n */\nexport const Streamed = defineComponent({\n name: \"Streamed\",\n setup(_, { slots }) {\n return () =>\n h(\n Suspense,\n {},\n {\n default: () => slots.default?.(),\n fallback: () => slots.fallback?.(),\n },\n );\n },\n});\n\nexport type StreamedProps = InstanceType<typeof Streamed>[\"$props\"];\n","import { defineComponent, inject } from \"vue\";\n\nimport { HTTP_STATUS_KEY } from \"../context\";\n\n// Module-scope render function — returns null since the component emits no DOM.\n// Hoisted to satisfy `unicorn/consistent-function-scoping` and to avoid\n// re-creating the closure on every component instantiation.\nconst renderNull = (): null => null;\n\n/**\n * Render-time HTTP status declaration. Mount inside a route component (typical\n * use case: a glob `*` route's NotFound page) when the status is decided by\n * the rendered tree rather than a loader.\n *\n * Writes `code` to the nearest `<HttpStatusProvider>`'s sink during `setup()`\n * and renders nothing. With no provider mounted (the standard client-side\n * case) the component is a silent no-op — same component tree hydrates\n * without touching the DOM or warning about mismatches.\n *\n * Loader-driven errors (`LoaderNotFound` → 404, `LoaderRedirect` → 30x) keep\n * working as before; this component covers render-time decisions only.\n *\n * Last write wins when several `<HttpStatusCode />` instances mount in the\n * same render pass — sink reflects the last component that ran.\n *\n * ```vue-html\n * <HttpStatusProvider :sink=\"sink\">\n * <RouterProvider :router=\"router\">\n * <App />\n * </RouterProvider>\n * </HttpStatusProvider>\n *\n * <!-- inside NotFound.vue -->\n * <HttpStatusCode :code=\"404\" />\n * ```\n *\n * **`renderToWebStream` (streaming SSR):** Vue 3 `<Suspense>` is\n * chunked-blocking — Vue waits for every `async setup()` inside a boundary\n * before emitting the chunks past it. So in practice `<HttpStatusCode />`\n * inside a `<Suspense>` boundary still writes to the sink before the\n * response headers flush. Still, prefer mounting in the shell to avoid\n * coupling the contract to that particular Vue 3 streaming behaviour. With\n * `renderToString` there is no ordering concern at all.\n *\n * **Hydration symmetry:** `<HttpStatusProvider>` wraps a render slot, so\n * Vue emits a fragment marker pair (`<!--[-->` / `<!--]-->`) around its\n * children server-side. Mount the same `<HttpStatusProvider>` on the\n * client (with a throwaway sink) to keep the marker count balanced — see\n * the `ssr/` example's `entry-client.ts`. Otherwise hydration logs\n * \"Hydration completed but contains mismatches\".\n *\n * **Valid `code` range:** Node's `res.end()` throws `Invalid status code`\n * on `NaN`, `0`, negative values, or values `> 999` — this surfaces as a\n * 5xx / dropped connection, not silent corruption. Pass a real HTTP status\n * integer (commonly 4xx/5xx; 100-999 is what Node accepts).\n */\nexport const HttpStatusCode = defineComponent({\n name: \"HttpStatusCode\",\n props: {\n /** HTTP status to apply to the response. Common values: 404, 410, 451, 503. */\n code: { type: Number, required: true },\n },\n setup(props) {\n const sink = inject(HTTP_STATUS_KEY, null);\n\n if (sink) {\n sink.code = props.code;\n }\n\n return renderNull;\n },\n});\n\nexport type HttpStatusCodeProps = InstanceType<typeof HttpStatusCode>[\"$props\"];\n","import { defineComponent, provide } from \"vue\";\n\nimport { HTTP_STATUS_KEY } from \"../context\";\n\nimport type { HttpStatusSink } from \"../utils/createHttpStatusSink\";\nimport type { PropType } from \"vue\";\n\nexport const HttpStatusProvider = defineComponent({\n name: \"HttpStatusProvider\",\n props: {\n sink: { type: Object as PropType<HttpStatusSink>, required: true },\n },\n setup(props, { slots }) {\n provide(HTTP_STATUS_KEY, props.sink);\n\n return () => slots.default?.();\n },\n});\n\nexport type HttpStatusProviderProps = InstanceType<\n typeof HttpStatusProvider\n>[\"$props\"];\n","/**\n * Render-scoped HTTP status sink. Created per request on the server, passed to\n * `<HttpStatusProvider :sink=\"...\">`, and read after `renderToString` /\n * `renderToWebStream` to apply the value to the HTTP response.\n *\n * Last write wins: if the rendered tree mounts more than one\n * `<HttpStatusCode />`, the value reflects the last component that ran during\n * the render pass.\n *\n * No-op on the client — `<HttpStatusCode />` reads the optional injected sink\n * and skips the write when no provider is mounted, so the same component tree\n * can be hydrated without changing behaviour.\n *\n * Constraints:\n * - **Per-request only.** Don't share a sink across requests; the rendered\n * tree mutates `code` in place. Module-level singletons leak status\n * between concurrent requests.\n * - **Don't `Object.freeze` the sink.** The component writes to `.code`;\n * freezing makes the assignment throw under ESM strict mode.\n * - **Hydration symmetry:** mount `<HttpStatusProvider>` on both server and\n * client (with a throwaway client sink). Vue emits `<!--[-->` / `<!--]-->`\n * fragment markers around the provider's slot; an extra provider on one\n * side trips Vue with \"Hydration completed but contains mismatches\".\n */\nexport interface HttpStatusSink {\n code: number | undefined;\n}\n\nexport function createHttpStatusSink(): HttpStatusSink {\n return { code: undefined };\n}\n"],"mappings":"kIAEA,MAAa,GAAA,EAAA,EAAA,iBAA6B,CACxC,KAAM,aACN,MAAM,EAAG,CAAE,SAAS,CAClB,IAAM,GAAA,EAAA,EAAA,KAAc,GAAM,CAM1B,OAJA,EAAA,EAAA,eAAgB,CACd,EAAQ,MAAQ,IAChB,KAEY,EAAQ,MAAQ,EAAM,WAAW,CAAG,EAAM,YAAY,EAEvE,CAAC,CCXW,GAAA,EAAA,EAAA,iBAA6B,CACxC,KAAM,aACN,MAAM,EAAG,CAAE,SAAS,CAClB,IAAM,GAAA,EAAA,EAAA,KAAc,GAAM,CAM1B,OAJA,EAAA,EAAA,eAAgB,CACd,EAAQ,MAAQ,IAChB,KAEY,EAAQ,MAAQ,EAAM,YAAY,CAAG,EAAM,WAAW,EAEvE,CAAC,CCPI,EAAgB,IAAI,YAAqB,GAG7C,CAqBF,SAAgB,EAAyB,EAAyB,CAChE,GAAM,CAAE,SAAUA,EAAAA,GAAU,CAI5B,OAHgB,EAAM,MAAM,QACH,kBAEN,IAAQ,ECF7B,MAAa,GAAA,EAAA,EAAA,iBAAwB,CACnC,KAAM,QACN,MAAO,CAEL,KAAM,CAAE,KAAM,OAAQ,SAAU,GAAM,CACvC,CACD,MAAM,MAAM,EAAO,CAAE,SAAS,CAC5B,IAAM,EAAQ,MAAM,EAAY,EAAM,KAAK,CAE3C,UAAa,EAAM,UAAU,CAAE,QAAO,CAAC,EAE1C,CAAC,CC7BW,GAAA,EAAA,EAAA,iBAA2B,CACtC,KAAM,WACN,MAAM,EAAG,CAAE,SAAS,CAClB,WAAA,EAAA,EAAA,GAEIC,EAAAA,SACA,EAAE,CACF,CACE,YAAe,EAAM,WAAW,CAChC,aAAgB,EAAM,YAAY,CACnC,CACF,EAEN,CAAC,CCrBI,MAAyB,KAiDlB,GAAA,EAAA,EAAA,iBAAiC,CAC5C,KAAM,iBACN,MAAO,CAEL,KAAM,CAAE,KAAM,OAAQ,SAAU,GAAM,CACvC,CACD,MAAM,EAAO,CACX,IAAM,GAAA,EAAA,EAAA,QAAcC,EAAAA,EAAiB,KAAK,CAM1C,OAJI,IACF,EAAK,KAAO,EAAM,MAGb,GAEV,CAAC,CChEW,GAAA,EAAA,EAAA,iBAAqC,CAChD,KAAM,qBACN,MAAO,CACL,KAAM,CAAE,KAAM,OAAoC,SAAU,GAAM,CACnE,CACD,MAAM,EAAO,CAAE,SAAS,CAGtB,OAFA,EAAA,EAAA,SAAQC,EAAAA,EAAiB,EAAM,KAAK,KAEvB,EAAM,WAAW,EAEjC,CAAC,CCWF,SAAgB,GAAuC,CACrD,MAAO,CAAE,KAAM,IAAA,GAAW"}
|
|
1
|
+
{"version":3,"file":"ssr.js","names":["useRoute","Suspense","HTTP_STATUS_KEY","HTTP_STATUS_KEY"],"sources":["../../src/components/ClientOnly.ts","../../src/components/ServerOnly.ts","../../src/composables/useDeferred.ts","../../src/components/Await.ts","../../src/components/Streamed.ts","../../src/components/HttpStatusCode.ts","../../src/components/HttpStatusProvider.ts","../../src/utils/createHttpStatusSink.ts"],"sourcesContent":["import { defineComponent, onMounted, ref } from \"vue\";\n\nexport const ClientOnly = defineComponent({\n name: \"ClientOnly\",\n setup(_, { slots }) {\n const mounted = ref(false);\n\n onMounted(() => {\n mounted.value = true;\n });\n\n return () => (mounted.value ? slots.default?.() : slots.fallback?.());\n },\n});\n\nexport type ClientOnlyProps = InstanceType<typeof ClientOnly>[\"$props\"];\n","import { defineComponent, onMounted, ref } from \"vue\";\n\nexport const ServerOnly = defineComponent({\n name: \"ServerOnly\",\n setup(_, { slots }) {\n const mounted = ref(false);\n\n onMounted(() => {\n mounted.value = true;\n });\n\n return () => (mounted.value ? slots.fallback?.() : slots.default?.());\n },\n});\n\nexport type ServerOnlyProps = InstanceType<typeof ServerOnly>[\"$props\"];\n","import { useRoute } from \"./useRoute\";\n\ninterface DeferredContext {\n ssrDataDeferred?: Record<string, Promise<unknown>>;\n}\n\nconst NEVER_PROMISE = new Promise<never>(() => {\n // Intentionally never resolves — surfaces a forever-pending Suspense boundary\n // when a key is requested that the loader never declared.\n});\n\n/**\n * Read a deferred promise published by `defer({ deferred: { <key>: Promise } })`\n * inside an SSR data loader. Returns the Promise for use inside `async setup()`\n * (Vue's native Suspense pattern) or paired with `<Await name=\"key\">`.\n *\n * ```ts\n * // Vue async setup pattern\n * export default defineComponent({\n * async setup() {\n * const reviews = await useDeferred<Review[]>(\"reviews\");\n * return () => h(\"div\", reviews.map(...));\n * },\n * });\n * ```\n *\n * Returns a forever-pending promise when the key is missing — surfaces\n * loader/consumer key drift as a visible Suspense fallback rather than a\n * silent runtime error.\n */\nexport function useDeferred<T = unknown>(key: string): Promise<T> {\n const { route } = useRoute();\n const context = route.value.context as DeferredContext;\n const deferred = context.ssrDataDeferred;\n\n return (deferred?.[key] ?? NEVER_PROMISE) as Promise<T>;\n}\n","import { defineComponent } from \"vue\";\n\nimport { useDeferred } from \"../composables/useDeferred\";\n\n/**\n * Reads `useDeferred(name)` and hands the resolved value to the `default`\n * scoped slot via Vue's native `async setup()` Suspense pattern. Wrap in\n * `<Streamed>` (or Vue's `<Suspense>`).\n *\n * ```vue-html\n * <Streamed>\n * <Await name=\"reviews\" v-slot=\"{ value }\">\n * <ReviewList :items=\"value\" />\n * </Await>\n * <template #fallback>\n * <Spinner />\n * </template>\n * </Streamed>\n * ```\n *\n * Or with the render function:\n *\n * ```ts\n * h(Await, { name: \"reviews\" }, {\n * default: ({ value }: { value: Review[] }) => h(ReviewList, { items: value }),\n * });\n * ```\n *\n * Implementation: `async setup()` awaits the deferred promise. Vue's\n * `<Suspense>` boundary catches the pending promise and shows the fallback\n * until resolution. Rejection bubbles to the nearest `onErrorCaptured`\n * handler.\n */\nexport const Await = defineComponent({\n name: \"Await\",\n props: {\n /** Deferred key declared in the loader's `defer({ deferred: { <name>: ... } })`. */\n name: { type: String, required: true },\n },\n async setup(props, { slots }) {\n const value = await useDeferred(props.name);\n\n return () => slots.default?.({ value });\n },\n});\n\nexport type AwaitProps = InstanceType<typeof Await>[\"$props\"];\n","import { defineComponent, h, Suspense } from \"vue\";\n\n/**\n * Cross-adapter alias for Vue's native `<Suspense>`. Symmetric naming with\n * the React/Preact/Solid/Svelte/Angular `<Streamed>` components.\n *\n * Slots:\n * - `default` — content (may contain `<Await>` or `async setup()` children).\n * - `fallback` — shown while any descendant suspends.\n *\n * Vue's `<Suspense>` is **blocking** under SSR (no out-of-order placeholder\n * resolution) — render of HTML after `<Streamed>` waits for every\n * `async setup()` inside. This matches Vue 3's stable streaming behaviour\n * (vs React 19 / Solid which support OOO resolution).\n */\nexport const Streamed = defineComponent({\n name: \"Streamed\",\n setup(_, { slots }) {\n return () =>\n h(\n Suspense,\n {},\n {\n default: () => slots.default?.(),\n fallback: () => slots.fallback?.(),\n },\n );\n },\n});\n\nexport type StreamedProps = InstanceType<typeof Streamed>[\"$props\"];\n","import { defineComponent, inject } from \"vue\";\n\nimport { HTTP_STATUS_KEY } from \"../context\";\n\n// Module-scope render function — returns null since the component emits no DOM.\n// Hoisted to satisfy `unicorn/consistent-function-scoping` and to avoid\n// re-creating the closure on every component instantiation.\nconst renderNull = (): null => null;\n\n/**\n * Render-time HTTP status declaration. Mount inside a route component (typical\n * use case: a glob `*` route's NotFound page) when the status is decided by\n * the rendered tree rather than a loader.\n *\n * Writes `code` to the nearest `<HttpStatusProvider>`'s sink during `setup()`\n * and renders nothing. With no provider mounted (the standard client-side\n * case) the component is a silent no-op — same component tree hydrates\n * without touching the DOM or warning about mismatches.\n *\n * Loader-driven errors (`LoaderNotFound` → 404, `LoaderRedirect` → 30x) keep\n * working as before; this component covers render-time decisions only.\n *\n * Last write wins when several `<HttpStatusCode />` instances mount in the\n * same render pass — sink reflects the last component that ran.\n *\n * ```vue-html\n * <HttpStatusProvider :sink=\"sink\">\n * <RouterProvider :router=\"router\">\n * <App />\n * </RouterProvider>\n * </HttpStatusProvider>\n *\n * <!-- inside NotFound.vue -->\n * <HttpStatusCode :code=\"404\" />\n * ```\n *\n * **`renderToWebStream` (streaming SSR):** Vue 3 `<Suspense>` is\n * chunked-blocking — Vue waits for every `async setup()` inside a boundary\n * before emitting the chunks past it. So in practice `<HttpStatusCode />`\n * inside a `<Suspense>` boundary still writes to the sink before the\n * response headers flush. Still, prefer mounting in the shell to avoid\n * coupling the contract to that particular Vue 3 streaming behaviour. With\n * `renderToString` there is no ordering concern at all.\n *\n * **Hydration symmetry:** `<HttpStatusProvider>` wraps a render slot, so\n * Vue emits a fragment marker pair (`<!--[-->` / `<!--]-->`) around its\n * children server-side. Mount the same `<HttpStatusProvider>` on the\n * client (with a throwaway sink) to keep the marker count balanced — see\n * the `ssr/` example's `entry-client.ts`. Otherwise hydration logs\n * \"Hydration completed but contains mismatches\".\n *\n * **Valid `code` range:** Node's `res.end()` throws `Invalid status code`\n * on `NaN`, `0`, negative values, or values `> 999` — this surfaces as a\n * 5xx / dropped connection, not silent corruption. Pass a real HTTP status\n * integer (commonly 4xx/5xx; 100-999 is what Node accepts).\n */\nexport const HttpStatusCode = defineComponent({\n name: \"HttpStatusCode\",\n props: {\n /** HTTP status to apply to the response. Common values: 404, 410, 451, 503. */\n code: { type: Number, required: true },\n },\n setup(props) {\n const sink = inject(HTTP_STATUS_KEY, null);\n\n if (sink) {\n sink.code = props.code;\n }\n\n return renderNull;\n },\n});\n\nexport type HttpStatusCodeProps = InstanceType<typeof HttpStatusCode>[\"$props\"];\n","import { defineComponent, provide } from \"vue\";\n\nimport { HTTP_STATUS_KEY } from \"../context\";\n\nimport type { HttpStatusSink } from \"../utils/createHttpStatusSink\";\nimport type { PropType } from \"vue\";\n\nexport const HttpStatusProvider = defineComponent({\n name: \"HttpStatusProvider\",\n props: {\n sink: { type: Object as PropType<HttpStatusSink>, required: true },\n },\n setup(props, { slots }) {\n provide(HTTP_STATUS_KEY, props.sink);\n\n return () => slots.default?.();\n },\n});\n\nexport type HttpStatusProviderProps = InstanceType<\n typeof HttpStatusProvider\n>[\"$props\"];\n","/**\n * Render-scoped HTTP status sink. Created per request on the server, passed to\n * `<HttpStatusProvider :sink=\"...\">`, and read after `renderToString` /\n * `renderToWebStream` to apply the value to the HTTP response.\n *\n * Last write wins: if the rendered tree mounts more than one\n * `<HttpStatusCode />`, the value reflects the last component that ran during\n * the render pass.\n *\n * No-op on the client — `<HttpStatusCode />` reads the optional injected sink\n * and skips the write when no provider is mounted, so the same component tree\n * can be hydrated without changing behaviour.\n *\n * Constraints:\n * - **Per-request only.** Don't share a sink across requests; the rendered\n * tree mutates `code` in place. Module-level singletons leak status\n * between concurrent requests.\n * - **Don't `Object.freeze` the sink.** The component writes to `.code`;\n * freezing makes the assignment throw under ESM strict mode.\n * - **Hydration symmetry:** mount `<HttpStatusProvider>` on both server and\n * client (with a throwaway client sink). Vue emits `<!--[-->` / `<!--]-->`\n * fragment markers around the provider's slot; an extra provider on one\n * side trips Vue with \"Hydration completed but contains mismatches\".\n */\nexport interface HttpStatusSink {\n code: number | undefined;\n}\n\nexport function createHttpStatusSink(): HttpStatusSink {\n return { code: undefined };\n}\n"],"mappings":"kIAEA,MAAa,GAAA,EAAA,EAAA,iBAA6B,CACxC,KAAM,aACN,MAAM,EAAG,CAAE,SAAS,CAClB,IAAM,GAAA,EAAA,EAAA,KAAc,EAAK,EAMzB,OAJA,EAAA,EAAA,eAAgB,CACd,EAAQ,MAAQ,EAClB,CAAC,MAEa,EAAQ,MAAQ,EAAM,UAAU,EAAI,EAAM,WAAW,CACrE,CACF,CAAC,ECXY,GAAA,EAAA,EAAA,iBAA6B,CACxC,KAAM,aACN,MAAM,EAAG,CAAE,SAAS,CAClB,IAAM,GAAA,EAAA,EAAA,KAAc,EAAK,EAMzB,OAJA,EAAA,EAAA,eAAgB,CACd,EAAQ,MAAQ,EAClB,CAAC,MAEa,EAAQ,MAAQ,EAAM,WAAW,EAAI,EAAM,UAAU,CACrE,CACF,CAAC,ECPK,EAAgB,IAAI,YAAqB,CAG/C,CAAC,EAqBD,SAAgB,EAAyB,EAAyB,CAChE,GAAM,CAAE,SAAUA,EAAAA,EAAS,EAI3B,OAHgB,EAAM,MAAM,QACH,kBAEN,IAAQ,CAC7B,CCHA,MAAa,GAAA,EAAA,EAAA,iBAAwB,CACnC,KAAM,QACN,MAAO,CAEL,KAAM,CAAE,KAAM,OAAQ,SAAU,EAAK,CACvC,EACA,MAAM,MAAM,EAAO,CAAE,SAAS,CAC5B,IAAM,EAAQ,MAAM,EAAY,EAAM,IAAI,EAE1C,UAAa,EAAM,UAAU,CAAE,OAAM,CAAC,CACxC,CACF,CAAC,EC7BY,GAAA,EAAA,EAAA,iBAA2B,CACtC,KAAM,WACN,MAAM,EAAG,CAAE,SAAS,CAClB,WAAA,EAAA,EAAA,GAEIC,EAAAA,SACA,CAAC,EACD,CACE,YAAe,EAAM,UAAU,EAC/B,aAAgB,EAAM,WAAW,CACnC,CACF,CACJ,CACF,CAAC,ECrBK,MAAyB,KAiDlB,GAAA,EAAA,EAAA,iBAAiC,CAC5C,KAAM,iBACN,MAAO,CAEL,KAAM,CAAE,KAAM,OAAQ,SAAU,EAAK,CACvC,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAA,EAAA,QAAcC,EAAAA,EAAiB,IAAI,EAMzC,OAJI,IACF,EAAK,KAAO,EAAM,MAGb,CACT,CACF,CAAC,EChEY,GAAA,EAAA,EAAA,iBAAqC,CAChD,KAAM,qBACN,MAAO,CACL,KAAM,CAAE,KAAM,OAAoC,SAAU,EAAK,CACnE,EACA,MAAM,EAAO,CAAE,SAAS,CAGtB,OAFA,EAAA,EAAA,SAAQC,EAAAA,EAAiB,EAAM,IAAI,MAEtB,EAAM,UAAU,CAC/B,CACF,CAAC,ECWD,SAAgB,GAAuC,CACrD,MAAO,CAAE,KAAM,IAAA,EAAU,CAC3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRoute-BT3SkdOc.js","names":[],"sources":["../../src/context.ts","../../src/composables/useRoute.ts"],"sourcesContent":["import type { RouteContext as RouteContextType } from \"./types\";\nimport type { HttpStatusSink } from \"./utils/createHttpStatusSink\";\nimport type { Router, Navigator } from \"@real-router/core\";\nimport type { InjectionKey } from \"vue\";\n\nexport const RouterKey: InjectionKey<Router> = Symbol(\"RouterKey\");\n\nexport const NavigatorKey: InjectionKey<Navigator> = Symbol(\"NavigatorKey\");\n\nexport const RouteKey: InjectionKey<RouteContextType> = Symbol(\"RouteKey\");\n\nexport const HTTP_STATUS_KEY: InjectionKey<HttpStatusSink> =\n Symbol(\"HttpStatusSink\");\n","import { inject } from \"vue\";\n\nimport { RouteKey } from \"../context\";\n\nimport type { RouteContext } from \"../types\";\nimport type { Params, State } from \"@real-router/core\";\nimport type { Ref } from \"vue\";\n\n/**\n * Return shape for `useRoute()` — `RouteContext<P>` with `route` narrowed\n * to the non-nullable variant. The composable throws when `route.value`\n * would be `undefined`, so consumers can read `.value.params.x` without a\n * nullable guard. Extracted from inline duplication at two call sites.\n */\nexport type UseRouteReturn<P extends Params = Params> = Omit<\n RouteContext<P>,\n \"route\"\n> & { route: Readonly<Ref<State<P>>> };\n\nexport const useRoute = <P extends Params = Params>(): UseRouteReturn<P> => {\n const routeContext = inject(RouteKey);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouterProvider\");\n }\n\n if (!routeContext.route.value) {\n throw new Error(\n \"useRoute called with no active route. Did you forget to await router.start() before rendering, or is the router stopped/disposed?\",\n );\n }\n\n return routeContext as UseRouteReturn<P>;\n};\n"],"mappings":"qBAKA,MAAa,EAAkC,OAAO,
|
|
1
|
+
{"version":3,"file":"useRoute-BT3SkdOc.js","names":[],"sources":["../../src/context.ts","../../src/composables/useRoute.ts"],"sourcesContent":["import type { RouteContext as RouteContextType } from \"./types\";\nimport type { HttpStatusSink } from \"./utils/createHttpStatusSink\";\nimport type { Router, Navigator } from \"@real-router/core\";\nimport type { InjectionKey } from \"vue\";\n\nexport const RouterKey: InjectionKey<Router> = Symbol(\"RouterKey\");\n\nexport const NavigatorKey: InjectionKey<Navigator> = Symbol(\"NavigatorKey\");\n\nexport const RouteKey: InjectionKey<RouteContextType> = Symbol(\"RouteKey\");\n\nexport const HTTP_STATUS_KEY: InjectionKey<HttpStatusSink> =\n Symbol(\"HttpStatusSink\");\n","import { inject } from \"vue\";\n\nimport { RouteKey } from \"../context\";\n\nimport type { RouteContext } from \"../types\";\nimport type { Params, State } from \"@real-router/core\";\nimport type { Ref } from \"vue\";\n\n/**\n * Return shape for `useRoute()` — `RouteContext<P>` with `route` narrowed\n * to the non-nullable variant. The composable throws when `route.value`\n * would be `undefined`, so consumers can read `.value.params.x` without a\n * nullable guard. Extracted from inline duplication at two call sites.\n */\nexport type UseRouteReturn<P extends Params = Params> = Omit<\n RouteContext<P>,\n \"route\"\n> & { route: Readonly<Ref<State<P>>> };\n\nexport const useRoute = <P extends Params = Params>(): UseRouteReturn<P> => {\n const routeContext = inject(RouteKey);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouterProvider\");\n }\n\n if (!routeContext.route.value) {\n throw new Error(\n \"useRoute called with no active route. Did you forget to await router.start() before rendering, or is the router stopped/disposed?\",\n );\n }\n\n return routeContext as UseRouteReturn<P>;\n};\n"],"mappings":"qBAKA,MAAa,EAAkC,OAAO,WAAW,EAEpD,EAAwC,OAAO,cAAc,EAE7D,EAA2C,OAAO,UAAU,EAE5D,EACX,OAAO,gBAAgB,ECOZ,MAA+D,CAC1E,IAAM,GAAA,EAAA,EAAA,QAAsB,CAAQ,EAEpC,GAAI,CAAC,EACH,MAAU,MAAM,+CAA+C,EAGjE,GAAI,CAAC,EAAa,MAAM,MACtB,MAAU,MACR,mIACF,EAGF,OAAO,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createHttpStatusSink-DduXvbGr.d.mts","names":[],"sources":["../../src/utils/createHttpStatusSink.ts"],"mappings":";;AAwBA
|
|
1
|
+
{"version":3,"file":"createHttpStatusSink-DduXvbGr.d.mts","names":[],"sources":["../../src/utils/createHttpStatusSink.ts"],"mappings":";;AAwBA;;;;AACM;AAGN;;;;AAAsD;;;;;;;;;;;;;;UAJrC,cAAA;EACf,IAAI;AAAA;AAAA,iBAGU,oBAAA,CAAA,GAAwB,cAAc"}
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as _$vue from "vue";
|
|
2
1
|
import { Directive, InjectionKey, Plugin, PropType, Ref, ShallowRef, VNode } from "vue";
|
|
3
2
|
import { NavigationOptions, Navigator, Navigator as Navigator$1, Params, Router, RouterError, State } from "@real-router/core";
|
|
4
3
|
import { RouteUtils } from "@real-router/route-utils";
|
|
@@ -23,7 +22,7 @@ type NotFoundProps = Record<string, never>;
|
|
|
23
22
|
//#endregion
|
|
24
23
|
//#region src/components/RouteView/RouteView.d.ts
|
|
25
24
|
declare const RouteView: {
|
|
26
|
-
new (...args: any[]):
|
|
25
|
+
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
|
|
27
26
|
nodeName: {
|
|
28
27
|
type: StringConstructor;
|
|
29
28
|
required: true;
|
|
@@ -32,16 +31,16 @@ declare const RouteView: {
|
|
|
32
31
|
type: BooleanConstructor;
|
|
33
32
|
default: boolean;
|
|
34
33
|
};
|
|
35
|
-
}>> & Readonly<{}>, () => VNode | null, {}, {}, {},
|
|
34
|
+
}>> & Readonly<{}>, () => VNode | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
|
|
36
35
|
keepAlive: boolean;
|
|
37
|
-
}, true, {}, {},
|
|
36
|
+
}, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
|
|
38
37
|
P: {};
|
|
39
38
|
B: {};
|
|
40
39
|
D: {};
|
|
41
40
|
C: {};
|
|
42
41
|
M: {};
|
|
43
42
|
Defaults: {};
|
|
44
|
-
}, Readonly<
|
|
43
|
+
}, Readonly<import("vue").ExtractPropTypes<{
|
|
45
44
|
nodeName: {
|
|
46
45
|
type: StringConstructor;
|
|
47
46
|
required: true;
|
|
@@ -56,7 +55,7 @@ declare const RouteView: {
|
|
|
56
55
|
__isFragment?: never;
|
|
57
56
|
__isTeleport?: never;
|
|
58
57
|
__isSuspense?: never;
|
|
59
|
-
} &
|
|
58
|
+
} & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
|
|
60
59
|
nodeName: {
|
|
61
60
|
type: StringConstructor;
|
|
62
61
|
required: true;
|
|
@@ -65,12 +64,12 @@ declare const RouteView: {
|
|
|
65
64
|
type: BooleanConstructor;
|
|
66
65
|
default: boolean;
|
|
67
66
|
};
|
|
68
|
-
}>> & Readonly<{}>, () => VNode | null, {}, {}, {},
|
|
67
|
+
}>> & Readonly<{}>, () => VNode | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
|
|
69
68
|
keepAlive: boolean;
|
|
70
|
-
}, {}, string, {},
|
|
71
|
-
Match:
|
|
69
|
+
}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & {
|
|
70
|
+
Match: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
72
71
|
segment: {
|
|
73
|
-
type:
|
|
72
|
+
type: import("vue").PropType<string>;
|
|
74
73
|
required: true;
|
|
75
74
|
};
|
|
76
75
|
exact: {
|
|
@@ -78,16 +77,16 @@ declare const RouteView: {
|
|
|
78
77
|
default: boolean;
|
|
79
78
|
};
|
|
80
79
|
fallback: {
|
|
81
|
-
type:
|
|
80
|
+
type: import("vue").PropType<VNode | (() => VNode)>;
|
|
82
81
|
default: undefined;
|
|
83
82
|
};
|
|
84
83
|
keepAlive: {
|
|
85
84
|
type: BooleanConstructor;
|
|
86
85
|
default: boolean;
|
|
87
86
|
};
|
|
88
|
-
}>, {}, {}, {}, {},
|
|
87
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
89
88
|
segment: {
|
|
90
|
-
type:
|
|
89
|
+
type: import("vue").PropType<string>;
|
|
91
90
|
required: true;
|
|
92
91
|
};
|
|
93
92
|
exact: {
|
|
@@ -95,7 +94,7 @@ declare const RouteView: {
|
|
|
95
94
|
default: boolean;
|
|
96
95
|
};
|
|
97
96
|
fallback: {
|
|
98
|
-
type:
|
|
97
|
+
type: import("vue").PropType<VNode | (() => VNode)>;
|
|
99
98
|
default: undefined;
|
|
100
99
|
};
|
|
101
100
|
keepAlive: {
|
|
@@ -103,18 +102,18 @@ declare const RouteView: {
|
|
|
103
102
|
default: boolean;
|
|
104
103
|
};
|
|
105
104
|
}>> & Readonly<{}>, {
|
|
106
|
-
fallback: VNode<
|
|
105
|
+
fallback: VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
107
106
|
[key: string]: any;
|
|
108
107
|
}> | (() => VNode);
|
|
109
108
|
keepAlive: boolean;
|
|
110
109
|
exact: boolean;
|
|
111
|
-
}, {}, {}, {}, string,
|
|
112
|
-
Self:
|
|
113
|
-
NotFound:
|
|
110
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
111
|
+
Self: import("vue").FunctionalComponent<SelfProps, {}, any, {}>;
|
|
112
|
+
NotFound: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
114
113
|
};
|
|
115
114
|
//#endregion
|
|
116
115
|
//#region src/components/Link.d.ts
|
|
117
|
-
declare const Link:
|
|
116
|
+
declare const Link: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
118
117
|
routeName: {
|
|
119
118
|
type: StringConstructor;
|
|
120
119
|
required: true;
|
|
@@ -157,9 +156,9 @@ declare const Link: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
|
|
|
157
156
|
type: StringConstructor;
|
|
158
157
|
default: undefined;
|
|
159
158
|
};
|
|
160
|
-
}>, () =>
|
|
159
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
161
160
|
[key: string]: any;
|
|
162
|
-
}>, {}, {}, {},
|
|
161
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
163
162
|
routeName: {
|
|
164
163
|
type: StringConstructor;
|
|
165
164
|
required: true;
|
|
@@ -211,10 +210,10 @@ declare const Link: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
|
|
|
211
210
|
ignoreQueryParams: boolean;
|
|
212
211
|
target: string;
|
|
213
212
|
hash: string;
|
|
214
|
-
}, {}, {}, {}, string,
|
|
213
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
215
214
|
//#endregion
|
|
216
215
|
//#region src/components/RouterErrorBoundary.d.ts
|
|
217
|
-
declare const RouterErrorBoundary:
|
|
216
|
+
declare const RouterErrorBoundary: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
218
217
|
fallback: {
|
|
219
218
|
type: PropType<(error: RouterError, resetError: () => void) => VNode>;
|
|
220
219
|
required: true;
|
|
@@ -223,9 +222,9 @@ declare const RouterErrorBoundary: _$vue.DefineComponent<_$vue.ExtractPropTypes<
|
|
|
223
222
|
type: PropType<(error: RouterError, toRoute: State | null, fromRoute: State | null) => void>;
|
|
224
223
|
default: undefined;
|
|
225
224
|
};
|
|
226
|
-
}>, () => VNode<
|
|
225
|
+
}>, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
227
226
|
[key: string]: any;
|
|
228
|
-
}>, {}, {}, {},
|
|
227
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
229
228
|
fallback: {
|
|
230
229
|
type: PropType<(error: RouterError, resetError: () => void) => VNode>;
|
|
231
230
|
required: true;
|
|
@@ -236,7 +235,7 @@ declare const RouterErrorBoundary: _$vue.DefineComponent<_$vue.ExtractPropTypes<
|
|
|
236
235
|
};
|
|
237
236
|
}>> & Readonly<{}>, {
|
|
238
237
|
onError: (error: RouterError, toRoute: State | null, fromRoute: State | null) => void;
|
|
239
|
-
}, {}, {}, {}, string,
|
|
238
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
240
239
|
type RouterErrorBoundaryProps = InstanceType<typeof RouterErrorBoundary>["$props"];
|
|
241
240
|
//#endregion
|
|
242
241
|
//#region src/directives/vLink.d.ts
|
|
@@ -497,8 +496,68 @@ interface ScrollRestorationOptions {
|
|
|
497
496
|
storageKey?: string | undefined;
|
|
498
497
|
}
|
|
499
498
|
//#endregion
|
|
499
|
+
//#region ../../shared/dom-utils/scroll-spy.d.ts
|
|
500
|
+
/**
|
|
501
|
+
* Router-coordinated scroll spy (#575).
|
|
502
|
+
*
|
|
503
|
+
* On `IntersectionObserver` notifications the utility picks the topmost
|
|
504
|
+
* visible anchor inside the configured scroll container and emits a forced
|
|
505
|
+
* same-route transition with `{ hash, replace: true, force: true, hashChange:
|
|
506
|
+
* true }` through `router.navigate(...)`. The URL plugin
|
|
507
|
+
* (`@real-router/browser-plugin` or `@real-router/navigation-plugin`) updates
|
|
508
|
+
* `state.context.url.hash` so sibling hash-aware `<Link hash>` re-highlights
|
|
509
|
+
* via the standard `createActiveRouteSource` pipeline.
|
|
510
|
+
*
|
|
511
|
+
* **Anti-flicker gates** (RFC §5.2):
|
|
512
|
+
* 1. `getTransitionSource(router).getSnapshot().isTransitioning` — skip emits
|
|
513
|
+
* while a transition is in-flight (re-entrant lock).
|
|
514
|
+
* 2. `coolingDown` — set on a user-driven hash transition (e.g. `<Link hash>`
|
|
515
|
+
* click + smooth `scrollIntoView`). Cleared on `scrollend` or after a
|
|
516
|
+
* 500ms safety timeout. Spy's own emits are excluded via the synchronous
|
|
517
|
+
* `selfEmitting` flag — required so the spy doesn't rate-limit itself.
|
|
518
|
+
*
|
|
519
|
+
* **Self-healing** (RFC §7.3): if the initial URL contains a hash without a
|
|
520
|
+
* matching `id` (e.g. `/page#nonexistent`), the first IO event emitted right
|
|
521
|
+
* after observe()-ing picks the topmost real anchor and corrects the URL.
|
|
522
|
+
*
|
|
523
|
+
* **Hash-only transition pipeline cost** (RFC §5.3): for same-route same-
|
|
524
|
+
* params hash-only navigations, `getTransitionPath` returns empty
|
|
525
|
+
* `toDeactivate` / `toActivate` arrays, so `runGuards` is a no-op. The only
|
|
526
|
+
* work is the URL plugin's `onTransitionSuccess` write and the
|
|
527
|
+
* `getTransitionSource` flip — cheap.
|
|
528
|
+
*
|
|
529
|
+
* **Architecture**: decomposed into 4 private subsystem closure factories
|
|
530
|
+
* (`createUrlPluginDetector`, `createCooldown`, `createDebouncer`,
|
|
531
|
+
* `createObserverPair`). The main `createScrollSpy` wires them together
|
|
532
|
+
* around the shared `silenced` / `destroyed` / `selfEmitting` flags and the
|
|
533
|
+
* `flush()` emit logic. Each subsystem owns its state + cleanup; `destroy()`
|
|
534
|
+
* delegates to each. See section banners below.
|
|
535
|
+
*
|
|
536
|
+
* @returns A `ScrollSpy` handle whose `destroy()` is idempotent.
|
|
537
|
+
*/
|
|
538
|
+
interface ScrollSpyOptions {
|
|
539
|
+
/**
|
|
540
|
+
* CSS selector for anchor candidates. Empty string `""` or `undefined`
|
|
541
|
+
* disables the spy (returns a NOOP handle). Common values:
|
|
542
|
+
* `"[id]"`, `"[id]:is(h1,h2,h3)"`, `"section[id]"`.
|
|
543
|
+
*/
|
|
544
|
+
selector: string;
|
|
545
|
+
/**
|
|
546
|
+
* `IntersectionObserver` `rootMargin`. Default
|
|
547
|
+
* `"-20% 0px -60% 0px"` — an anchor is considered "active" once it crosses
|
|
548
|
+
* into the top 20 % of the viewport (or scroll container).
|
|
549
|
+
*/
|
|
550
|
+
rootMargin?: string | undefined;
|
|
551
|
+
/**
|
|
552
|
+
* Lazy getter for the scrollable container. Resolved on every event.
|
|
553
|
+
* `null` (or missing getter) falls back to the window viewport
|
|
554
|
+
* (`root: null` on the `IntersectionObserver`).
|
|
555
|
+
*/
|
|
556
|
+
scrollContainer?: (() => HTMLElement | null) | undefined;
|
|
557
|
+
}
|
|
558
|
+
//#endregion
|
|
500
559
|
//#region src/RouterProvider.d.ts
|
|
501
|
-
declare const RouterProvider:
|
|
560
|
+
declare const RouterProvider: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
502
561
|
router: {
|
|
503
562
|
type: PropType<Router>;
|
|
504
563
|
required: true;
|
|
@@ -510,13 +569,16 @@ declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
|
|
|
510
569
|
scrollRestoration: {
|
|
511
570
|
type: PropType<ScrollRestorationOptions>;
|
|
512
571
|
};
|
|
572
|
+
scrollSpy: {
|
|
573
|
+
type: PropType<ScrollSpyOptions>;
|
|
574
|
+
};
|
|
513
575
|
viewTransitions: {
|
|
514
576
|
type: BooleanConstructor;
|
|
515
577
|
default: boolean;
|
|
516
578
|
};
|
|
517
|
-
}>, () =>
|
|
579
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
518
580
|
[key: string]: any;
|
|
519
|
-
}>[] | undefined, {}, {}, {},
|
|
581
|
+
}>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
520
582
|
router: {
|
|
521
583
|
type: PropType<Router>;
|
|
522
584
|
required: true;
|
|
@@ -528,6 +590,9 @@ declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
|
|
|
528
590
|
scrollRestoration: {
|
|
529
591
|
type: PropType<ScrollRestorationOptions>;
|
|
530
592
|
};
|
|
593
|
+
scrollSpy: {
|
|
594
|
+
type: PropType<ScrollSpyOptions>;
|
|
595
|
+
};
|
|
531
596
|
viewTransitions: {
|
|
532
597
|
type: BooleanConstructor;
|
|
533
598
|
default: boolean;
|
|
@@ -535,7 +600,7 @@ declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
|
|
|
535
600
|
}>> & Readonly<{}>, {
|
|
536
601
|
announceNavigation: boolean;
|
|
537
602
|
viewTransitions: boolean;
|
|
538
|
-
}, {}, {}, {}, string,
|
|
603
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
539
604
|
//#endregion
|
|
540
605
|
//#region src/context.d.ts
|
|
541
606
|
declare const RouterKey: InjectionKey<Router>;
|
package/dist/esm/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/RouteView.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useRouter.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/types.ts","../../src/composables/useRoute.ts","../../src/composables/useRouteNode.ts","../../src/composables/useRouterTransition.ts","../../src/composables/useRouteExit.ts","../../src/composables/useRouteEnter.ts","../../src/createRouterPlugin.ts","../../../../shared/dom-utils/scroll-restore.ts","../../src/RouterProvider.ts","../../src/context.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/RouteView.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useRouter.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/types.ts","../../src/composables/useRoute.ts","../../src/composables/useRouteNode.ts","../../src/composables/useRouterTransition.ts","../../src/composables/useRouteExit.ts","../../src/composables/useRouteEnter.ts","../../src/createRouterPlugin.ts","../../../../shared/dom-utils/scroll-restore.ts","../../../../shared/dom-utils/scroll-spy.ts","../../src/RouterProvider.ts","../../src/context.ts"],"mappings":";;;;;;UAEiB,cAAA;EAAA,SACN,QAAA;EAAA,SACA,SAAS;AAAA;AAAA,UAGH,UAAA;EAAA,SACN,OAAA;EAAA,SACA,KAAA;EAAA,SACA,QAAA,GAAW,KAAA,UAAe,KAAK;EAAA,SAC/B,SAAA;AAAA;AAAA,UAGM,SAAA;EAPU;EAAA,SAShB,QAAA,GAAW,KAAA,UAAe,KAAK;AAAA;AAAA,KAG9B,aAAA,GAAgB,MAAM;;;cC0MrB,SAAA;EAAA;;;;;;;;;4BAzDE,KAAA,mCAAY,qBAAA,gBAAA,qBAAA,oBAAA,WAAA;;;;;;;;;;;;;;;;;;4BAAZ,KAAA;;;;;;;;;;;;;;;0BAAA,KAAA,mCAAY,qBAAA,gBAAA,qBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCnHd,IAAA,gBAAI,eAAA,eAAA,gBAAA;;;;;;UAaK,QAAA,CAAS,MAAA;;;;UAIT,QAAA,CAAS,iBAAA;;;;;;;;;;;;;;;;;;;;;;;EF/CG;AAAA;;;;AC0MlC;;;;;;;;;;;;;UC/JsB,QAAA,CAAS,MAAA;;;;UAIT,QAAA,CAAS,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCzDlB,mBAAA,gBAAmB,eAAA,eAAA,gBAAA;;UAIR,QAAA,EACf,KAAA,EAAO,WAAA,EAAa,UAAA,iBAA2B,KAAA;;;;UAKhC,QAAA,EAEd,KAAA,EAAO,WAAA,EACP,OAAA,EAAS,KAAA,SACT,SAAA,EAAW,KAAA;;;;;;;UAVG,QAAA,EACf,KAAA,EAAO,WAAA,EAAa,UAAA,iBAA2B,KAAA;;;;UAKhC,QAAA,EAEd,KAAA,EAAO,WAAA,EACP,OAAA,EAAS,KAAA,SACT,SAAA,EAAW,KAAA;;;;mBAFJ,WAAA,EAAW,OAAA,EACT,KAAA,SAAY,SAAA,EACV,KAAA;AAAA;KAmCT,wBAAA,GAA2B,YAAY,QAC1C,mBAAA;;;UCtDQ,kBAAA;EACf,IAAA;EACA,MAAA,GAAS,MAAA;EACT,OAAA,GAAU,iBAAiB;AAAA;AAAA,cA4JhB,KAAA,EAAO,SAAA,CAAU,WAAA,EAAa,kBAAA;;;cC9J9B,SAAA,QAAgB,MAQ5B;;;cCRY,YAAA,QAAmB,WAQ/B;;;cCPY,aAAA,QAAoB,UAIhC;;;;;;;APTD;;UQYiB,YAAA,WAAuB,MAAA,GAAS,MAAA;EAC/C,SAAA,EAAW,WAAA;EACX,KAAA,EAAO,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,CAAA;EAC1B,aAAA,EAAe,QAAA,CAAS,GAAA,CAAI,KAAA;AAAA;AAAA,UAGb,SAAA,WAAoB,MAAA,GAAS,MAAA;EAC5C,SAAA;EACA,WAAA,GAAc,CAAA;EACd,YAAA,GAAe,iBAAA;EACf,KAAA;EACA,eAAA;EACA,YAAA;EACA,iBAAA;EACA,MAAA;ERjBkB;AAGpB;;;;;;;;EQwBE,IAAA;AAAA;;;;;;ARpCF;;;KSYY,cAAA,WAAyB,MAAA,GAAS,MAAA,IAAU,IAAA,CACtD,YAAA,CAAa,CAAA;EAET,KAAA,EAAO,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,CAAA;AAAA;AAAA,cAEnB,QAAA,aAAsB,MAAA,GAAS,MAAA,OAAW,cAAA,CAAe,CAAA;;;iBCVtD,YAAA,CAAa,QAAA,WAAmB,YAAY;;;iBCD5C,mBAAA,CAAA,GAAuB,UAAU,CAAC,0BAAA;;;UCFjC,gBAAA;;EAEf,KAAA,EAAO,KAAA;;EAEP,SAAA,EAAW,KAAA;EZRI;;;;AAEG;AAGpB;;EYWE,MAAA,EAAQ,WAAA;AAAA;AAAA,UAGO,mBAAA;EZZN;;;;;EYkBT,aAAa;AAAA;AAAA,KAGH,gBAAA,IACV,OAAA,EAAS,gBAAA,YACC,OAAO;;;;;;;;AZhBuB;AAG1C;;;;AAAkC;;;;AC0MlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBW9HgB,YAAA,CACd,OAAA,EAAS,gBAAA,EACT,OAAA,GAAU,mBAAmB;;;UC3Fd,iBAAA;;EAEf,KAAA,EAAO,KAAA;;EAEP,aAAA,EAAe,KAAK;AAAA;AAAA,KAGV,iBAAA,IAAqB,OAA0B,EAAjB,iBAAiB;AAAA,UAE1C,oBAAA;EbZN;AACS;AAGpB;;;EacE,aAAa;AAAA;;;;;;;AbVK;AAGpB;;;;;;;;AAE0C;AAG1C;;;;AAAkC;;;;AC0MlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBYhJgB,aAAA,CACd,OAAA,EAAS,iBAAA,EACT,OAAA,GAAU,oBAAoB;;;iBCxEhB,kBAAA,CAAmB,MAAA,EAAQ,MAAA,GAAS,MAAM;;;KCW9C,qBAAA;AAAA,UAEK,wBAAA;EACf,IAAA,GAAO,qBAAA;EACP,eAAA;EACA,eAAA,UAAyB,WAAA;EfrBV;;;;AAEG;AAGpB;;;;;;;Ee6BE,QAAA,GAAW,cAAA;Ef1BwB;;;AACjB;AAGpB;;;Ee8BE,UAAA;AAAA;;;;;;;;Af1CF;;;;AAEoB;AAGpB;;;;;;;;;;;AAIoB;AAGpB;;;;;;;;AAE0C;AAG1C;;;;AAAkC;;;UgBuBjB,gBAAA;EfmLJ;;;;;Ee7KX,QAAA;;;;;;EAOA,UAAA;Ef6Ga;;;;;EetGb,eAAA,UAAyB,WAAW;AAAA;;;cCXzB,cAAA,gBAAc,eAAA,eAAA,gBAAA;;UAIL,QAAA,CAAS,MAAA;;;;;;;;UAQT,QAAA,CAAS,wBAAA;EAAA;;UAGT,QAAA,CAAS,gBAAA;EAAA;;;;;;;;;UAXT,QAAA,CAAS,MAAA;;;;;;;;UAQT,QAAA,CAAS,wBAAA;EAAA;;UAGT,QAAA,CAAS,gBAAA;EAAA;;;;;;;;;;;cC7DlB,SAAA,EAAW,YAAY,CAAC,MAAA;AAAA,cAExB,YAAA,EAAc,YAAY,CAAC,WAAA;AAAA,cAE3B,QAAA,EAAU,YAAY,CAAC,YAAA"}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,i as t,r as n,t as r}from"./useRoute-2ocUdDHc.mjs";import{Fragment as i,KeepAlive as a,Suspense as o,computed as s,defineComponent as c,h as l,inject as u,isVNode as d,markRaw as f,onScopeDispose as p,provide as m,shallowRef as h,watch as g}from"vue";import{UNKNOWN_ROUTE as _,getNavigator as v}from"@real-router/core";import{getRouteUtils as ee,startsWithSegment as te}from"@real-router/route-utils";import{canonicalJson as ne,createActiveRouteSource as re,createDismissableError as ie,createRouteNodeSource as ae,createRouteSource as oe,getTransitionSource as y}from"@real-router/sources";import{getPluginApi as se}from"@real-router/core/api";function b(){return null}const x=c({name:`RouteView.Match`,props:{segment:{type:String,required:!0},exact:{type:Boolean,default:!1},fallback:{type:[Object,Function],default:void 0},keepAlive:{type:Boolean,default:!1}},render:b}),S=c({name:`RouteView.Self`,props:{fallback:{type:[Object,Function],default:void 0}},render:b}),C=c({name:`RouteView.NotFound`,render:b});function ce(e,t,n){return n?e===t:te(e,t)}function w(e){return e===!0||e===``||e===`keep-alive`}function T(e){if(Array.isArray(e)){let t=[];for(let n of e)Array.isArray(n)?t.push(...T(n)):d(n)&&t.push(n);return t}return d(e)?[e]:[]}function E(e,t){let n=T(e);for(let e of n)e.type===x||e.type===S||e.type===C?t.push(e):e.type===i&&E(e.children,t)}function le(e,t){return e.type===C?(t.notFoundChildren=e.children,!0):e.type===S?(t.selfVNode===null&&(t.selfVNode=e,t.selfFallback=e.props?.fallback),!0):!1}function ue(e,t,n){let r=e.props,i=r?.segment??``,a=r?.exact??!1;return{isActive:ce(t,n?`${n}.${i}`:i,a),fallback:r?.fallback}}function de(e,t,n,r,i){if(r.selfVNode!==null&&t===n)return e.push(r.selfVNode),r.selfFallback;if(t===_&&r.notFoundChildren!==null){let t=i.filter(e=>e.type===C).at(-1);t&&e.push(t)}}function fe(e,t,n){let r={selfVNode:null,selfFallback:void 0,notFoundChildren:null},i=!1,a,o=!1,s=[];for(let c of e){if(!o&&c.type===x){let e=c.props;w(e?.keepAlive)&&(o=!0)}if(le(c,r)||i)continue;let e=ue(c,t,n);e.isActive&&(i=!0,a=e.fallback,s.push(c))}return i||(a=de(s,t,n,r,e)),{rendered:s,activeMatchFound:i,fallback:a,hasPerMatchKA:o}}function D(e){let t=h(e.getSnapshot());return p(e.subscribe(()=>{t.value=e.getSnapshot()})),t}const O=()=>{let t=u(e);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function k(e){let t=O(),n=D(ae(t,e));return{navigator:v(t),route:s(()=>n.value.route),previousRoute:s(()=>n.value.previousRoute)}}function A(e){return e.children?.default?.()??null}function j(e,t){let n=e.get(t);if(n)return n;let r=f(c({name:`KeepAlive-${t}`,setup(e,t){return()=>t.slots.default?.()}}));return e.set(t,r),r}function M(e,t){if(t===void 0)return e;let n=typeof t==`function`?t():t;return l(o,{},{default:()=>e,fallback:()=>n})}let N=null;function pe(){return N??=f(c({name:`KeepAlive-placeholder`,render(){return null}})),N}function me(e,t,n){let r=e.props?.segment??`__not-found__`,i=j(t,r),o=A(e)??[];return M(l(a,null,{default:()=>l(i,{key:r},{default:()=>o})}),n)}function P(e,t,n){let r=e.props;if(w(r?.keepAlive)&&e.type===x){let n=r?.segment??`__not-found__`,o=j(t,n),s=A(e)??[];return l(i,[l(a,null,{default:()=>l(o,{key:n},{default:()=>s})})])}let o=A(e);return o?l(i,[l(a,null,{default:()=>l(pe())}),M(l(i,o),n)]):null}const F=c({name:`RouteView`,props:{nodeName:{type:String,required:!0},keepAlive:{type:Boolean,default:!1}},setup(e,{slots:t}){let n=k(e.nodeName),r=new Map;return()=>{let a=n.route.value;if(!a)return null;let o=t.default?.(),s=[];E(o,s);let{rendered:c,fallback:u,hasPerMatchKA:d}=fe(s,a.name,e.nodeName);if(c.length===0)return null;let f=c[0];if(e.keepAlive)return me(f,r,u);if(f.type!==x&&f.type!==S&&f.type!==C)return null;if(d)return P(f,r,u);let p=A(f);return p?M(l(i,p),u):null}}}),I=Object.assign(F,{Match:x,Self:S,NotFound:C}),L=Object.freeze({}),R=Object.freeze({}),z=`data-real-router-announcer`,he=Object.freeze({destroy:()=>{}});function ge(e,t){if(typeof document>`u`)return he;let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=_e(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),be(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=ye(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),ve()}}}function _e(){let e=document.querySelector(`[${z}]`);if(e)return e;let t=document.createElement(`div`);return t.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),t.setAttribute(`aria-live`,`assertive`),t.setAttribute(`aria-atomic`,`true`),t.setAttribute(z,``),(document.body??document.documentElement).prepend(t),t}function ve(){document.querySelector(`[${z}]`)?.remove()}function ye(e,t,n,r){if(n)try{let t=n(e);if(t)return t}catch(e){console.error(`[real-router] getAnnouncementText threw; falling back to default resolution.`,e)}let i=(r?.textContent??``).trim(),a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function be(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const B=Object.freeze({destroy:()=>{}});function xe(e,t){if(globalThis.window===void 0)return B;let n=t?.mode??`restore`;if(n===`native`)return B;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=t?.behavior??`auto`,o=t?.storageKey??`real-router:scroll`,s,c=()=>{if(s!==void 0)return s;try{let e=sessionStorage.getItem(o);s=e?JSON.parse(e):{}}catch{s={}}return s},l=(e,t)=>{try{let n=c();if(n[e]===t)return;n[e]=t,sessionStorage.setItem(o,JSON.stringify(n))}catch{}},u=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let d=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},f=e=>{let t=i?.();t?t.scrollTo({top:e,left:0,behavior:a}):globalThis.scrollTo({top:e,left:0,behavior:a})},p=e=>{let t=e.context?.url?.hash;if(t!==void 0){if(r&&t.length>0){let e=document.getElementById(t);if(e){e.scrollIntoView({behavior:a});return}}f(0);return}let n=globalThis.location.hash;if(r&&n.length>1){let e;try{e=decodeURIComponent(n.slice(1))}catch{e=n.slice(1)}let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:a});return}}f(0)},m=!1,h=!1,g=e=>{try{return Se(e)}catch{return h||(h=!0,console.error(`[real-router] scroll-restore: route "${e.name}" has params that cannot be canonicalized (e.g. BigInt or cyclic structure). Scroll position will not be captured or restored for this route.`)),null}},_=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;if(t){let e=g(t);e!==null&&l(e,d())}requestAnimationFrame(()=>{if(!m){if(n===`top`||!r){p(e);return}if(r.navigationType!==`replace`){if(r.direction===`back`||r.navigationType===`traverse`||r.navigationType===`reload`){let t=g(e);f(t===null?0:c()[t]??0);return}p(e)}}})}),v=()=>{let t=e.getState();if(t){let e=g(t);e!==null&&l(e,d())}};return globalThis.addEventListener(`pagehide`,v),{destroy:()=>{if(!m){m=!0,_(),globalThis.removeEventListener(`pagehide`,v);try{history.scrollRestoration=u}catch{}}}}}const V=new WeakMap;function Se(e){let t=V.get(e);if(t!==void 0)return t;let n=`${e.name}:${Ce(e.params)}`;return V.set(e,n),n}function Ce(e){return JSON.stringify(e,we)}function we(e,t){if(typeof t==`function`)return`<fn>`;if(typeof t==`symbol`)return`<sym>`;if(typeof t==`object`&&t&&!Array.isArray(t)){let e=Object.create(null),n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}const Te=Object.freeze({destroy:()=>{}});function Ee(e){if(typeof document>`u`||typeof document.startViewTransition!=`function`)return Te;let t=null,n=null,r=!1,i=()=>{t?.(),t=null},a=e.subscribeLeave(({signal:e})=>{if(!e.aborted)return r=!1,i(),new Promise(a=>{let o=new Promise(e=>{t=e});e.addEventListener(`abort`,()=>{r||(i(),n?.skipTransition?.(),a())},{once:!0});try{n=document.startViewTransition(()=>(a(),o))}catch{i(),a()}})}),o=e.subscribe(()=>{let e=t;r=!0,t=null,e===null?n=null:setTimeout(()=>{e(),n=null},0)});return{destroy:()=>{a(),o(),n?.skipTransition?.(),n=null,i()}}}function H(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}const U=/%[\dA-Fa-f]{2}/;function De(e){if(U.test(e))try{return encodeURI(decodeURIComponent(e)).replaceAll(`#`,`%23`)}catch{}return encodeURI(e).replaceAll(`#`,`%23`)}function Oe(e,t,n,r){try{let i=r?.hash,a;i!==void 0&&(a=i.startsWith(`#`)?i.slice(1):i);let o=e.buildUrl;if(o){let e=o(t,n,a===void 0?void 0:{hash:a});if(typeof e==`string`&&e.length>0)return e}let s=e.buildPath(t,n);if(typeof s!=`string`||s.length===0){console.error(`[real-router] Route "${t}" yielded an empty path. The element will render without an href attribute.`);return}return a?`${s}#${De(a)}`:s}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function ke(e,t,n,r,i){let a={...i};r!==void 0&&(a.hash=r);let o=e.getState();if(o?.name===t&&Ne(o.params,n)){let e=o.context?.url?.hash??``;e!==(r??e)&&(a.force=!0,a.hashChange=!0)}return e.navigate(t,n,a)}const Ae=/\s/,je=/\S+/g;function W(e){return e?Ae.test(e)?e.match(je)??[]:[e]:[]}function Me(e,t,n){if(e&&t){let e=W(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=W(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function Ne(e,t){if(Object.is(e,t))return!0;if(!e||!t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;let r=e,i=t;for(let e of n)if(!Object.prototype.hasOwnProperty.call(t,e)||!Object.is(r[e],i[e]))return!1;return!0}function Pe(e){if(!e)return;let t=e.tagName;t===`A`||t===`BUTTON`||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`))}function Fe(e,t){if(typeof e==`function`){e(t);return}if(Array.isArray(e)){let n=e;for(let e of n)if(typeof e==`function`&&(e(t),t.defaultPrevented))return}}const Ie=c({name:`Link`,inheritAttrs:!1,props:{routeName:{type:String,required:!0},routeParams:{type:Object,default:()=>L},routeOptions:{type:Object,default:()=>R},class:{type:String,default:void 0},activeClassName:{type:String,default:`active`},activeStrict:{type:Boolean,default:!1},ignoreQueryParams:{type:Boolean,default:!0},target:{type:String,default:void 0},hash:{type:String,default:void 0}},setup(e,{slots:t,attrs:n}){let r=O(),i=h(!1);g(()=>[e.routeName,ne(e.routeParams),e.activeStrict,e.ignoreQueryParams,e.hash],([t,n,a,o,s],c,l)=>{let u=e.routeParams,d=re(r,t,u,s===void 0?{strict:a,ignoreQueryParams:o}:{strict:a,ignoreQueryParams:o,hash:s});i.value=d.getSnapshot(),l(d.subscribe(()=>{i.value=d.getSnapshot()}))},{immediate:!0,flush:`sync`});let a=s(()=>Oe(r,e.routeName,e.routeParams,e.hash===void 0?void 0:{hash:e.hash})),o=s(()=>Me(i.value,e.activeClassName,e.class)),c=t=>{n.onClick!==void 0&&n.onClick!==null&&(Fe(n.onClick,t),t.defaultPrevented)||!H(t)||e.target===`_blank`||(t.preventDefault(),ke(r,e.routeName,e.routeParams,e.hash,e.routeOptions).catch(()=>{}))};return()=>{let r={...n};return delete r.onClick,l(`a`,{...r,href:a.value,class:o.value,target:e.target,onClick:c},t.default?.())}}}),Le=c({name:`RouterErrorBoundary`,props:{fallback:{type:Function,required:!0},onError:{type:Function,default:void 0}},setup(e,{slots:t}){let n=D(ie(O()));return g(()=>n.value.version,()=>{n.value.error&&e.onError?.(n.value.error,n.value.toRoute,n.value.fromRoute)},{immediate:!0}),()=>{let r=t.default?.()??[],a=n.value.error?e.fallback(n.value.error,n.value.resetError):null;return l(i,null,[...r,a])}}}),G=[];function K(e){return G.push(e),()=>{let t=G.lastIndexOf(e);t!==-1&&G.splice(t,1)}}function q(){let e=G.at(-1);if(!e)throw Error(`v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.`);return e}const J=new WeakMap;function Y(e){return e==null?(console.error(`[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.`),!1):typeof e.name==`string`?!0:(console.error("[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation."),!1)}function Re(e,t){return n=>{H(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function ze(e,t,n){return r=>{r.key===`Enter`&&!(n instanceof HTMLButtonElement)&&e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{})}}function X(e,t,n){let r=Re(t,n),i=ze(t,n,e);e.addEventListener(`click`,r),e.addEventListener(`keydown`,i),J.set(e,{click:r,keydown:i})}function Z(e){let t=J.get(e);t&&(e.removeEventListener(`click`,t.click),e.removeEventListener(`keydown`,t.keydown),J.delete(e))}const Be={mounted(e,t){let n=q();Pe(e),e.style.cursor=`pointer`,Y(t.value)&&X(e,n,t.value)},updated(e,t){if(t.value===t.oldValue)return;let n=q();Z(e),Y(t.value)&&X(e,n,t.value)},beforeUnmount(e){Z(e)}},Ve=()=>{let e=u(n);if(!e)throw Error(`useNavigator must be used within a RouterProvider`);return e},He=()=>ee(se(O()).getTree());function Ue(){return D(y(O()))}function We(e,t){let n=O(),r=t?.skipSameRoute??!0;p(n.subscribeLeave(({route:t,nextRoute:n,signal:i})=>{if(!(r&&t.name===n.name)&&!i.aborted)return e({route:t,nextRoute:n,signal:i})}))}function Ge(e,t){let{route:n,previousRoute:i}=r(),a=t?.skipSameRoute??!0,o=null;g(n,t=>{let n=i.value;t.transition.from&&(a&&t.transition.from===t.name||o===t||!n||(o=t,e({route:t,previousRoute:n})))})}function Q(e){let t=v(e),n=oe(e),r=n.getSnapshot(),i=h(r.route),a=h(r.previousRoute);return{navigator:t,route:i,previousRoute:a,unsubscribe:n.subscribe(()=>{let e=n.getSnapshot();i.value=e.route,a.value=e.previousRoute})}}function Ke(r){return{install(i){let a=K(r),{navigator:o,route:s,previousRoute:c,unsubscribe:l}=Q(r);`onUnmount`in i&&i.onUnmount(()=>{a(),l()}),i.provide(e,r),i.provide(n,o),i.provide(t,{navigator:o,route:s,previousRoute:c})}}}function $(e,t){g(e,(e,n,r)=>{let i=t(e);i&&r(()=>{i.destroy()})},{immediate:!0})}const qe=c({name:`RouterProvider`,props:{router:{type:Object,required:!0},announceNavigation:{type:Boolean,default:!1},scrollRestoration:{type:Object},viewTransitions:{type:Boolean,default:!1}},setup(r,{slots:i}){$(()=>[r.router,r.announceNavigation],([e,t])=>t?ge(e):void 0),$(()=>[r.router,r.scrollRestoration!==void 0,r.scrollRestoration?.mode,r.scrollRestoration?.anchorScrolling,r.scrollRestoration?.behavior,r.scrollRestoration?.storageKey],([e,t,n,i,a,o])=>{if(t)return xe(e,{mode:n,anchorScrolling:i,behavior:a,storageKey:o,scrollContainer:r.scrollRestoration?.scrollContainer})}),$(()=>[r.router,r.viewTransitions],([e,t])=>t?Ee(e):void 0);let a=K(r.router),{navigator:o,route:s,previousRoute:c,unsubscribe:l}=Q(r.router);return p(()=>{a(),l()}),m(e,r.router),m(n,o),m(t,{navigator:o,route:s,previousRoute:c}),()=>i.default?.()}});export{Ie as Link,n as NavigatorKey,t as RouteKey,I as RouteView,Le as RouterErrorBoundary,e as RouterKey,qe as RouterProvider,Ke as createRouterPlugin,Ve as useNavigator,r as useRoute,Ge as useRouteEnter,We as useRouteExit,k as useRouteNode,He as useRouteUtils,O as useRouter,Ue as useRouterTransition,Be as vLink};
|
|
1
|
+
import{a as e,i as t,r as n,t as r}from"./useRoute-2ocUdDHc.mjs";import{Fragment as i,KeepAlive as a,Suspense as o,computed as s,defineComponent as c,h as l,inject as u,isVNode as d,markRaw as f,onScopeDispose as p,provide as m,shallowRef as h,watch as g}from"vue";import{UNKNOWN_ROUTE as _,getNavigator as v}from"@real-router/core";import{getRouteUtils as y,startsWithSegment as b}from"@real-router/route-utils";import{canonicalJson as ee,createActiveRouteSource as te,createDismissableError as ne,createRouteNodeSource as re,createRouteSource as ie,getTransitionSource as x}from"@real-router/sources";import{getPluginApi as ae}from"@real-router/core/api";function S(){return null}const C=c({name:`RouteView.Match`,props:{segment:{type:String,required:!0},exact:{type:Boolean,default:!1},fallback:{type:[Object,Function],default:void 0},keepAlive:{type:Boolean,default:!1}},render:S}),w=c({name:`RouteView.Self`,props:{fallback:{type:[Object,Function],default:void 0}},render:S}),T=c({name:`RouteView.NotFound`,render:S});function oe(e,t,n){return n?e===t:b(e,t)}function E(e){return e===!0||e===``||e===`keep-alive`}function D(e){if(Array.isArray(e)){let t=[];for(let n of e)Array.isArray(n)?t.push(...D(n)):d(n)&&t.push(n);return t}return d(e)?[e]:[]}function O(e,t){let n=D(e);for(let e of n)e.type===C||e.type===w||e.type===T?t.push(e):e.type===i&&O(e.children,t)}function se(e,t){return e.type===T?(t.notFoundChildren=e.children,!0):e.type===w?(t.selfVNode===null&&(t.selfVNode=e,t.selfFallback=e.props?.fallback),!0):!1}function ce(e,t,n){let r=e.props,i=r?.segment??``,a=r?.exact??!1;return{isActive:oe(t,n?`${n}.${i}`:i,a),fallback:r?.fallback}}function le(e,t,n,r,i){if(r.selfVNode!==null&&t===n)return e.push(r.selfVNode),r.selfFallback;if(t===_&&r.notFoundChildren!==null){let t=i.filter(e=>e.type===T).at(-1);t&&e.push(t)}}function ue(e,t,n){let r={selfVNode:null,selfFallback:void 0,notFoundChildren:null},i=!1,a,o=!1,s=[];for(let c of e){if(!o&&c.type===C){let e=c.props;E(e?.keepAlive)&&(o=!0)}if(se(c,r)||i)continue;let e=ce(c,t,n);e.isActive&&(i=!0,a=e.fallback,s.push(c))}return i||(a=le(s,t,n,r,e)),{rendered:s,activeMatchFound:i,fallback:a,hasPerMatchKA:o}}function k(e){let t=h(e.getSnapshot());return p(e.subscribe(()=>{t.value=e.getSnapshot()})),t}const A=()=>{let t=u(e);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function j(e){let t=A(),n=k(re(t,e));return{navigator:v(t),route:s(()=>n.value.route),previousRoute:s(()=>n.value.previousRoute)}}function M(e){return e.children?.default?.()??null}function N(e,t){let n=e.get(t);if(n)return n;let r=f(c({name:`KeepAlive-${t}`,setup(e,t){return()=>t.slots.default?.()}}));return e.set(t,r),r}function P(e,t){if(t===void 0)return e;let n=typeof t==`function`?t():t;return l(o,{},{default:()=>e,fallback:()=>n})}let F=null;function de(){return F??=f(c({name:`KeepAlive-placeholder`,render(){return null}})),F}function fe(e,t,n){let r=e.props?.segment??`__not-found__`,i=N(t,r),o=M(e)??[];return P(l(a,null,{default:()=>l(i,{key:r},{default:()=>o})}),n)}function pe(e,t,n){let r=e.props;if(E(r?.keepAlive)&&e.type===C){let n=r?.segment??`__not-found__`,o=N(t,n),s=M(e)??[];return l(i,[l(a,null,{default:()=>l(o,{key:n},{default:()=>s})})])}let o=M(e);return o?l(i,[l(a,null,{default:()=>l(de())}),P(l(i,o),n)]):null}const me=c({name:`RouteView`,props:{nodeName:{type:String,required:!0},keepAlive:{type:Boolean,default:!1}},setup(e,{slots:t}){let n=j(e.nodeName),r=new Map;return()=>{let a=n.route.value;if(!a)return null;let o=t.default?.(),s=[];O(o,s);let{rendered:c,fallback:u,hasPerMatchKA:d}=ue(s,a.name,e.nodeName);if(c.length===0)return null;let f=c[0];if(e.keepAlive)return fe(f,r,u);if(f.type!==C&&f.type!==w&&f.type!==T)return null;if(d)return pe(f,r,u);let p=M(f);return p?P(l(i,p),u):null}}}),he=Object.assign(me,{Match:C,Self:w,NotFound:T}),ge=Object.freeze({}),I=Object.freeze({}),L=`data-real-router-announcer`,_e=Object.freeze({destroy:()=>{}});function ve(e,t){if(typeof document>`u`)return _e;let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=ye(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),Se(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=xe(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),be()}}}function ye(){let e=document.querySelector(`[${L}]`);if(e)return e;let t=document.createElement(`div`);return t.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),t.setAttribute(`aria-live`,`assertive`),t.setAttribute(`aria-atomic`,`true`),t.setAttribute(L,``),(document.body??document.documentElement).prepend(t),t}function be(){document.querySelector(`[${L}]`)?.remove()}function xe(e,t,n,r){if(n)try{let t=n(e);if(t)return t}catch(e){console.error(`[real-router] getAnnouncementText threw; falling back to default resolution.`,e)}let i=(r?.textContent??``).trim(),a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function Se(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const R=Object.freeze({destroy:()=>{}});function Ce(e,t){if(globalThis.window===void 0)return R;let n=t?.mode??`restore`;if(n===`native`)return R;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=t?.behavior??`auto`,o=t?.storageKey??`real-router:scroll`,s,c=()=>{if(s!==void 0)return s;try{let e=sessionStorage.getItem(o);s=e?JSON.parse(e):{}}catch{s={}}return s},l=(e,t)=>{try{let n=c();if(n[e]===t)return;n[e]=t,sessionStorage.setItem(o,JSON.stringify(n))}catch{}},u=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let d=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},f=e=>{let t=i?.();t?t.scrollTo({top:e,left:0,behavior:a}):globalThis.scrollTo({top:e,left:0,behavior:a})},p=e=>{if(!i){globalThis.scrollTo({top:e,left:0,behavior:a});return}let t=0,n=()=>{if(h)return;let r=i();if(r){if(r.scrollTo({top:e,left:0,behavior:a}),a!==`smooth`&&Math.abs(r.scrollTop-e)<=1)return}else globalThis.scrollTo({top:e,left:0,behavior:a});t>=10||(t+=1,requestAnimationFrame(n))};n()},m=e=>{let t=e.context?.url?.hash;if(t!==void 0){if(r&&t.length>0){let e=document.getElementById(t);if(e){e.scrollIntoView({behavior:a});return}}f(0);return}let n=globalThis.location.hash;if(r&&n.length>1){let e;try{e=decodeURIComponent(n.slice(1))}catch{e=n.slice(1)}let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:a});return}}f(0)},h=!1,g=!1,_=e=>{try{return we(e)}catch{return g||(g=!0,console.error(`[real-router] scroll-restore: route "${e.name}" has params that cannot be canonicalized (e.g. BigInt or cyclic structure). Scroll position will not be captured or restored for this route.`)),null}},v=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;if(t){let e=_(t);e!==null&&l(e,d())}requestAnimationFrame(()=>{if(!h){if(n===`top`){m(e);return}if(e.transition.reload||r?.navigationType===`reload`){let t=_(e);p(t===null?0:c()[t]??0);return}if(r?.direction===`back`||r?.navigationType===`traverse`){let t=_(e);p(t===null?0:c()[t]??0);return}e.transition.replace||r?.navigationType===`replace`||m(e)}})}),y=()=>{let t=e.getState();if(t){let e=_(t);e!==null&&l(e,d())}};return globalThis.addEventListener(`pagehide`,y),{destroy:()=>{if(!h){h=!0,v(),globalThis.removeEventListener(`pagehide`,y);try{history.scrollRestoration=u}catch{}}}}}const z=new WeakMap;function we(e){let t=z.get(e);if(t!==void 0)return t;let n=`${e.name}:${Te(e.params)}`;return z.set(e,n),n}function Te(e){return JSON.stringify(e,Ee)}function Ee(e,t){if(typeof t==`function`)return`<fn>`;if(typeof t==`symbol`)return`<sym>`;if(typeof t==`object`&&t&&!Array.isArray(t)){let e=Object.create(null),n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}const B=Object.freeze({destroy:()=>{}}),V=e=>e.context?.url,De=e=>{let t=null,n=1/0,r=null,i=-1/0;for(let a of e){if(!a.isIntersecting)continue;let e=a.rootBounds?.top??0,o=a.boundingClientRect.top-e;o>=0?o<n&&(t=a,n=o):o>i&&(r=a,i=o)}return t??r},Oe=(e,t)=>{let n=null,r=e=>{let n=e.context;n&&n.url===void 0&&(console.warn(`[real-router] scroll-spy: state.context.url is not claimed. Spy requires browser-plugin or navigation-plugin. Disabling.`),t())},i=e.getState();if(i)r(i);else{let t=!1;n=e.subscribe(({route:e})=>{t||(t=!0,r(e),n?.(),n=null)})}return{destroy(){n?.(),n=null}}},ke=e=>{let t=!1,n=null,r=null,i=null,a=()=>{n!==null&&(clearTimeout(n),n=null),i&&(r??globalThis).removeEventListener(`scrollend`,i),i=null,r=null,t=!1};return{get active(){return t},start(){a(),t=!0;let o=()=>{a()};i=o,r=e(),(r??globalThis).addEventListener(`scrollend`,o,{once:!0}),n=setTimeout(o,500)},destroy(){a()}}},Ae=(e,t)=>{let n=null,r=null;return{schedule(){n===null&&(n=requestAnimationFrame(()=>{n=null,r!==null&&clearTimeout(r),r=setTimeout(()=>{r=null,e()},t)}))},destroy(){n!==null&&(cancelAnimationFrame(n),n=null),r!==null&&(clearTimeout(r),r=null)}}},H=(e,t,n,r,i,a)=>{let o=new Set,s=new Map,c=!1,l=null,u=new IntersectionObserver(e=>{if(!a()){for(let t of e)s.set(t.target,t);r()}},{root:n(),rootMargin:t,threshold:0}),d=()=>{let t=n()??document,r;try{r=t.querySelectorAll(e)}catch{i();return}let a=new Set;for(let e of r){let t=e.id;t&&!c&&(a.has(t)&&(c=!0,console.warn(`[real-router] scroll-spy: duplicate id "${t}" observed. Selection picks the topmost visible match deterministically.`)),a.add(t)),!o.has(e)&&(u.observe(e),o.add(e))}},f=()=>{for(let e of o)e.isConnected||(u.unobserve(e),o.delete(e),s.delete(e));d()};d();let p=n()??document.body,m=new MutationObserver(()=>{l!==null&&clearTimeout(l),l=setTimeout(()=>{l=null,f()},250)});return m.observe(p,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`id`]}),{pending:s,destroy(){u.disconnect(),m.disconnect(),l!==null&&(clearTimeout(l),l=null),o.clear(),s.clear()}}};function je(e,t){if(typeof document>`u`||typeof IntersectionObserver>`u`)return B;let{selector:n}=t;if(!n)return B;let r=t.rootMargin??`-20% 0px -60% 0px`,i=t.scrollContainer,a=()=>i?.()??null,o=!1,s=!1,c=!1,l=()=>s||o,u=null,d=x(e),f=Oe(e,()=>{s=!0}),p=ke(a),m=Ae(()=>{u?.()},150),h=H(n,r,a,()=>{m.schedule()},()=>{s||(s=!0,console.warn(`[real-router] scroll-spy: invalid selector "${n}". Disabling.`))},l);u=()=>{if(o||s){h.pending.clear();return}if(d.getSnapshot().isTransitioning||p.active||h.pending.size===0)return;let t=De(h.pending.values());if(h.pending.clear(),!t)return;let n=t.target.id;if(!n)return;let r=e.getState();if(!r||n===(V(r)?.hash??``))return;let i={hash:n,replace:!0,force:!0,hashChange:!0};c=!0,e.navigate(r.name,r.params,i).catch(()=>{}).finally(()=>{c=!1})};let g=e.subscribe(({route:e})=>{c||V(e)?.hashChanged&&p.start()});return{destroy(){o||(o=!0,g(),h.destroy(),m.destroy(),p.destroy(),f.destroy())}}}const Me=Object.freeze({destroy:()=>{}});function Ne(e){if(typeof document>`u`||typeof document.startViewTransition!=`function`)return Me;let t=null,n=null,r=!1,i=()=>{t?.(),t=null},a=e.subscribeLeave(({signal:e})=>{if(!e.aborted)return r=!1,i(),new Promise(a=>{let o=new Promise(e=>{t=e});e.addEventListener(`abort`,()=>{r||(i(),n?.skipTransition?.(),a())},{once:!0});try{n=document.startViewTransition(()=>(a(),o))}catch{i(),a()}})}),o=e.subscribe(()=>{let e=t;r=!0,t=null,e===null?n=null:setTimeout(()=>{e(),n=null},0)});return{destroy:()=>{a(),o(),n?.skipTransition?.(),n=null,i()}}}function U(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}const Pe=/%[\dA-Fa-f]{2}/;function Fe(e){if(Pe.test(e))try{return encodeURI(decodeURIComponent(e)).replaceAll(`#`,`%23`)}catch{}return encodeURI(e).replaceAll(`#`,`%23`)}function Ie(e,t,n,r){try{let i=r?.hash,a;i!==void 0&&(a=i.startsWith(`#`)?i.slice(1):i);let o=e.buildUrl;if(o){let e=o(t,n,a===void 0?void 0:{hash:a});if(typeof e==`string`&&e.length>0)return e}let s=e.buildPath(t,n);if(typeof s!=`string`||s.length===0){console.error(`[real-router] Route "${t}" yielded an empty path. The element will render without an href attribute.`);return}return a?`${s}#${Fe(a)}`:s}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function Le(e,t,n,r,i){let a={...i};r!==void 0&&(a.hash=r);let o=e.getState();if(o?.name===t&&Ve(o.params,n)){let e=o.context?.url?.hash??``;e!==(r??e)&&(a.force=!0,a.hashChange=!0)}return e.navigate(t,n,a)}const Re=/\s/,ze=/\S+/g;function W(e){return e?Re.test(e)?e.match(ze)??[]:[e]:[]}function Be(e,t,n){if(e&&t){let e=W(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=W(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function Ve(e,t){if(Object.is(e,t))return!0;if(!e||!t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;let r=e,i=t;for(let e of n)if(!Object.prototype.hasOwnProperty.call(t,e)||!Object.is(r[e],i[e]))return!1;return!0}function He(e){if(!e)return;let t=e.tagName;t===`A`||t===`BUTTON`||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`))}function Ue(e,t){if(typeof e==`function`){e(t);return}if(Array.isArray(e)){let n=e;for(let e of n)if(typeof e==`function`&&(e(t),t.defaultPrevented))return}}const We=c({name:`Link`,inheritAttrs:!1,props:{routeName:{type:String,required:!0},routeParams:{type:Object,default:()=>ge},routeOptions:{type:Object,default:()=>I},class:{type:String,default:void 0},activeClassName:{type:String,default:`active`},activeStrict:{type:Boolean,default:!1},ignoreQueryParams:{type:Boolean,default:!0},target:{type:String,default:void 0},hash:{type:String,default:void 0}},setup(e,{slots:t,attrs:n}){let r=A(),i=h(!1);g(()=>[e.routeName,ee(e.routeParams),e.activeStrict,e.ignoreQueryParams,e.hash],([t,n,a,o,s],c,l)=>{let u=e.routeParams,d=te(r,t,u,s===void 0?{strict:a,ignoreQueryParams:o}:{strict:a,ignoreQueryParams:o,hash:s});i.value=d.getSnapshot(),l(d.subscribe(()=>{i.value=d.getSnapshot()}))},{immediate:!0,flush:`sync`});let a=s(()=>Ie(r,e.routeName,e.routeParams,e.hash===void 0?void 0:{hash:e.hash})),o=s(()=>Be(i.value,e.activeClassName,e.class)),c=t=>{n.onClick!==void 0&&n.onClick!==null&&(Ue(n.onClick,t),t.defaultPrevented)||!U(t)||e.target===`_blank`||(t.preventDefault(),Le(r,e.routeName,e.routeParams,e.hash,e.routeOptions).catch(()=>{}))};return()=>{let r={...n};return delete r.onClick,l(`a`,{...r,href:a.value,class:o.value,target:e.target,onClick:c},t.default?.())}}}),Ge=c({name:`RouterErrorBoundary`,props:{fallback:{type:Function,required:!0},onError:{type:Function,default:void 0}},setup(e,{slots:t}){let n=k(ne(A()));return g(()=>n.value.version,()=>{n.value.error&&e.onError?.(n.value.error,n.value.toRoute,n.value.fromRoute)},{immediate:!0}),()=>{let r=t.default?.()??[],a=n.value.error?e.fallback(n.value.error,n.value.resetError):null;return l(i,null,[...r,a])}}}),G=[];function K(e){return G.push(e),()=>{let t=G.lastIndexOf(e);t!==-1&&G.splice(t,1)}}function q(){let e=G.at(-1);if(!e)throw Error(`v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.`);return e}const J=new WeakMap;function Y(e){return e==null?(console.error(`[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.`),!1):typeof e.name==`string`?!0:(console.error("[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation."),!1)}function Ke(e,t){return n=>{U(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function qe(e,t,n){return r=>{r.key===`Enter`&&!(n instanceof HTMLButtonElement)&&e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{})}}function X(e,t,n){let r=Ke(t,n),i=qe(t,n,e);e.addEventListener(`click`,r),e.addEventListener(`keydown`,i),J.set(e,{click:r,keydown:i})}function Z(e){let t=J.get(e);t&&(e.removeEventListener(`click`,t.click),e.removeEventListener(`keydown`,t.keydown),J.delete(e))}const Je={mounted(e,t){let n=q();He(e),e.style.cursor=`pointer`,Y(t.value)&&X(e,n,t.value)},updated(e,t){if(t.value===t.oldValue)return;let n=q();Z(e),Y(t.value)&&X(e,n,t.value)},beforeUnmount(e){Z(e)}},Ye=()=>{let e=u(n);if(!e)throw Error(`useNavigator must be used within a RouterProvider`);return e},Xe=()=>y(ae(A()).getTree());function Ze(){return k(x(A()))}function Qe(e,t){let n=A(),r=t?.skipSameRoute??!0;p(n.subscribeLeave(({route:t,nextRoute:n,signal:i})=>{if(!(r&&t.name===n.name)&&!i.aborted)return e({route:t,nextRoute:n,signal:i})}))}function $e(e,t){let{route:n,previousRoute:i}=r(),a=t?.skipSameRoute??!0,o=null;g(n,t=>{let n=i.value;t.transition.from&&(a&&t.transition.from===t.name||o===t||!n||(o=t,e({route:t,previousRoute:n})))})}function Q(e){let t=v(e),n=ie(e),r=n.getSnapshot(),i=h(r.route),a=h(r.previousRoute);return{navigator:t,route:i,previousRoute:a,unsubscribe:n.subscribe(()=>{let e=n.getSnapshot();i.value=e.route,a.value=e.previousRoute})}}function et(r){return{install(i){let a=K(r),{navigator:o,route:s,previousRoute:c,unsubscribe:l}=Q(r);`onUnmount`in i&&i.onUnmount(()=>{a(),l()}),i.provide(e,r),i.provide(n,o),i.provide(t,{navigator:o,route:s,previousRoute:c})}}}function $(e,t){g(e,(e,n,r)=>{let i=t(e);i&&r(()=>{i.destroy()})},{immediate:!0})}const tt=c({name:`RouterProvider`,props:{router:{type:Object,required:!0},announceNavigation:{type:Boolean,default:!1},scrollRestoration:{type:Object},scrollSpy:{type:Object},viewTransitions:{type:Boolean,default:!1}},setup(r,{slots:i}){$(()=>[r.router,r.announceNavigation],([e,t])=>t?ve(e):void 0),$(()=>[r.router,r.scrollRestoration!==void 0,r.scrollRestoration?.mode,r.scrollRestoration?.anchorScrolling,r.scrollRestoration?.behavior,r.scrollRestoration?.storageKey],([e,t,n,i,a,o])=>{if(t)return Ce(e,{mode:n,anchorScrolling:i,behavior:a,storageKey:o,scrollContainer:r.scrollRestoration?.scrollContainer})}),$(()=>[r.router,r.scrollSpy!==void 0&&r.scrollSpy.selector!==``,r.scrollSpy?.selector,r.scrollSpy?.rootMargin],([e,t,n,i])=>{if(!(!t||!n))return je(e,{selector:n,rootMargin:i,scrollContainer:r.scrollSpy?.scrollContainer})}),$(()=>[r.router,r.viewTransitions],([e,t])=>t?Ne(e):void 0);let a=K(r.router),{navigator:o,route:s,previousRoute:c,unsubscribe:l}=Q(r.router);return p(()=>{a(),l()}),m(e,r.router),m(n,o),m(t,{navigator:o,route:s,previousRoute:c}),()=>i.default?.()}});export{We as Link,n as NavigatorKey,t as RouteKey,he as RouteView,Ge as RouterErrorBoundary,e as RouterKey,tt as RouterProvider,et as createRouterPlugin,Ye as useNavigator,r as useRoute,$e as useRouteEnter,Qe as useRouteExit,j as useRouteNode,Xe as useRouteUtils,A as useRouter,Ze as useRouterTransition,Je as vLink};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|