@storybook/tanstack-react 10.5.0-alpha.2 → 10.5.0-alpha.4

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.
@@ -172,12 +172,17 @@ function resolveTree(Story, context) {
172
172
  let tree = duplicateRouteTree(syntheticRoot2, { overrides: routeOverrides }), leaf = tree.byId.get(routerParameterRoute.id) ?? tree.root;
173
173
  return injectStoryComponent(leaf, Story, routeOverrides, leaf.id), { tree, leaf };
174
174
  }
175
- let plainOptions = routerParameterRoute ?? {}, syntheticRoot = createRootRoute(
175
+ let plainOptions = routerParameterRoute ?? {}, {
176
+ path: plainRoutePath,
177
+ id: plainRouteId,
178
+ ...plainRouteRest
179
+ } = plainOptions, syntheticRouteId = plainRoutePath ? void 0 : plainRouteId ?? "storybook-story", syntheticRoot = createRootRoute(
176
180
  routeOverrides?.__root__ ?? {}
177
181
  ), syntheticChild = createRoute2({
178
182
  component: () => React.createElement(Story, null),
179
- id: "storybook-story",
180
- ...plainOptions,
183
+ id: syntheticRouteId,
184
+ path: plainRoutePath,
185
+ ...plainRouteRest,
181
186
  getParentRoute: () => syntheticRoot
182
187
  });
183
188
  return syntheticRoot.addChildren([syntheticChild]), injectStoryComponent(syntheticChild, Story, routeOverrides, syntheticChild.id), {
@@ -325,7 +325,6 @@ declare const useLoaderDeps: Mock<typeof useLoaderDeps$1>;
325
325
  declare const useRouteContext: Mock<typeof useRouteContext$1>;
326
326
  declare const useCanGoBack: Mock<typeof useCanGoBack$1>;
327
327
  declare const useLinkProps: Mock<typeof useLinkProps$1>;
328
- declare const Outlet: () => null;
329
328
  declare const Navigate: typeof Navigate$1;
330
329
  declare const Link: ({ to, children, ...props }: {
331
330
  to: string;
@@ -341,4 +340,4 @@ declare const Link: ({ to, children, ...props }: {
341
340
  */
342
341
  declare function createFileRoute(path: string): (options: any) => _tanstack_react_router.Route<unknown, _tanstack_router_core.AnyRoute, "/", "/" | `/${any}/`, string, "/" | `/${any}/`, undefined, _tanstack_router_core.ResolveParams<"/">, _tanstack_router_core.AnyContext, _tanstack_router_core.AnyContext, _tanstack_router_core.AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
343
342
 
344
- export { Link, Navigate, Outlet, createFileRoute, useBlocker, useCanGoBack, useLinkProps, useLoaderData, useLoaderDeps, useLocation, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useSearch };
343
+ export { Link, Navigate, createFileRoute, useBlocker, useCanGoBack, useLinkProps, useLoaderData, useLoaderDeps, useLocation, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useSearch };
@@ -27,7 +27,7 @@ var useNavigate = fn(_useNavigate).mockName("@tanstack/react-router::useNavigate
27
27
  "@tanstack/react-router::useRouterState"
28
28
  ), useLoaderData = fn(_useLoaderData).mockName("@tanstack/react-router::useLoaderData"), useLoaderDeps = fn(_useLoaderDeps).mockName("@tanstack/react-router::useLoaderDeps"), useRouteContext = fn(_useRouteContext).mockName(
29
29
  "@tanstack/react-router::useRouteContext"
30
- ), useCanGoBack = fn(_useCanGoBack).mockName("@tanstack/react-router::useCanGoBack"), useLinkProps = fn(_useLinkProps).mockName("@tanstack/react-router::useLinkProps"), Outlet = () => null, Navigate = ({ to, href }) => (useEffect(() => {
30
+ ), useCanGoBack = fn(_useCanGoBack).mockName("@tanstack/react-router::useCanGoBack"), useLinkProps = fn(_useLinkProps).mockName("@tanstack/react-router::useLinkProps"), Navigate = ({ to, href }) => (useEffect(() => {
31
31
  onNavigate({ to: to || href });
32
32
  }, [to, href]), null), Link = ({
33
33
  to,
@@ -62,7 +62,6 @@ function createFileRoute(path) {
62
62
  export {
63
63
  Link,
64
64
  Navigate,
65
- Outlet,
66
65
  createFileRoute,
67
66
  useBlocker,
68
67
  useCanGoBack,
package/dist/index.d.ts CHANGED
@@ -8,31 +8,39 @@ import { RoutesByPath, RouteOptions, ResolveParams, AnyContext } from '@tanstack
8
8
  import { BuilderOptions } from '@storybook/builder-vite';
9
9
  import { StorybookConfig as StorybookConfig$1 } from '@storybook/react-vite';
10
10
 
11
- declare global {
12
- interface SymbolConstructor {
13
- readonly observable: symbol;
14
- }
15
- }
16
-
17
11
  /**
18
- @see Simplify
19
- */
20
- interface SimplifyOptions {
21
- /**
22
- Do the simplification recursively.
12
+ Convert a union type to an intersection type.
23
13
 
24
- @default false
25
- */
26
- deep?: boolean;
27
- }
14
+ Inspired by [this Stack Overflow answer](https://stackoverflow.com/a/50375286/2172153).
15
+
16
+ @example
17
+ ```
18
+ import type {UnionToIntersection} from 'type-fest';
19
+
20
+ type Union = {the(): void} | {great(arg: string): void} | {escape: boolean};
28
21
 
29
- // Flatten a type without worrying about the result.
30
- type Flatten<
31
- AnyType,
32
- Options extends SimplifyOptions = {},
33
- > = Options['deep'] extends true
34
- ? {[KeyType in keyof AnyType]: Simplify<AnyType[KeyType], Options>}
35
- : {[KeyType in keyof AnyType]: AnyType[KeyType]};
22
+ type Intersection = UnionToIntersection<Union>;
23
+ //=> {the(): void} & {great(arg: string): void} & {escape: boolean}
24
+ ```
25
+
26
+ @category Type
27
+ */
28
+ type UnionToIntersection<Union> = (
29
+ // `extends unknown` is always going to be the case and is used to convert the
30
+ // `Union` into a [distributive conditional
31
+ // type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
32
+ Union extends unknown
33
+ // The union type is used as the only argument to a function since the union
34
+ // of function arguments is an intersection.
35
+ ? (distributedUnion: Union) => void
36
+ // This won't happen.
37
+ : never
38
+ // Infer the `Intersection` type since TypeScript represents the positional
39
+ // arguments of unions of functions as an intersection of the union.
40
+ ) extends ((mergedIntersection: infer Intersection) => void)
41
+ // The `& Union` is to ensure result of `UnionToIntersection<A | B>` is always assignable to `A | B`
42
+ ? Intersection & Union
43
+ : never;
36
44
 
37
45
  /**
38
46
  Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
@@ -79,27 +87,25 @@ const literal = {foo: 123, bar: 'hello', baz: 456};
79
87
  const someType: SomeType = literal;
80
88
  const someInterface: SomeInterface = literal;
81
89
 
82
- function fn(object: Record<string, unknown>): void {}
90
+ declare function fn(object: Record<string, unknown>): void;
83
91
 
84
92
  fn(literal); // Good: literal object type is sealed
85
93
  fn(someType); // Good: type is sealed
94
+ // @ts-expect-error
86
95
  fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
87
96
  fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
88
97
  ```
89
98
 
90
99
  @link https://github.com/microsoft/TypeScript/issues/15300
91
-
100
+ @see {@link SimplifyDeep}
92
101
  @category Object
93
102
  */
94
- type Simplify<
95
- AnyType,
96
- Options extends SimplifyOptions = {},
97
- > = Flatten<AnyType> extends AnyType
98
- ? Flatten<AnyType, Options>
99
- : AnyType;
103
+ type Simplify<T> = {[KeyType in keyof T]: T[KeyType]} & {};
100
104
 
101
105
  /**
102
- Remove any index signatures from the given object type, so that only explicitly defined properties remain.
106
+ Omit any index signatures from the given object type, leaving only explicitly defined properties.
107
+
108
+ This is the counterpart of `PickIndexSignature`.
103
109
 
104
110
  Use-cases:
105
111
  - Remove overly permissive signatures from third-party types.
@@ -113,8 +119,9 @@ It relies on the fact that an empty object (`{}`) is assignable to an object wit
113
119
  ```
114
120
  const indexed: Record<string, unknown> = {}; // Allowed
115
121
 
122
+ // @ts-expect-error
116
123
  const keyed: Record<'foo', unknown> = {}; // Error
117
- // => TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
124
+ // TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
118
125
  ```
119
126
 
120
127
  Instead of causing a type error like the above, you can also use a [conditional type](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) to test whether a type is assignable to another:
@@ -123,147 +130,75 @@ Instead of causing a type error like the above, you can also use a [conditional
123
130
  type Indexed = {} extends Record<string, unknown>
124
131
  ? '✅ `{}` is assignable to `Record<string, unknown>`'
125
132
  : '❌ `{}` is NOT assignable to `Record<string, unknown>`';
126
- // => '✅ `{}` is assignable to `Record<string, unknown>`'
133
+
134
+ type IndexedResult = Indexed;
135
+ //=> '✅ `{}` is assignable to `Record<string, unknown>`'
127
136
 
128
137
  type Keyed = {} extends Record<'foo' | 'bar', unknown>
129
- ? "✅ `{}` is assignable to `Record<'foo' | 'bar', unknown>`"
130
- : "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`";
131
- // => "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`"
138
+ ? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
139
+ : '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
140
+
141
+ type KeyedResult = Keyed;
142
+ //=> '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`'
132
143
  ```
133
144
 
134
145
  Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
135
146
 
136
147
  ```
137
- import type {RemoveIndexSignature} from 'type-fest';
138
-
139
- type RemoveIndexSignature<ObjectType> = {
148
+ type OmitIndexSignature<ObjectType> = {
140
149
  [KeyType in keyof ObjectType // Map each key of `ObjectType`...
141
- ]: ObjectType[KeyType]; // ...to its original value, i.e. `RemoveIndexSignature<Foo> == Foo`.
150
+ ]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
142
151
  };
143
152
  ```
144
153
 
145
154
  ...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
146
155
 
147
156
  ```
148
- import type {RemoveIndexSignature} from 'type-fest';
149
-
150
- type RemoveIndexSignature<ObjectType> = {
157
+ type OmitIndexSignature<ObjectType> = {
151
158
  [KeyType in keyof ObjectType
152
- // Is `{}` assignable to `Record<KeyType, unknown>`?
153
- as {} extends Record<KeyType, unknown>
154
- ? ... // ✅ `{}` is assignable to `Record<KeyType, unknown>`
155
- : ... // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
159
+ // Is `{}` assignable to `Record<KeyType, unknown>`?
160
+ as {} extends Record<KeyType, unknown>
161
+ ? never // ✅ `{}` is assignable to `Record<KeyType, unknown>`
162
+ : KeyType // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
156
163
  ]: ObjectType[KeyType];
157
164
  };
158
165
  ```
159
166
 
160
167
  If `{}` is assignable, it means that `KeyType` is an index signature and we want to remove it. If it is not assignable, `KeyType` is a "real" key and we want to keep it.
161
168
 
162
- ```
163
- import type {RemoveIndexSignature} from 'type-fest';
164
-
165
- type RemoveIndexSignature<ObjectType> = {
166
- [KeyType in keyof ObjectType
167
- as {} extends Record<KeyType, unknown>
168
- ? never // => Remove this `KeyType`.
169
- : KeyType // => Keep this `KeyType` as it is.
170
- ]: ObjectType[KeyType];
171
- };
172
- ```
173
-
174
169
  @example
175
170
  ```
176
- import type {RemoveIndexSignature} from 'type-fest';
171
+ import type {OmitIndexSignature} from 'type-fest';
177
172
 
178
- interface Example {
173
+ type Example = {
179
174
  // These index signatures will be removed.
180
- [x: string]: any
181
- [x: number]: any
182
- [x: symbol]: any
183
- [x: `head-${string}`]: string
184
- [x: `${string}-tail`]: string
185
- [x: `head-${string}-tail`]: string
186
- [x: `${bigint}`]: string
187
- [x: `embedded-${number}`]: string
175
+ [x: string]: any;
176
+ [x: number]: any;
177
+ [x: symbol]: any;
178
+ [x: `head-${string}`]: string;
179
+ [x: `${string}-tail`]: string;
180
+ [x: `head-${string}-tail`]: string;
181
+ [x: `${bigint}`]: string;
182
+ [x: `embedded-${number}`]: string;
188
183
 
189
184
  // These explicitly defined keys will remain.
190
185
  foo: 'bar';
191
186
  qux?: 'baz';
192
- }
187
+ };
193
188
 
194
- type ExampleWithoutIndexSignatures = RemoveIndexSignature<Example>;
195
- // => { foo: 'bar'; qux?: 'baz' | undefined; }
189
+ type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
190
+ //=> {foo: 'bar'; qux?: 'baz'}
196
191
  ```
197
192
 
193
+ @see {@link PickIndexSignature}
198
194
  @category Object
199
195
  */
200
- type RemoveIndexSignature<ObjectType> = {
196
+ type OmitIndexSignature<ObjectType> = {
201
197
  [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
202
198
  ? never
203
199
  : KeyType]: ObjectType[KeyType];
204
200
  };
205
201
 
206
- /**
207
- Convert a union type to an intersection type using [distributive conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
208
-
209
- Inspired by [this Stack Overflow answer](https://stackoverflow.com/a/50375286/2172153).
210
-
211
- @example
212
- ```
213
- import type {UnionToIntersection} from 'type-fest';
214
-
215
- type Union = {the(): void} | {great(arg: string): void} | {escape: boolean};
216
-
217
- type Intersection = UnionToIntersection<Union>;
218
- //=> {the(): void; great(arg: string): void; escape: boolean};
219
- ```
220
-
221
- A more applicable example which could make its way into your library code follows.
222
-
223
- @example
224
- ```
225
- import type {UnionToIntersection} from 'type-fest';
226
-
227
- class CommandOne {
228
- commands: {
229
- a1: () => undefined,
230
- b1: () => undefined,
231
- }
232
- }
233
-
234
- class CommandTwo {
235
- commands: {
236
- a2: (argA: string) => undefined,
237
- b2: (argB: string) => undefined,
238
- }
239
- }
240
-
241
- const union = [new CommandOne(), new CommandTwo()].map(instance => instance.commands);
242
- type Union = typeof union;
243
- //=> {a1(): void; b1(): void} | {a2(argA: string): void; b2(argB: string): void}
244
-
245
- type Intersection = UnionToIntersection<Union>;
246
- //=> {a1(): void; b1(): void; a2(argA: string): void; b2(argB: string): void}
247
- ```
248
-
249
- @category Type
250
- */
251
- type UnionToIntersection<Union> = (
252
- // `extends unknown` is always going to be the case and is used to convert the
253
- // `Union` into a [distributive conditional
254
- // type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
255
- Union extends unknown
256
- // The union type is used as the only argument to a function since the union
257
- // of function arguments is an intersection.
258
- ? (distributedUnion: Union) => void
259
- // This won't happen.
260
- : never
261
- // Infer the `Intersection` type since TypeScript represents the positional
262
- // arguments of unions of functions as an intersection of the union.
263
- ) extends ((mergedIntersection: infer Intersection) => void)
264
- ? Intersection
265
- : never;
266
-
267
202
  /** Union of every registered full path (e.g. `'/' | '/admin/users' | '/$libraryId/$version'`). */
268
203
  type RegisteredFullPath = keyof Register['router']['routesByPath'];
269
204
  type IsAppRouteTree<TRoute> = TRoute extends Register['router']['routeTree'] ? true : false;
@@ -389,7 +324,7 @@ interface TanStackTypes<TRoute = undefined, Path extends DefaultStoryPath<TRoute
389
324
  /** Extracts and unions all args types from an array of decorators. */
390
325
  type DecoratorsArgs<TRenderer extends Renderer, Decorators> = UnionToIntersection<Decorators extends DecoratorFunction<TRenderer, infer TArgs> ? TArgs : unknown>;
391
326
  type InferCombinedTypes<T, TArgs, Decorators> = ReactTypes & T & {
392
- args: Simplify<TArgs & Simplify<RemoveIndexSignature<DecoratorsArgs<ReactTypes & T, Decorators>>>>;
327
+ args: Simplify<TArgs & Simplify<OmitIndexSignature<DecoratorsArgs<ReactTypes & T, Decorators>>>>;
393
328
  };
394
329
  type Preview<TRoute extends AnyRoute | undefined = undefined> = ProjectAnnotations<ReactTypes & TanStackTypes<TRoute>>;
395
330
  declare function definePreview<TRoute extends AnyRoute | undefined = undefined, const TPath extends DefaultStoryPath<TRoute> = DefaultStoryPath<TRoute>, Addons extends PreviewAddon<never>[] = []>(preview: {
@@ -435,4 +370,4 @@ interface TanStackPreview<T extends AddonTypes, TRoute extends AnyRoute | undefi
435
370
  }>;
436
371
  }
437
372
 
438
- export { type CreateStoryRouteOptions, type DefaultStoryPath, type FrameworkOptions, type IsRoute, type Meta, type Preview, type RouterParameters, type StoryObj, type StoryRouteFileOptions, type StoryRouteOptions, type StorybookConfig, type TanStackParameters, type TanStackPreviewOptions, type TanStackTypes, definePreview };
373
+ export { type CreateStoryRouteOptions, type DefaultStoryPath, type FrameworkOptions, type IsRoute, type Meta, type Preview, type RouterParameters, type StoryObj, type StoryRouteFileOptions, type StoryRouteOptions, type StorybookConfig, type TanStackParameters, type TanStackPreview, type TanStackPreviewOptions, type TanStackTypes, definePreview };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  preview_exports
3
- } from "./_browser-chunks/chunk-73EPJ7AY.js";
3
+ } from "./_browser-chunks/chunk-SNKUITN7.js";
4
4
  import "./_browser-chunks/chunk-4BE7D4DS.js";
5
5
 
6
6
  // src/index.ts
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_1b4p1p975w4 from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_1b4p1p975w4 from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_1b4p1p975w4 from "node:module";
1
+ import CJS_COMPAT_NODE_URL_k79t92w4o from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_k79t92w4o from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_k79t92w4o from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_1b4p1p975w4.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_1b4p1p975w4.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_1b4p1p975w4.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_k79t92w4o.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_k79t92w4o.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_k79t92w4o.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_1b4p1p975w4 from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_1b4p1p975w4 from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_1b4p1p975w4 from "node:module";
1
+ import CJS_COMPAT_NODE_URL_k79t92w4o from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_k79t92w4o from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_k79t92w4o from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_1b4p1p975w4.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_1b4p1p975w4.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_1b4p1p975w4.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_k79t92w4o.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_k79t92w4o.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_k79t92w4o.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
package/dist/preview.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  loaders,
4
4
  optimizeDeps,
5
5
  parameters
6
- } from "./_browser-chunks/chunk-73EPJ7AY.js";
6
+ } from "./_browser-chunks/chunk-SNKUITN7.js";
7
7
  import "./_browser-chunks/chunk-4BE7D4DS.js";
8
8
  export {
9
9
  applyDecorators,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/tanstack-react",
3
- "version": "10.5.0-alpha.2",
3
+ "version": "10.5.0-alpha.4",
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.5.0-alpha.2",
79
- "@storybook/react": "10.5.0-alpha.2",
80
- "@storybook/react-vite": "10.5.0-alpha.2"
78
+ "@storybook/builder-vite": "10.5.0-alpha.4",
79
+ "@storybook/react": "10.5.0-alpha.4",
80
+ "@storybook/react-vite": "10.5.0-alpha.4"
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.5.0-alpha.2",
98
+ "storybook": "^10.5.0-alpha.4",
99
99
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
100
100
  },
101
101
  "peerDependenciesMeta": {
@@ -14,7 +14,7 @@ const meta = {
14
14
  },
15
15
  // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
16
16
  tags: ['autodocs'],
17
- // More on argTypes: https://storybook.js.org/docs/api/argtypes
17
+ // More on argTypes: https://storybook.js.org/docs/api/arg-types
18
18
  argTypes: {
19
19
  backgroundColor: { control: 'color' },
20
20
  },
@@ -0,0 +1,73 @@
1
+ import React from 'react';
2
+
3
+ import type { Meta, StoryObj } from '@storybook/tanstack-react';
4
+
5
+ import { Outlet, createRootRoute, createRoute } from '@tanstack/react-router';
6
+ import { expect, within } from 'storybook/test';
7
+
8
+ // Regression coverage for https://github.com/storybookjs/storybook/issues/35007
9
+ // `@tanstack/react-router`'s `Outlet` used to be mocked as `() => null`, which
10
+ // silently swallowed any leaf content rendered inside a root layout. These
11
+ // stories assert that both the root layout and the leaf content render.
12
+
13
+ function LeafContent() {
14
+ return <p data-testid="tanstack-outlet-leaf">leaf rendered inside root outlet</p>;
15
+ }
16
+
17
+ const RootRoute = createRootRoute({
18
+ component: () => (
19
+ <div data-testid="tanstack-outlet-root">
20
+ <h1>root layout</h1>
21
+ <Outlet />
22
+ </div>
23
+ ),
24
+ });
25
+
26
+ const LeafRoute = createRoute({
27
+ getParentRoute: () => RootRoute,
28
+ path: '/',
29
+ component: LeafContent,
30
+ });
31
+
32
+ RootRoute.addChildren([LeafRoute]);
33
+
34
+ const meta = {
35
+ component: LeafContent,
36
+ parameters: { layout: 'fullscreen' },
37
+ } satisfies Meta<typeof LeafContent>;
38
+
39
+ export default meta;
40
+
41
+ type Story = StoryObj<typeof meta>;
42
+
43
+ /** Passing the leaf `Route` should render it inside the root layout's `<Outlet />`. */
44
+ export const RendersLeafInsideRootOutlet: Story = {
45
+ parameters: {
46
+ tanstack: { router: { route: LeafRoute } },
47
+ },
48
+ play: async ({ canvasElement }) => {
49
+ const canvas = within(canvasElement);
50
+ await expect(canvas.getByTestId('tanstack-outlet-root')).toBeInTheDocument();
51
+ await expect(
52
+ canvas.getByRole('heading', { level: 1, name: 'root layout' })
53
+ ).toBeInTheDocument();
54
+ await expect(canvas.getByTestId('tanstack-outlet-leaf')).toBeInTheDocument();
55
+ },
56
+ };
57
+
58
+ /** Passing the whole route tree plus an explicit `path` resolves through the same outlet. */
59
+ export const RendersLeafViaRouteTreePath: Story = {
60
+ parameters: {
61
+ tanstack: {
62
+ router: { route: RootRoute, path: '/' },
63
+ },
64
+ },
65
+ play: async ({ canvasElement }) => {
66
+ const canvas = within(canvasElement);
67
+ await expect(canvas.getByTestId('tanstack-outlet-root')).toBeInTheDocument();
68
+ await expect(
69
+ canvas.getByRole('heading', { level: 1, name: 'root layout' })
70
+ ).toBeInTheDocument();
71
+ await expect(canvas.getByTestId('tanstack-outlet-leaf')).toBeInTheDocument();
72
+ },
73
+ };