@octanejs/tanstack-router 0.2.9 → 0.3.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 +23 -7
- package/package.json +4 -3
- package/src/Asset.tsrx +1 -1
- package/src/Await.tsrx +1 -1
- package/src/CatchBoundary.tsrx +11 -41
- package/src/ClientOnly.tsrx +1 -1
- package/src/ErrorComponent.tsrx +38 -0
- package/src/HeadContent.tsrx +4 -2
- package/src/Link.tsrx +3 -1
- package/src/Link.tsrx.d.ts +3 -0
- package/src/Match.tsrx +3 -3
- package/src/MatchRoute.tsrx +5 -5
- package/src/Matches.tsrx +6 -19
- package/src/Navigate.tsrx +1 -1
- package/src/Outlet.tsrx +2 -2
- package/src/RouteNotFound.tsrx +1 -1
- package/src/RouterProvider.tsrx +1 -1
- package/src/ScriptOnce.tsrx +14 -15
- package/src/Scripts.tsrx +1 -1
- package/src/ScrollRestoration.tsrx +1 -1
- package/src/Transitioner.tsrx +80 -62
- package/src/assetComponent.tsrx +1 -1
- package/src/compiled/Document.tsrx +2 -0
- package/src/compiled/Link.tsrx +1 -3
- package/src/compiled/Matches.tsrx +128 -120
- package/src/compiled/RouterProvider.tsrx +27 -0
- package/src/compiled.ts +6 -3
- package/src/core.ts +8 -0
- package/src/externalHydration.ts +2 -2
- package/src/fileRoute.ts +1 -1
- package/src/headContentBinding.ts +10 -15
- package/src/history.ts +16 -8
- package/src/historyState.ts +37 -0
- package/src/hookBindings.ts +2 -0
- package/src/index.ts +4 -4
- package/src/{link.ts → linkApi.ts} +1 -3
- package/src/linkBinding.ts +14 -10
- package/src/linkComponent.tsrx +3 -3
- package/src/not-found.tsrx +4 -4
- package/src/route.ts +2 -1
- package/src/router.ts +5 -0
- package/src/routerStateBinding.ts +2 -0
- package/src/scriptComponent.tsrx +22 -15
- package/src/scroll-restoration.tsrx +1 -1
- package/src/ssr/RouterClient.tsrx +1 -1
- package/src/ssr/renderRouterToStream.ts +13 -4
- package/src/useBlocker.tsrx +1 -1
- package/src/useStore.ts +2 -0
package/src/not-found.tsrx
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
import { isNotFound } from '@tanstack/router-core';
|
|
7
7
|
import type { ErrorComponentProps, NotFoundError } from '@tanstack/router-core';
|
|
8
8
|
import type { OctaneNode } from 'octane';
|
|
9
|
-
import type { ErrorInfo } from './route
|
|
10
|
-
import { useRouter } from './context
|
|
11
|
-
import { useStore } from './useStore
|
|
9
|
+
import type { ErrorInfo } from './route';
|
|
10
|
+
import { useRouter } from './context';
|
|
11
|
+
import { useStore } from './useStore';
|
|
12
12
|
import { CatchBoundary } from './CatchBoundary.tsrx';
|
|
13
13
|
|
|
14
14
|
function NotFoundFallback(props: {
|
|
15
15
|
error: unknown;
|
|
16
|
-
render?: (error: NotFoundError) => OctaneNode;
|
|
16
|
+
render?: ((error: NotFoundError) => OctaneNode) | undefined;
|
|
17
17
|
}) {
|
|
18
18
|
if (isNotFound(props.error)) {
|
|
19
19
|
return props.render ? props.render(props.error) : null;
|
package/src/route.ts
CHANGED
|
@@ -637,7 +637,8 @@ export class RouteApi<TId, TRouter extends AnyRouter = RegisteredRouter> extends
|
|
|
637
637
|
}) as unknown as typeof this.Link;
|
|
638
638
|
}
|
|
639
639
|
|
|
640
|
-
notFound = (opts?: NotFoundError) =>
|
|
640
|
+
override notFound = (opts?: NotFoundError) =>
|
|
641
|
+
notFound({ routeId: this.id, ...opts } as NotFoundError);
|
|
641
642
|
}
|
|
642
643
|
|
|
643
644
|
export function getRouteApi<const TId, TRouter extends AnyRouter = RegisteredRouter>(
|
package/src/router.ts
CHANGED
|
@@ -11,7 +11,9 @@ import {
|
|
|
11
11
|
createNonReactiveMutableStore,
|
|
12
12
|
createNonReactiveReadonlyStore,
|
|
13
13
|
} from '@tanstack/router-core';
|
|
14
|
+
import { isServer } from '@tanstack/router-core/isServer';
|
|
14
15
|
import { createAtom, batch } from '@tanstack/store';
|
|
16
|
+
import { prepareInitialHistoryState } from './historyState';
|
|
15
17
|
import type { RouterHistory } from '@tanstack/history';
|
|
16
18
|
import type {
|
|
17
19
|
AnyRoute,
|
|
@@ -73,6 +75,9 @@ export class Router<
|
|
|
73
75
|
// render-readiness boundary and the previous view-transition/load wrapper is
|
|
74
76
|
// no longer needed. HTTP status is derived on demand by the SSR layer
|
|
75
77
|
// (`getSsrStatus`), not stored on the router.
|
|
78
|
+
if (!options.history && !(isServer ?? options.isServer ?? isServerEnv)) {
|
|
79
|
+
prepareInitialHistoryState();
|
|
80
|
+
}
|
|
76
81
|
super(options, octaneStoreFactory);
|
|
77
82
|
}
|
|
78
83
|
}
|
package/src/scriptComponent.tsrx
CHANGED
|
@@ -1,26 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
'use strong';
|
|
2
|
+
|
|
3
|
+
import { trustHTML, useId } from 'octane';
|
|
2
4
|
import type { RouterManagedTag } from '@tanstack/router-core';
|
|
3
|
-
import { getAssetKeys } from './assetKeys
|
|
5
|
+
import { getAssetKeys } from './assetKeys';
|
|
6
|
+
|
|
7
|
+
function scriptAttributes(attrs: RouterManagedTag['attrs']) {
|
|
8
|
+
if (!attrs || !Object.prototype.hasOwnProperty.call(attrs, '__executeOnMount')) return attrs;
|
|
9
|
+
const { __executeOnMount: _compilerMetadata, ...attributes } = attrs;
|
|
10
|
+
return attributes;
|
|
11
|
+
}
|
|
4
12
|
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
13
|
+
// A direct host row leaves no item frame behind when router-core's transport
|
|
14
|
+
// scripts remove themselves before hydration.
|
|
15
|
+
// External scripts follow dynamic-insertion loading rules: neither array order
|
|
16
|
+
// nor a defer attribute serializes their execution after client navigation.
|
|
9
17
|
export function createScripts(useScripts: () => Array<RouterManagedTag>) {
|
|
10
18
|
function Scripts() @{
|
|
11
19
|
const owner = useId();
|
|
12
20
|
const scripts = useScripts();
|
|
13
21
|
const keys = getAssetKeys('body', owner, scripts);
|
|
14
22
|
<>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
key
|
|
20
|
-
'
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
})}
|
|
23
|
+
@for (const script of scripts; index position; key keys[position]!.assetKey) {
|
|
24
|
+
<script
|
|
25
|
+
{...scriptAttributes(script.attrs)}
|
|
26
|
+
__executeOnMount
|
|
27
|
+
data-tsr-managed-key={keys[position]!.managedKey}
|
|
28
|
+
dangerouslySetInnerHTML={trustHTML(script.children ?? '')}
|
|
29
|
+
/>
|
|
30
|
+
}
|
|
24
31
|
</>
|
|
25
32
|
}
|
|
26
33
|
return Scripts;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// server's script.
|
|
8
8
|
import { getScrollRestorationScriptForRouter } from '@tanstack/router-core/scroll-restoration-script';
|
|
9
9
|
import type { AnyRouter } from '@tanstack/router-core';
|
|
10
|
-
import { useRouter } from './context
|
|
10
|
+
import { useRouter } from './context';
|
|
11
11
|
import { ScriptOnce } from './ScriptOnce.tsrx';
|
|
12
12
|
|
|
13
13
|
function rendersScript(router: AnyRouter): boolean {
|
|
@@ -2,7 +2,7 @@ import { use } from 'octane';
|
|
|
2
2
|
import { hydrate } from '@tanstack/router-core/ssr/client';
|
|
3
3
|
import type { AnyRouter } from '@tanstack/router-core';
|
|
4
4
|
import { RouterProvider } from '../RouterProvider.tsrx';
|
|
5
|
-
import { toExternalHydrationThenable } from '../externalHydration
|
|
5
|
+
import { toExternalHydrationThenable } from '../externalHydration';
|
|
6
6
|
|
|
7
7
|
const hydrationPromises = new WeakMap<AnyRouter, PromiseLike<void>>();
|
|
8
8
|
const ready = {
|
|
@@ -95,9 +95,13 @@ export async function renderRouterToStream({
|
|
|
95
95
|
// transform does). So, for a document render, fold the leading style run into the
|
|
96
96
|
// shell `<head>` and prepend the doctype — what octane's native-injection
|
|
97
97
|
// document mode (and, before it, an explicit relocate transform) used to do. Only
|
|
98
|
-
// the
|
|
99
|
-
//
|
|
100
|
-
//
|
|
98
|
+
// the styles move: the comment naming octane's hydration protocol stays before
|
|
99
|
+
// `<html>`, where hydrateRoot reads it. Only the shell prefix (through `</head>`)
|
|
100
|
+
// is buffered; everything after streams straight through, preserving
|
|
101
|
+
// out-of-order boundary flushing. A non-document render (no `</head>`) passes
|
|
102
|
+
// through unchanged.
|
|
103
|
+
const LEADING_STYLE = /<style\b[\s\S]*?<\/style>/gi;
|
|
104
|
+
|
|
101
105
|
export function finalizeDocumentShell(
|
|
102
106
|
source: ReadableStream<Uint8Array>,
|
|
103
107
|
): ReadableStream<Uint8Array> {
|
|
@@ -131,9 +135,14 @@ export function finalizeDocumentShell(
|
|
|
131
135
|
if (htmlStart >= 0) {
|
|
132
136
|
if (htmlStart > 0) {
|
|
133
137
|
const leading = prefix.slice(0, htmlStart);
|
|
138
|
+
const styles = leading.match(LEADING_STYLE) ?? [];
|
|
134
139
|
const doc = prefix.slice(htmlStart);
|
|
135
140
|
const headClose = doc.indexOf('</head>');
|
|
136
|
-
prefix =
|
|
141
|
+
prefix =
|
|
142
|
+
leading.replace(LEADING_STYLE, '') +
|
|
143
|
+
doc.slice(0, headClose) +
|
|
144
|
+
styles.join('') +
|
|
145
|
+
doc.slice(headClose);
|
|
137
146
|
}
|
|
138
147
|
if (!/^\s*<!doctype/i.test(prefix)) prefix = '<!DOCTYPE html>' + prefix;
|
|
139
148
|
}
|
package/src/useBlocker.tsrx
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { useState, useEffect, isChildrenBlock } from 'octane';
|
|
10
10
|
import type { OctaneNode } from 'octane';
|
|
11
11
|
import type { BlockerFnArgs, HistoryAction, HistoryLocation } from '@tanstack/history';
|
|
12
|
-
import { useRouter } from './context
|
|
12
|
+
import { useRouter } from './context';
|
|
13
13
|
|
|
14
14
|
// Blocker types, ported from react-router's useBlocker.tsx. Upstream derives the
|
|
15
15
|
// location shapes from the registered route tree's generics; the octane binding's
|
package/src/useStore.ts
CHANGED