@storybook/tanstack-react 11.0.0-alpha.6 → 11.0.0-alpha.7

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.
@@ -12,6 +12,7 @@ __export(preview_exports, {
12
12
  applyDecorators: () => applyDecorators,
13
13
  beforeEach: () => beforeEach,
14
14
  loaders: () => loaders,
15
+ mount: () => mount,
15
16
  optimizeDeps: () => optimizeDeps,
16
17
  parameters: () => parameters
17
18
  });
@@ -188,9 +189,8 @@ function createStoryRouter({
188
189
  defaultNotFoundComponent(props) {
189
190
  return React.createElement("div", null, "Route not found: ", props.routeId);
190
191
  },
191
- defaultErrorComponent({ error }) {
192
- return React.createElement("div", null, "Story did something wrong : ", String(error));
193
- },
192
+ // Let render errors reach Storybook so it shows them and story tests fail.
193
+ disableGlobalCatchBoundary: !0,
194
194
  context: routerContext
195
195
  });
196
196
  }
@@ -263,30 +263,6 @@ function resolveTree(Story, context) {
263
263
  };
264
264
  }
265
265
 
266
- // src/routing/before-each.ts
267
- var storyRouters = /* @__PURE__ */ new Map(), routerBeforeEach = async (context) => {
268
- let cached = storyRouters.get(context.id);
269
- if (cached) {
270
- context.tanstackRouter = cached;
271
- return;
272
- }
273
- let storyContext = context, parameterContext = (context.parameters.tanstack?.router ?? {}).context, routerContext = typeof parameterContext == "function" ? parameterContext({ storyContext }) : parameterContext, router = createStoryRouter({
274
- Story: StoryFromContext,
275
- context: storyContext,
276
- routerContext
277
- }), load = router.load();
278
- if (context.abortSignal && !context.abortSignal.aborted ? (load.catch(() => {
279
- }), await Promise.race([
280
- load,
281
- new Promise(
282
- (resolve) => context.abortSignal.addEventListener("abort", () => resolve(), { once: !0 })
283
- )
284
- ])) : await load, !context.abortSignal?.aborted)
285
- return storyRouters.set(context.id, router), context.tanstackRouter = router, () => {
286
- storyRouters.delete(context.id);
287
- };
288
- };
289
-
290
266
  // src/routing/loader.ts
291
267
  import { RootRoute as RootRoute3 } from "@tanstack/react-router";
292
268
  function getComponentFromRoute(route) {
@@ -306,8 +282,43 @@ var routeComponentLoader = (context) => {
306
282
  }
307
283
  };
308
284
 
285
+ // src/routing/story-router.ts
286
+ import { mount as reactMount } from "@storybook/react/entry-preview";
287
+ var storyRouters = /* @__PURE__ */ new Map(), loadedRouters = /* @__PURE__ */ new WeakSet(), routerBeforeEach = (context) => {
288
+ let cached = storyRouters.get(context.id);
289
+ if (cached) {
290
+ context.tanstackRouter = cached;
291
+ return;
292
+ }
293
+ let storyContext = context, parameterContext = (context.parameters.tanstack?.router ?? {}).context, routerContext = typeof parameterContext == "function" ? parameterContext({ storyContext }) : parameterContext, router = createStoryRouter({
294
+ Story: StoryFromContext,
295
+ context: storyContext,
296
+ routerContext
297
+ });
298
+ return storyRouters.set(context.id, router), context.tanstackRouter = router, () => {
299
+ storyRouters.delete(context.id);
300
+ };
301
+ }, routerMount = (context) => async (...args) => {
302
+ let router = context.tanstackRouter;
303
+ if (router && !loadedRouters.has(router)) {
304
+ if (context.abortSignal?.aborted)
305
+ return context.canvas;
306
+ let load = router.load();
307
+ if (context.abortSignal ? (load.catch(() => {
308
+ }), await Promise.race([
309
+ load,
310
+ new Promise(
311
+ (resolve) => context.abortSignal.addEventListener("abort", () => resolve(), { once: !0 })
312
+ )
313
+ ])) : await load, context.abortSignal?.aborted)
314
+ return context.canvas;
315
+ loadedRouters.add(router);
316
+ }
317
+ return reactMount(context)(...args);
318
+ };
319
+
309
320
  // src/preview.tsx
310
- var loaders = [routeComponentLoader], beforeEach = [routerBeforeEach], applyDecorators = (storyFn, allDecorators) => (
321
+ var loaders = [routeComponentLoader], beforeEach = [routerBeforeEach], mount = routerMount, applyDecorators = (storyFn, allDecorators) => (
311
322
  // reorder decorators so `jsxDecorator` is innermost, and `tanstackRouteDecorator` is just outside it
312
323
  // There is an issue if `tanstackRouteDecorator` is innermost. All stories crashes due to a bug with the jsxDecorator.
313
324
  reactApplyDecorators(storyFn, [
@@ -325,6 +336,7 @@ var loaders = [routeComponentLoader], beforeEach = [routerBeforeEach], applyDeco
325
336
  export {
326
337
  loaders,
327
338
  beforeEach,
339
+ mount,
328
340
  applyDecorators,
329
341
  parameters,
330
342
  optimizeDeps,
@@ -102,7 +102,8 @@ interface RouterParameters<TRoute = undefined, Path extends (TRoute extends AnyR
102
102
  type FrameworkName = CompatibleString<'@storybook/tanstack-react'>;
103
103
  type BuilderName = CompatibleString<'@storybook/builder-vite'>;
104
104
  type FrameworkOptions = {
105
- /** Builder options passed through to @storybook/builder-vite. */builder?: BuilderOptions;
105
+ /** Builder options passed through to @storybook/builder-vite. */builder?: BuilderOptions; /** Render stories inside `React.StrictMode`. */
106
+ strictMode?: boolean;
106
107
  };
107
108
  type StorybookConfigFramework = {
108
109
  framework: FrameworkName | {
@@ -325,13 +325,16 @@ declare const useRouteContext: Mock<typeof useRouteContext$1>;
325
325
  declare const useCanGoBack: Mock<typeof useCanGoBack$1>;
326
326
  declare const useLinkProps: Mock<typeof useLinkProps$1>;
327
327
  declare const Navigate: typeof Navigate$1;
328
+ type LinkRenderState = {
329
+ isActive: boolean;
330
+ };
328
331
  declare const Link: ({
329
332
  to,
330
333
  children,
331
334
  ...props
332
335
  }: {
333
336
  to: string;
334
- children?: React.ReactNode;
337
+ children?: React.ReactNode | ((state: LinkRenderState) => React.ReactNode);
335
338
  [key: string]: unknown;
336
339
  }) => React.DetailedReactHTMLElement<{
337
340
  onClick: (e: React.MouseEvent) => void;
@@ -38,7 +38,7 @@ var useNavigate = fn(_useNavigate).mockName("@tanstack/react-router::useNavigate
38
38
  children,
39
39
  ...props
40
40
  }) => {
41
- let location = useLocation(), { onClick: _navigate, ...linkProps } = _useLinkProps({ to, ...props });
41
+ let location = useLocation(), { onClick: _navigate, ...linkProps } = _useLinkProps({ to, ...props }), resolvedChildren = typeof children == "function" ? children({ isActive: linkProps["data-status"] === "active" }) : children;
42
42
  return React.createElement(
43
43
  "a",
44
44
  {
@@ -47,7 +47,7 @@ var useNavigate = fn(_useNavigate).mockName("@tanstack/react-router::useNavigate
47
47
  e.preventDefault(), onNavigate({ to, from: location.href });
48
48
  }
49
49
  },
50
- children
50
+ resolvedChildren
51
51
  );
52
52
  };
53
53
  function createFileRoute(path) {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as TanStackPreviewOptions, c as IsRoute, d as StoryRouteOptions, i as TanStackParameters, l as RouterParameters, n as FrameworkOptions, o as TanStackTypes, r as StorybookConfig, s as CreateStoryRouteOptions, t as DefaultStoryPath, u as StoryRouteFileOptions } from "./chunk-7NHqRJ4O.js";
1
+ import { a as TanStackPreviewOptions, c as IsRoute, d as StoryRouteOptions, i as TanStackParameters, l as RouterParameters, n as FrameworkOptions, o as TanStackTypes, r as StorybookConfig, s as CreateStoryRouteOptions, t as DefaultStoryPath, u as StoryRouteFileOptions } from "./chunk-CCjcehAj.js";
2
2
  import { ComponentType } from "react";
3
3
  import { AddonTypes, InferTypes, MetaInput, MetaTypes, PreviewAddonEntry } from "storybook/internal/csf";
4
4
  import { Args, ArgsStoryFn, ComponentAnnotations, DecoratorFunction, Parameters, ProjectAnnotations, StoryAnnotations } from "storybook/internal/types";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  preview_exports
3
- } from "./_browser-chunks/chunk-O6D7CVOG.js";
3
+ } from "./_browser-chunks/chunk-TENGSR2C.js";
4
4
  import "./_browser-chunks/chunk-NGWBYAM4.js";
5
5
  import "./_browser-chunks/chunk-4BE7D4DS.js";
6
6
 
@@ -1,4 +1,4 @@
1
- import { r as StorybookConfig } from "../chunk-7NHqRJ4O.js";
1
+ import { r as StorybookConfig } from "../chunk-CCjcehAj.js";
2
2
 
3
3
  //#region code/frameworks/tanstack-react/.dts-emit/code/frameworks/tanstack-react/src/node/index.d.ts
4
4
  declare function defineMain(config: StorybookConfig): StorybookConfig;
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_gyp5bmiktk from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_gyp5bmiktk from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_gyp5bmiktk from "node:module";
1
+ import CJS_COMPAT_NODE_URL_0cuxg6ixjttb from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_0cuxg6ixjttb from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_0cuxg6ixjttb from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_gyp5bmiktk.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_gyp5bmiktk.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_gyp5bmiktk.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_0cuxg6ixjttb.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_0cuxg6ixjttb.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_0cuxg6ixjttb.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
package/dist/preset.js CHANGED
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_gyp5bmiktk from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_gyp5bmiktk from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_gyp5bmiktk from "node:module";
1
+ import CJS_COMPAT_NODE_URL_0cuxg6ixjttb from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_0cuxg6ixjttb from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_0cuxg6ixjttb from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_gyp5bmiktk.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_gyp5bmiktk.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_gyp5bmiktk.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_0cuxg6ixjttb.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_0cuxg6ixjttb.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_0cuxg6ixjttb.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
package/dist/preview.d.ts CHANGED
@@ -1,12 +1,13 @@
1
- import { i as TanStackParameters } from "./chunk-7NHqRJ4O.js";
1
+ import { i as TanStackParameters } from "./chunk-CCjcehAj.js";
2
2
  import { BeforeEach, DecoratorFunction, LoaderFunction, Renderer } from "storybook/internal/types";
3
3
  import { applyDecorators as applyDecorators$1 } from "@storybook/react/entry-preview-docs";
4
4
 
5
5
  //#region code/frameworks/tanstack-react/.dts-emit/code/frameworks/tanstack-react/src/preview.d.ts
6
6
  declare const loaders: LoaderFunction<Renderer>[];
7
7
  declare const beforeEach: BeforeEach<Renderer>[];
8
+ declare const mount: ((context: import("storybook/internal/types").StoryContext<import("@storybook/react").ReactRenderer, import("@storybook/react").Args>) => (ui?: import("react").JSX.Element) => Promise<import("storybook/internal/types").Canvas>) | undefined;
8
9
  declare const applyDecorators: (storyFn: Parameters<typeof applyDecorators$1>[0], allDecorators: DecoratorFunction[]) => any;
9
10
  declare const parameters: TanStackParameters;
10
11
  declare const optimizeDeps: string[];
11
12
  //#endregion
12
- export { applyDecorators, beforeEach, loaders, optimizeDeps, parameters };
13
+ export { applyDecorators, beforeEach, loaders, mount, optimizeDeps, parameters };
package/dist/preview.js CHANGED
@@ -2,15 +2,17 @@ import {
2
2
  applyDecorators,
3
3
  beforeEach,
4
4
  loaders,
5
+ mount,
5
6
  optimizeDeps,
6
7
  parameters
7
- } from "./_browser-chunks/chunk-O6D7CVOG.js";
8
+ } from "./_browser-chunks/chunk-TENGSR2C.js";
8
9
  import "./_browser-chunks/chunk-NGWBYAM4.js";
9
10
  import "./_browser-chunks/chunk-4BE7D4DS.js";
10
11
  export {
11
12
  applyDecorators,
12
13
  beforeEach,
13
14
  loaders,
15
+ mount,
14
16
  optimizeDeps,
15
17
  parameters
16
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/tanstack-react",
3
- "version": "11.0.0-alpha.6",
3
+ "version": "11.0.0-alpha.7",
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": "11.0.0-alpha.6",
79
- "@storybook/react": "11.0.0-alpha.6",
80
- "@storybook/react-vite": "11.0.0-alpha.6"
78
+ "@storybook/builder-vite": "11.0.0-alpha.7",
79
+ "@storybook/react": "11.0.0-alpha.7",
80
+ "@storybook/react-vite": "11.0.0-alpha.7"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@tanstack/react-router": "^1.168.10",
@@ -95,7 +95,7 @@
95
95
  "@tanstack/start-client-core": "^1.167.9",
96
96
  "react": "^18.0.0 || ^19.0.0",
97
97
  "react-dom": "^18.0.0 || ^19.0.0",
98
- "storybook": "^11.0.0-alpha.6",
98
+ "storybook": "^11.0.0-alpha.7",
99
99
  "vite": "^6.3.0 || ^7.0.0 || ^8.0.0"
100
100
  },
101
101
  "peerDependenciesMeta": {
@@ -0,0 +1,72 @@
1
+ import React from 'react';
2
+
3
+ import type { Meta, StoryObj } from '@storybook/tanstack-react';
4
+
5
+ import { expect, within } from 'storybook/test';
6
+
7
+ let mockedUser = 'unmocked';
8
+ const beforeLoadCalls: string[] = [];
9
+
10
+ function BeforeLoadViewer() {
11
+ return <p data-testid="before-load-user">{beforeLoadCalls.join(',') || 'missing'}</p>;
12
+ }
13
+
14
+ const meta = {
15
+ component: BeforeLoadViewer,
16
+ parameters: {
17
+ tanstack: {
18
+ router: {
19
+ route: {
20
+ beforeLoad: () => {
21
+ beforeLoadCalls.push(mockedUser);
22
+ },
23
+ },
24
+ },
25
+ },
26
+ },
27
+ beforeEach: () => {
28
+ mockedUser = 'from-beforeEach';
29
+ return () => {
30
+ mockedUser = 'unmocked';
31
+ beforeLoadCalls.length = 0;
32
+ };
33
+ },
34
+ } satisfies Meta<typeof BeforeLoadViewer>;
35
+
36
+ export default meta;
37
+
38
+ type Story = StoryObj<typeof meta>;
39
+
40
+ /** Route `beforeLoad` runs after the story's `beforeEach`, so it sees its mocks. */
41
+ export const BeforeLoadSeesBeforeEach: Story = {
42
+ play: async ({ canvasElement }) => {
43
+ const canvas = within(canvasElement);
44
+ await expect(canvas.getByTestId('before-load-user')).toHaveTextContent('from-beforeEach');
45
+ await expect(beforeLoadCalls.length).toBeGreaterThan(0);
46
+ await expect(beforeLoadCalls.every((call) => call === 'from-beforeEach')).toBe(true);
47
+ },
48
+ };
49
+
50
+ /** Route `beforeLoad` runs when `play` calls `mount`, so it sees mocks set up in `play`. */
51
+ export const BeforeLoadSeesPlayBeforeMount: Story = {
52
+ play: async ({ mount }) => {
53
+ mockedUser = 'from-play';
54
+ const canvas = await mount();
55
+ await expect(canvas.getByTestId('before-load-user')).toHaveTextContent('from-play');
56
+ await expect(beforeLoadCalls.length).toBeGreaterThan(0);
57
+ await expect(beforeLoadCalls.every((call) => call === 'from-play')).toBe(true);
58
+ },
59
+ };
60
+
61
+ let routerStatusInBeforeEach = 'unset';
62
+
63
+ /** The story router exists in the story's `beforeEach`, before its initial load. */
64
+ export const RouterAvailableInBeforeEach: Story = {
65
+ beforeEach: (context) => {
66
+ const router = (context as any).tanstackRouter;
67
+ routerStatusInBeforeEach = router ? router.state.status : 'missing';
68
+ },
69
+ play: async () => {
70
+ await expect(routerStatusInBeforeEach).toBe('idle');
71
+ },
72
+ };