@storybook/tanstack-react 10.6.0-alpha.0 → 10.6.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_browser-chunks/{chunk-WQHJSC2D.js → chunk-4W5ZAMIP.js} +45 -8
- package/dist/_browser-chunks/{chunk-XKNIZ3MM.js → chunk-LTDGLEVR.js} +9 -1
- package/dist/chunk-B2-fTWlC.d.ts +131 -0
- package/dist/export-mocks/react-router.d.ts +294 -291
- package/dist/export-mocks/react-router.js +16 -12
- package/dist/export-mocks/start-storage-context.d.ts +12 -10
- package/dist/export-mocks/start.d.ts +61 -49
- package/dist/export-mocks/start.js +3 -2
- package/dist/index.d.ts +54 -186
- package/dist/index.js +2 -2
- package/dist/node/index.d.ts +4 -26
- package/dist/node/index.js +6 -6
- package/dist/preset.d.ts +5 -4
- package/dist/preset.js +16 -7
- package/dist/preview.d.ts +6 -106
- package/dist/preview.js +2 -2
- package/package.json +6 -6
- package/template/stories/PathlessLayout.stories.tsx +150 -0
package/dist/preset.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { PresetProperty } from
|
|
2
|
-
import { StorybookConfigVite } from
|
|
1
|
+
import { PresetProperty } from "storybook/internal/types";
|
|
2
|
+
import { StorybookConfigVite } from "@storybook/builder-vite";
|
|
3
3
|
|
|
4
|
+
//#region code/frameworks/tanstack-react/.dts-emit/code/frameworks/tanstack-react/src/preset.d.ts
|
|
4
5
|
declare const core: PresetProperty<'core'>;
|
|
5
6
|
declare const previewAnnotations: PresetProperty<'previewAnnotations'>;
|
|
6
7
|
declare const optimizeViteDeps: string[];
|
|
7
8
|
declare const viteFinal: StorybookConfigVite['viteFinal'];
|
|
8
|
-
|
|
9
|
-
export { core, optimizeViteDeps, previewAnnotations, viteFinal };
|
|
9
|
+
//#endregion
|
|
10
|
+
export { core, optimizeViteDeps, previewAnnotations, viteFinal };
|
package/dist/preset.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import CJS_COMPAT_NODE_URL_unqn55oi61 from 'node:url';
|
|
2
|
+
import CJS_COMPAT_NODE_PATH_unqn55oi61 from 'node:path';
|
|
3
|
+
import CJS_COMPAT_NODE_MODULE_unqn55oi61 from "node:module";
|
|
4
4
|
|
|
5
|
-
var __filename =
|
|
6
|
-
var __dirname =
|
|
7
|
-
var require =
|
|
5
|
+
var __filename = CJS_COMPAT_NODE_URL_unqn55oi61.fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = CJS_COMPAT_NODE_PATH_unqn55oi61.dirname(__filename);
|
|
7
|
+
var require = CJS_COMPAT_NODE_MODULE_unqn55oi61.createRequire(import.meta.url);
|
|
8
8
|
|
|
9
9
|
// ------------------------------------------------------------
|
|
10
10
|
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
|
|
@@ -31,7 +31,7 @@ var dirname = function(p) {
|
|
|
31
31
|
import { viteFinal as reactViteFinal } from "@storybook/react-vite/preset";
|
|
32
32
|
|
|
33
33
|
// src/plugins/server-code-elimination.ts
|
|
34
|
-
import {
|
|
34
|
+
import { types as t, transformSync } from "storybook/internal/babel";
|
|
35
35
|
var SERVER_FN_RE = /\bcreateServerFn\b/, MIDDLEWARE_RE = /\bcreateMiddleware\b/, ISOMORPHIC_FN_RE = /\bcreateIsomorphicFn\b/, SERVER_ONLY_FN_RE = /\bcreateServerOnlyFn\b/, CLIENT_ONLY_FN_RE = /\bcreateClientOnlyFn\b/, ROUTE_FACTORY_RE = /\b(createFileRoute|createRootRoute|createRootRouteWithContext|createRoute)\b/, ROUTE_FACTORIES = /* @__PURE__ */ new Set([
|
|
36
36
|
"createFileRoute",
|
|
37
37
|
"createRootRoute",
|
|
@@ -215,12 +215,21 @@ function stripServerOption(options) {
|
|
|
215
215
|
return (t.isIdentifier(key) ? key.name : void 0) !== "server";
|
|
216
216
|
}), options.properties.length !== initialLength;
|
|
217
217
|
}
|
|
218
|
+
function getJsxRootIdentifier(name) {
|
|
219
|
+
for (; t.isJSXMemberExpression(name); )
|
|
220
|
+
name = name.object;
|
|
221
|
+
return t.isJSXIdentifier(name) ? name : null;
|
|
222
|
+
}
|
|
218
223
|
function collectReferencedIdentifiers(programPath) {
|
|
219
224
|
let referenced = /* @__PURE__ */ new Set();
|
|
220
225
|
return programPath.traverse({
|
|
221
226
|
enter(path2) {
|
|
222
227
|
let { node } = path2;
|
|
223
228
|
!t.isIdentifier(node) || path2.isBindingIdentifier() || path2.findParent((p) => p.isImportDeclaration()) || referenced.add(node.name);
|
|
229
|
+
},
|
|
230
|
+
JSXOpeningElement(path2) {
|
|
231
|
+
let root = getJsxRootIdentifier(path2.node.name);
|
|
232
|
+
root && referenced.add(root.name);
|
|
224
233
|
}
|
|
225
234
|
}), referenced;
|
|
226
235
|
}
|
package/dist/preview.d.ts
CHANGED
|
@@ -1,111 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { RoutesByPath, RouteOptions, ResolveParams, AnyContext } from '@tanstack/router-core';
|
|
5
|
-
import { Decorator } from '@storybook/react';
|
|
6
|
-
|
|
7
|
-
/** Union of every registered full path (e.g. `'/' | '/admin/users' | '/$libraryId/$version'`). */
|
|
8
|
-
type RegisteredFullPath = keyof Register['router']['routesByPath'];
|
|
9
|
-
type IsAppRouteTree<TRoute> = TRoute extends Register['router']['routeTree'] ? true : false;
|
|
10
|
-
type IsRoute<T> = T extends AnyRoute ? true : T extends FileRoutesByPath[keyof FileRoutesByPath] ? true : false;
|
|
11
|
-
type ExtractAllPathsFromFileRoutes<TRoute extends FileRoutesByPath[keyof FileRoutesByPath]['preLoaderRoute'] | AnyRoute> = TRoute['path'];
|
|
12
|
-
type StoryRoutePath<TRoute = undefined> = TRoute extends FileRoutesByPath[keyof FileRoutesByPath] ? ExtractAllPathsFromFileRoutes<TRoute> : keyof FileRoutesByPath | `/${string}`;
|
|
13
|
-
type StoryRouteSearch<TRoute> = IsAppRouteTree<TRoute> extends true ? Record<string, unknown> : TRoute extends FileRoutesByPath[keyof FileRoutesByPath] ? TRoute['preLoaderRoute'] extends {
|
|
14
|
-
types: {
|
|
15
|
-
allSearch: infer A;
|
|
16
|
-
};
|
|
17
|
-
} ? A : never : Record<string, unknown>;
|
|
18
|
-
type StoryRouteFileOptions<TRoute = undefined> = IsRoute<TRoute> extends true ? TRoute extends {
|
|
19
|
-
options: infer O;
|
|
20
|
-
} ? Pick<O, Extract<keyof O, 'loader' | 'beforeLoad' | 'validateSearch' | 'loaderDeps' | 'context' | 'params' | 'head' | 'search' | 'parseParams' | 'context'>> : Pick<RouteOptions<unknown>, 'loader' | 'beforeLoad' | 'validateSearch' | 'loaderDeps' | 'context' | 'params' | 'head' | 'search' | 'parseParams' | 'context'> : Pick<RouteOptions<unknown>, 'loader' | 'beforeLoad' | 'validateSearch' | 'loaderDeps' | 'context' | 'params' | 'head' | 'search' | 'parseParams' | 'context'>;
|
|
21
|
-
type CreateStoryRouteOptions<TRoute = undefined> = StoryRouteFileOptions<TRoute> & {
|
|
22
|
-
path?: StoryRoutePath<TRoute>;
|
|
23
|
-
};
|
|
24
|
-
type StoryRouteOptions<TRoute = undefined> = CreateStoryRouteOptions<TRoute> | (TRoute extends AnyRoute ? TRoute : AnyRoute);
|
|
25
|
-
/**
|
|
26
|
-
* Per-route override options for use inside `RouteTreeOverrides`.
|
|
27
|
-
* Users can override `loader`, `beforeLoad`, etc. for a specific route.
|
|
28
|
-
*/
|
|
29
|
-
interface RouteOverrideOptions<TRoute extends FileRoutesByPath[keyof FileRoutesByPath]['preLoaderRoute'] | undefined = undefined> {
|
|
30
|
-
/** Override the route's loader function. */
|
|
31
|
-
loader?: TRoute extends FileRoutesByPath[keyof FileRoutesByPath]['preLoaderRoute'] ? TRoute['options']['loader'] | ((ctx: unknown) => Promise<unknown> | unknown) : (ctx: unknown) => Promise<unknown> | unknown;
|
|
32
|
-
/** Override the route's beforeLoad function. */
|
|
33
|
-
beforeLoad?: TRoute extends FileRoutesByPath[keyof FileRoutesByPath]['preLoaderRoute'] ? TRoute['options']['beforeLoad'] | ((ctx: unknown) => Promise<void> | void) : (ctx: unknown) => Promise<void> | void;
|
|
34
|
-
/** Override the route's search params validation. */
|
|
35
|
-
validateSearch?: TRoute extends FileRoutesByPath[keyof FileRoutesByPath]['preLoaderRoute'] ? TRoute['options']['validateSearch'] | ((search: unknown) => Promise<void> | void) : (search: unknown) => Promise<void> | void;
|
|
36
|
-
/** Override the route's loader dependencies. */
|
|
37
|
-
loaderDeps?: TRoute extends FileRoutesByPath[keyof FileRoutesByPath]['preLoaderRoute'] ? TRoute['options']['loaderDeps'] | string[] : string[];
|
|
38
|
-
/** Override the route's context function. */
|
|
39
|
-
context?: TRoute extends FileRoutesByPath[keyof FileRoutesByPath]['preLoaderRoute'] ? TRoute['options']['context'] | ((ctx: unknown) => Promise<unknown> | unknown) : (ctx: unknown) => Promise<unknown> | unknown;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* A map of route overrides keyed by route ID.
|
|
43
|
-
* Each entry can override `loader`, `beforeLoad`, etc. for that route.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```ts
|
|
47
|
-
* routeOverrides: {
|
|
48
|
-
* '/_authed': { beforeLoad: () => {} },
|
|
49
|
-
* '/demo/form/simple/$id': {
|
|
50
|
-
* loader: async () => ({ name: 'Mock User' }),
|
|
51
|
-
* },
|
|
52
|
-
* }
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
type RouteTreeOverrides = Partial<{
|
|
56
|
-
[routePath in keyof FileRoutesByPath]: RouteOverrideOptions<FileRoutesByPath[routePath]['preLoaderRoute']> | undefined;
|
|
57
|
-
}>;
|
|
58
|
-
interface RouterParameters<TRoute = undefined, Path extends TRoute extends AnyRoute ? keyof RoutesByPath<TRoute> : RegisteredFullPath = TRoute extends AnyRoute ? keyof RoutesByPath<TRoute> : keyof FileRoutesByPath> {
|
|
59
|
-
route?: StoryRouteOptions<TRoute>;
|
|
60
|
-
/**
|
|
61
|
-
* Path to resolve the story route against.
|
|
62
|
-
* Constrained to known registered paths in route tree mode, but can be any string in app route mode (since the user may be passing a custom `route` that doesn't exist in the registered tree).
|
|
63
|
-
*/
|
|
64
|
-
path?: Path;
|
|
65
|
-
/** URL params to interpolate into the path (e.g. `{ id: '42' }` for `/$id`). */
|
|
66
|
-
params?: ResolveParams<Path>;
|
|
67
|
-
/** Search/query params to append to the URL (e.g. `{ tab: 'details' }`). */
|
|
68
|
-
query?: Partial<StoryRouteSearch<TRoute>>;
|
|
69
|
-
/**
|
|
70
|
-
* Override options for specific routes in the app route tree (route tree mode only).
|
|
71
|
-
*
|
|
72
|
-
* Each key is a route ID (e.g. `'/about'`, `'__root__'`, `'/demo/form/simple/$id'`).
|
|
73
|
-
* Values can override `loader`, `beforeLoad`, etc. for that route.
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```ts
|
|
77
|
-
* routeOverrides: {
|
|
78
|
-
* '/_authed': { beforeLoad: () => {} },
|
|
79
|
-
* '/demo/form/simple/$id': {
|
|
80
|
-
* loader: async () => ({ name: 'Mock User' }),
|
|
81
|
-
* },
|
|
82
|
-
* }
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
routeOverrides?: RouteTreeOverrides;
|
|
86
|
-
context?: Record<string, unknown>;
|
|
87
|
-
/**
|
|
88
|
-
*
|
|
89
|
-
*/
|
|
90
|
-
useRouterContext?: ({ storyContext }: {
|
|
91
|
-
storyContext: Parameters<Decorator>[1];
|
|
92
|
-
}) => AnyContext;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** Path constraint mirroring `RouterParameters`'s second generic. */
|
|
96
|
-
type DefaultStoryPath<TRoute> = TRoute extends AnyRoute ? keyof RoutesByPath<TRoute> : RegisteredFullPath;
|
|
97
|
-
interface TanStackPreviewOptions<TRoute = undefined, Path extends DefaultStoryPath<TRoute> = DefaultStoryPath<TRoute>> {
|
|
98
|
-
/** Router configuration for stories */
|
|
99
|
-
router?: RouterParameters<TRoute, Path>;
|
|
100
|
-
}
|
|
101
|
-
interface TanStackParameters<TRoute = undefined, Path extends DefaultStoryPath<TRoute> = DefaultStoryPath<TRoute>> {
|
|
102
|
-
/** TanStack framework configuration (router integration). */
|
|
103
|
-
tanstack?: TanStackPreviewOptions<TRoute, Path>;
|
|
104
|
-
}
|
|
1
|
+
import { i as TanStackParameters } from "./chunk-B2-fTWlC.js";
|
|
2
|
+
import { DecoratorFunction, LoaderFunction, Renderer } from "storybook/internal/types";
|
|
3
|
+
import { applyDecorators as applyDecorators$1 } from "@storybook/react/entry-preview-docs";
|
|
105
4
|
|
|
5
|
+
//#region code/frameworks/tanstack-react/.dts-emit/code/frameworks/tanstack-react/src/preview.d.ts
|
|
106
6
|
declare const loaders: LoaderFunction<Renderer>[];
|
|
107
7
|
declare const applyDecorators: (storyFn: Parameters<typeof applyDecorators$1>[0], allDecorators: DecoratorFunction[]) => any;
|
|
108
8
|
declare const parameters: TanStackParameters;
|
|
109
9
|
declare const optimizeDeps: string[];
|
|
110
|
-
|
|
111
|
-
export { applyDecorators, loaders, optimizeDeps, parameters };
|
|
10
|
+
//#endregion
|
|
11
|
+
export { applyDecorators, loaders, optimizeDeps, parameters };
|
package/dist/preview.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
loaders,
|
|
4
4
|
optimizeDeps,
|
|
5
5
|
parameters
|
|
6
|
-
} from "./_browser-chunks/chunk-
|
|
7
|
-
import "./_browser-chunks/chunk-
|
|
6
|
+
} from "./_browser-chunks/chunk-4W5ZAMIP.js";
|
|
7
|
+
import "./_browser-chunks/chunk-LTDGLEVR.js";
|
|
8
8
|
import "./_browser-chunks/chunk-4BE7D4DS.js";
|
|
9
9
|
export {
|
|
10
10
|
applyDecorators,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/tanstack-react",
|
|
3
|
-
"version": "10.6.0-alpha.
|
|
3
|
+
"version": "10.6.0-alpha.1",
|
|
4
4
|
"description": "Storybook for TanStack (React, Vite): Router and Start ready Storybook framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"storybook",
|
|
@@ -75,9 +75,9 @@
|
|
|
75
75
|
"!src/**/*"
|
|
76
76
|
],
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@storybook/builder-vite": "10.6.0-alpha.
|
|
79
|
-
"@storybook/react": "10.6.0-alpha.
|
|
80
|
-
"@storybook/react-vite": "10.6.0-alpha.
|
|
78
|
+
"@storybook/builder-vite": "10.6.0-alpha.1",
|
|
79
|
+
"@storybook/react": "10.6.0-alpha.1",
|
|
80
|
+
"@storybook/react-vite": "10.6.0-alpha.1"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@tanstack/react-router": "^1.168.10",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"@tanstack/router-core": "^1.168.9",
|
|
86
86
|
"@tanstack/start-client-core": "^1.167.9",
|
|
87
87
|
"@types/node": "^22.19.1",
|
|
88
|
-
"typescript": "^
|
|
88
|
+
"typescript": "^6.0.3",
|
|
89
89
|
"vite": "^7.0.4"
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"@tanstack/start-client-core": "^1.167.9",
|
|
96
96
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
97
97
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
98
|
-
"storybook": "^10.6.0-alpha.
|
|
98
|
+
"storybook": "^10.6.0-alpha.1",
|
|
99
99
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
100
100
|
},
|
|
101
101
|
"peerDependenciesMeta": {
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/tanstack-react';
|
|
4
|
+
|
|
5
|
+
import { Outlet, createRootRoute, createRoute } from '@tanstack/react-router';
|
|
6
|
+
import { expect, fn, within } from 'storybook/test';
|
|
7
|
+
|
|
8
|
+
// Regression coverage for pathless layout routes (`_authed`-style underscore
|
|
9
|
+
// files and `(group)` directories). The layout must render and its
|
|
10
|
+
// `beforeLoad` must run, while contributing nothing to the URL: the story
|
|
11
|
+
// mounts at `/dashboard`, not `/_authed/dashboard`.
|
|
12
|
+
|
|
13
|
+
function LeafContent() {
|
|
14
|
+
return <p data-testid="pathless-leaf">leaf rendered under a pathless layout</p>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const onBeforeLoad = fn();
|
|
18
|
+
|
|
19
|
+
const RootRoute = createRootRoute({
|
|
20
|
+
component: () => (
|
|
21
|
+
<div data-testid="pathless-root">
|
|
22
|
+
<h1>root layout</h1>
|
|
23
|
+
<Outlet />
|
|
24
|
+
</div>
|
|
25
|
+
),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const PathlessLayout = createRoute({
|
|
29
|
+
id: 'authed',
|
|
30
|
+
getParentRoute: () => RootRoute,
|
|
31
|
+
beforeLoad: onBeforeLoad,
|
|
32
|
+
component: () => (
|
|
33
|
+
<section data-testid="pathless-layout">
|
|
34
|
+
<Outlet />
|
|
35
|
+
</section>
|
|
36
|
+
),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const DashboardRoute = createRoute({
|
|
40
|
+
path: '/dashboard',
|
|
41
|
+
getParentRoute: () => PathlessLayout,
|
|
42
|
+
component: LeafContent,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
PathlessLayout.addChildren([DashboardRoute]);
|
|
46
|
+
|
|
47
|
+
// Regression coverage for a pathless layout nested under a pathful ancestor
|
|
48
|
+
// (e.g. `/products/_authed`): the layout's mount URL must be inferred from
|
|
49
|
+
// its pathful ancestor, not just '/'.
|
|
50
|
+
|
|
51
|
+
const onNestedBeforeLoad = fn();
|
|
52
|
+
|
|
53
|
+
function ProductsLayout() {
|
|
54
|
+
return (
|
|
55
|
+
<div data-testid="products-layout">
|
|
56
|
+
<Outlet />
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const ProductsRoute = createRoute({
|
|
62
|
+
path: '/products',
|
|
63
|
+
getParentRoute: () => RootRoute,
|
|
64
|
+
component: ProductsLayout,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const NestedPathlessLayout = createRoute({
|
|
68
|
+
id: 'nested-authed',
|
|
69
|
+
getParentRoute: () => ProductsRoute,
|
|
70
|
+
beforeLoad: onNestedBeforeLoad,
|
|
71
|
+
component: () => (
|
|
72
|
+
<section data-testid="nested-pathless-layout">
|
|
73
|
+
<Outlet />
|
|
74
|
+
</section>
|
|
75
|
+
),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const NestedSettingsRoute = createRoute({
|
|
79
|
+
path: '/settings',
|
|
80
|
+
getParentRoute: () => NestedPathlessLayout,
|
|
81
|
+
component: LeafContent,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
NestedPathlessLayout.addChildren([NestedSettingsRoute]);
|
|
85
|
+
ProductsRoute.addChildren([NestedPathlessLayout]);
|
|
86
|
+
|
|
87
|
+
// A single `addChildren` call per parent: it replaces (not appends to) the
|
|
88
|
+
// children array, so `RootRoute`'s two top-level branches must be registered
|
|
89
|
+
// together.
|
|
90
|
+
RootRoute.addChildren([PathlessLayout, ProductsRoute]);
|
|
91
|
+
|
|
92
|
+
const meta = {
|
|
93
|
+
component: LeafContent,
|
|
94
|
+
parameters: { layout: 'fullscreen' },
|
|
95
|
+
} satisfies Meta<typeof LeafContent>;
|
|
96
|
+
|
|
97
|
+
export default meta;
|
|
98
|
+
|
|
99
|
+
type Story = StoryObj<typeof meta>;
|
|
100
|
+
|
|
101
|
+
/** The leaf mounts at the layout-free URL, with every ancestor layout rendered. */
|
|
102
|
+
export const RendersLeafThroughPathlessLayout: Story = {
|
|
103
|
+
parameters: {
|
|
104
|
+
tanstack: { router: { route: DashboardRoute, path: '/dashboard' } },
|
|
105
|
+
},
|
|
106
|
+
play: async ({ canvasElement }) => {
|
|
107
|
+
const canvas = within(canvasElement);
|
|
108
|
+
await expect(canvas.getByTestId('pathless-root')).toBeInTheDocument();
|
|
109
|
+
await expect(canvas.getByTestId('pathless-layout')).toBeInTheDocument();
|
|
110
|
+
await expect(canvas.getByTestId('pathless-leaf')).toBeInTheDocument();
|
|
111
|
+
await expect(onBeforeLoad).toHaveBeenCalled();
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/** Binding the layout route itself (no path) mounts the story at the layout's position. */
|
|
116
|
+
export const BoundDirectlyToPathlessLayout: Story = {
|
|
117
|
+
parameters: {
|
|
118
|
+
tanstack: { router: { route: PathlessLayout } },
|
|
119
|
+
},
|
|
120
|
+
play: async ({ canvasElement }) => {
|
|
121
|
+
const canvas = within(canvasElement);
|
|
122
|
+
// injectStoryComponent replaces the layout's own `component` with the
|
|
123
|
+
// story's render (LeafContent), so `pathless-layout` itself is gone —
|
|
124
|
+
// assert the root layout plus the leaf content that now renders in its place.
|
|
125
|
+
await expect(canvas.getByTestId('pathless-root')).toBeInTheDocument();
|
|
126
|
+
await expect(canvas.getByTestId('pathless-leaf')).toBeInTheDocument();
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A pathless layout nested under a pathful ancestor (`/products`). Binding
|
|
132
|
+
* the story directly to the nested layout must mount it at `/products`
|
|
133
|
+
* (inferred from the ancestor's path), with the root and the `/products`
|
|
134
|
+
* ancestor both rendered around the story's own content.
|
|
135
|
+
*/
|
|
136
|
+
export const BoundDirectlyToNestedPathlessLayout: Story = {
|
|
137
|
+
parameters: {
|
|
138
|
+
tanstack: { router: { route: NestedPathlessLayout } },
|
|
139
|
+
},
|
|
140
|
+
play: async ({ canvasElement }) => {
|
|
141
|
+
const canvas = within(canvasElement);
|
|
142
|
+
await expect(canvas.getByTestId('pathless-root')).toBeInTheDocument();
|
|
143
|
+
await expect(canvas.getByTestId('products-layout')).toBeInTheDocument();
|
|
144
|
+
// injectStoryComponent replaces the nested layout's own `component`, so
|
|
145
|
+
// `nested-pathless-layout` itself is gone — assert the leaf content that
|
|
146
|
+
// now renders in its place instead.
|
|
147
|
+
await expect(canvas.getByTestId('pathless-leaf')).toBeInTheDocument();
|
|
148
|
+
await expect(onNestedBeforeLoad).toHaveBeenCalled();
|
|
149
|
+
},
|
|
150
|
+
};
|