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

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_reum8t9ydbr from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_reum8t9ydbr from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_reum8t9ydbr 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_reum8t9ydbr.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_reum8t9ydbr.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_reum8t9ydbr.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_reum8t9ydbr from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_reum8t9ydbr from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_reum8t9ydbr 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_reum8t9ydbr.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_reum8t9ydbr.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_reum8t9ydbr.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -20,7 +20,7 @@ var _lazyMatch = () => {
20
20
  var m = Object.defineProperty, V = Object.getOwnPropertyDescriptor, G = Object.getOwnPropertyNames, T = Object.prototype.hasOwnProperty, q = (r, e) => {
21
21
  for (var n in e) m(r, n, { get: e[n], enumerable: !0 });
22
22
  }, H = (r, e, n, a) => {
23
- if (e && typeof e == "object" || typeof e == "function") for (let t3 of G(e)) !T.call(r, t3) && t3 !== n && m(r, t3, { get: () => e[t3], enumerable: !(a = V(e, t3)) || a.enumerable });
23
+ if (e && typeof e == "object" || typeof e == "function") for (let t of G(e)) !T.call(r, t) && t !== n && m(r, t, { get: () => e[t], enumerable: !(a = V(e, t)) || a.enumerable });
24
24
  return r;
25
25
  }, J = (r) => H(m({}, "__esModule", { value: !0 }), r), w = {};
26
26
  q(w, { default: () => re });
@@ -29,8 +29,8 @@ var _lazyMatch = () => {
29
29
  return (n) => {
30
30
  let a = e.get(n);
31
31
  if (a) return a;
32
- let t3 = r(n);
33
- return e.set(n, t3), t3;
32
+ let t = r(n);
33
+ return e.set(n, t), t;
34
34
  };
35
35
  }, rr = (r, e, n = {}) => {
36
36
  let a = { cache: {}, input: r, index: 0, indexMax: 0, options: n, output: [] };
@@ -40,16 +40,16 @@ var _lazyMatch = () => {
40
40
  let n = {};
41
41
  for (let a of r) {
42
42
  if (a.length !== 1) throw new Error(`Invalid character: "${a}"`);
43
- let t3 = a.charCodeAt(0);
44
- n[t3] = !0;
43
+ let t = a.charCodeAt(0);
44
+ n[t] = !0;
45
45
  }
46
46
  return (a) => {
47
- let t3 = a.index, o = a.input;
47
+ let t = a.index, o = a.input;
48
48
  for (; a.index < o.length && o.charCodeAt(a.index) in n; ) a.index += 1;
49
49
  let u = a.index;
50
- if (u > t3) {
50
+ if (u > t) {
51
51
  if (!h(e) && !a.options.silent) {
52
- let s = a.input.slice(t3, u), c = d(e) ? e(s, o, String(t3)) : e;
52
+ let s = a.input.slice(t, u), c = d(e) ? e(s, o, String(t)) : e;
53
53
  h(c) || a.output.push(c);
54
54
  }
55
55
  a.indexMax = Math.max(a.indexMax, a.index);
@@ -57,10 +57,10 @@ var _lazyMatch = () => {
57
57
  return !0;
58
58
  };
59
59
  }, nr = (r, e) => {
60
- let n = r.source, a = r.flags.replace(/y|$/, "y"), t3 = new RegExp(n, a);
60
+ let n = r.source, a = r.flags.replace(/y|$/, "y"), t = new RegExp(n, a);
61
61
  return g((o) => {
62
- t3.lastIndex = o.index;
63
- let u = t3.exec(o.input);
62
+ t.lastIndex = o.index;
63
+ let u = t.exec(o.input);
64
64
  if (u) {
65
65
  if (!h(e) && !o.options.silent) {
66
66
  let s = d(e) ? e(...u, o.input, String(o.index)) : e;
@@ -72,56 +72,56 @@ var _lazyMatch = () => {
72
72
  }, ar = (r, e) => (n) => {
73
73
  if (n.input.startsWith(r, n.index)) {
74
74
  if (!h(e) && !n.options.silent) {
75
- let t3 = d(e) ? e(r, n.input, String(n.index)) : e;
76
- h(t3) || n.output.push(t3);
75
+ let t = d(e) ? e(r, n.input, String(n.index)) : e;
76
+ h(t) || n.output.push(t);
77
77
  }
78
78
  return n.index += r.length, n.indexMax = Math.max(n.indexMax, n.index), !0;
79
79
  } else return !1;
80
80
  }, C = (r, e, n, a) => {
81
- let t3 = v(r);
81
+ let t = v(r);
82
82
  return g(_(M((o) => {
83
83
  let u = 0;
84
84
  for (; u < n; ) {
85
85
  let s = o.index;
86
- if (!t3(o) || (u += 1, o.index === s)) break;
86
+ if (!t(o) || (u += 1, o.index === s)) break;
87
87
  }
88
88
  return u >= e;
89
89
  })));
90
90
  }, tr = (r, e) => C(r, 0, 1), f = (r, e) => C(r, 0, 1 / 0), x = (r, e) => {
91
91
  let n = r.map(v);
92
92
  return g(_(M((a) => {
93
- for (let t3 = 0, o = n.length; t3 < o; t3++) if (!n[t3](a)) return !1;
93
+ for (let t = 0, o = n.length; t < o; t++) if (!n[t](a)) return !1;
94
94
  return !0;
95
95
  })));
96
96
  }, l = (r, e) => {
97
97
  let n = r.map(v);
98
98
  return g(_((a) => {
99
- for (let t3 = 0, o = n.length; t3 < o; t3++) if (n[t3](a)) return !0;
99
+ for (let t = 0, o = n.length; t < o; t++) if (n[t](a)) return !0;
100
100
  return !1;
101
101
  }));
102
102
  }, M = (r, e = !1) => {
103
103
  let n = v(r);
104
104
  return (a) => {
105
- let t3 = a.index, o = a.output.length, u = n(a);
106
- return (!u || e) && (a.index = t3, a.output.length !== o && (a.output.length = o)), u;
105
+ let t = a.index, o = a.output.length, u = n(a);
106
+ return (!u || e) && (a.index = t, a.output.length !== o && (a.output.length = o)), u;
107
107
  };
108
108
  }, _ = (r, e) => v(r), g = /* @__PURE__ */ (() => {
109
109
  let r = 0;
110
110
  return (e) => {
111
111
  let n = v(e), a = r += 1;
112
- return (t3) => {
112
+ return (t) => {
113
113
  var o;
114
- if (t3.options.memoization === !1) return n(t3);
115
- let u = t3.index, s = (o = t3.cache)[a] || (o[a] = /* @__PURE__ */ new Map()), c = s.get(u);
114
+ if (t.options.memoization === !1) return n(t);
115
+ let u = t.index, s = (o = t.cache)[a] || (o[a] = /* @__PURE__ */ new Map()), c = s.get(u);
116
116
  if (c === !1) return !1;
117
- if (W(c)) return t3.index = c, !0;
118
- if (c) return t3.index = c.index, c.output?.length && t3.output.push(...c.output), !0;
117
+ if (W(c)) return t.index = c, !0;
118
+ if (c) return t.index = c.index, c.output?.length && t.output.push(...c.output), !0;
119
119
  {
120
- let Z = t3.output.length;
121
- if (n(t3)) {
122
- let D = t3.index, U = t3.output.length;
120
+ let Z = t.output.length;
121
+ if (n(t)) {
122
+ let D = t.index, U = t.output.length;
123
123
  if (U > Z) {
124
- let ee = t3.output.slice(Z, U);
124
+ let ee = t.output.slice(Z, U);
125
125
  s.set(u, { index: D, output: ee });
126
126
  } else s.set(u, D);
127
127
  return !0;
@@ -160,7 +160,7 @@ var _lazyMatch = () => {
160
160
  }, sr = i(/^\*\*\/\*$/, ".*"), cr = i(/^\*\*\/(\*)?([ a-zA-Z0-9._-]+)$/, (r, e, n) => `.*${e ? "" : "(?:^|/)"}${n.replaceAll(".", "\\.")}`), lr = i(/^\*\*\/(\*)?([ a-zA-Z0-9._-]*)\{([ a-zA-Z0-9._-]+(?:,[ a-zA-Z0-9._-]+)*)\}$/, (r, e, n, a) => `.*${e ? "" : "(?:^|/)"}${n.replaceAll(".", "\\.")}(?:${a.replaceAll(",", "|").replaceAll(".", "\\.")})`), y = i(/\\./, p), pr = i(/[$.*+?^(){}[\]\|]/, (r) => `\\${r}`), vr = i(/./, p), hr = i(/^(?:!!)*!(.*)$/, (r, e) => `(?!^${L(e)}$).*?`), dr = i(/^(!!)+/, ""), fr = l([hr, dr]), xr = i(/\/(\*\*\/)+/, "(?:/.+/|/)"), gr = i(/^(\*\*\/)+/, "(?:^|.*/)"), mr = i(/\/(\*\*)$/, "(?:/.*|$)"), _r = i(/\*\*/, ".*"), j = l([xr, gr, mr, _r]), Sr = i(/\*\/(?!\*\*\/)/, "[^/]*/"), yr = i(/\*/, "[^/]*"), N = l([Sr, yr]), k = i("?", "[^/]"), $r = i("[", p), wr = i("]", p), Ar = i(/[!^]/, "^/"), br = i(/[a-z]-[a-z]|[0-9]-[0-9]/i, p), Cr = i(/[$.*+?^(){}[\|]/, (r) => `\\${r}`), Mr = i(/[^\]]/, p), Er = l([y, Cr, br, Mr]), B = x([$r, tr(Ar), f(Er), wr]), Pr = i("{", "(?:"), Or = i("}", ")"), Rr = i(/(\d+)\.\.(\d+)/, (r, e, n) => or(+e, +n, Math.min(e.length, n.length)).join("|")), zr = i(/([a-z]+)\.\.([a-z]+)/, (r, e, n) => R(e, n).join("|")), jr = i(/([A-Z]+)\.\.([A-Z]+)/, (r, e, n) => R(e.toLowerCase(), n.toLowerCase()).join("|").toUpperCase()), Nr = l([Rr, zr, jr]), I = x([Pr, Nr, Or]), kr = i("{", "(?:"), Br = i("}", ")"), Ir = i(",", "|"), Fr = i(/[$.*+?^(){[\]\|]/, (r) => `\\${r}`), Lr = i(/[^}]/, p), Zr = E(() => F), Dr = l([j, N, k, B, I, Zr, y, Fr, Ir, Lr]), F = x([kr, f(Dr), Br]), Ur = f(l([sr, cr, lr, fr, j, N, k, B, I, F, y, pr, vr])), Vr = Ur, Gr = z(Vr), L = Gr, Tr = i(/\\./, p), qr = i(/./, p), Hr = i(/\*\*\*+/, "*"), Jr = i(/([^/{[(!])\*\*/, (r, e) => `${e}*`), Qr = i(/(^|.)\*\*(?=[^*/)\]}])/, (r, e) => `${e}*`), Wr = f(l([Tr, Hr, Jr, Qr, qr])), Kr = Wr, Xr = z(Kr), Yr = Xr, $ = (r, e) => {
161
161
  let n = Array.isArray(r) ? r : [r];
162
162
  if (!n.length) return !1;
163
- let a = n.map($.compile), t3 = n.every((s) => /(\/(?:\*\*)?|\[\/\])$/.test(s)), o = e.replace(/[\\\/]+/g, "/").replace(/\/$/, t3 ? "/" : "");
163
+ let a = n.map($.compile), t = n.every((s) => /(\/(?:\*\*)?|\[\/\])$/.test(s)), o = e.replace(/[\\\/]+/g, "/").replace(/\/$/, t ? "/" : "");
164
164
  return a.some((s) => s.test(o));
165
165
  };
166
166
  $.compile = (r) => new RegExp(`^${L(Yr(r))}$`, "s");
@@ -367,7 +367,10 @@ function moduleInterceptionPlugin({
367
367
  }
368
368
 
369
369
  // src/plugins/server-code-elimination.ts
370
- import { types as t, transformSync } from "storybook/internal/babel";
370
+ import {
371
+ SourceEditor,
372
+ walk
373
+ } from "storybook/internal/csf-tools";
371
374
  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([
372
375
  "createFileRoute",
373
376
  "createRootRoute",
@@ -392,114 +395,114 @@ function serverCodeEliminationPlugin(options = {}) {
392
395
  async handler(code, id) {
393
396
  if (!/\.[mc]?[jt]sx?$/.test(id) || excludeFiles.some((excluded) => id.includes(excluded)) || !ANY_PATTERN_RE.test(code))
394
397
  return null;
395
- let state = { code, modified: !1, needsFnImport: !1 }, result = transformSync(code, {
396
- filename: id,
397
- sourceType: "module",
398
- parserOpts: {
399
- plugins: ["typescript", "jsx"]
400
- },
401
- plugins: [() => serverCodeElimination(state)],
402
- sourceMaps: !0,
403
- configFile: !1,
404
- babelrc: !1
405
- });
406
- return !state.modified || !result?.code ? null : {
407
- code: result.code,
408
- map: result.map
409
- };
398
+ let editor = new SourceEditor(code, id);
399
+ return eliminateServerCode(editor) ? { code: editor.toString(), map: editor.generateMap({ source: id }).toString() } : null;
410
400
  }
411
401
  }
412
402
  };
413
403
  }
414
- function serverCodeElimination(state) {
415
- function sbFnCall() {
416
- return state.needsFnImport = !0, buildFnCall();
417
- }
418
- function sbFnCallWithImpl(impl) {
419
- return state.needsFnImport = !0, buildFnCallWithImpl(impl);
420
- }
421
- return {
422
- visitor: {
423
- Program(programPath) {
424
- let tanstackImports = collectTanstackImports(programPath.node.body), resolves = (name, factory) => resolvesToFactory(tanstackImports, name, factory);
425
- programPath.traverse({
426
- CallExpression(path) {
427
- let node = path.node;
428
- if (ROUTE_FACTORY_RE.test(state.code)) {
429
- let routeOptionsArg = getRouteFactoryOptionsArg(node, tanstackImports);
430
- routeOptionsArg && stripServerOption(routeOptionsArg) && (state.modified = !0);
431
- }
432
- if (t.isIdentifier(node.callee) && resolves(node.callee.name, "createServerOnlyFn") && SERVER_ONLY_FN_RE.test(state.code)) {
433
- path.replaceWith(sbFnCall()), state.modified = !0;
434
- return;
435
- }
436
- if (t.isIdentifier(node.callee) && resolves(node.callee.name, "createClientOnlyFn") && CLIENT_ONLY_FN_RE.test(state.code)) {
437
- let innerFn = node.arguments[0];
438
- innerFn && t.isExpression(innerFn) && (path.replaceWith(sbFnCallWithImpl(innerFn)), state.modified = !0);
439
- return;
440
- }
441
- let methodName = getMethodName(node);
442
- if (!methodName)
443
- return;
444
- let root = findChainRoot(node);
445
- if (root) {
446
- if (methodName === "handler" && resolves(root.rootName, "createServerFn") && SERVER_FN_RE.test(state.code)) {
447
- let handlerArg = node.arguments[0];
448
- if (handlerArg) {
449
- if (t.isIdentifier(handlerArg)) {
450
- let binding = path.scope.getBinding(handlerArg.name);
451
- binding && binding.referencePaths.length === 1 && binding.path.remove();
452
- }
453
- node.arguments[0] = sbFnCall();
454
- }
455
- state.modified = !0;
456
- return;
457
- }
458
- if (resolves(root.rootName, "createMiddleware") && MIDDLEWARE_RE.test(state.code)) {
459
- (methodName === "server" || methodName === "inputValidator") && t.isMemberExpression(path.node.callee) && (path.replaceWith(path.node.callee.object), state.modified = !0);
460
- return;
461
- }
462
- if (resolves(root.rootName, "createIsomorphicFn") && ISOMORPHIC_FN_RE.test(state.code)) {
463
- if (methodName === "client") {
464
- let innerFn = node.arguments[0];
465
- innerFn && t.isExpression(innerFn) && (path.replaceWith(sbFnCallWithImpl(innerFn)), state.modified = !0);
466
- return;
467
- }
468
- if (methodName === "server") {
469
- let parent = path.parent;
470
- (!t.isMemberExpression(parent) || !t.isCallExpression(path.parentPath?.parent)) && (path.replaceWith(sbFnCall()), state.modified = !0);
471
- }
472
- return;
473
- }
474
- }
475
- }
476
- }), state.modified && (state.needsFnImport && programPath.node.body.unshift(buildFnImport()), eliminateDeadImports(programPath));
404
+ var FN_IMPORT = 'import { fn as __sb_fn } from "storybook/test";';
405
+ function eliminateServerCode(editor) {
406
+ let { code, program, edits } = editor, tanstackImports = collectTanstackImports(program), resolves = (name, factory) => resolvesToFactory(tanstackImports, name, factory), removed = [], isGone = (node) => removed.some((span) => span.start <= node.start && node.end <= span.end), replace = (span, text) => {
407
+ edits.overwrite(span.start, span.end, text), removed.push(span);
408
+ }, remove = (span) => {
409
+ span.end > span.start && (edits.remove(span.start, span.end), removed.push(span));
410
+ }, modified = !1, needsFnImport = !1, fnCall = (span) => {
411
+ needsFnImport = !0, replace(span, "__sb_fn()");
412
+ }, fnCallWithImpl = (call, impl) => {
413
+ needsFnImport = !0, replace({ start: call.start, end: impl.start }, "__sb_fn("), replace({ start: impl.end, end: call.end }, ")");
414
+ };
415
+ if (walk(program, (node, parent) => {
416
+ if (isGone(node))
417
+ return !1;
418
+ if (node.type !== "CallExpression")
419
+ return;
420
+ if (ROUTE_FACTORY_RE.test(code)) {
421
+ let routeOptionsArg = getRouteFactoryOptionsArg(node, tanstackImports);
422
+ if (routeOptionsArg) {
423
+ let serverOptions = routeOptionsArg.properties.filter(isServerOption);
424
+ serverOptions.forEach(
425
+ (option) => remove(listItemRange(routeOptionsArg.properties, option))
426
+ ), modified ||= serverOptions.length > 0;
477
427
  }
478
428
  }
479
- };
480
- }
481
- function buildFnImport() {
482
- return t.importDeclaration(
483
- [t.importSpecifier(t.identifier("__sb_fn"), t.identifier("fn"))],
484
- t.stringLiteral("storybook/test")
485
- );
429
+ if (node.callee.type === "Identifier" && resolves(node.callee.name, "createServerOnlyFn") && SERVER_ONLY_FN_RE.test(code))
430
+ return fnCall(node), modified = !0, !1;
431
+ if (node.callee.type === "Identifier" && resolves(node.callee.name, "createClientOnlyFn") && CLIENT_ONLY_FN_RE.test(code)) {
432
+ let innerFn = node.arguments[0];
433
+ innerFn && innerFn.type !== "SpreadElement" && (fnCallWithImpl(node, innerFn), modified = !0);
434
+ return;
435
+ }
436
+ let methodName = getMethodName(node);
437
+ if (!methodName)
438
+ return;
439
+ let root = findChainRoot(node);
440
+ if (root) {
441
+ if (methodName === "handler" && resolves(root.rootName, "createServerFn") && SERVER_FN_RE.test(code)) {
442
+ let handlerArg = node.arguments[0];
443
+ handlerArg && (handlerArg.type === "Identifier" && removeSingleUseDeclaration(editor, editor.scopes.bindingOf(handlerArg), remove), fnCall(handlerArg)), modified = !0;
444
+ return;
445
+ }
446
+ if (resolves(root.rootName, "createMiddleware") && MIDDLEWARE_RE.test(code)) {
447
+ (methodName === "server" || methodName === "inputValidator") && node.callee.type === "MemberExpression" && (remove({ start: node.callee.object.end, end: node.end }), modified = !0);
448
+ return;
449
+ }
450
+ if (resolves(root.rootName, "createIsomorphicFn") && ISOMORPHIC_FN_RE.test(code)) {
451
+ if (methodName === "client") {
452
+ let innerFn = node.arguments[0];
453
+ innerFn && innerFn.type !== "SpreadElement" && (fnCallWithImpl(node, innerFn), modified = !0);
454
+ return;
455
+ }
456
+ if (methodName === "server") {
457
+ let grandparent = parent && editor.parentOf(parent);
458
+ if (parent?.type !== "MemberExpression" || grandparent?.type !== "CallExpression")
459
+ return fnCall(node), modified = !0, !1;
460
+ }
461
+ }
462
+ }
463
+ }), !modified)
464
+ return !1;
465
+ if (needsFnImport) {
466
+ let at = program.body.filter(
467
+ (statement) => statement.type === "ExpressionStatement" && statement.directive
468
+ ).at(-1)?.end ?? (code.startsWith("#!") ? code.indexOf(`
469
+ `) + 1 : 0);
470
+ edits.appendLeft(at, `${at > 0 ? `
471
+ ` : ""}${FN_IMPORT}
472
+ `);
473
+ }
474
+ return eliminateDeadCode(editor, isGone, remove), !0;
486
475
  }
487
- function buildFnCall() {
488
- return t.callExpression(t.identifier("__sb_fn"), []);
476
+ function listItemRange(items, item) {
477
+ let index = items.indexOf(item), next = items[index + 1], previous = items[index - 1];
478
+ return next ? { start: item.start, end: next.start } : previous ? { start: previous.end, end: item.end } : item;
489
479
  }
490
- function buildFnCallWithImpl(impl) {
491
- return t.callExpression(t.identifier("__sb_fn"), [impl]);
480
+ function removeSingleUseDeclaration(editor, binding, remove) {
481
+ if (!binding || binding.references.length !== 1)
482
+ return;
483
+ if (binding.kind === "function" || binding.kind === "class") {
484
+ remove(binding.node);
485
+ return;
486
+ }
487
+ let declaration = binding.declaration;
488
+ if (!(!["var", "let", "const"].includes(binding.kind) || binding.node.type !== "VariableDeclarator" || !declaration)) {
489
+ if (declaration.declarations.length === 1) {
490
+ editor.parentOf(declaration)?.type !== "ExportNamedDeclaration" && remove(declaration);
491
+ return;
492
+ }
493
+ remove(listItemRange(declaration.declarations, binding.node));
494
+ }
492
495
  }
493
- function collectTanstackImports(body) {
496
+ function collectTanstackImports(program) {
494
497
  let imports = /* @__PURE__ */ new Map();
495
- for (let node of body) {
496
- if (!t.isImportDeclaration(node))
498
+ for (let node of program.body) {
499
+ if (node.type !== "ImportDeclaration")
497
500
  continue;
498
501
  let src = node.source.value;
499
502
  if (!(!src.includes("@tanstack/") && !src.includes("export-mocks") && !src.includes("@storybook/tanstack-react"))) {
500
503
  for (let spec of node.specifiers)
501
- if (t.isImportSpecifier(spec)) {
502
- let importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
504
+ if (spec.type === "ImportSpecifier") {
505
+ let importedName = spec.imported.type === "Identifier" ? spec.imported.name : String(spec.imported.value);
503
506
  imports.set(spec.local.name, importedName);
504
507
  }
505
508
  }
@@ -513,9 +516,9 @@ function findChainRoot(node) {
513
516
  let current = node;
514
517
  for (; ; ) {
515
518
  let callee = current.callee;
516
- if (t.isIdentifier(callee))
519
+ if (callee.type === "Identifier")
517
520
  return { rootCall: current, rootName: callee.name };
518
- if (t.isMemberExpression(callee) && t.isCallExpression(callee.object)) {
521
+ if (callee.type === "MemberExpression" && callee.object.type === "CallExpression") {
519
522
  current = callee.object;
520
523
  continue;
521
524
  }
@@ -523,90 +526,99 @@ function findChainRoot(node) {
523
526
  }
524
527
  }
525
528
  function getMethodName(node) {
526
- return t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.property) ? node.callee.property.name : null;
529
+ return node.callee.type === "MemberExpression" && node.callee.property.type === "Identifier" ? node.callee.property.name : null;
527
530
  }
528
531
  function getRouteFactoryOptionsArg(node, imports) {
529
532
  if (!getRouteFactoryName(node, imports))
530
533
  return null;
531
534
  let optionsArg = node.arguments[0];
532
- return t.isObjectExpression(optionsArg) ? optionsArg : null;
535
+ return optionsArg?.type === "ObjectExpression" ? optionsArg : null;
533
536
  }
534
537
  function getRouteFactoryName(node, imports) {
535
- if (t.isIdentifier(node.callee)) {
538
+ if (node.callee.type === "Identifier") {
536
539
  let resolved = imports.get(node.callee.name) ?? node.callee.name;
537
540
  return ROUTE_FACTORIES.has(resolved) ? resolved : null;
538
541
  }
539
- if (t.isCallExpression(node.callee) && t.isIdentifier(node.callee.callee)) {
542
+ if (node.callee.type === "CallExpression" && node.callee.callee.type === "Identifier") {
540
543
  let calleeName = node.callee.callee.name, resolved = imports.get(calleeName) ?? calleeName;
541
544
  return ROUTE_FACTORIES.has(resolved) ? resolved : null;
542
545
  }
543
546
  return null;
544
547
  }
545
- function stripServerOption(options) {
546
- let initialLength = options.properties.length;
547
- return options.properties = options.properties.filter((prop) => {
548
- if (!t.isObjectProperty(prop) || prop.computed)
549
- return !0;
550
- let key = prop.key;
551
- return (t.isIdentifier(key) ? key.name : void 0) !== "server";
552
- }), options.properties.length !== initialLength;
548
+ function isServerOption(prop) {
549
+ return prop.type === "Property" && !prop.method && prop.kind === "init" && !prop.computed && prop.key.type === "Identifier" && prop.key.name === "server";
553
550
  }
554
- function getJsxRootIdentifier(name) {
555
- for (; t.isJSXMemberExpression(name); )
556
- name = name.object;
557
- return t.isJSXIdentifier(name) ? name : null;
551
+ function isPure(node, scopes) {
552
+ if (!node)
553
+ return !0;
554
+ switch (node.type) {
555
+ case "Identifier":
556
+ return scopes.program.bindings.has(node.name);
557
+ case "Literal":
558
+ case "ThisExpression":
559
+ case "MetaProperty":
560
+ case "FunctionExpression":
561
+ case "ArrowFunctionExpression":
562
+ return !0;
563
+ case "ClassExpression":
564
+ return (node.decorators?.length ?? 0) === 0 && isPure(node.superClass, scopes) && node.body.body.every((member) => isPure(member, scopes));
565
+ case "MethodDefinition":
566
+ return (!node.computed || isPure(node.key, scopes)) && (node.decorators?.length ?? 0) === 0;
567
+ case "PropertyDefinition":
568
+ return (!node.computed || isPure(node.key, scopes)) && (node.decorators?.length ?? 0) === 0 && (!node.static || isPure(node.value, scopes));
569
+ case "Property":
570
+ return (!node.computed || isPure(node.key, scopes)) && (node.method || isPure(node.value, scopes));
571
+ case "BinaryExpression":
572
+ case "LogicalExpression":
573
+ return isPure(node.left, scopes) && isPure(node.right, scopes);
574
+ case "ArrayExpression":
575
+ return node.elements.every((element) => isPure(element, scopes));
576
+ case "ObjectExpression":
577
+ return node.properties.every((property) => isPure(property, scopes));
578
+ case "UnaryExpression":
579
+ return isPure(node.argument, scopes);
580
+ case "TemplateLiteral":
581
+ return node.expressions.every((expression) => isPure(expression, scopes));
582
+ default:
583
+ return !1;
584
+ }
558
585
  }
559
- function collectReferencedIdentifiers(programPath) {
560
- let referenced = /* @__PURE__ */ new Set();
561
- return programPath.traverse({
562
- enter(path) {
563
- let { node } = path;
564
- !t.isIdentifier(node) || path.isBindingIdentifier() || path.findParent((p) => p.isImportDeclaration()) || referenced.add(node.name);
565
- },
566
- JSXOpeningElement(path) {
567
- let root = getJsxRootIdentifier(path.node.name);
568
- root && referenced.add(root.name);
586
+ function eliminateDeadCode(editor, isGone, remove) {
587
+ let { program, scopes, edits } = editor, isLive = (identifier) => !!scopes.bindingOf(identifier)?.references.some((reference) => !isGone(reference)), deadSpecifiers = /* @__PURE__ */ new Set(), changed = !0;
588
+ for (; changed; ) {
589
+ changed = !1;
590
+ for (let statement of program.body) {
591
+ if (isGone(statement))
592
+ continue;
593
+ (statement.type === "FunctionDeclaration" ? statement.id && !isLive(statement.id) : statement.type === "VariableDeclaration" && statement.declarations.every(
594
+ (declarator) => declarator.id.type === "Identifier" && !isLive(declarator.id) && isPure(declarator.init, scopes)
595
+ )) && (remove(statement), changed = !0);
569
596
  }
570
- }), referenced;
571
- }
572
- function removeDeadTopLevelDeclarations(programPath) {
573
- let referenced = collectReferencedIdentifiers(programPath), removed = !1;
574
- for (let stmtPath of programPath.get("body"))
575
- if (!(stmtPath.isImportDeclaration() || stmtPath.isExportDeclaration())) {
576
- if (stmtPath.isFunctionDeclaration()) {
577
- let id = stmtPath.node.id;
578
- id && !referenced.has(id.name) && (stmtPath.remove(), removed = !0);
597
+ for (let statement of program.body) {
598
+ if (statement.type !== "ImportDeclaration" || isGone(statement))
599
+ continue;
600
+ let specifiers = statement.specifiers.filter((spec) => !deadSpecifiers.has(spec)), live = specifiers.filter((spec) => isLive(spec.local));
601
+ if (specifiers.length === 0 || live.length === specifiers.length)
602
+ continue;
603
+ if (specifiers.filter((spec) => !live.includes(spec)).forEach((spec) => deadSpecifiers.add(spec)), changed = !0, live.length === 0) {
604
+ remove(statement);
579
605
  continue;
580
606
  }
581
- stmtPath.isVariableDeclaration() && stmtPath.get("declarations").every((declPath) => {
582
- if (!t.isIdentifier(declPath.node.id) || referenced.has(declPath.node.id.name)) return !1;
583
- let initPath = declPath.get("init");
584
- return !declPath.node.init || initPath.isPure();
585
- }) && (stmtPath.remove(), removed = !0);
607
+ let named = live.filter((spec) => spec.type === "ImportSpecifier"), clause = [
608
+ ...live.filter((spec) => spec.type !== "ImportSpecifier").map((spec) => editor.source(spec)),
609
+ ...named.length > 0 ? [`{ ${named.map((spec) => editor.source(spec)).join(", ")} }`] : []
610
+ ].join(", ");
611
+ edits.overwrite(
612
+ statement.start,
613
+ statement.source.start,
614
+ `import ${statement.importKind === "type" ? "type " : ""}${clause} from `
615
+ );
586
616
  }
587
- return removed;
588
- }
589
- function removeDeadImportSpecifiers(programPath) {
590
- let referenced = collectReferencedIdentifiers(programPath), removed = !1;
591
- return programPath.traverse({
592
- ImportDeclaration(path) {
593
- if (path.node.specifiers.length === 0)
594
- return;
595
- let specifiers = path.node.specifiers.filter((spec) => referenced.has(spec.local.name));
596
- specifiers.length === 0 ? (path.remove(), removed = !0) : specifiers.length !== path.node.specifiers.length && (path.node.specifiers = specifiers, removed = !0);
597
- }
598
- }), removed;
599
- }
600
- function eliminateDeadImports(programPath) {
601
- let changed = !0;
602
- for (; changed; ) {
603
- let d = removeDeadTopLevelDeclarations(programPath), i = removeDeadImportSpecifiers(programPath);
604
- changed = d || i;
605
617
  }
606
618
  }
607
619
 
608
620
  // src/plugins/server-only-stub.ts
609
- import { babelParse as parse2, types as t2 } from "storybook/internal/babel";
621
+ import { parseModule } from "storybook/internal/csf-tools";
610
622
  var SERVER_FILE_RE = /\.server\.(?:[mc]?[jt]sx?)$/;
611
623
  function serverOnlyStubPlugin(options = {}) {
612
624
  let patterns = [SERVER_FILE_RE, ...options.extraPatterns ?? []];
@@ -637,29 +649,27 @@ function serverOnlyStubPlugin(options = {}) {
637
649
  };
638
650
  }
639
651
  function collectExports(code, id) {
640
- let named = /* @__PURE__ */ new Set(), hasDefault = !1, ast;
652
+ let named = /* @__PURE__ */ new Set(), hasDefault = !1, program;
641
653
  try {
642
- ast = parse2(code);
654
+ ({ program } = parseModule(code, id));
643
655
  } catch {
644
656
  return { named, hasDefault };
645
657
  }
646
- for (let node of ast.program.body) {
647
- if (t2.isExportDefaultDeclaration(node)) {
658
+ for (let node of program.body) {
659
+ if (node.type === "ExportDefaultDeclaration") {
648
660
  hasDefault = !0;
649
661
  continue;
650
662
  }
651
- if (!t2.isExportAllDeclaration(node) && t2.isExportNamedDeclaration(node)) {
652
- let decl = node.declaration;
653
- if (decl)
654
- if (t2.isVariableDeclaration(decl))
655
- for (let declarator of decl.declarations)
656
- t2.isIdentifier(declarator.id) && named.add(declarator.id.name);
657
- else (t2.isFunctionDeclaration(decl) || t2.isClassDeclaration(decl)) && decl.id?.name && named.add(decl.id.name);
658
- for (let spec of node.specifiers)
659
- if (t2.isExportSpecifier(spec)) {
660
- let exportedName = t2.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value;
661
- exportedName !== "default" ? named.add(exportedName) : hasDefault = !0;
662
- }
663
+ if (node.type !== "ExportNamedDeclaration")
664
+ continue;
665
+ let decl = node.declaration;
666
+ if (decl?.type === "VariableDeclaration")
667
+ for (let declarator of decl.declarations)
668
+ declarator.id.type === "Identifier" && named.add(declarator.id.name);
669
+ else (decl?.type === "FunctionDeclaration" || decl?.type === "ClassDeclaration") && decl.id?.name && named.add(decl.id.name);
670
+ for (let spec of node.specifiers) {
671
+ let exportedName = spec.exported.type === "Identifier" ? spec.exported.name : String(spec.exported.value);
672
+ exportedName !== "default" ? named.add(exportedName) : hasDefault = !0;
663
673
  }
664
674
  }
665
675
  return { named, hasDefault };
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.8",
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.8",
79
+ "@storybook/react": "11.0.0-alpha.8",
80
+ "@storybook/react-vite": "11.0.0-alpha.8"
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.8",
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
+ };