@storybook/tanstack-react 10.6.0-alpha.4 → 10.6.0-alpha.6

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.
@@ -9,6 +9,7 @@ import {
9
9
  var preview_exports = {};
10
10
  __export(preview_exports, {
11
11
  applyDecorators: () => applyDecorators,
12
+ beforeEach: () => beforeEach,
12
13
  loaders: () => loaders,
13
14
  optimizeDeps: () => optimizeDeps,
14
15
  parameters: () => parameters
@@ -16,16 +17,16 @@ __export(preview_exports, {
16
17
  import { applyDecorators as reactApplyDecorators } from "@storybook/react/entry-preview-docs";
17
18
 
18
19
  // src/routing/decorator.tsx
19
- import React from "react";
20
20
  import {
21
21
  createMemoryHistory,
22
22
  createRootRoute,
23
23
  createRoute as createRoute2,
24
24
  createRouter,
25
- RouterProvider,
25
+ defaultStringifySearch,
26
26
  interpolatePath as interpolatePath2,
27
- defaultStringifySearch
27
+ RouterProvider
28
28
  } from "@tanstack/react-router";
29
+ import React from "react";
29
30
 
30
31
  // src/routing/duplicate-tree.ts
31
32
  import {
@@ -55,9 +56,12 @@ function initSourceTree(route, counter) {
55
56
  for (let child of children)
56
57
  initSourceTree(child, counter);
57
58
  }
59
+ function layoutIdFor(id) {
60
+ return id.length > 1 && id.endsWith("/") ? id.slice(0, -1) : id;
61
+ }
58
62
  function cloneChild(oldRoute, parent, overrides, byId) {
59
63
  let options = oldRoute.options ?? {}, { id: originalId, getParentRoute: _g, ...rest } = options, override = getOverrideFor(overrides, oldRoute.id), { id: overrideId, ...overrideRest } = override, merged = { ...rest, ...overrideRest }, explicitId = "id" in override ? overrideId : originalId, cloned = createRoute({
60
- ...!merged.path && explicitId != null ? { id: explicitId } : {},
64
+ ...!merged.path && explicitId != null ? { id: layoutIdFor(explicitId) } : {},
61
65
  ...merged,
62
66
  getParentRoute: () => parent
63
67
  });
@@ -155,17 +159,15 @@ var StoryContext = React.createContext({ Story: () => null }), StoryFromContext
155
159
  return React.createElement(Story, null);
156
160
  }, tanstackRouteDecorator = (Story, context) => React.createElement(TanStackRouterStory, { Story, context });
157
161
  function TanStackRouterStory({ Story, context }) {
158
- let routerContext = context.parameters.tanstack?.router?.useRouterContext?.({
162
+ let router = context.tanstackRouter, routerContext = context.parameters.tanstack?.router?.useRouterContext?.({
159
163
  storyContext: context
160
- }), router = React.useMemo(
161
- () => createStoryRouter({ Story: StoryFromContext, context, routerContext }),
162
- // eslint-disable-next-line react-hooks/exhaustive-deps
163
- [context.id]
164
- ), providerContext = React.useMemo(
165
- () => ({
166
- ...context.parameters.tanstack?.router?.context,
167
- ...routerContext
168
- }),
164
+ });
165
+ if (!router)
166
+ throw new Error(
167
+ "No story router found on the story context: the `routerBeforeEach` hook of @storybook/tanstack-react did not run before rendering. Note that portable stories are not supported by this framework."
168
+ );
169
+ let providerContext = React.useMemo(
170
+ () => routerContext,
169
171
  // eslint-disable-next-line react-hooks/exhaustive-deps
170
172
  [context.id, routerContext]
171
173
  );
@@ -265,6 +267,30 @@ function resolveTree(Story, context) {
265
267
  };
266
268
  }
267
269
 
270
+ // src/routing/before-each.ts
271
+ var storyRouters = /* @__PURE__ */ new Map(), routerBeforeEach = async (context) => {
272
+ let cached = storyRouters.get(context.id);
273
+ if (cached) {
274
+ context.tanstackRouter = cached;
275
+ return;
276
+ }
277
+ let storyContext = context, parameterContext = (context.parameters.tanstack?.router ?? {}).context, routerContext = typeof parameterContext == "function" ? parameterContext({ storyContext }) : parameterContext, router = createStoryRouter({
278
+ Story: StoryFromContext,
279
+ context: storyContext,
280
+ routerContext
281
+ }), load = router.load();
282
+ if (context.abortSignal && !context.abortSignal.aborted ? (load.catch(() => {
283
+ }), await Promise.race([
284
+ load,
285
+ new Promise(
286
+ (resolve) => context.abortSignal.addEventListener("abort", () => resolve(), { once: !0 })
287
+ )
288
+ ])) : await load, !context.abortSignal?.aborted)
289
+ return storyRouters.set(context.id, router), context.tanstackRouter = router, () => {
290
+ storyRouters.delete(context.id);
291
+ };
292
+ };
293
+
268
294
  // src/routing/loader.ts
269
295
  import { RootRoute as RootRoute3 } from "@tanstack/react-router";
270
296
  function getComponentFromRoute(route) {
@@ -285,7 +311,7 @@ var routeComponentLoader = (context) => {
285
311
  };
286
312
 
287
313
  // src/preview.tsx
288
- var loaders = [routeComponentLoader], applyDecorators = (storyFn, allDecorators) => (
314
+ var loaders = [routeComponentLoader], beforeEach = [routerBeforeEach], applyDecorators = (storyFn, allDecorators) => (
289
315
  // reorder decorators so `jsxDecorator` is innermost, and `tanstackRouteDecorator` is just outside it
290
316
  // There is an issue if `tanstackRouteDecorator` is innermost. All stories crashes due to a bug with the jsxDecorator.
291
317
  reactApplyDecorators(storyFn, [
@@ -302,6 +328,7 @@ var loaders = [routeComponentLoader], applyDecorators = (storyFn, allDecorators)
302
328
 
303
329
  export {
304
330
  loaders,
331
+ beforeEach,
305
332
  applyDecorators,
306
333
  parameters,
307
334
  optimizeDeps,
@@ -86,10 +86,11 @@ interface RouterParameters<TRoute = undefined, Path extends (TRoute extends AnyR
86
86
  * ```
87
87
  */
88
88
  routeOverrides?: RouteTreeOverrides;
89
- context?: Record<string, unknown>;
90
- /**
91
- *
92
- */
89
+ /** Object or factory; the factory runs before initial router load outside React, so loader and beforeLoad can read its values. */
90
+ context?: Record<string, unknown> | ((options: {
91
+ storyContext: Parameters<Decorator>[1];
92
+ }) => Record<string, unknown>);
93
+ /** React hook render context reaches components, not the initial loader or beforeLoad; use the context factory for loader-visible values. */
93
94
  useRouterContext?: ({
94
95
  storyContext
95
96
  }: {
@@ -334,7 +334,6 @@ declare const Link: ({
334
334
  children?: React.ReactNode;
335
335
  [key: string]: unknown;
336
336
  }) => React.DetailedReactHTMLElement<{
337
- href: string;
338
337
  onClick: (e: React.MouseEvent) => void;
339
338
  }, HTMLElement>;
340
339
  /**
@@ -38,15 +38,14 @@ var useNavigate = fn(_useNavigate).mockName("@tanstack/react-router::useNavigate
38
38
  children,
39
39
  ...props
40
40
  }) => {
41
- let location = useLocation();
41
+ let location = useLocation(), { onClick: _navigate, ...linkProps } = _useLinkProps({ to, ...props });
42
42
  return React.createElement(
43
43
  "a",
44
44
  {
45
- href: to,
45
+ ...linkProps,
46
46
  onClick: (e) => {
47
47
  e.preventDefault(), onNavigate({ to, from: location.href });
48
- },
49
- ...props
48
+ }
50
49
  },
51
50
  children
52
51
  );
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-CT6Edisg.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-B0pqNVvJ.js";
2
2
  import { ComponentType } from "react";
3
3
  import { AddonTypes, InferTypes, PreviewAddon } from "storybook/internal/csf";
4
4
  import { Args, ArgsStoryFn, ComponentAnnotations, DecoratorFunction, Parameters, ProjectAnnotations, Renderer, 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-5B7CRIA6.js";
3
+ } from "./_browser-chunks/chunk-HRV4LMK3.js";
4
4
  import "./_browser-chunks/chunk-LTDGLEVR.js";
5
5
  import "./_browser-chunks/chunk-4BE7D4DS.js";
6
6
 
@@ -1,4 +1,4 @@
1
- import { r as StorybookConfig } from "../chunk-CT6Edisg.js";
1
+ import { r as StorybookConfig } from "../chunk-B0pqNVvJ.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_fr5elf42854 from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_fr5elf42854 from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_fr5elf42854 from "node:module";
1
+ import CJS_COMPAT_NODE_URL_bncj3zf7qim from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_bncj3zf7qim from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_bncj3zf7qim from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_fr5elf42854.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_fr5elf42854.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_fr5elf42854.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_bncj3zf7qim.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_bncj3zf7qim.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_bncj3zf7qim.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_fr5elf42854 from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_fr5elf42854 from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_fr5elf42854 from "node:module";
1
+ import CJS_COMPAT_NODE_URL_bncj3zf7qim from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_bncj3zf7qim from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_bncj3zf7qim from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_fr5elf42854.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_fr5elf42854.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_fr5elf42854.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_bncj3zf7qim.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_bncj3zf7qim.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_bncj3zf7qim.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -13,23 +13,310 @@ var require = CJS_COMPAT_NODE_MODULE_fr5elf42854.createRequire(import.meta.url);
13
13
  // src/preset.ts
14
14
  import { fileURLToPath } from "node:url";
15
15
 
16
- // ../../../node_modules/pathe/dist/shared/pathe.ff20891b.mjs
17
- var _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
16
+ // ../../../node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
17
+ var _lazyMatch = () => {
18
+ var __lib__ = (() => {
19
+ var m = Object.defineProperty, V = Object.getOwnPropertyDescriptor, G = Object.getOwnPropertyNames, T = Object.prototype.hasOwnProperty, q = (r, e) => {
20
+ for (var n in e) m(r, n, { get: e[n], enumerable: !0 });
21
+ }, H = (r, e, n, a) => {
22
+ 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
+ return r;
24
+ }, J = (r) => H(m({}, "__esModule", { value: !0 }), r), w = {};
25
+ q(w, { default: () => re });
26
+ var A = (r) => Array.isArray(r), d = (r) => typeof r == "function", Q = (r) => r.length === 0, W = (r) => typeof r == "number", K = (r) => typeof r == "object" && r !== null, X = (r) => r instanceof RegExp, b = (r) => typeof r == "string", h = (r) => r === void 0, Y = (r) => {
27
+ let e = /* @__PURE__ */ new Map();
28
+ return (n) => {
29
+ let a = e.get(n);
30
+ if (a) return a;
31
+ let t3 = r(n);
32
+ return e.set(n, t3), t3;
33
+ };
34
+ }, rr = (r, e, n = {}) => {
35
+ let a = { cache: {}, input: r, index: 0, indexMax: 0, options: n, output: [] };
36
+ if (v(e)(a) && a.index === r.length) return a.output;
37
+ throw new Error(`Failed to parse at index ${a.indexMax}`);
38
+ }, i = (r, e) => A(r) ? er(r, e) : b(r) ? ar(r, e) : nr(r, e), er = (r, e) => {
39
+ let n = {};
40
+ for (let a of r) {
41
+ if (a.length !== 1) throw new Error(`Invalid character: "${a}"`);
42
+ let t3 = a.charCodeAt(0);
43
+ n[t3] = !0;
44
+ }
45
+ return (a) => {
46
+ let t3 = a.index, o = a.input;
47
+ for (; a.index < o.length && o.charCodeAt(a.index) in n; ) a.index += 1;
48
+ let u = a.index;
49
+ if (u > t3) {
50
+ if (!h(e) && !a.options.silent) {
51
+ let s = a.input.slice(t3, u), c = d(e) ? e(s, o, String(t3)) : e;
52
+ h(c) || a.output.push(c);
53
+ }
54
+ a.indexMax = Math.max(a.indexMax, a.index);
55
+ }
56
+ return !0;
57
+ };
58
+ }, nr = (r, e) => {
59
+ let n = r.source, a = r.flags.replace(/y|$/, "y"), t3 = new RegExp(n, a);
60
+ return g((o) => {
61
+ t3.lastIndex = o.index;
62
+ let u = t3.exec(o.input);
63
+ if (u) {
64
+ if (!h(e) && !o.options.silent) {
65
+ let s = d(e) ? e(...u, o.input, String(o.index)) : e;
66
+ h(s) || o.output.push(s);
67
+ }
68
+ return o.index += u[0].length, o.indexMax = Math.max(o.indexMax, o.index), !0;
69
+ } else return !1;
70
+ });
71
+ }, ar = (r, e) => (n) => {
72
+ if (n.input.startsWith(r, n.index)) {
73
+ if (!h(e) && !n.options.silent) {
74
+ let t3 = d(e) ? e(r, n.input, String(n.index)) : e;
75
+ h(t3) || n.output.push(t3);
76
+ }
77
+ return n.index += r.length, n.indexMax = Math.max(n.indexMax, n.index), !0;
78
+ } else return !1;
79
+ }, C = (r, e, n, a) => {
80
+ let t3 = v(r);
81
+ return g(_(M((o) => {
82
+ let u = 0;
83
+ for (; u < n; ) {
84
+ let s = o.index;
85
+ if (!t3(o) || (u += 1, o.index === s)) break;
86
+ }
87
+ return u >= e;
88
+ })));
89
+ }, tr = (r, e) => C(r, 0, 1), f = (r, e) => C(r, 0, 1 / 0), x = (r, e) => {
90
+ let n = r.map(v);
91
+ return g(_(M((a) => {
92
+ for (let t3 = 0, o = n.length; t3 < o; t3++) if (!n[t3](a)) return !1;
93
+ return !0;
94
+ })));
95
+ }, l = (r, e) => {
96
+ let n = r.map(v);
97
+ return g(_((a) => {
98
+ for (let t3 = 0, o = n.length; t3 < o; t3++) if (n[t3](a)) return !0;
99
+ return !1;
100
+ }));
101
+ }, M = (r, e = !1) => {
102
+ let n = v(r);
103
+ return (a) => {
104
+ let t3 = a.index, o = a.output.length, u = n(a);
105
+ return (!u || e) && (a.index = t3, a.output.length !== o && (a.output.length = o)), u;
106
+ };
107
+ }, _ = (r, e) => v(r), g = /* @__PURE__ */ (() => {
108
+ let r = 0;
109
+ return (e) => {
110
+ let n = v(e), a = r += 1;
111
+ return (t3) => {
112
+ var o;
113
+ if (t3.options.memoization === !1) return n(t3);
114
+ let u = t3.index, s = (o = t3.cache)[a] || (o[a] = /* @__PURE__ */ new Map()), c = s.get(u);
115
+ if (c === !1) return !1;
116
+ if (W(c)) return t3.index = c, !0;
117
+ if (c) return t3.index = c.index, c.output?.length && t3.output.push(...c.output), !0;
118
+ {
119
+ let Z = t3.output.length;
120
+ if (n(t3)) {
121
+ let D = t3.index, U = t3.output.length;
122
+ if (U > Z) {
123
+ let ee = t3.output.slice(Z, U);
124
+ s.set(u, { index: D, output: ee });
125
+ } else s.set(u, D);
126
+ return !0;
127
+ } else return s.set(u, !1), !1;
128
+ }
129
+ };
130
+ };
131
+ })(), E = (r) => {
132
+ let e;
133
+ return (n) => (e || (e = v(r())), e(n));
134
+ }, v = Y((r) => {
135
+ if (d(r)) return Q(r) ? E(r) : r;
136
+ if (b(r) || X(r)) return i(r);
137
+ if (A(r)) return x(r);
138
+ if (K(r)) return l(Object.values(r));
139
+ throw new Error("Invalid rule");
140
+ }), P = "abcdefghijklmnopqrstuvwxyz", ir = (r) => {
141
+ let e = "";
142
+ for (; r > 0; ) {
143
+ let n = (r - 1) % 26;
144
+ e = P[n] + e, r = Math.floor((r - 1) / 26);
145
+ }
146
+ return e;
147
+ }, O = (r) => {
148
+ let e = 0;
149
+ for (let n = 0, a = r.length; n < a; n++) e = e * 26 + P.indexOf(r[n]) + 1;
150
+ return e;
151
+ }, S = (r, e) => {
152
+ if (e < r) return S(e, r);
153
+ let n = [];
154
+ for (; r <= e; ) n.push(r++);
155
+ return n;
156
+ }, or = (r, e, n) => S(r, e).map((a) => String(a).padStart(n, "0")), R = (r, e) => S(O(r), O(e)).map(ir), p = (r) => r, z = (r) => ur((e) => rr(e, r, { memoization: !1 }).join("")), ur = (r) => {
157
+ let e = {};
158
+ return (n) => e[n] ?? (e[n] = r(n));
159
+ }, 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) => {
160
+ let n = Array.isArray(r) ? r : [r];
161
+ if (!n.length) return !1;
162
+ let a = n.map($.compile), t3 = n.every((s) => /(\/(?:\*\*)?|\[\/\])$/.test(s)), o = e.replace(/[\\\/]+/g, "/").replace(/\/$/, t3 ? "/" : "");
163
+ return a.some((s) => s.test(o));
164
+ };
165
+ $.compile = (r) => new RegExp(`^${L(Yr(r))}$`, "s");
166
+ var re = $;
167
+ return J(w);
168
+ })();
169
+ return __lib__.default || __lib__;
170
+ }, _match, zeptomatch = (path, pattern) => (_match || (_match = _lazyMatch(), _lazyMatch = null), _match(path, pattern)), _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
18
171
  function normalizeWindowsPath(input = "") {
19
172
  return input && input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
20
173
  }
21
- var _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/, _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
174
+ var _UNC_REGEX = /^[/\\]{2}/, _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/, _DRIVE_LETTER_RE = /^[A-Za-z]:$/, _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/, _EXTNAME_RE = /.(\.[^./]+|\.)$/, _PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/, sep = "/", normalize = function(path) {
175
+ if (path.length === 0)
176
+ return ".";
177
+ path = normalizeWindowsPath(path);
178
+ let isUNCPath = path.match(_UNC_REGEX), isPathAbsolute = isAbsolute(path), trailingSeparator = path[path.length - 1] === "/";
179
+ return path = normalizeString(path, !isPathAbsolute), path.length === 0 ? isPathAbsolute ? "/" : trailingSeparator ? "./" : "." : (trailingSeparator && (path += "/"), _DRIVE_LETTER_RE.test(path) && (path += "/"), isUNCPath ? isPathAbsolute ? `//${path}` : `//./${path}` : isPathAbsolute && !isAbsolute(path) ? `/${path}` : path);
180
+ }, join = function(...segments) {
181
+ let path = "";
182
+ for (let seg of segments)
183
+ if (seg)
184
+ if (path.length > 0) {
185
+ let pathTrailing = path[path.length - 1] === "/", segLeading = seg[0] === "/";
186
+ pathTrailing && segLeading ? path += seg.slice(1) : path += pathTrailing || segLeading ? seg : `/${seg}`;
187
+ } else
188
+ path += seg;
189
+ return normalize(path);
190
+ };
191
+ function cwd() {
192
+ return typeof process < "u" && typeof process.cwd == "function" ? process.cwd().replace(/\\/g, "/") : "/";
193
+ }
194
+ var resolve = function(...arguments_) {
195
+ arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
196
+ let resolvedPath = "", resolvedAbsolute = !1;
197
+ for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
198
+ let path = index >= 0 ? arguments_[index] : cwd();
199
+ !path || path.length === 0 || (resolvedPath = `${path}/${resolvedPath}`, resolvedAbsolute = isAbsolute(path));
200
+ }
201
+ return resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute), resolvedAbsolute && !isAbsolute(resolvedPath) ? `/${resolvedPath}` : resolvedPath.length > 0 ? resolvedPath : ".";
202
+ };
203
+ function normalizeString(path, allowAboveRoot) {
204
+ let res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, char = null;
205
+ for (let index = 0; index <= path.length; ++index) {
206
+ if (index < path.length)
207
+ char = path[index];
208
+ else {
209
+ if (char === "/")
210
+ break;
211
+ char = "/";
212
+ }
213
+ if (char === "/") {
214
+ if (!(lastSlash === index - 1 || dots === 1)) if (dots === 2) {
215
+ if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
216
+ if (res.length > 2) {
217
+ let lastSlashIndex = res.lastIndexOf("/");
218
+ lastSlashIndex === -1 ? (res = "", lastSegmentLength = 0) : (res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/")), lastSlash = index, dots = 0;
219
+ continue;
220
+ } else if (res.length > 0) {
221
+ res = "", lastSegmentLength = 0, lastSlash = index, dots = 0;
222
+ continue;
223
+ }
224
+ }
225
+ allowAboveRoot && (res += res.length > 0 ? "/.." : "..", lastSegmentLength = 2);
226
+ } else
227
+ res.length > 0 ? res += `/${path.slice(lastSlash + 1, index)}` : res = path.slice(lastSlash + 1, index), lastSegmentLength = index - lastSlash - 1;
228
+ lastSlash = index, dots = 0;
229
+ } else char === "." && dots !== -1 ? ++dots : dots = -1;
230
+ }
231
+ return res;
232
+ }
22
233
  var isAbsolute = function(p) {
23
234
  return _IS_ABSOLUTE_RE.test(p);
24
- };
25
- var dirname = function(p) {
235
+ }, toNamespacedPath = function(p) {
236
+ return normalizeWindowsPath(p);
237
+ }, extname = function(p) {
238
+ if (p === "..") return "";
239
+ let match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
240
+ return match && match[1] || "";
241
+ }, relative = function(from, to) {
242
+ let _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/"), _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
243
+ if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0])
244
+ return _to.join("/");
245
+ let _fromCopy = [..._from];
246
+ for (let segment of _fromCopy) {
247
+ if (_to[0] !== segment)
248
+ break;
249
+ _from.shift(), _to.shift();
250
+ }
251
+ return [..._from.map(() => ".."), ..._to].join("/");
252
+ }, dirname = function(p) {
26
253
  let segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
27
254
  return segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0]) && (segments[0] += "/"), segments.join("/") || (isAbsolute(p) ? "/" : ".");
255
+ }, format = function(p) {
256
+ let ext = p.ext ? p.ext.startsWith(".") ? p.ext : `.${p.ext}` : "", segments = [p.root, p.dir, p.base ?? (p.name ?? "") + ext].filter(
257
+ Boolean
258
+ );
259
+ return normalizeWindowsPath(
260
+ p.root ? resolve(...segments) : segments.join("/")
261
+ );
262
+ }, basename = function(p, extension) {
263
+ let segments = normalizeWindowsPath(p).split("/"), lastSegment = "";
264
+ for (let i = segments.length - 1; i >= 0; i--) {
265
+ let val = segments[i];
266
+ if (val) {
267
+ lastSegment = val;
268
+ break;
269
+ }
270
+ }
271
+ return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
272
+ }, parse = function(p) {
273
+ let root = _PATH_ROOT_RE.exec(p)?.[0]?.replace(/\\/g, "/") || "", base = basename(p), extension = extname(base);
274
+ return {
275
+ root,
276
+ dir: dirname(p),
277
+ base,
278
+ ext: extension,
279
+ name: base.slice(0, base.length - extension.length)
280
+ };
281
+ }, matchesGlob = (path, pattern) => zeptomatch(pattern, normalize(path)), _path = {
282
+ __proto__: null,
283
+ basename,
284
+ dirname,
285
+ extname,
286
+ format,
287
+ isAbsolute,
288
+ join,
289
+ matchesGlob,
290
+ normalize,
291
+ normalizeString,
292
+ parse,
293
+ relative,
294
+ resolve,
295
+ sep,
296
+ toNamespacedPath
28
297
  };
29
298
 
299
+ // ../../../node_modules/pathe/dist/index.mjs
300
+ var delimiter = globalThis.process?.platform === "win32" ? ";" : ":", _platforms = { posix: void 0, win32: void 0 }, mix = (del = delimiter) => new Proxy(_path, {
301
+ get(_, prop) {
302
+ return prop === "delimiter" ? del : prop === "posix" ? posix : prop === "win32" ? win32 : _platforms[prop] || _path[prop];
303
+ }
304
+ }), posix = mix(":"), win32 = mix(";");
305
+
30
306
  // src/preset.ts
31
307
  import { viteFinal as reactViteFinal } from "@storybook/react-vite/preset";
32
308
 
309
+ // src/plugins/incompatible-plugins.ts
310
+ var matchesPluginName = (p, matches) => {
311
+ if (Array.isArray(p))
312
+ return p.some((entry) => matchesPluginName(entry, matches));
313
+ let pluginRecord = p;
314
+ return typeof p == "object" && p !== null && "name" in pluginRecord && typeof pluginRecord.name == "string" && matches(pluginRecord.name);
315
+ }, isTanStackStartPlugin = (p) => matchesPluginName(p, (name) => name.startsWith("tanstack-start") || name.includes("rsc:")), isCloudflareVitePlugin = (p) => matchesPluginName(
316
+ p,
317
+ (name) => name === "vite-plugin-cloudflare" || name.startsWith("vite-plugin-cloudflare:")
318
+ );
319
+
33
320
  // src/plugins/server-code-elimination.ts
34
321
  import { types as t, transformSync } from "storybook/internal/babel";
35
322
  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([
@@ -87,19 +374,19 @@ function serverCodeElimination(state) {
87
374
  Program(programPath) {
88
375
  let tanstackImports = collectTanstackImports(programPath.node.body), resolves = (name, factory) => resolvesToFactory(tanstackImports, name, factory);
89
376
  programPath.traverse({
90
- CallExpression(path2) {
91
- let node = path2.node;
377
+ CallExpression(path) {
378
+ let node = path.node;
92
379
  if (ROUTE_FACTORY_RE.test(state.code)) {
93
380
  let routeOptionsArg = getRouteFactoryOptionsArg(node, tanstackImports);
94
381
  routeOptionsArg && stripServerOption(routeOptionsArg) && (state.modified = !0);
95
382
  }
96
383
  if (t.isIdentifier(node.callee) && resolves(node.callee.name, "createServerOnlyFn") && SERVER_ONLY_FN_RE.test(state.code)) {
97
- path2.replaceWith(sbFnCall()), state.modified = !0;
384
+ path.replaceWith(sbFnCall()), state.modified = !0;
98
385
  return;
99
386
  }
100
387
  if (t.isIdentifier(node.callee) && resolves(node.callee.name, "createClientOnlyFn") && CLIENT_ONLY_FN_RE.test(state.code)) {
101
388
  let innerFn = node.arguments[0];
102
- innerFn && t.isExpression(innerFn) && (path2.replaceWith(sbFnCallWithImpl(innerFn)), state.modified = !0);
389
+ innerFn && t.isExpression(innerFn) && (path.replaceWith(sbFnCallWithImpl(innerFn)), state.modified = !0);
103
390
  return;
104
391
  }
105
392
  let methodName = getMethodName(node);
@@ -111,7 +398,7 @@ function serverCodeElimination(state) {
111
398
  let handlerArg = node.arguments[0];
112
399
  if (handlerArg) {
113
400
  if (t.isIdentifier(handlerArg)) {
114
- let binding = path2.scope.getBinding(handlerArg.name);
401
+ let binding = path.scope.getBinding(handlerArg.name);
115
402
  binding && binding.referencePaths.length === 1 && binding.path.remove();
116
403
  }
117
404
  node.arguments[0] = sbFnCall();
@@ -120,18 +407,18 @@ function serverCodeElimination(state) {
120
407
  return;
121
408
  }
122
409
  if (resolves(root.rootName, "createMiddleware") && MIDDLEWARE_RE.test(state.code)) {
123
- (methodName === "server" || methodName === "inputValidator") && t.isMemberExpression(path2.node.callee) && (path2.replaceWith(path2.node.callee.object), state.modified = !0);
410
+ (methodName === "server" || methodName === "inputValidator") && t.isMemberExpression(path.node.callee) && (path.replaceWith(path.node.callee.object), state.modified = !0);
124
411
  return;
125
412
  }
126
413
  if (resolves(root.rootName, "createIsomorphicFn") && ISOMORPHIC_FN_RE.test(state.code)) {
127
414
  if (methodName === "client") {
128
415
  let innerFn = node.arguments[0];
129
- innerFn && t.isExpression(innerFn) && (path2.replaceWith(sbFnCallWithImpl(innerFn)), state.modified = !0);
416
+ innerFn && t.isExpression(innerFn) && (path.replaceWith(sbFnCallWithImpl(innerFn)), state.modified = !0);
130
417
  return;
131
418
  }
132
419
  if (methodName === "server") {
133
- let parent = path2.parent;
134
- (!t.isMemberExpression(parent) || !t.isCallExpression(path2.parentPath?.parent)) && (path2.replaceWith(sbFnCall()), state.modified = !0);
420
+ let parent = path.parent;
421
+ (!t.isMemberExpression(parent) || !t.isCallExpression(path.parentPath?.parent)) && (path.replaceWith(sbFnCall()), state.modified = !0);
135
422
  }
136
423
  return;
137
424
  }
@@ -223,12 +510,12 @@ function getJsxRootIdentifier(name) {
223
510
  function collectReferencedIdentifiers(programPath) {
224
511
  let referenced = /* @__PURE__ */ new Set();
225
512
  return programPath.traverse({
226
- enter(path2) {
227
- let { node } = path2;
228
- !t.isIdentifier(node) || path2.isBindingIdentifier() || path2.findParent((p) => p.isImportDeclaration()) || referenced.add(node.name);
513
+ enter(path) {
514
+ let { node } = path;
515
+ !t.isIdentifier(node) || path.isBindingIdentifier() || path.findParent((p) => p.isImportDeclaration()) || referenced.add(node.name);
229
516
  },
230
- JSXOpeningElement(path2) {
231
- let root = getJsxRootIdentifier(path2.node.name);
517
+ JSXOpeningElement(path) {
518
+ let root = getJsxRootIdentifier(path.node.name);
232
519
  root && referenced.add(root.name);
233
520
  }
234
521
  }), referenced;
@@ -253,11 +540,11 @@ function removeDeadTopLevelDeclarations(programPath) {
253
540
  function removeDeadImportSpecifiers(programPath) {
254
541
  let referenced = collectReferencedIdentifiers(programPath), removed = !1;
255
542
  return programPath.traverse({
256
- ImportDeclaration(path2) {
257
- if (path2.node.specifiers.length === 0)
543
+ ImportDeclaration(path) {
544
+ if (path.node.specifiers.length === 0)
258
545
  return;
259
- let specifiers = path2.node.specifiers.filter((spec) => referenced.has(spec.local.name));
260
- specifiers.length === 0 ? (path2.remove(), removed = !0) : specifiers.length !== path2.node.specifiers.length && (path2.node.specifiers = specifiers, removed = !0);
546
+ let specifiers = path.node.specifiers.filter((spec) => referenced.has(spec.local.name));
547
+ specifiers.length === 0 ? (path.remove(), removed = !0) : specifiers.length !== path.node.specifiers.length && (path.node.specifiers = specifiers, removed = !0);
261
548
  }
262
549
  }), removed;
263
550
  }
@@ -413,17 +700,13 @@ var core = async (config, options) => {
413
700
  "@tanstack/react-router > @tanstack/react-store",
414
701
  "use-sync-external-store/shim/with-selector"
415
702
  ], viteFinal = async (config, options) => {
416
- let reactConfig = await reactViteFinal(config, options), isTanStackStartPlugin = (p) => {
417
- if (Array.isArray(p))
418
- return p.some(isTanStackStartPlugin);
419
- let pluginRecord = p;
420
- return typeof p == "object" && p !== null && "name" in pluginRecord && typeof pluginRecord.name == "string" && (pluginRecord.name.startsWith("tanstack-start") || pluginRecord.name.includes("rsc:"));
421
- }, startMockPath = fileURLToPath(import.meta.resolve("./export-mocks/start.js")), startStorageContextMockPath = fileURLToPath(
703
+ let reactConfig = await reactViteFinal(config, options), startMockPath = fileURLToPath(import.meta.resolve("./export-mocks/start.js")), startStorageContextMockPath = fileURLToPath(
422
704
  import.meta.resolve("./export-mocks/start-storage-context.js")
423
705
  ), routerMockPath = fileURLToPath(
424
706
  import.meta.resolve("@storybook/tanstack-react/react-router")
425
707
  ), plugins = [
426
- ...(reactConfig.plugins ?? []).filter((p) => !isTanStackStartPlugin(p)),
708
+ // Drop user plugins that are incompatible with Storybook — see ./plugins/incompatible-plugins.ts
709
+ ...(reactConfig.plugins ?? []).filter((p) => !isTanStackStartPlugin(p) && !isCloudflareVitePlugin(p)),
427
710
  serverCodeEliminationPlugin({ excludeFiles: [dirname(startMockPath)] }),
428
711
  serverOnlyStubPlugin(),
429
712
  moduleInterceptionPlugin({ startMockPath, startStorageContextMockPath, routerMockPath })
package/dist/preview.d.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { i as TanStackParameters } from "./chunk-CT6Edisg.js";
2
- import { DecoratorFunction, LoaderFunction, Renderer } from "storybook/internal/types";
1
+ import { i as TanStackParameters } from "./chunk-B0pqNVvJ.js";
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
+ declare const beforeEach: BeforeEach<Renderer>[];
7
8
  declare const applyDecorators: (storyFn: Parameters<typeof applyDecorators$1>[0], allDecorators: DecoratorFunction[]) => any;
8
9
  declare const parameters: TanStackParameters;
9
10
  declare const optimizeDeps: string[];
10
11
  //#endregion
11
- export { applyDecorators, loaders, optimizeDeps, parameters };
12
+ export { applyDecorators, beforeEach, loaders, optimizeDeps, parameters };
package/dist/preview.js CHANGED
@@ -1,13 +1,15 @@
1
1
  import {
2
2
  applyDecorators,
3
+ beforeEach,
3
4
  loaders,
4
5
  optimizeDeps,
5
6
  parameters
6
- } from "./_browser-chunks/chunk-5B7CRIA6.js";
7
+ } from "./_browser-chunks/chunk-HRV4LMK3.js";
7
8
  import "./_browser-chunks/chunk-LTDGLEVR.js";
8
9
  import "./_browser-chunks/chunk-4BE7D4DS.js";
9
10
  export {
10
11
  applyDecorators,
12
+ beforeEach,
11
13
  loaders,
12
14
  optimizeDeps,
13
15
  parameters
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/tanstack-react",
3
- "version": "10.6.0-alpha.4",
3
+ "version": "10.6.0-alpha.6",
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.4",
79
- "@storybook/react": "10.6.0-alpha.4",
80
- "@storybook/react-vite": "10.6.0-alpha.4"
78
+ "@storybook/builder-vite": "10.6.0-alpha.6",
79
+ "@storybook/react": "10.6.0-alpha.6",
80
+ "@storybook/react-vite": "10.6.0-alpha.6"
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": "^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.4",
98
+ "storybook": "^10.6.0-alpha.6",
99
99
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
100
100
  },
101
101
  "peerDependenciesMeta": {
@@ -0,0 +1,45 @@
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
+ const loaderCalls: unknown[] = [];
8
+
9
+ function LoaderContextViewer() {
10
+ return <p data-testid="loader-context">{String(loaderCalls[0] ?? 'missing')}</p>;
11
+ }
12
+
13
+ const meta = {
14
+ component: LoaderContextViewer,
15
+ parameters: {
16
+ tanstack: {
17
+ router: {
18
+ context: () => {
19
+ loaderCalls.length = 0;
20
+ return { injected: 'from-factory' };
21
+ },
22
+ route: {
23
+ loader: ({ context }: { context: unknown }) => {
24
+ loaderCalls.push((context as any)?.injected ?? null);
25
+ },
26
+ },
27
+ },
28
+ },
29
+ },
30
+ } satisfies Meta<typeof LoaderContextViewer>;
31
+
32
+ export default meta;
33
+
34
+ type Story = StoryObj<typeof meta>;
35
+
36
+ /** Factory router context is visible to the route loader before render. */
37
+ export const FactoryValuesReachLoader: Story = {
38
+ play: async ({ canvasElement }) => {
39
+ const canvas = within(canvasElement);
40
+ await expect(canvas.getByTestId('loader-context')).toHaveTextContent('from-factory');
41
+
42
+ await expect(loaderCalls.length).toBeGreaterThan(0);
43
+ await expect(loaderCalls.every((call) => call === 'from-factory')).toBe(true);
44
+ },
45
+ };
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+
3
+ import type { Meta, StoryObj } from '@storybook/tanstack-react';
4
+
5
+ import { useRouter } from '@tanstack/react-router';
6
+ import { expect, within } from 'storybook/test';
7
+
8
+ const InjectedContext = React.createContext('missing-provider');
9
+
10
+ function RouterContextViewer() {
11
+ const router = useRouter();
12
+ const injected = (router.options.context as { injected?: string } | undefined)?.injected;
13
+ return <p data-testid="injected-router-context">{injected ?? 'missing-context'}</p>;
14
+ }
15
+
16
+ const meta = {
17
+ component: RouterContextViewer,
18
+ decorators: [
19
+ (Story) => (
20
+ <InjectedContext.Provider value="from-react-hook">
21
+ <Story />
22
+ </InjectedContext.Provider>
23
+ ),
24
+ ],
25
+ parameters: {
26
+ tanstack: {
27
+ router: {
28
+ useRouterContext: () => ({ injected: React.useContext(InjectedContext) }),
29
+ },
30
+ },
31
+ },
32
+ } satisfies Meta<typeof RouterContextViewer>;
33
+
34
+ export default meta;
35
+
36
+ type Story = StoryObj<typeof meta>;
37
+
38
+ /** Hook-derived values read from a decorator's React provider must reach the story's router. */
39
+ export const HookValuesReachRouter: Story = {
40
+ play: async ({ canvasElement }) => {
41
+ await expect(within(canvasElement).getByTestId('injected-router-context')).toHaveTextContent(
42
+ 'from-react-hook'
43
+ );
44
+ },
45
+ };