1- import type { Decorator } from '@storybook/react' ;
1+ import type { Decorator } from '@storybook/react-vite ' ;
22import type { ComponentType } from 'react' ;
33import {
44 type ActionFunction ,
5- type IndexRouteObject ,
65 type LinksFunction ,
76 type LoaderFunction ,
87 type MetaFunction ,
9- type NonIndexRouteObject ,
10- RouterProvider ,
11- createMemoryRouter ,
12- } from 'react-router-dom' ;
8+ createRoutesStub ,
9+ } from 'react-router' ;
1310
14- export type StubRouteObject = StubIndexRouteObject | StubNonIndexRouteObject ;
15-
16- interface StubNonIndexRouteObject
17- extends Omit < NonIndexRouteObject , 'loader' | 'action' | 'element' | 'errorElement' | 'children' > {
11+ export interface StubRouteObject {
12+ path ?: string ;
13+ index ?: boolean ;
1814 loader ?: LoaderFunction ;
1915 action ?: ActionFunction ;
20- children ?: StubRouteObject [ ] ;
2116 meta ?: MetaFunction ;
2217 links ?: LinksFunction ;
23- // biome-ignore lint/suspicious/noExplicitAny: allow any here
18+ // biome-ignore lint/suspicious/noExplicitAny: allow any here for Storybook compatibility
2419 Component ?: ComponentType < any > ;
25- }
26-
27- interface StubIndexRouteObject
28- extends Omit < IndexRouteObject , 'loader' | 'action' | 'element' | 'errorElement' | 'children' > {
29- loader ?: LoaderFunction ;
30- action ?: ActionFunction ;
3120 children ?: StubRouteObject [ ] ;
32- meta ?: MetaFunction ;
33- links ?: LinksFunction ;
34- // biome-ignore lint/suspicious/noExplicitAny: allow any here
35- Component ?: ComponentType < any > ;
21+ // biome-ignore lint/suspicious/noExplicitAny: allow any here for Storybook compatibility
22+ errorElement ?: any ;
3623}
3724
3825interface RemixStubOptions {
@@ -42,34 +29,28 @@ interface RemixStubOptions {
4229
4330export const withReactRouterStubDecorator = ( options : RemixStubOptions ) : Decorator => {
4431 const { routes, initialPath = '/' } = options ;
45- // This outer function runs once when Storybook loads the story meta
4632
4733 return ( Story , context ) => {
48- // This inner function runs when the story component actually renders
34+ // Map routes to include the Story component if no Component is provided
4935 const mappedRoutes = routes . map ( ( route ) => ( {
5036 ...route ,
5137 Component : route . Component ?? ( ( ) => < Story { ...context . args } /> ) ,
5238 } ) ) ;
5339
5440 // Get the base path (without existing query params from options)
5541 const basePath = initialPath . split ( '?' ) [ 0 ] ;
56-
42+
5743 // Get the current search string from the actual browser window, if available
5844 // If not available, use a default search string with parameters needed for the data table
59- const currentWindowSearch = typeof window !== 'undefined'
60- ? window . location . search
61- : '?page=0&pageSize=10' ;
62-
45+ const currentWindowSearch = typeof window !== 'undefined' ? window . location . search : '?page=0&pageSize=10' ;
46+
6347 // Combine them for the initial entry
6448 const actualInitialPath = `${ basePath } ${ currentWindowSearch } ` ;
6549
66- // Create a memory router, initializing it with the path derived from the window's search params
67- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
68- const router = createMemoryRouter ( mappedRoutes as any , {
69- initialEntries : [ actualInitialPath ] , // Use the path combined with window.location.search
70- } ) ;
50+ // Use React Router's official createRoutesStub
51+ const Stub = createRoutesStub ( mappedRoutes ) ;
7152
72- return < RouterProvider router = { router } /> ;
53+ return < Stub initialEntries = { [ actualInitialPath ] } /> ;
7354 } ;
7455} ;
7556
0 commit comments