Skip to content

Commit ae7de6e

Browse files
Merge pull request #1035 from storybookjs/next
Create a new pull request by comparing changes across two branches
2 parents 8a0ce23 + 125bdd3 commit ae7de6e

File tree

16 files changed

+316
-110
lines changed

16 files changed

+316
-110
lines changed

code/addons/test/src/postinstall.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ export default async function postInstall(options: PostinstallOptions) {
145145
`);
146146
}
147147

148+
const mswVersionSpecifier = await packageManager.getInstalledVersion('msw');
149+
const coercedMswVersion = mswVersionSpecifier ? coerce(mswVersionSpecifier) : null;
150+
151+
if (coercedMswVersion && !satisfies(coercedMswVersion, '>=2.0.0')) {
152+
reasons.push(dedent`
153+
• The addon uses Vitest behind the scenes, which supports only version 2 and above of MSW. However, we have detected version ${picocolors.bold(coercedMswVersion.version)} in this project.
154+
Please update the 'msw' package and try again.
155+
`);
156+
}
157+
148158
if (info.frameworkPackageName === '@storybook/nextjs') {
149159
const nextVersion = await packageManager.getInstalledVersion('next');
150160
if (!nextVersion) {
@@ -159,6 +169,7 @@ export default async function postInstall(options: PostinstallOptions) {
159169
reasons.unshift(
160170
`Storybook Test's automated setup failed due to the following package incompatibilities:`
161171
);
172+
reasons.push('--------------------------------');
162173
reasons.push(
163174
dedent`
164175
You can fix these issues and rerun the command to reinstall. If you wish to roll back the installation, remove ${picocolors.bold(colors.pink(ADDON_NAME))} from the "addons" array

code/builders/builder-vite/src/codegen-importfn-script.test.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import { beforeEach, describe, expect, it, vi } from 'vitest';
1+
import { describe, expect, it, vi } from 'vitest';
22

33
import { toImportFn } from './codegen-importfn-script';
44

55
describe('toImportFn', () => {
66
it('should correctly map story paths to import functions for absolute paths on Linux', async () => {
7-
const root = '/absolute/path';
7+
vi.spyOn(process, 'cwd').mockReturnValue('/absolute/path');
8+
89
const stories = ['/absolute/path/to/story1.js', '/absolute/path/to/story2.js'];
910

10-
const result = await toImportFn(root, stories);
11+
const result = await toImportFn(stories);
1112

1213
expect(result).toMatchInlineSnapshot(`
1314
"const importers = {
@@ -22,10 +23,10 @@ describe('toImportFn', () => {
2223
});
2324

2425
it('should correctly map story paths to import functions for absolute paths on Windows', async () => {
25-
const root = 'C:\\absolute\\path';
26+
vi.spyOn(process, 'cwd').mockReturnValue('C:\\absolute\\path');
2627
const stories = ['C:\\absolute\\path\\to\\story1.js', 'C:\\absolute\\path\\to\\story2.js'];
2728

28-
const result = await toImportFn(root, stories);
29+
const result = await toImportFn(stories);
2930

3031
expect(result).toMatchInlineSnapshot(`
3132
"const importers = {
@@ -43,7 +44,7 @@ describe('toImportFn', () => {
4344
const root = '/absolute/path';
4445
const stories: string[] = [];
4546

46-
const result = await toImportFn(root, stories);
47+
const result = await toImportFn(stories);
4748

4849
expect(result).toMatchInlineSnapshot(`
4950
"const importers = {};

code/builders/builder-vite/src/codegen-importfn-script.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ function toImportPath(relativePath: string) {
2929
*
3030
* @param stories An array of absolute story paths.
3131
*/
32-
export async function toImportFn(root: string, stories: string[]) {
32+
export async function toImportFn(stories: string[]) {
3333
const objectEntries = stories.map((file) => {
34-
const relativePath = relative(root, file);
34+
const relativePath = relative(process.cwd(), file);
3535

3636
return [toImportPath(relativePath), genDynamicImport(normalize(file))] as [string, string];
3737
});
@@ -51,5 +51,5 @@ export async function generateImportFnScriptCode(options: Options): Promise<stri
5151

5252
// We can then call toImportFn to create a function that can be used to load each story dynamically.
5353
// eslint-disable-next-line @typescript-eslint/return-await
54-
return await toImportFn(options.projectRoot || process.cwd(), stories);
54+
return await toImportFn(stories);
5555
}

code/builders/builder-vite/src/vite-config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,18 @@ export async function commonConfig(
5353

5454
const { viteConfigPath } = await getBuilderOptions<BuilderOptions>(options);
5555

56-
options.projectRoot = options.projectRoot || resolve(options.configDir, '..');
56+
const projectRoot = resolve(options.configDir, '..');
5757

5858
// I destructure away the `build` property from the user's config object
5959
// I do this because I can contain config that breaks storybook, such as we had in a lit project.
6060
// If the user needs to configure the `build` they need to do so in the viteFinal function in main.js.
6161
const { config: { build: buildProperty = undefined, ...userConfig } = {} } =
62-
(await loadConfigFromFile(configEnv, viteConfigPath, options.projectRoot)) ?? {};
62+
(await loadConfigFromFile(configEnv, viteConfigPath, projectRoot)) ?? {};
6363

6464
const sbConfig: InlineConfig = {
6565
configFile: false,
6666
cacheDir: resolvePathInStorybookCache('sb-vite', options.cacheKey),
67-
root: options.projectRoot,
67+
root: projectRoot,
6868
// Allow storybook deployed as subfolder. See https://github.com/storybookjs/builder-vite/issues/238
6969
base: './',
7070
plugins: await pluginConfig(options),

code/core/src/manager/container/Panel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const createPanelActions = memoize(1)((api) => ({
1616
togglePosition: () => api.togglePanelPosition(),
1717
}));
1818

19-
const getPanels = (api: API) => {
19+
const getPanels = memoize(1)((api: API) => {
2020
const allPanels = api.getElements(Addon_TypesEnum.PANEL);
2121
const story = api.getCurrentStoryData();
2222

@@ -42,7 +42,7 @@ const getPanels = (api: API) => {
4242
});
4343

4444
return filteredPanels;
45-
};
45+
});
4646

4747
const mapper = ({ state, api }: Combo) => ({
4848
panels: getPanels(api),

code/core/src/types/modules/core-common.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ export interface BuilderOptions {
195195
ignorePreview?: boolean;
196196
cache?: FileSystemCache;
197197
configDir: string;
198-
projectRoot?: string;
199198
docsMode?: boolean;
200199
features?: StorybookConfigRaw['features'];
201200
versionCheck?: VersionCheck;

code/frameworks/react-native-web-vite/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@
5353
"prep": "jiti ../../../scripts/prepare/bundle.ts"
5454
},
5555
"dependencies": {
56+
"@babel/plugin-transform-modules-commonjs": "^7.26.3",
57+
"@babel/preset-react": "^7.26.3",
5658
"@bunchtogether/vite-plugin-flow": "^1.0.2",
5759
"@joshwooding/vite-plugin-react-docgen-typescript": "0.4.2",
5860
"@storybook/builder-vite": "workspace:*",
5961
"@storybook/react": "workspace:*",
6062
"@storybook/react-vite": "workspace:*",
6163
"@vitejs/plugin-react": "^4.3.2",
64+
"vite-plugin-babel": "^1.3.0",
6265
"vite-tsconfig-paths": "^5.1.4"
6366
},
6467
"devDependencies": {

code/frameworks/react-native-web-vite/src/preset.ts

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { viteFinal as reactViteFinal } from '@storybook/react-vite/preset';
33
import { esbuildFlowPlugin, flowPlugin } from '@bunchtogether/vite-plugin-flow';
44
import react from '@vitejs/plugin-react';
55
import type { InlineConfig, PluginOption } from 'vite';
6+
import babel from 'vite-plugin-babel';
67
import tsconfigPaths from 'vite-tsconfig-paths';
78

89
import type { FrameworkOptions, StorybookConfig } from './types';
@@ -64,25 +65,68 @@ export function reactNativeWeb(): PluginOption {
6465
export const viteFinal: StorybookConfig['viteFinal'] = async (config, options) => {
6566
const { mergeConfig } = await import('vite');
6667

67-
const { pluginReactOptions = {} } =
68+
const { pluginReactOptions = {}, pluginBabelOptions = {} } =
6869
await options.presets.apply<FrameworkOptions>('frameworkOptions');
6970

71+
const isDevelopment = options.configType !== 'PRODUCTION';
72+
7073
const reactConfig = await reactViteFinal(config, options);
7174

7275
const { plugins = [] } = reactConfig;
7376

7477
plugins.unshift(
7578
tsconfigPaths(),
79+
80+
// fix for react native packages shipping with flow types untranspiled
7681
flowPlugin({
7782
exclude: [/node_modules\/(?!react-native|@react-native)/],
7883
}),
7984
react({
85+
...pluginReactOptions,
86+
jsxRuntime: pluginReactOptions.jsxRuntime || 'automatic',
8087
babel: {
8188
babelrc: false,
8289
configFile: false,
90+
...pluginReactOptions.babel,
91+
},
92+
}),
93+
94+
// we need to add this extra babel config because the react plugin doesn't allow
95+
// for transpiling node_modules. We need this because many react native packages are un-transpiled.
96+
// see this pr for more context: https://github.com/vitejs/vite-plugin-react/pull/306
97+
// However we keep the react plugin to get the fast refresh and the other stuff its doing
98+
babel({
99+
...pluginBabelOptions,
100+
include: pluginBabelOptions.include || [/node_modules\/(react-native|@react-native)/],
101+
exclude: pluginBabelOptions.exclude,
102+
babelConfig: {
103+
...pluginBabelOptions.babelConfig,
104+
babelrc: false,
105+
configFile: false,
106+
presets: [
107+
[
108+
'@babel/preset-react',
109+
{
110+
development: isDevelopment,
111+
runtime: 'automatic',
112+
...(pluginBabelOptions.presetReact || {}),
113+
},
114+
],
115+
...(pluginBabelOptions.babelConfig?.presets || []),
116+
],
117+
plugins: [
118+
[
119+
// this is a fix for reanimated not working in production
120+
'@babel/plugin-transform-modules-commonjs',
121+
{
122+
strict: false,
123+
strictMode: false, // prevent "use strict" injections
124+
allowTopLevelThis: true, // dont rewrite global `this` -> `undefined`
125+
},
126+
],
127+
...(pluginBabelOptions.babelConfig?.plugins || []),
128+
],
83129
},
84-
jsxRuntime: 'automatic',
85-
...pluginReactOptions,
86130
})
87131
);
88132

@@ -91,6 +135,7 @@ export const viteFinal: StorybookConfig['viteFinal'] = async (config, options) =
91135
return mergeConfig(reactConfig, {
92136
optimizeDeps: {
93137
esbuildOptions: {
138+
// fix for react native packages shipping with flow types untranspiled
94139
plugins: [esbuildFlowPlugin(new RegExp(/\.(flow|jsx?)$/), (_path: string) => 'jsx')],
95140
},
96141
},

code/frameworks/react-native-web-vite/src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@ import type {
66
} from '@storybook/react-vite';
77

88
import type { BabelOptions, Options as ReactOptions } from '@vitejs/plugin-react';
9+
import type { BabelPluginOptions } from 'vite-plugin-babel';
910

1011
export type FrameworkOptions = FrameworkOptionsBase & {
1112
pluginReactOptions?: Omit<ReactOptions, 'babel'> & { babel?: BabelOptions };
13+
pluginBabelOptions?: BabelPluginOptions & {
14+
presetReact?: {
15+
[key: string]: any;
16+
runtime?: 'automatic' | 'classic';
17+
importSource?: string;
18+
};
19+
};
1220
};
1321

1422
type FrameworkName = CompatibleString<'@storybook/react-native-web-vite'>;

code/lib/cli-storybook/src/add.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,19 @@ export async function add(
111111

112112
let shouldAddToMain = true;
113113
if (checkInstalled(addonName, requireMain(configDir))) {
114-
const { shouldForceInstall } = await prompts({
115-
type: 'confirm',
116-
name: 'shouldForceInstall',
117-
message: `The Storybook addon "${addonName}" is already present in ${mainConfig}. Do you wish to install it again?`,
118-
});
119-
120-
if (!shouldForceInstall) {
121-
return;
122-
}
123-
124114
shouldAddToMain = false;
115+
if (!yes) {
116+
logger.log(`The Storybook addon "${addonName}" is already present in ${mainConfig}.`);
117+
const { shouldForceInstall } = await prompts({
118+
type: 'confirm',
119+
name: 'shouldForceInstall',
120+
message: `Do you wish to install it again?`,
121+
});
122+
123+
if (!shouldForceInstall) {
124+
return;
125+
}
126+
}
125127
}
126128

127129
const main = await readConfig(mainConfig);

0 commit comments

Comments
 (0)