import { useEffect, useState } from 'react'; import { IntlProvider } from 'react-intl'; import { MemoryRouter, Route } from 'react-router'; import { configureStore } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; import type { Preview } from '@storybook/react-vite'; import { initialize, mswLoader } from 'msw-storybook-addon'; import { action } from 'storybook/actions'; import type { LocaleData } from '@/mastodon/locales'; import { reducerWithInitialState, rootReducer } from '@/mastodon/reducers'; import { defaultMiddleware } from '@/mastodon/store/store'; import { mockHandlers, unhandledRequestHandler } from '@/testing/api'; // If you want to run the dark theme during development, // you can change the below to `/application.scss` import '../app/javascript/styles/mastodon-light.scss'; const localeFiles = import.meta.glob('@/mastodon/locales/*.json', { query: { as: 'json' }, }); // Initialize MSW initialize({ onUnhandledRequest: unhandledRequestHandler, }); const preview: Preview = { // Auto-generate docs: https://storybook.js.org/docs/writing-docs/autodocs tags: ['autodocs'], globalTypes: { locale: { description: 'Locale for the story', toolbar: { title: 'Locale', icon: 'globe', items: Object.keys(localeFiles).map((path) => path.replace('/mastodon/locales/', '').replace('.json', ''), ), dynamicTitle: true, }, }, }, initialGlobals: { locale: 'en', }, decorators: [ (Story, { parameters }) => { const { state = {} } = parameters; let reducer = rootReducer; if (typeof state === 'object' && state) { reducer = reducerWithInitialState(state as Record); } const store = configureStore({ reducer, middleware(getDefaultMiddleware) { return getDefaultMiddleware(defaultMiddleware); }, }); return ( ); }, (Story, { globals }) => { const currentLocale = (globals.locale as string) || 'en'; const [messages, setMessages] = useState< Record> >({}); const currentLocaleData = messages[currentLocale]; useEffect(() => { async function loadLocaleData() { const { default: localeFile } = (await import( `@/mastodon/locales/${currentLocale}.json` )) as { default: LocaleData['messages'] }; setMessages((prevLocales) => ({ ...prevLocales, [currentLocale]: localeFile, })); } if (!currentLocaleData) { void loadLocaleData(); } }, [currentLocale, currentLocaleData]); return ( ); }, (Story) => ( { if (location.pathname !== '/') { action(`route change to ${location.pathname}`)(location); } return null; }} /> ), ], loaders: [mswLoader], parameters: { layout: 'centered', controls: { matchers: { color: /(background|color)$/i, date: /Date$/i, }, }, a11y: { // 'todo' - show a11y violations in the test UI only // 'error' - fail CI on a11y violations // 'off' - skip a11y checks entirely test: 'todo', }, state: {}, docs: {}, msw: { handlers: mockHandlers, }, }, }; export default preview;