From add44fcc6aaa1860b2eb20e2a6a46663fad3ac0c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 28 Nov 2023 09:54:54 +0100 Subject: [PATCH 01/51] dynamic import vite to force ESM mode --- code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts | 5 +++-- code/frameworks/svelte-vite/src/preset.ts | 2 +- .../sveltekit/src/plugins/mock-sveltekit-stores.ts | 5 +++-- code/frameworks/sveltekit/src/preset.ts | 2 +- code/frameworks/vue-vite/src/plugins/vue-docgen.ts | 4 ++-- code/frameworks/vue-vite/src/preset.ts | 2 +- code/frameworks/vue3-vite/src/plugins/vue-docgen.ts | 4 ++-- code/frameworks/vue3-vite/src/preset.ts | 5 +++-- 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts index 5ee6f7e53ce8..1e33174e11a5 100644 --- a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts +++ b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts @@ -6,7 +6,6 @@ import svelteDoc from 'sveltedoc-parser'; import type { SvelteComponentDoc, SvelteParserOptions } from 'sveltedoc-parser'; import { logger } from '@storybook/node-logger'; import { preprocess } from 'svelte/compiler'; -import { createFilter } from 'vite'; import { replace, typescript } from 'svelte-preprocess'; /* @@ -59,10 +58,12 @@ function getNameFromFilename(filename: string) { return base[0].toUpperCase() + base.slice(1); } -export function svelteDocgen(svelteOptions: Record = {}): PluginOption { +export async function svelteDocgen(svelteOptions: Record = {}): Promise { const cwd = process.cwd(); const { preprocess: preprocessOptions, logDocgen = false } = svelteOptions; const include = /\.(svelte)$/; + const { createFilter } = await import('vite'); + const filter = createFilter(include); let docPreprocessOptions: Parameters[1] | undefined; diff --git a/code/frameworks/svelte-vite/src/preset.ts b/code/frameworks/svelte-vite/src/preset.ts index 220812cf7c5a..2abc47c9d8b1 100644 --- a/code/frameworks/svelte-vite/src/preset.ts +++ b/code/frameworks/svelte-vite/src/preset.ts @@ -26,7 +26,7 @@ export const viteFinal: NonNullable = async (confi } // Add docgen plugin - plugins.push(svelteDocgen(svelteConfig)); + plugins.push(await svelteDocgen(svelteConfig)); await handleSvelteKit(plugins, options); diff --git a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts index 873ce8bf3517..62031b412bcf 100644 --- a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts +++ b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts @@ -1,7 +1,8 @@ import { resolve } from 'node:path'; -import { mergeConfig, type Plugin } from 'vite'; +import type { Plugin } from 'vite'; -export function mockSveltekitStores() { +export async function mockSveltekitStores() { + const { mergeConfig } = await import('vite'); return { name: 'storybook:sveltekit-mock-stores', enforce: 'post', diff --git a/code/frameworks/sveltekit/src/preset.ts b/code/frameworks/sveltekit/src/preset.ts index 45cfe7d0a6dd..bef848c9250d 100644 --- a/code/frameworks/sveltekit/src/preset.ts +++ b/code/frameworks/sveltekit/src/preset.ts @@ -32,7 +32,7 @@ export const viteFinal: NonNullable = async (confi ]) ) .concat(configOverrides()) - .concat(mockSveltekitStores()); + .concat(await mockSveltekitStores()); return { ...baseConfig, plugins }; }; diff --git a/code/frameworks/vue-vite/src/plugins/vue-docgen.ts b/code/frameworks/vue-vite/src/plugins/vue-docgen.ts index e80ca52d60c2..4fb6107e5bc8 100644 --- a/code/frameworks/vue-vite/src/plugins/vue-docgen.ts +++ b/code/frameworks/vue-vite/src/plugins/vue-docgen.ts @@ -1,10 +1,10 @@ import { parse } from 'vue-docgen-api'; import type { PluginOption } from 'vite'; -import { createFilter } from 'vite'; import MagicString from 'magic-string'; -export function vueDocgen(): PluginOption { +export async function vueDocgen(): Promise { const include = /\.(vue)$/; + const { createFilter } = await import('vite'); const filter = createFilter(include); return { diff --git a/code/frameworks/vue-vite/src/preset.ts b/code/frameworks/vue-vite/src/preset.ts index 3030587afaaa..598b325d1b00 100644 --- a/code/frameworks/vue-vite/src/preset.ts +++ b/code/frameworks/vue-vite/src/preset.ts @@ -1,6 +1,5 @@ import { dirname, join } from 'path'; import type { PresetProperty } from '@storybook/types'; -import { mergeConfig } from 'vite'; import type { StorybookConfig } from './types'; import { vueDocgen } from './plugins/vue-docgen'; @@ -21,6 +20,7 @@ export const core: PresetProperty<'core', StorybookConfig> = async (config, opti }; export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => { + const { mergeConfig } = await import('vite'); return mergeConfig(config, { plugins: [vueDocgen()], resolve: { diff --git a/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts b/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts index 6bed6a1fed98..f8008fc3a4bd 100644 --- a/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts +++ b/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts @@ -1,10 +1,10 @@ import { parse } from 'vue-docgen-api'; import type { PluginOption } from 'vite'; -import { createFilter } from 'vite'; import MagicString from 'magic-string'; -export function vueDocgen(): PluginOption { +export async function vueDocgen(): Promise { const include = /\.(vue)$/; + const { createFilter } = await import('vite'); const filter = createFilter(include); return { diff --git a/code/frameworks/vue3-vite/src/preset.ts b/code/frameworks/vue3-vite/src/preset.ts index b987f0381c0b..bc9fd7752d1e 100644 --- a/code/frameworks/vue3-vite/src/preset.ts +++ b/code/frameworks/vue3-vite/src/preset.ts @@ -1,6 +1,6 @@ import { hasVitePlugins } from '@storybook/builder-vite'; import type { PresetProperty } from '@storybook/types'; -import { mergeConfig, type PluginOption } from 'vite'; +import type { PluginOption } from 'vite'; import { dirname, join } from 'path'; import type { StorybookConfig } from './types'; import { vueDocgen } from './plugins/vue-docgen'; @@ -23,8 +23,9 @@ export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets } // Add docgen plugin - plugins.push(vueDocgen()); + plugins.push(await vueDocgen()); + const { mergeConfig } = await import('vite'); return mergeConfig(config, { plugins, resolve: { From 78f1c3569f55c1500aa6ab96ab45dddabd3fcaf5 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 28 Nov 2023 09:56:48 +0100 Subject: [PATCH 02/51] improve readability of list of sandbox templates --- scripts/utils/options.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/utils/options.ts b/scripts/utils/options.ts index f5340c037a85..b6e7c930b9fc 100644 --- a/scripts/utils/options.ts +++ b/scripts/utils/options.ts @@ -140,11 +140,12 @@ export function getOptions( const checkStringValue = (raw: string) => { if (option.values && !option.values.includes(raw)) { - const possibleOptions = chalk.cyan(option.values.join(', ')); + const possibleOptions = chalk.cyan(option.values.join('\n')); throw new Error( dedent`Unexpected value '${chalk.yellow(raw)}' for option '${chalk.magenta(key)}'. - These are the possible options: ${possibleOptions}\n\n` + These are the possible options: + ${possibleOptions}\n\n` ); } return raw; From 3fc9be5f3f03a54f535845427c597aa92676b53c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 28 Nov 2023 10:34:26 +0100 Subject: [PATCH 03/51] add eslint rule to enforce dynamic vite imports --- code/.eslintrc.js | 12 ++++++++++++ code/builders/builder-vite/src/vite-config.test.ts | 1 + .../sveltekit/src/plugins/config-overrides.ts | 2 +- code/ui/.storybook/main.ts | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/code/.eslintrc.js b/code/.eslintrc.js index 953ccaf79d25..ab453987a3ee 100644 --- a/code/.eslintrc.js +++ b/code/.eslintrc.js @@ -34,6 +34,18 @@ module.exports = { allowIndexSignaturePropertyAccess: true, }, ], + '@typescript-eslint/no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'vite', + message: 'Please dynamically import from vite instead, to force the use of ESM', + allowTypeImports: true, + }, + ], + }, + ], }, overrides: [ { diff --git a/code/builders/builder-vite/src/vite-config.test.ts b/code/builders/builder-vite/src/vite-config.test.ts index c4f2f212be48..a373bf7dce19 100644 --- a/code/builders/builder-vite/src/vite-config.test.ts +++ b/code/builders/builder-vite/src/vite-config.test.ts @@ -1,4 +1,5 @@ import type { Options, Presets } from '@storybook/types'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports import { loadConfigFromFile } from 'vite'; import { commonConfig } from './vite-config'; diff --git a/code/frameworks/sveltekit/src/plugins/config-overrides.ts b/code/frameworks/sveltekit/src/plugins/config-overrides.ts index d132764d6e5c..db5294a13242 100644 --- a/code/frameworks/sveltekit/src/plugins/config-overrides.ts +++ b/code/frameworks/sveltekit/src/plugins/config-overrides.ts @@ -1,4 +1,4 @@ -import { type Plugin } from 'vite'; +import type { Plugin } from 'vite'; export function configOverrides() { return { diff --git a/code/ui/.storybook/main.ts b/code/ui/.storybook/main.ts index 4800dda1e181..a15c3a4fd988 100644 --- a/code/ui/.storybook/main.ts +++ b/code/ui/.storybook/main.ts @@ -1,5 +1,6 @@ import path from 'path'; import pluginTurbosnap from 'vite-plugin-turbosnap'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports import { mergeConfig } from 'vite'; import type { StorybookConfig } from '../../frameworks/react-vite'; From 6b5d9c7446284e442f8356991a2a8b73c701421f Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 20 Dec 2023 11:54:51 -0300 Subject: [PATCH 04/51] fix upgrade command --- code/lib/cli/src/upgrade.test.ts | 2 +- code/lib/cli/src/upgrade.ts | 38 +++++++++++++++---- .../core-events/src/errors/server-errors.ts | 34 ++++++++++++++++- 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/code/lib/cli/src/upgrade.test.ts b/code/lib/cli/src/upgrade.test.ts index 3acb5fd92a0d..6fcea5f84596 100644 --- a/code/lib/cli/src/upgrade.test.ts +++ b/code/lib/cli/src/upgrade.test.ts @@ -63,7 +63,7 @@ describe('addNxPackagesToReject', () => { const flags = ['--reject', '/preset-create-react-app/', '--some-flag', 'hello']; expect(addNxPackagesToReject(flags)).toMatchObject([ '--reject', - '/(preset-create-react-app|@nrwl/storybook|@nx/storybook)/', + '"/(preset-create-react-app|@nrwl/storybook|@nx/storybook)/"', '--some-flag', 'hello', ]); diff --git a/code/lib/cli/src/upgrade.ts b/code/lib/cli/src/upgrade.ts index aefd6bc8bc07..12ef940a090a 100644 --- a/code/lib/cli/src/upgrade.ts +++ b/code/lib/cli/src/upgrade.ts @@ -3,6 +3,10 @@ import { telemetry, getStorybookCoreVersion } from '@storybook/telemetry'; import semver from 'semver'; import { logger } from '@storybook/node-logger'; import { withTelemetry } from '@storybook/core-server'; +import { + ConflictingVersionTagsError, + UpgradeStorybookPackagesError, +} from '@storybook/core-events/server-errors'; import type { PackageJsonWithMaybeDeps, PackageManagerName } from './js-package-manager'; import { getPackageDetails, JsPackageManagerFactory, useNpmWarning } from './js-package-manager'; @@ -117,7 +121,7 @@ export const addNxPackagesToReject = (flags: string[]) => { if (newFlags[index + 1].endsWith('/') && newFlags[index + 1].startsWith('/')) { // Remove last and first slash so that I can add the parentheses newFlags[index + 1] = newFlags[index + 1].substring(1, newFlags[index + 1].length - 1); - newFlags[index + 1] = `/(${newFlags[index + 1]}|@nrwl/storybook|@nx/storybook)/`; + newFlags[index + 1] = `"/(${newFlags[index + 1]}|@nrwl/storybook|@nx/storybook)/"`; } else { // Adding the two packages as comma-separated values // If the existing rejects are in regex format, they will be ignored. @@ -163,12 +167,10 @@ export const doUpgrade = async ({ const beforeVersion = await getStorybookCoreVersion(); - commandLog(`Checking for latest versions of '@storybook/*' packages`); + commandLog(`Checking for latest versions of '@storybook/*' packages\n`); if (tag && prerelease) { - throw new Error( - `Cannot set both --tag and --prerelease. Use --tag next to get the latest prereleae` - ); + throw new ConflictingVersionTagsError(); } let target = 'latest'; @@ -187,20 +189,40 @@ export const doUpgrade = async ({ flags.push(target); flags = addExtraFlags(EXTRA_FLAGS, flags, await packageManager.retrievePackageJson()); flags = addNxPackagesToReject(flags); - const check = spawnSync('npx', ['npm-check-updates@latest', '/storybook/', ...flags], { + + const command = 'npx'; + const checkArgs = ['npm-check-updates@latest', '/storybook/', ...flags]; + const check = spawnSync(command, checkArgs, { stdio: 'pipe', shell: true, }); + + if (check.stderr && !check.stderr.toString().includes('npm notice')) { + throw new UpgradeStorybookPackagesError({ + command, + args: checkArgs, + errorMessage: check.stderr.toString(), + }); + } + logger.info(check.stdout.toString()); - logger.info(check.stderr.toString()); - const checkSb = spawnSync('npx', ['npm-check-updates@latest', 'sb', ...flags], { + const checkSbArgs = ['npm-check-updates@latest', 'sb', ...flags]; + const checkSb = spawnSync(command, checkSbArgs, { stdio: 'pipe', shell: true, }); logger.info(checkSb.stdout.toString()); logger.info(checkSb.stderr.toString()); + if (checkSb.stderr && !checkSb.stderr.toString().includes('npm notice')) { + throw new UpgradeStorybookPackagesError({ + command, + args: checkSbArgs, + errorMessage: checkSb.stderr.toString(), + }); + } + if (!dryRun) { commandLog(`Installing upgrades`); await packageManager.installDependencies(); diff --git a/code/lib/core-events/src/errors/server-errors.ts b/code/lib/core-events/src/errors/server-errors.ts index bacdd7d6055e..5f9f98d7ec8e 100644 --- a/code/lib/core-events/src/errors/server-errors.ts +++ b/code/lib/core-events/src/errors/server-errors.ts @@ -422,7 +422,7 @@ export class GenerateNewProjectOnInitError extends StorybookError { super(); } - template(): string { + template() { return dedent` There was an error while using ${this.data.packageManager} to create a new ${ this.data.projectType @@ -432,3 +432,35 @@ export class GenerateNewProjectOnInitError extends StorybookError { `; } } + +export class ConflictingVersionTagsError extends StorybookError { + readonly category = Category.CLI_UPGRADE; + + readonly code = 1; + + template() { + return 'Cannot set both --tag and --prerelease. Use --tag=next to get the latest prerelease.'; + } +} + +export class UpgradeStorybookPackagesError extends StorybookError { + readonly category = Category.CLI_UPGRADE; + + readonly code = 2; + + constructor(public data: { command: string; args: string[]; errorMessage: string }) { + super(); + } + + template() { + return dedent` + There was an error while trying to upgrade your Storybook dependencies. + + Command: + ${this.data.command} ${this.data.args.join(' ')} + + Error: + ${this.data.errorMessage} + `; + } +} From e3479a02fade42353ec6a1900c191f62f5de1845 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Wed, 27 Dec 2023 00:16:38 +0800 Subject: [PATCH 05/51] Viewport: Store viewport, rotation in globals --- code/addons/essentials/package.json | 4 +- .../addons/essentials/src/viewport/preview.ts | 2 + code/addons/viewport/package.json | 4 ++ code/addons/viewport/preview.js | 1 + code/addons/viewport/src/Tool.tsx | 72 +++++++++---------- code/addons/viewport/src/preview.ts | 1 + code/addons/viewport/src/shortcuts.ts | 31 ++++---- 7 files changed, 57 insertions(+), 58 deletions(-) create mode 100644 code/addons/essentials/src/viewport/preview.ts create mode 100644 code/addons/viewport/preview.js create mode 100644 code/addons/viewport/src/preview.ts diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index ab47a59356b8..bd0ef466715d 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -43,6 +43,7 @@ "./outline/manager": "./dist/outline/manager.js", "./toolbars/manager": "./dist/toolbars/manager.js", "./viewport/manager": "./dist/viewport/manager.js", + "./viewport/preview": "./dist/viewport/preview.js", "./package.json": "./package.json" }, "main": "dist/index.js", @@ -102,7 +103,8 @@ "./src/docs/preview.ts", "./src/highlight/preview.ts", "./src/measure/preview.ts", - "./src/outline/preview.ts" + "./src/outline/preview.ts", + "./src/viewport/preview.ts" ] }, "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17" diff --git a/code/addons/essentials/src/viewport/preview.ts b/code/addons/essentials/src/viewport/preview.ts new file mode 100644 index 000000000000..34ee7de45614 --- /dev/null +++ b/code/addons/essentials/src/viewport/preview.ts @@ -0,0 +1,2 @@ +// @ts-expect-error (no types needed for this) +export * from '@storybook/addon-viewport/preview'; diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index c110c4fba7f9..1537d5d54f09 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -29,6 +29,7 @@ "require": "./dist/index.js", "import": "./dist/index.mjs" }, + "./preview": "./dist/preview.js", "./manager": "./dist/manager.js", "./package.json": "./package.json" }, @@ -72,6 +73,9 @@ ], "managerEntries": [ "./src/manager.tsx" + ], + "previewEntries": [ + "./src/preview.ts" ] }, "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17", diff --git a/code/addons/viewport/preview.js b/code/addons/viewport/preview.js new file mode 100644 index 000000000000..6a4da7cfa953 --- /dev/null +++ b/code/addons/viewport/preview.js @@ -0,0 +1 @@ +export { globals } from './dist/preview'; diff --git a/code/addons/viewport/src/Tool.tsx b/code/addons/viewport/src/Tool.tsx index 093d16bb57ba..229f5e21bafa 100644 --- a/code/addons/viewport/src/Tool.tsx +++ b/code/addons/viewport/src/Tool.tsx @@ -6,10 +6,10 @@ import { styled, Global, type Theme, withTheme } from '@storybook/theming'; import { IconButton, WithTooltip, TooltipLinkList } from '@storybook/components'; -import { useStorybookApi, useParameter, useAddonState } from '@storybook/manager-api'; +import { useStorybookApi, useParameter, useGlobals } from '@storybook/manager-api'; import { GrowIcon, TransferIcon } from '@storybook/icons'; import { registerShortcuts } from './shortcuts'; -import { PARAM_KEY, ADDON_ID } from './constants'; +import { PARAM_KEY } from './constants'; import { MINIMAL_VIEWPORTS } from './defaults'; import type { ViewportAddonParameter, ViewportMap, ViewportStyles, Styles } from './models'; @@ -35,19 +35,21 @@ const responsiveViewport: ViewportItem = { const baseViewports: ViewportItem[] = [responsiveViewport]; -const toLinks = memoize(50)((list: ViewportItem[], active: LinkBase, set, state, close): Link[] => { - return list - .filter((i) => i.id !== responsiveViewport.id || active.id !== i.id) - .map((i) => { - return { - ...i, - onClick: () => { - set({ ...state, selected: i.id }); - close(); - }, - }; - }); -}); +const toLinks = memoize(50)( + (list: ViewportItem[], active: LinkBase, updateGlobals, close): Link[] => { + return list + .filter((i) => i.id !== responsiveViewport.id || active.id !== i.id) + .map((i) => { + return { + ...i, + onClick: () => { + updateGlobals({ viewport: i.id }); + close(); + }, + }; + }); + } +); interface LinkBase { id: string; @@ -95,11 +97,6 @@ const IconButtonLabel = styled.div(({ theme }) => ({ marginLeft: 10, })); -interface ViewportToolState { - isRotated: boolean; - selected: string | null; -} - const getStyles = ( prevStyles: ViewportStyles | undefined, styles: Styles, @@ -115,16 +112,14 @@ const getStyles = ( export const ViewportTool: FC = memo( withTheme(({ theme }: { theme: Theme }) => { + const [globals, updateGlobals] = useGlobals(); + const { viewports = MINIMAL_VIEWPORTS, defaultOrientation = 'portrait', - defaultViewport = responsiveViewport.id, + defaultViewport = globals.viewport || responsiveViewport.id, disable, } = useParameter(PARAM_KEY, {}); - const [state, setState] = useAddonState(ADDON_ID, { - selected: defaultViewport, - isRotated: defaultOrientation === 'landscape', - }); const list = toList(viewports); const api = useStorybookApi(); @@ -138,28 +133,29 @@ export const ViewportTool: FC = memo( } useEffect(() => { - registerShortcuts(api, setState, Object.keys(viewports)); - }, [viewports]); + registerShortcuts(api, globals, updateGlobals, Object.keys(viewports)); + }, [viewports, globals.viewport]); useEffect(() => { - setState({ - selected: + updateGlobals({ + viewport: defaultViewport || - (state.selected && viewports[state.selected] ? state.selected : responsiveViewport.id), - isRotated: defaultOrientation === 'landscape', + (globals.viewport && viewports[globals.viewport] + ? globals.viewport + : responsiveViewport.id), + viewportRotated: defaultOrientation === 'landscape', }); }, [defaultOrientation, defaultViewport]); - const { selected, isRotated } = state; const item = - list.find((i) => i.id === selected) || + list.find((i) => i.id === globals.viewport) || list.find((i) => i.id === defaultViewport) || list.find((i) => i.default) || responsiveViewport; const ref = useRef(); - const styles = getStyles(ref.current, item.styles, isRotated); + const styles = getStyles(ref.current, item.styles, globals.viewportRotated); useEffect(() => { ref.current = styles; @@ -174,7 +170,7 @@ export const ViewportTool: FC = memo( ( - + )} closeOnOutsideClick onVisibleChange={setIsTooltipVisible} @@ -184,13 +180,13 @@ export const ViewportTool: FC = memo( title="Change the size of the preview" active={isTooltipVisible || !!styles} onDoubleClick={() => { - setState({ ...state, selected: responsiveViewport.id }); + updateGlobals({ viewport: responsiveViewport.id }); }} > {styles ? ( - {isRotated ? `${item.title} (L)` : `${item.title} (P)`} + {globals.viewportRotated ? `${item.title} (L)` : `${item.title} (P)`} ) : null} @@ -215,7 +211,7 @@ export const ViewportTool: FC = memo( key="viewport-rotate" title="Rotate viewport" onClick={() => { - setState({ ...state, isRotated: !isRotated }); + updateGlobals({ viewportRotated: !globals.viewportRotated }); }} > diff --git a/code/addons/viewport/src/preview.ts b/code/addons/viewport/src/preview.ts new file mode 100644 index 000000000000..afe0f1b5f0b4 --- /dev/null +++ b/code/addons/viewport/src/preview.ts @@ -0,0 +1 @@ +export const globals = { viewport: 'reset', viewportRotated: false }; diff --git a/code/addons/viewport/src/shortcuts.ts b/code/addons/viewport/src/shortcuts.ts index 39cff92af12b..47fd37cbb996 100644 --- a/code/addons/viewport/src/shortcuts.ts +++ b/code/addons/viewport/src/shortcuts.ts @@ -1,10 +1,6 @@ import type { API } from '@storybook/manager-api'; import { ADDON_ID } from './constants'; - -type State = { - selected: string; - isRotated: boolean; -}; +import { globals as defaultGlobals } from './preview'; const getCurrentViewportIndex = (viewportsKeys: string[], current: string): number => viewportsKeys.indexOf(current); @@ -23,16 +19,19 @@ const getPreviousViewport = (viewportsKeys: string[], current: string): string = : viewportsKeys[currentViewportIndex - 1]; }; -export const registerShortcuts = async (api: API, setState: any, viewportsKeys: string[]) => { +export const registerShortcuts = async ( + api: API, + globals: any, + updateGlobals: any, + viewportsKeys: string[] +) => { await api.setAddonShortcut(ADDON_ID, { label: 'Previous viewport', defaultShortcut: ['shift', 'V'], actionName: 'previous', action: () => { - const { selected, isRotated } = api.getAddonState(ADDON_ID); - setState({ - selected: getPreviousViewport(viewportsKeys, selected), - isRotated, + updateGlobals({ + viewport: getPreviousViewport(viewportsKeys, globals.viewport), }); }, }); @@ -42,10 +41,8 @@ export const registerShortcuts = async (api: API, setState: any, viewportsKeys: defaultShortcut: ['V'], actionName: 'next', action: () => { - const { selected, isRotated } = api.getAddonState(ADDON_ID); - setState({ - selected: getNextViewport(viewportsKeys, selected), - isRotated, + updateGlobals({ + viewport: getNextViewport(viewportsKeys, globals.viewport), }); }, }); @@ -55,11 +52,7 @@ export const registerShortcuts = async (api: API, setState: any, viewportsKeys: defaultShortcut: ['alt', 'V'], actionName: 'reset', action: () => { - const { isRotated } = api.getAddonState(ADDON_ID); - setState({ - selected: 'reset', - isRotated, - }); + updateGlobals(defaultGlobals); }, }); }; From 22808bacfce3c631ac764ab71f94501bb3611418 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 21 Dec 2023 18:13:19 -0300 Subject: [PATCH 06/51] upgrade docs-mdx to use mdx3 --- code/lib/core-server/package.json | 2 +- code/yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index b12fe37ae249..74e02800af96 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -68,7 +68,7 @@ "@storybook/core-events": "workspace:*", "@storybook/csf": "^0.1.2", "@storybook/csf-tools": "workspace:*", - "@storybook/docs-mdx": "^0.1.0", + "@storybook/docs-mdx": "0.1.1--canary.13.929b700.0", "@storybook/global": "^5.0.0", "@storybook/manager": "workspace:*", "@storybook/node-logger": "workspace:*", diff --git a/code/yarn.lock b/code/yarn.lock index 6fe3d551d312..e2c309bdd234 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -5460,7 +5460,7 @@ __metadata: "@storybook/core-events": "workspace:*" "@storybook/csf": "npm:^0.1.2" "@storybook/csf-tools": "workspace:*" - "@storybook/docs-mdx": "npm:^0.1.0" + "@storybook/docs-mdx": "npm:0.1.1--canary.13.929b700.0" "@storybook/global": "npm:^5.0.0" "@storybook/manager": "workspace:*" "@storybook/node-logger": "workspace:*" @@ -5593,10 +5593,10 @@ __metadata: languageName: node linkType: hard -"@storybook/docs-mdx@npm:^0.1.0": - version: 0.1.0 - resolution: "@storybook/docs-mdx@npm:0.1.0" - checksum: e4d510f0452a7a3cb09d9617920c18b974f836299dfba38d6b2e62fbfea418d71f340b6c280a87201b1336a7221c7cc16b47794c1f8e81d01dcfa1f599343085 +"@storybook/docs-mdx@npm:0.1.1--canary.13.929b700.0": + version: 0.1.1--canary.13.929b700.0 + resolution: "@storybook/docs-mdx@npm:0.1.1--canary.13.929b700.0" + checksum: 6d2608099deb3dbc789c5a62f0e36ff86c3fe90f728723eb0610b0313f7128a8587ffb23ffaae65737a87669c8f89f7aba058d8bf18b44b3b3132396915b3a45 languageName: node linkType: hard From b1113682438604831c6e2fdad3fe9c3ae59e83b7 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 22 Dec 2023 09:23:49 -0300 Subject: [PATCH 07/51] upgrade mdx-js/react in addon-docs --- code/addons/docs/package.json | 2 +- code/yarn.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index 84eb2c858ec2..49c99a534831 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -99,7 +99,7 @@ }, "dependencies": { "@jest/transform": "^29.3.1", - "@mdx-js/react": "^2.1.5", + "@mdx-js/react": "^3.0.0", "@storybook/blocks": "workspace:*", "@storybook/client-logger": "workspace:*", "@storybook/components": "workspace:*", diff --git a/code/yarn.lock b/code/yarn.lock index e2c309bdd234..321a5de49a7b 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -3514,15 +3514,15 @@ __metadata: languageName: node linkType: hard -"@mdx-js/react@npm:^2.1.5": - version: 2.3.0 - resolution: "@mdx-js/react@npm:2.3.0" +"@mdx-js/react@npm:^3.0.0": + version: 3.0.0 + resolution: "@mdx-js/react@npm:3.0.0" dependencies: "@types/mdx": "npm:^2.0.0" - "@types/react": "npm:>=16" peerDependencies: + "@types/react": ">=16" react: ">=16" - checksum: 6d647115703dbe258f7fe372499fa8c6fe17a053ff0f2a208111c9973a71ae738a0ed376770445d39194d217e00e1a015644b24f32c2f7cb4f57988de0649b15 + checksum: 865f6ebc7ae83c6cb9f7e92db4eddd3f85cd1664391643b4736887ddc32b0ddb5aec012db6fbc9b486b552e08e6d5ad800450fcd9d51c20665667ff0f174d966 languageName: node linkType: hard @@ -4733,7 +4733,7 @@ __metadata: resolution: "@storybook/addon-docs@workspace:addons/docs" dependencies: "@jest/transform": "npm:^29.3.1" - "@mdx-js/react": "npm:^2.1.5" + "@mdx-js/react": "npm:^3.0.0" "@rollup/pluginutils": "npm:^5.0.2" "@storybook/blocks": "workspace:*" "@storybook/client-logger": "workspace:*" @@ -8068,7 +8068,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:>=16, @types/react@npm:^18.0.37": +"@types/react@npm:*, @types/react@npm:^18.0.37": version: 18.2.43 resolution: "@types/react@npm:18.2.43" dependencies: From ecea7ddc1167ebd29cc5c33182127d0be7886c4a Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 28 Dec 2023 07:28:21 -0300 Subject: [PATCH 08/51] bring mdx-csf compiler into addon docs --- code/addons/docs/README.md | 14 - code/addons/docs/jest-transform-mdx.js | 22 - code/addons/docs/package.json | 8 +- code/addons/docs/src/compiler/index.test.ts | 2128 +++++++++++++++++++ code/addons/docs/src/compiler/index.ts | 29 + code/addons/docs/src/compiler/types.ts | 19 + code/addons/docs/src/mdx-loader.ts | 45 + code/addons/docs/src/plugins/mdx-plugin.ts | 18 +- code/addons/docs/src/preset.ts | 105 +- code/addons/docs/src/typings.d.ts | 1 - code/addons/docs/vitest.config.ts | 6 + code/yarn.lock | 911 +++++++- 12 files changed, 3140 insertions(+), 166 deletions(-) delete mode 100644 code/addons/docs/jest-transform-mdx.js create mode 100644 code/addons/docs/src/compiler/index.test.ts create mode 100644 code/addons/docs/src/compiler/index.ts create mode 100644 code/addons/docs/src/compiler/types.ts create mode 100644 code/addons/docs/src/mdx-loader.ts diff --git a/code/addons/docs/README.md b/code/addons/docs/README.md index 9a9a3debad2a..379b23f2d8a1 100644 --- a/code/addons/docs/README.md +++ b/code/addons/docs/README.md @@ -110,20 +110,6 @@ export default { }; ``` -If using in conjunction with the [storyshots add-on](https://github.com/storybookjs/storybook/blob/next/code/addons/storyshots-core/README.md), you will need to -configure Jest to transform MDX stories into something Storyshots can understand: - -Add the following to your Jest configuration: - -```json -{ - "transform": { - "^.+\\.[tj]sx?$": "babel-jest", - "^.+\\.mdx$": "@storybook/addon-docs/jest-transform-mdx" - } -} -``` - ### Be sure to check framework specific installation needs - [React](https://github.com/storybookjs/storybook/tree/next/code/addons/docs/react) (covered here) diff --git a/code/addons/docs/jest-transform-mdx.js b/code/addons/docs/jest-transform-mdx.js deleted file mode 100644 index eb3106944ae1..000000000000 --- a/code/addons/docs/jest-transform-mdx.js +++ /dev/null @@ -1,22 +0,0 @@ -const path = require('path'); -const { ScriptTransformer } = require('@jest/transform'); -const { dedent } = require('ts-dedent'); - -const { compile } = require('@storybook/mdx2-csf'); - -module.exports = { - async processAsync(src, filename, config, { instrument }) { - const code = await compile(src, { skipCsf: false }); - const result = dedent` - /* @jsx mdx */ - import React from 'react' - import { mdx } from '@mdx-js/react' - ${code} - `; - - const extension = path.extname(filename); - const jsFileName = `${filename.slice(0, -extension.length)}.js`; - - return new ScriptTransformer(config).transformSource(jsFileName, result, instrument); - }, -}; diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index 49c99a534831..6269405a41da 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -71,7 +71,6 @@ "./angular": "./angular/index.js", "./angular/index.js": "./angular/index.js", "./web-components/index.js": "./web-components/index.js", - "./jest-transform-mdx": "./jest-transform-mdx.js", "./package.json": "./package.json" }, "main": "dist/index.js", @@ -98,7 +97,8 @@ "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@jest/transform": "^29.3.1", + "@babel/core": "^7.12.3", + "@mdx-js/mdx": "^3.0.0", "@mdx-js/react": "^3.0.0", "@storybook/blocks": "workspace:*", "@storybook/client-logger": "workspace:*", @@ -106,7 +106,6 @@ "@storybook/csf-plugin": "workspace:*", "@storybook/csf-tools": "workspace:*", "@storybook/global": "^5.0.0", - "@storybook/mdx2-csf": "^1.0.0", "@storybook/node-logger": "workspace:*", "@storybook/preview-api": "workspace:*", "@storybook/react-dom-shim": "workspace:*", @@ -134,9 +133,6 @@ "./src/preview.ts", "./src/blocks.ts", "./src/shims/mdx-react-shim.ts" - ], - "externals": [ - "@storybook/mdx1-csf" ] }, "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17", diff --git a/code/addons/docs/src/compiler/index.test.ts b/code/addons/docs/src/compiler/index.test.ts new file mode 100644 index 000000000000..1f9618552c09 --- /dev/null +++ b/code/addons/docs/src/compiler/index.test.ts @@ -0,0 +1,2128 @@ +import { expect, describe, it } from 'vitest'; +import { dedent } from 'ts-dedent'; +import prettier from 'prettier'; +import { compileSync, compile } from './index'; + +expect.addSnapshotSerializer({ + serialize: (val: any) => (typeof val === 'string' ? val : val.toString()), + test: (val) => true, +}); + +const clean = (mdx: string) => { + const code = compileSync(mdx); + + return prettier + .format(code, { + parser: 'babel', + printWidth: 100, + tabWidth: 2, + bracketSpacing: true, + trailingComma: 'es5', + singleQuote: true, + }) + .trim(); +}; + +describe('mdx2', () => { + it('works', () => { + const input = dedent` + # hello + + + + world {2 + 1} + + bar + `; + + expect(clean(input)).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + p: 'p', + ..._provideComponents(), + ...props.components, + }, + { Meta, Story } = _components; + if (!Meta) _missingMdxReference('Meta', true); + if (!Story) _missingMdxReference('Story', true); + return _jsxs(_Fragment, { + children: [ + _jsx(_components.h1, { + children: 'hello', + }), + '\\n', + _jsx(Meta, { + title: 'foobar', + }), + '\\n', + _jsxs(_components.p, { + children: ['world ', 2 + 1], + }), + '\\n', + _jsx(Story, { + name: 'foo', + children: 'bar', + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + function _missingMdxReference(id, component) { + throw new Error( + 'Expected ' + + (component ? 'component' : 'object') + + ' \`' + + id + + '\` to be defined: you likely forgot to import, pass, or provide it.' + ); + } + `); + }); + + it('standalone jsx expressions', () => { + expect( + clean(dedent` + # Standalone JSX expressions + + {3 + 3} + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(_components.h1, { + children: 'Standalone JSX expressions', + }), + '\\n', + 3 + 3, + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); +}); + +describe('full snapshots', () => { + it('compileSync', () => { + const input = dedent` + # hello + + + + world {2 + 1} + + bar + `; + + expect(compileSync(input)).toMatchInlineSnapshot(` + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + function _createMdxContent(props) { + const _components = { + h1: "h1", + p: "p", + ..._provideComponents(), + ...props.components + }, {Meta, Story} = _components; + if (!Meta) _missingMdxReference("Meta", true); + if (!Story) _missingMdxReference("Story", true); + return _jsxs(_Fragment, { + children: [_jsx(_components.h1, { + children: "hello" + }), "\\n", _jsx(Meta, { + title: "foobar" + }), "\\n", _jsxs(_components.p, { + children: ["world ", 2 + 1] + }), "\\n", _jsx(Story, { + name: "foo", + children: "bar" + })] + }); + } + export default function MDXContent(props = {}) { + const {wrapper: MDXLayout} = { + ..._provideComponents(), + ...props.components + }; + return MDXLayout ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props + }) + }) : _createMdxContent(props); + } + function _missingMdxReference(id, component) { + throw new Error("Expected " + (component ? "component" : "object") + " \`" + id + "\` to be defined: you likely forgot to import, pass, or provide it."); + } + `); + }); + it('compile', async () => { + const input = dedent` + # hello + + + + world {2 + 1} + + bar + `; + expect(await compile(input)).toMatchInlineSnapshot(` + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + function _createMdxContent(props) { + const _components = { + h1: "h1", + p: "p", + ..._provideComponents(), + ...props.components + }, {Meta, Story} = _components; + if (!Meta) _missingMdxReference("Meta", true); + if (!Story) _missingMdxReference("Story", true); + return _jsxs(_Fragment, { + children: [_jsx(_components.h1, { + children: "hello" + }), "\\n", _jsx(Meta, { + title: "foobar" + }), "\\n", _jsxs(_components.p, { + children: ["world ", 2 + 1] + }), "\\n", _jsx(Story, { + name: "foo", + children: "bar" + })] + }); + } + export default function MDXContent(props = {}) { + const {wrapper: MDXLayout} = { + ..._provideComponents(), + ...props.components + }; + return MDXLayout ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props + }) + }) : _createMdxContent(props); + } + function _missingMdxReference(id, component) { + throw new Error("Expected " + (component ? "component" : "object") + " \`" + id + "\` to be defined: you likely forgot to import, pass, or provide it."); + } + `); + }); + it('sync & async should match', async () => { + const input = dedent` + # hello + + + + world {2 + 1} + + bar + `; + + const ou1 = compileSync(input); + const ou2 = await compile(input); + + expect(ou1).toEqual(ou2); + }); + + it('canvas with story', () => { + const input = dedent` + import { Canvas, Meta, Story } from '@storybook/addon-docs'; + + + + + +
I'm a story
+
+
+ `; + expect(compileSync(input)).toMatchInlineSnapshot(` + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Canvas, Meta, Story} from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsxs(_Fragment, { + children: [_jsx(Meta, { + title: "MDX/Badge" + }), "\\n", _jsx(Canvas, { + children: _jsx(Story, { + name: "foo", + children: _jsx("div", { + children: "I'm a story" + }) + }) + })] + }); + } + export default function MDXContent(props = {}) { + const {wrapper: MDXLayout} = { + ..._provideComponents(), + ...props.components + }; + return MDXLayout ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props + }) + }) : _createMdxContent(props); + } + `); + }); + + it('canvas without story children', () => { + const input = dedent` + import { Canvas } from '@storybook/addon-docs'; + + +

Some here

+
+ `; + expect(compileSync(input)).toMatchInlineSnapshot(` + import {jsx as _jsx} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Canvas} from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsx(Canvas, { + children: _jsx("h2", { + children: "Some here" + }) + }); + } + export default function MDXContent(props = {}) { + const {wrapper: MDXLayout} = { + ..._provideComponents(), + ...props.components + }; + return MDXLayout ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props + }) + }) : _createMdxContent(props); + } + `); + }); +}); + +describe('docs-mdx-compiler-plugin', () => { + it('component-args.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + # Args + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + args: { + a: 1, + b: 2, + }, + argTypes: { + a: { + name: 'A', + }, + b: { + name: 'B', + }, + }, + }), + '\\n', + _jsx(_components.h1, { + children: 'Args', + }), + '\\n', + _jsx(Story, { + name: 'component notes', + children: _jsx(Button, { + children: 'Component notes', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('component-id.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + component: Button, + id: 'button-id', + }), + '\\n', + _jsx(Story, { + name: 'component notes', + children: _jsx(Button, { + children: 'Component notes', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('csf-imports.mdx', () => { + expect( + clean(dedent` + import { Story, Meta, Canvas } from '@storybook/addon-docs'; + import { Welcome, Button } from '@storybook/angular/demo'; + import * as MyStories from './My.stories'; + import { Other } from './Other.stories'; + + + + # Stories from CSF imports + + + + + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Story, Meta, Canvas } from '@storybook/addon-docs'; + import { Welcome, Button } from '@storybook/angular/demo'; + import * as MyStories from './My.stories'; + import { Other } from './Other.stories'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'MDX/CSF imports', + }), + '\\n', + _jsx(_components.h1, { + children: 'Stories from CSF imports', + }), + '\\n', + _jsx(Story, { + story: MyStories.Basic, + }), + '\\n', + _jsx(Canvas, { + children: _jsx(Story, { + story: Other, + }), + }), + '\\n', + _jsx(Story, { + name: 'renamed', + story: MyStories.Foo, + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('decorators.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + +
{storyFn()}
]} + /> + + # Decorated story + +
{storyFn()}
]}> + +
+ `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + div: 'div', + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + decorators: [ + (storyFn) => + _jsx(_components.div, { + style: { + backgroundColor: 'yellow', + }, + children: storyFn(), + }), + ], + }), + '\\n', + _jsx(_components.h1, { + children: 'Decorated story', + }), + '\\n', + _jsx(Story, { + name: 'one', + decorators: [ + (storyFn) => + _jsx(_components.div, { + className: 'local', + children: storyFn(), + }), + ], + children: _jsx(Button, { + children: 'One', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('docs-only.mdx', () => { + expect( + clean(dedent` + import { Meta } from '@storybook/addon-docs'; + + + + # Documentation only + + This is a documentation-only MDX file which cleans a dummy 'docsOnly: true' story. + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + p: 'p', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'docs-only', + }), + '\\n', + _jsx(_components.h1, { + children: 'Documentation only', + }), + '\\n', + _jsx(_components.p, { + children: + "This is a documentation-only MDX file which cleans a dummy 'docsOnly: true' story.", + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('loaders.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + ({ foo: 1 })]} /> + + # Story with loader + + ({ bar: 2 })]}> + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + loaders: [ + async () => ({ + foo: 1, + }), + ], + }), + '\\n', + _jsx(_components.h1, { + children: 'Story with loader', + }), + '\\n', + _jsx(Story, { + name: 'one', + loaders: [ + async () => ({ + bar: 2, + }), + ], + children: _jsx(Button, { + children: 'One', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('meta-quotes-in-title.mdx', () => { + expect( + clean(dedent` + import { Meta } from '@storybook/addon-docs'; + + + `) + ).toMatchInlineSnapshot(` + import { jsx as _jsx } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsx(Meta, { + title: "Addons/Docs/what's in a title?", + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('non-story-exports.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + # Story definition + + + + + + export const two = 2; + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + export const two = 2; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + }), + '\\n', + _jsx(_components.h1, { + children: 'Story definition', + }), + '\\n', + _jsx(Story, { + name: 'one', + children: _jsx(Button, { + children: 'One', + }), + }), + '\\n', + '\\n', + _jsx(Story, { + name: 'hello story', + children: _jsx(Button, { + children: 'Hello button', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('parameters.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + + + + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + component: Button, + parameters: { + notes: 'component notes', + }, + }), + '\\n', + _jsx(Story, { + name: 'component notes', + children: _jsx(Button, { + children: 'Component notes', + }), + }), + '\\n', + _jsx(Story, { + name: 'story notes', + parameters: { + notes: 'story notes', + }, + children: _jsx(Button, { + children: 'Story notes', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('previews.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Canvas, Story, Meta } from '@storybook/addon-docs'; + + + + # Canvas + + Canvases can contain normal components, stories, and story references + + + + + + + + + + + + + Canvas without a story + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Canvas, Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + p: 'p', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + component: Button, + parameters: { + notes: 'component notes', + }, + }), + '\\n', + _jsx(_components.h1, { + children: 'Canvas', + }), + '\\n', + _jsx(_components.p, { + children: 'Canvases can contain normal components, stories, and story references', + }), + '\\n', + _jsxs(Canvas, { + children: [ + _jsx(Button, { + children: 'Just a button', + }), + _jsx(Story, { + name: 'hello button', + children: _jsx(Button, { + children: 'Hello button', + }), + }), + _jsx(Story, { + name: 'two', + children: _jsx(Button, { + children: 'Two', + }), + }), + _jsx(Story, { + id: 'welcome--welcome', + }), + ], + }), + '\\n', + _jsx(_components.p, { + children: 'Canvas without a story', + }), + '\\n', + _jsx(Canvas, { + children: _jsx(Button, { + children: 'Just a button', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('story-args.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + # Args + + export const Template = (args) => ; + + + {Template.bind({})} + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + export const Template = (args) => + _jsx(Button, { + children: 'Component notes', + }); + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + }), + '\\n', + _jsx(_components.h1, { + children: 'Args', + }), + '\\n', + '\\n', + _jsx(Story, { + name: 'component notes', + args: { + a: 1, + b: 2, + }, + argTypes: { + a: { + name: 'A', + }, + b: { + name: 'B', + }, + }, + children: Template.bind({}), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('story-current.mdx', () => { + expect( + clean(dedent` + import { Story } from '@storybook/addon-docs'; + + # Current story + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Story } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(_components.h1, { + children: 'Current story', + }), + '\\n', + _jsx(Story, { + id: '.', + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('story-def-text-only.mdx', () => { + expect( + clean(dedent` + import { Story, Meta } from '@storybook/addon-docs'; + + + + # Story definition + + Plain text + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Text', + }), + '\\n', + _jsx(_components.h1, { + children: 'Story definition', + }), + '\\n', + _jsx(Story, { + name: 'text', + children: 'Plain text', + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('story-definitions.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + # Story definition + + + + + + + + + + + + + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + }), + '\\n', + _jsx(_components.h1, { + children: 'Story definition', + }), + '\\n', + _jsx(Story, { + name: 'one', + children: _jsx(Button, { + children: 'One', + }), + }), + '\\n', + _jsx(Story, { + name: 'hello story', + children: _jsx(Button, { + children: 'Hello button', + }), + }), + '\\n', + _jsx(Story, { + name: 'w/punctuation', + children: _jsx(Button, { + children: 'with punctuation', + }), + }), + '\\n', + _jsx(Story, { + name: '1 fine day', + children: _jsx(Button, { + children: 'starts with number', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('story-function-var.mdx', () => { + expect( + clean(dedent` + import { Meta, Story } from '@storybook/addon-docs'; + + + + export const basicFn = () => + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + p: 'p', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(_components.h1, { + children: 'Hello MDX', + }), + '\\n', + _jsx(_components.p, { + children: 'This is some random content.', + }), + '\\n', + _jsx(Button, { + children: 'Hello button', + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + describe('csf3', () => { + it('auto-title-docs-only.mdx', () => { + expect( + clean(dedent` + import { Meta } from '@storybook/addon-docs'; + + + + # Auto-title Docs Only + + Spme **markdown** here! + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: 'h1', + p: 'p', + strong: 'strong', + ..._provideComponents(), + ...props.components, + }; + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, {}), + '\\n', + _jsx(_components.h1, { + children: 'Auto-title Docs Only', + }), + '\\n', + _jsxs(_components.p, { + children: [ + 'Spme ', + _jsx(_components.strong, { + children: 'markdown', + }), + ' here!', + ], + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('auto-title.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + component: Button, + }), + '\\n', + _jsx(Story, { + name: 'Basic', + children: _jsx(Button, { + children: 'Basic', + }), + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('default-render.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + + `) + ).toMatchInlineSnapshot(` + import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; + import { useMDXComponents as _provideComponents } from '@mdx-js/react'; + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsxs(_Fragment, { + children: [ + _jsx(Meta, { + title: 'Button', + component: Button, + }), + '\\n', + _jsx(Story, { + name: 'Basic', + }), + ], + }); + } + export default function MDXContent(props = {}) { + const { wrapper: MDXLayout } = { + ..._provideComponents(), + ...props.components, + }; + return MDXLayout + ? _jsx(MDXLayout, { + ...props, + children: _jsx(_createMdxContent, { + ...props, + }), + }) + : _createMdxContent(props); + } + `); + }); + + it('component-render.mdx', () => { + expect( + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + ', + }, + }; + const componentMeta = { + title: 'Button', + args: { + a: 1, + b: 2, + }, + argTypes: { + a: { + name: 'A', + }, + b: { + name: 'B', + }, + }, + tags: ['stories-mdx'], + includeStories: ['componentNotes'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -429,42 +423,29 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - component: Button, - id: 'button-id', - }), - '\\n', - _jsx(Story, { - name: 'component notes', - children: _jsx(Button, { - children: 'Component notes', - }), - }), - ], + export const componentNotes = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Component notes', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + componentNotes.storyName = 'component notes'; + componentNotes.parameters = { + storySource: { + source: '', + }, + }; + const componentMeta = { + title: 'Button', + id: 'button-id', + component: Button, + tags: ['stories-mdx'], + includeStories: ['componentNotes'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -489,59 +470,21 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Story, Meta, Canvas } from '@storybook/addon-docs'; - import { Welcome, Button } from '@storybook/angular/demo'; - import * as MyStories from './My.stories'; - import { Other } from './Other.stories'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'MDX/CSF imports', - }), - '\\n', - _jsx(_components.h1, { - children: 'Stories from CSF imports', - }), - '\\n', - _jsx(Story, { - story: MyStories.Basic, - }), - '\\n', - _jsx(Canvas, { - children: _jsx(Story, { - story: Other, - }), - }), - '\\n', - _jsx(Story, { - name: 'renamed', - story: MyStories.Foo, - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const _Basic_ = MyStories.Basic; + export const _Other_ = Other; + export const _Foo_ = MyStories.Foo; + _Foo_.storyName = 'renamed'; + const componentMeta = { + title: 'MDX/CSF imports', + tags: ['stories-mdx'], + includeStories: ['_Basic_', '_Other_', '_Foo_'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -563,66 +506,43 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - div: 'div', - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - decorators: [ - (storyFn) => - _jsx(_components.div, { - style: { - backgroundColor: 'yellow', - }, - children: storyFn(), - }), - ], - }), - '\\n', - _jsx(_components.h1, { - children: 'Decorated story', - }), - '\\n', - _jsx(Story, { - name: 'one', - decorators: [ - (storyFn) => - _jsx(_components.div, { - className: 'local', - children: storyFn(), - }), - ], - children: _jsx(Button, { - children: 'One', - }), - }), - ], + export const one = () => + /*#__PURE__*/ _jsx(Button, { + children: 'One', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + one.storyName = 'one'; + one.parameters = { + storySource: { + source: '', + }, + }; + one.decorators = [ + (storyFn) => + /*#__PURE__*/ _jsx('div', { + className: 'local', + children: storyFn(), + }), + ]; + const componentMeta = { + title: 'Button', + decorators: [ + (storyFn) => + /*#__PURE__*/ _jsx('div', { + style: { + backgroundColor: 'yellow', + }, + children: storyFn(), + }), + ], + tags: ['stories-mdx'], + includeStories: ['one'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -638,47 +558,23 @@ describe('docs-mdx-compiler-plugin', () => { This is a documentation-only MDX file which cleans a dummy 'docsOnly: true' story. `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - p: 'p', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'docs-only', - }), - '\\n', - _jsx(_components.h1, { - children: 'Documentation only', - }), - '\\n', - _jsx(_components.p, { - children: - "This is a documentation-only MDX file which cleans a dummy 'docsOnly: true' story.", - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const __page = () => { + throw new Error('Docs-only story'); + }; + __page.parameters = { + docsOnly: true, + }; + const componentMeta = { + title: 'docs-only', + tags: ['stories-mdx'], + includeStories: ['__page'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -697,59 +593,37 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - loaders: [ - async () => ({ - foo: 1, - }), - ], - }), - '\\n', - _jsx(_components.h1, { - children: 'Story with loader', - }), - '\\n', - _jsx(Story, { - name: 'one', - loaders: [ - async () => ({ - bar: 2, - }), - ], - children: _jsx(Button, { - children: 'One', - }), - }), - ], + export const one = () => + /*#__PURE__*/ _jsx(Button, { + children: 'One', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + one.storyName = 'one'; + one.parameters = { + storySource: { + source: '', + }, + }; + one.loaders = [ + async () => ({ + bar: 2, + }), + ]; + const componentMeta = { + title: 'Button', + loaders: [ + async () => ({ + foo: 1, + }), + ], + tags: ['stories-mdx'], + includeStories: ['one'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -761,28 +635,23 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { jsx as _jsx } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - return _jsx(Meta, { - title: "Addons/Docs/what's in a title?", - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const __page = () => { + throw new Error('Docs-only story'); + }; + __page.parameters = { + docsOnly: true, + }; + const componentMeta = { + title: "Addons/Docs/what's in a title?", + tags: ['stories-mdx'], + includeStories: ['__page'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -807,58 +676,37 @@ describe('docs-mdx-compiler-plugin', () => {
`) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - export const two = 2; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - }), - '\\n', - _jsx(_components.h1, { - children: 'Story definition', - }), - '\\n', - _jsx(Story, { - name: 'one', - children: _jsx(Button, { - children: 'One', - }), - }), - '\\n', - '\\n', - _jsx(Story, { - name: 'hello story', - children: _jsx(Button, { - children: 'Hello button', - }), - }), - ], + export const one = () => + /*#__PURE__*/ _jsx(Button, { + children: 'One', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + one.storyName = 'one'; + one.parameters = { + storySource: { + source: '', + }, + }; + export const helloStory = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Hello button', + }); + helloStory.storyName = 'hello story'; + helloStory.parameters = { + storySource: { + source: '', + }, + }; + const componentMeta = { + title: 'Button', + tags: ['stories-mdx'], + includeStories: ['one', 'helloStory'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -879,54 +727,44 @@ describe('docs-mdx-compiler-plugin', () => {
`) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - component: Button, - parameters: { - notes: 'component notes', - }, - }), - '\\n', - _jsx(Story, { - name: 'component notes', - children: _jsx(Button, { - children: 'Component notes', - }), - }), - '\\n', - _jsx(Story, { - name: 'story notes', - parameters: { - notes: 'story notes', - }, - children: _jsx(Button, { - children: 'Story notes', - }), - }), - ], + export const componentNotes = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Component notes', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + componentNotes.storyName = 'component notes'; + componentNotes.parameters = { + storySource: { + source: '', + }, + }; + export const storyNotes = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Story notes', + }); + storyNotes.storyName = 'story notes'; + storyNotes.parameters = { + storySource: { + source: '', + }, + ...{ + notes: 'story notes', + }, + }; + const componentMeta = { + title: 'Button', + parameters: { + notes: 'component notes', + }, + component: Button, + tags: ['stories-mdx'], + includeStories: ['componentNotes', 'storyNotes'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -960,84 +798,41 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Canvas, Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - p: 'p', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - component: Button, - parameters: { - notes: 'component notes', - }, - }), - '\\n', - _jsx(_components.h1, { - children: 'Canvas', - }), - '\\n', - _jsx(_components.p, { - children: 'Canvases can contain normal components, stories, and story references', - }), - '\\n', - _jsxs(Canvas, { - children: [ - _jsx(Button, { - children: 'Just a button', - }), - _jsx(Story, { - name: 'hello button', - children: _jsx(Button, { - children: 'Hello button', - }), - }), - _jsx(Story, { - name: 'two', - children: _jsx(Button, { - children: 'Two', - }), - }), - _jsx(Story, { - id: 'welcome--welcome', - }), - ], - }), - '\\n', - _jsx(_components.p, { - children: 'Canvas without a story', - }), - '\\n', - _jsx(Canvas, { - children: _jsx(Button, { - children: 'Just a button', - }), - }), - ], + export const helloButton = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Hello button', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + helloButton.storyName = 'hello button'; + helloButton.parameters = { + storySource: { + source: '', + }, + }; + export const two = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Two', + }); + two.storyName = 'two'; + two.parameters = { + storySource: { + source: '', + }, + }; + const componentMeta = { + title: 'Button', + parameters: { + notes: 'component notes', + }, + component: Button, + tags: ['stories-mdx'], + includeStories: ['helloButton', 'two'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1062,64 +857,36 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - export const Template = (args) => - _jsx(Button, { - children: 'Component notes', - }); - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - }), - '\\n', - _jsx(_components.h1, { - children: 'Args', - }), - '\\n', - '\\n', - _jsx(Story, { - name: 'component notes', - args: { - a: 1, - b: 2, - }, - argTypes: { - a: { - name: 'A', - }, - b: { - name: 'B', - }, - }, - children: Template.bind({}), - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const componentNotes = Template.bind({}); + componentNotes.storyName = 'component notes'; + componentNotes.argTypes = { + a: { + name: 'A', + }, + b: { + name: 'B', + }, + }; + componentNotes.args = { + a: 1, + b: 2, + }; + componentNotes.parameters = { + storySource: { + source: 'args => ', + }, + }; + const componentMeta = { + title: 'Button', + tags: ['stories-mdx'], + includeStories: ['componentNotes'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1133,41 +900,15 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Story } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(_components.h1, { - children: 'Current story', - }), - '\\n', - _jsx(Story, { - id: '.', - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + const componentMeta = { + includeStories: [], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1183,46 +924,24 @@ describe('docs-mdx-compiler-plugin', () => { Plain text `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Text', - }), - '\\n', - _jsx(_components.h1, { - children: 'Story definition', - }), - '\\n', - _jsx(Story, { - name: 'text', - children: 'Plain text', - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const text = () => 'Plain text'; + text.storyName = 'text'; + text.parameters = { + storySource: { + source: '"Plain text"', + }, + }; + const componentMeta = { + title: 'Text', + tags: ['stories-mdx'], + includeStories: ['text'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1253,70 +972,57 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - }), - '\\n', - _jsx(_components.h1, { - children: 'Story definition', - }), - '\\n', - _jsx(Story, { - name: 'one', - children: _jsx(Button, { - children: 'One', - }), - }), - '\\n', - _jsx(Story, { - name: 'hello story', - children: _jsx(Button, { - children: 'Hello button', - }), - }), - '\\n', - _jsx(Story, { - name: 'w/punctuation', - children: _jsx(Button, { - children: 'with punctuation', - }), - }), - '\\n', - _jsx(Story, { - name: '1 fine day', - children: _jsx(Button, { - children: 'starts with number', - }), - }), - ], + export const one = () => + /*#__PURE__*/ _jsx(Button, { + children: 'One', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + one.storyName = 'one'; + one.parameters = { + storySource: { + source: '', + }, + }; + export const helloStory = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Hello button', + }); + helloStory.storyName = 'hello story'; + helloStory.parameters = { + storySource: { + source: '', + }, + }; + export const wPunctuation = () => + /*#__PURE__*/ _jsx(Button, { + children: 'with punctuation', + }); + wPunctuation.storyName = 'w/punctuation'; + wPunctuation.parameters = { + storySource: { + source: '', + }, + }; + export const _1FineDay = () => + /*#__PURE__*/ _jsx(Button, { + children: 'starts with number', + }); + _1FineDay.storyName = '1 fine day'; + _1FineDay.parameters = { + storySource: { + source: '', + }, + }; + const componentMeta = { + title: 'Button', + tags: ['stories-mdx'], + includeStories: ['one', 'helloStory', 'wPunctuation', '_1FineDay'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1336,66 +1042,24 @@ describe('docs-mdx-compiler-plugin', () => { {basicFn} `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Meta, Story } from '@storybook/addon-docs'; - export const basicFn = () => { - const { Button } = _provideComponents() || {}; - if (!Button) _missingMdxReference('Button', true); - return _jsx(Button, {}); + export const basic = assertIsFn(basicFn); + basic.storyName = 'basic'; + basic.parameters = { + storySource: { + source: 'basicFn', + }, }; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - p: 'p', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'story-function-var', - }), - '\\n', - '\\n', - _jsx(_components.h1, { - children: 'Button', - }), - '\\n', - _jsx(_components.p, { - children: 'I can define a story with the function defined in CSF:', - }), - '\\n', - _jsx(Story, { - name: 'basic', - children: basicFn, - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } - function _missingMdxReference(id, component) { - throw new Error( - 'Expected ' + - (component ? 'component' : 'object') + - ' \`' + - id + - '\` to be defined: you likely forgot to import, pass, or provide it.' - ); - } + const componentMeta = { + title: 'story-function-var', + tags: ['stories-mdx'], + includeStories: ['basic'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1412,48 +1076,28 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { jsx as _jsx } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - function _createMdxContent(props) { - const { Story } = { - ..._provideComponents(), - ...props.components, - }; - if (!Story) _missingMdxReference('Story', true); - return _jsx(Story, { - name: 'function', - height: '100px', - children: () => { - const btn = document.createElement('button'); - btn.innerHTML = 'Hello Button'; - btn.addEventListener('click', action('Click')); - return btn; - }, - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } - function _missingMdxReference(id, component) { - throw new Error( - 'Expected ' + - (component ? 'component' : 'object') + - ' \`' + - id + - '\` to be defined: you likely forgot to import, pass, or provide it.' - ); - } + export const functionStory = () => { + const btn = document.createElement('button'); + btn.innerHTML = 'Hello Button'; + btn.addEventListener('click', action('Click')); + return btn; + }; + functionStory.storyName = 'function'; + functionStory.parameters = { + storySource: { + source: + '() => {\\n const btn = document.createElement("button");\\n btn.innerHTML = "Hello Button";\\n btn.addEventListener("click", action("Click"));\\n return btn;\\n}', + }, + }; + const componentMeta = { + includeStories: ['functionStory'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1472,53 +1116,34 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { + export const multipleChildren = () => + /*#__PURE__*/ _jsxs(_Fragment, { children: [ - _jsx(Meta, { - title: 'Multiple', - }), - '\\n', - _jsx(_components.h1, { - children: 'Multiple children', + /*#__PURE__*/ _jsx('p', { + children: 'Hello Child #1', }), - '\\n', - _jsxs(Story, { - name: 'multiple children', - children: [ - _jsx('p', { - children: 'Hello Child #1', - }), - _jsx('p', { - children: 'Hello Child #2', - }), - ], + /*#__PURE__*/ _jsx('p', { + children: 'Hello Child #2', }), ], }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + multipleChildren.storyName = 'multiple children'; + multipleChildren.parameters = { + storySource: { + source: '

{"Hello Child #1"}

\\n

{"Hello Child #2"}

', + }, + }; + const componentMeta = { + title: 'Multiple', + tags: ['stories-mdx'], + includeStories: ['multipleChildren'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1546,58 +1171,33 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Story, Meta } from '@storybook/addon-docs'; - import { Welcome, Button } from '@storybook/angular/demo'; - import { linkTo } from '@storybook/addon-links'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'MDX|Welcome', - }), - '\\n', - _jsx(_components.h1, { - children: 'Story object', - }), - '\\n', - _jsx(Story, { - name: 'to storybook', - height: '300px', - children: { - template: - '', - props: { - showApp: linkTo('Button'), - }, - moduleMetadata: { - declarations: [Welcome], - }, - }, - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const toStorybook = () => ({ + template: '', + props: { + showApp: linkTo('Button'), + }, + moduleMetadata: { + declarations: [Welcome], + }, + }); + toStorybook.storyName = 'to storybook'; + toStorybook.parameters = { + storySource: { + source: + '{\\n template: "",\\n props: {\\n showApp: linkTo("Button")\\n },\\n moduleMetadata: {\\n declarations: [Welcome]\\n }\\n}', + }, + }; + const componentMeta = { + title: 'MDX|Welcome', + tags: ['stories-mdx'], + includeStories: ['toStorybook'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1611,41 +1211,15 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Story } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(_components.h1, { - children: 'Story reference', - }), - '\\n', - _jsx(Story, { - id: 'welcome--welcome', - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + const componentMeta = { + includeStories: [], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1661,29 +1235,23 @@ describe('docs-mdx-compiler-plugin', () => { ].join('\n') ) ).toMatchInlineSnapshot(` - import { jsx as _jsx } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Meta, Story } from '@storybook/addon-docs'; - import { titleFunction } from '../title-generators'; - function _createMdxContent(props) { - return _jsx(Meta, { - title: \`\${titleFunction('template')}\`, - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const __page = () => { + throw new Error('Docs-only story'); + }; + __page.parameters = { + docsOnly: true, + }; + const componentMeta = { + title: \`\${titleFunction('template')}\`, + tags: ['stories-mdx'], + includeStories: ['__page'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1699,49 +1267,63 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - p: 'p', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(_components.h1, { - children: 'Hello MDX', - }), - '\\n', - _jsx(_components.p, { - children: 'This is some random content.', - }), - '\\n', - _jsx(Button, { - children: 'Hello button', - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + const componentMeta = { + includeStories: [], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); + it('errors on missing story props', async () => { + await expect(async () => + clean(dedent` + import { Button } from '@storybook/react/demo'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + # Bad story + + + + + `) + ).rejects.toThrow('Expected a Story name, id, or story attribute'); + }); + + it("errors on story 'of' prop", async () => { + await expect(async () => + clean(dedent` + import * as MyStories from './My.stories'; + import { Story, Meta } from '@storybook/addon-docs'; + + + + # Bad story + + + `) + ).rejects.toThrow(`The 'of' prop is not supported in .stories.mdx files, only .mdx files. + See https://storybook.js.org/docs/7.0/react/writing-docs/mdx on how to write MDX files and stories separately.`); + }); + + it("errors on meta 'of' prop", async () => { + await expect(async () => + clean(dedent` + import * as MyStories from './My.stories'; + import { Meta } from '@storybook/addon-docs'; + + + `) + ).rejects.toThrow(`The 'of' prop is not supported in .stories.mdx files, only .mdx files. + See https://storybook.js.org/docs/7.0/react/writing-docs/mdx on how to write MDX files and stories separately.`); + }); + describe('csf3', () => { it('auto-title-docs-only.mdx', () => { expect( @@ -1755,51 +1337,22 @@ describe('docs-mdx-compiler-plugin', () => { Spme **markdown** here! `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - const _components = { - h1: 'h1', - p: 'p', - strong: 'strong', - ..._provideComponents(), - ...props.components, - }; - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, {}), - '\\n', - _jsx(_components.h1, { - children: 'Auto-title Docs Only', - }), - '\\n', - _jsxs(_components.p, { - children: [ - 'Spme ', - _jsx(_components.strong, { - children: 'markdown', - }), - ' here!', - ], - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const __page = () => { + throw new Error('Docs-only story'); + }; + __page.parameters = { + docsOnly: true, + }; + const componentMeta = { + tags: ['stories-mdx'], + includeStories: ['__page'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1816,40 +1369,27 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - component: Button, - }), - '\\n', - _jsx(Story, { - name: 'Basic', - children: _jsx(Button, { - children: 'Basic', - }), - }), - ], + export const basic = () => + /*#__PURE__*/ _jsx(Button, { + children: 'Basic', }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + basic.storyName = 'Basic'; + basic.parameters = { + storySource: { + source: '', + }, + }; + const componentMeta = { + component: Button, + tags: ['stories-mdx'], + includeStories: ['basic'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1864,38 +1404,25 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - component: Button, - }), - '\\n', - _jsx(Story, { - name: 'Basic', - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const basic = {}; + basic.storyName = 'Basic'; + basic.parameters = { + storySource: { + source: '{}', + }, + }; + const componentMeta = { + title: 'Button', + component: Button, + tags: ['stories-mdx'], + includeStories: ['basic'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1910,42 +1437,29 @@ describe('docs-mdx-compiler-plugin', () => { `) ).toMatchInlineSnapshot(` - import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime'; - import { useMDXComponents as _provideComponents } from '@mdx-js/react'; - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - function _createMdxContent(props) { - return _jsxs(_Fragment, { - children: [ - _jsx(Meta, { - title: 'Button', - component: Button, - render: (args) => - _jsx(Button, { - ...args, - }), - }), - '\\n', - _jsx(Story, { - name: 'Basic', - }), - ], - }); - } - export default function MDXContent(props = {}) { - const { wrapper: MDXLayout } = { - ..._provideComponents(), - ...props.components, - }; - return MDXLayout - ? _jsx(MDXLayout, { - ...props, - children: _jsx(_createMdxContent, { - ...props, - }), - }) - : _createMdxContent(props); - } + export const basic = {}; + basic.storyName = 'Basic'; + basic.parameters = { + storySource: { + source: '{}', + }, + }; + const componentMeta = { + title: 'Button', + component: Button, + render: (args) => + /*#__PURE__*/ _jsx(Button, { + ...args, + }), + tags: ['stories-mdx'], + includeStories: ['basic'], + }; + componentMeta.parameters = componentMeta.parameters || {}; + componentMeta.parameters.docs = { + ...(componentMeta.parameters.docs || {}), + page: MDXContent, + }; + export default componentMeta; `); }); @@ -1960,42 +1474,29 @@ describe('docs-mdx-compiler-plugin', () => { - - `) - ).toMatchInlineSnapshot(` - export const componentNotes = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Component notes', - }); - componentNotes.storyName = 'component notes'; - componentNotes.parameters = { - storySource: { - source: '', - }, - }; - const componentMeta = { - title: 'Button', - args: { - a: 1, - b: 2, - }, - argTypes: { - a: { - name: 'A', - }, - b: { - name: 'B', - }, - }, - tags: ['stories-mdx'], - includeStories: ['componentNotes'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('component-id.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - - - - - - `) - ).toMatchInlineSnapshot(` - export const componentNotes = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Component notes', - }); - componentNotes.storyName = 'component notes'; - componentNotes.parameters = { - storySource: { - source: '', - }, - }; - const componentMeta = { - title: 'Button', - id: 'button-id', - component: Button, - tags: ['stories-mdx'], - includeStories: ['componentNotes'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - it('csf-imports.mdx', () => { expect( - clean(dedent` + clean( + compileSync(dedent` import { Story, Meta, Canvas } from '@storybook/addon-docs'; import { Welcome, Button } from '@storybook/angular/demo'; import * as MyStories from './My.stories'; @@ -461,94 +315,47 @@ describe('docs-mdx-compiler-plugin', () => { # Stories from CSF imports - + - + - - - `) - ).toMatchInlineSnapshot(` - export const _Basic_ = MyStories.Basic; - export const _Other_ = Other; - export const _Foo_ = MyStories.Foo; - _Foo_.storyName = 'renamed'; - const componentMeta = { - title: 'MDX/CSF imports', - tags: ['stories-mdx'], - includeStories: ['_Basic_', '_Other_', '_Foo_'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('decorators.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - -
{storyFn()}
]} - /> - - # Decorated story - -
{storyFn()}
]}> - -
`) + ) ).toMatchInlineSnapshot(` - export const one = () => - /*#__PURE__*/ _jsx(Button, { - children: 'One', + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Story, Meta, Canvas} from '@storybook/addon-docs'; + import {Welcome, Button} from '@storybook/angular/demo'; + import * as MyStories from './My.stories'; + import {Other} from './Other.stories'; + function _createMdxContent(props) { + const _components = { + h1: "h1", + ..._provideComponents(), + ...props.components + }; + return _jsxs(_Fragment, { + children: [_jsx(Meta, { + title: "MDX/CSF imports" + }), "\\n", _jsx(_components.h1, { + children: "Stories from CSF imports" + }), "\\n", _jsx(Story, { + of: MyStories.Basic + }), "\\n", _jsx(Canvas, { + children: _jsx(Story, { + of: Other + }) + })] }); - one.storyName = 'one'; - one.parameters = { - storySource: { - source: '', - }, - }; - one.decorators = [ - (storyFn) => - /*#__PURE__*/ _jsx('div', { - className: 'local', - children: storyFn(), - }), - ]; - const componentMeta = { - title: 'Button', - decorators: [ - (storyFn) => - /*#__PURE__*/ _jsx('div', { - style: { - backgroundColor: 'yellow', - }, - children: storyFn(), - }), - ], - tags: ['stories-mdx'], - includeStories: ['one'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; + } `); }); it('docs-only.mdx', () => { expect( - clean(dedent` + clean( + compileSync(dedent` import { Meta } from '@storybook/addon-docs'; @@ -557,107 +364,56 @@ describe('docs-mdx-compiler-plugin', () => { This is a documentation-only MDX file which cleans a dummy 'docsOnly: true' story. `) + ) ).toMatchInlineSnapshot(` - export const __page = () => { - throw new Error('Docs-only story'); - }; - __page.parameters = { - docsOnly: true, - }; - const componentMeta = { - title: 'docs-only', - tags: ['stories-mdx'], - includeStories: ['__page'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('loaders.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - ({ foo: 1 })]} /> - - # Story with loader - - ({ bar: 2 })]}> - - - `) - ).toMatchInlineSnapshot(` - export const one = () => - /*#__PURE__*/ _jsx(Button, { - children: 'One', + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Meta} from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: "h1", + p: "p", + ..._provideComponents(), + ...props.components + }; + return _jsxs(_Fragment, { + children: [_jsx(Meta, { + title: "docs-only" + }), "\\n", _jsx(_components.h1, { + children: "Documentation only" + }), "\\n", _jsx(_components.p, { + children: "This is a documentation-only MDX file which cleans a dummy 'docsOnly: true' story." + })] }); - one.storyName = 'one'; - one.parameters = { - storySource: { - source: '', - }, - }; - one.loaders = [ - async () => ({ - bar: 2, - }), - ]; - const componentMeta = { - title: 'Button', - loaders: [ - async () => ({ - foo: 1, - }), - ], - tags: ['stories-mdx'], - includeStories: ['one'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; + } `); }); it('meta-quotes-in-title.mdx', () => { expect( - clean(dedent` + clean( + compileSync(dedent` import { Meta } from '@storybook/addon-docs'; `) + ) ).toMatchInlineSnapshot(` - export const __page = () => { - throw new Error('Docs-only story'); - }; - __page.parameters = { - docsOnly: true, - }; - const componentMeta = { - title: "Addons/Docs/what's in a title?", - tags: ['stories-mdx'], - includeStories: ['__page'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; + import {jsx as _jsx} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Meta} from '@storybook/addon-docs'; + function _createMdxContent(props) { + return _jsx(Meta, { + title: "Addons/Docs/what's in a title?" + }); + } `); }); it('non-story-exports.mdx', () => { expect( - clean(dedent` + clean( + compileSync(dedent` import { Button } from '@storybook/react/demo'; import { Story, Meta } from '@storybook/addon-docs'; @@ -665,879 +421,193 @@ describe('docs-mdx-compiler-plugin', () => { # Story definition - - - + export const two = 2; - - - - - `) - ).toMatchInlineSnapshot(` - export const one = () => - /*#__PURE__*/ _jsx(Button, { - children: 'One', - }); - one.storyName = 'one'; - one.parameters = { - storySource: { - source: '', - }, - }; - export const helloStory = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Hello button', - }); - helloStory.storyName = 'hello story'; - helloStory.parameters = { - storySource: { - source: '', - }, - }; - const componentMeta = { - title: 'Button', - tags: ['stories-mdx'], - includeStories: ['one', 'helloStory'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('parameters.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - - - - - - - - - - `) - ).toMatchInlineSnapshot(` - export const componentNotes = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Component notes', - }); - componentNotes.storyName = 'component notes'; - componentNotes.parameters = { - storySource: { - source: '', - }, - }; - export const storyNotes = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Story notes', - }); - storyNotes.storyName = 'story notes'; - storyNotes.parameters = { - storySource: { - source: '', - }, - ...{ - notes: 'story notes', - }, - }; - const componentMeta = { - title: 'Button', - parameters: { - notes: 'component notes', - }, - component: Button, - tags: ['stories-mdx'], - includeStories: ['componentNotes', 'storyNotes'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('previews.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Canvas, Story, Meta } from '@storybook/addon-docs'; - - - - # Canvas - - Canvases can contain normal components, stories, and story references - - - - - - - - - - - - - Canvas without a story - - - - `) + ) ).toMatchInlineSnapshot(` - export const helloButton = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Hello button', - }); - helloButton.storyName = 'hello button'; - helloButton.parameters = { - storySource: { - source: '', - }, - }; - export const two = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Two', + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Button} from '@storybook/react/demo'; + import {Story, Meta} from '@storybook/addon-docs'; + export const two = 2; + function _createMdxContent(props) { + const _components = { + h1: "h1", + ..._provideComponents(), + ...props.components + }; + return _jsxs(_Fragment, { + children: [_jsx(Meta, { + title: "Button" + }), "\\n", _jsx(_components.h1, { + children: "Story definition" + }), "\\n", _jsx(Story, { + of: Button + })] }); - two.storyName = 'two'; - two.parameters = { - storySource: { - source: '', - }, - }; - const componentMeta = { - title: 'Button', - parameters: { - notes: 'component notes', - }, - component: Button, - tags: ['stories-mdx'], - includeStories: ['helloButton', 'two'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('story-args.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - - - # Args - - export const Template = (args) => ; - - - {Template.bind({})} - - `) - ).toMatchInlineSnapshot(` - export const componentNotes = Template.bind({}); - componentNotes.storyName = 'component notes'; - componentNotes.argTypes = { - a: { - name: 'A', - }, - b: { - name: 'B', - }, - }; - componentNotes.args = { - a: 1, - b: 2, - }; - componentNotes.parameters = { - storySource: { - source: 'args => ', - }, - }; - const componentMeta = { - title: 'Button', - tags: ['stories-mdx'], - includeStories: ['componentNotes'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; + } `); }); it('story-current.mdx', () => { expect( - clean(dedent` + clean( + compileSync(dedent` import { Story } from '@storybook/addon-docs'; # Current story `) + ) ).toMatchInlineSnapshot(` - const componentMeta = { - includeStories: [], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('story-def-text-only.mdx', () => { - expect( - clean(dedent` - import { Story, Meta } from '@storybook/addon-docs'; - - - - # Story definition - - Plain text - `) - ).toMatchInlineSnapshot(` - export const text = () => 'Plain text'; - text.storyName = 'text'; - text.parameters = { - storySource: { - source: '"Plain text"', - }, - }; - const componentMeta = { - title: 'Text', - tags: ['stories-mdx'], - includeStories: ['text'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('story-definitions.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - - - # Story definition - - - - - - - - - - - - - - - - - `) - ).toMatchInlineSnapshot(` - export const one = () => - /*#__PURE__*/ _jsx(Button, { - children: 'One', - }); - one.storyName = 'one'; - one.parameters = { - storySource: { - source: '', - }, - }; - export const helloStory = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Hello button', - }); - helloStory.storyName = 'hello story'; - helloStory.parameters = { - storySource: { - source: '', - }, - }; - export const wPunctuation = () => - /*#__PURE__*/ _jsx(Button, { - children: 'with punctuation', - }); - wPunctuation.storyName = 'w/punctuation'; - wPunctuation.parameters = { - storySource: { - source: '', - }, - }; - export const _1FineDay = () => - /*#__PURE__*/ _jsx(Button, { - children: 'starts with number', - }); - _1FineDay.storyName = '1 fine day'; - _1FineDay.parameters = { - storySource: { - source: '', - }, - }; - const componentMeta = { - title: 'Button', - tags: ['stories-mdx'], - includeStories: ['one', 'helloStory', 'wPunctuation', '_1FineDay'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('story-function-var.mdx', () => { - expect( - clean(dedent` - import { Meta, Story } from '@storybook/addon-docs'; - - - - export const basicFn = () => - `) - ).toMatchInlineSnapshot(` - const componentMeta = { - includeStories: [], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; + import {jsx as _jsx} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Meta, Story} from '@storybook/addon-docs'; + import {titleFunction} from '../title-generators'; + function _createMdxContent(props) { + return _jsx(Meta, { + title: \`\${titleFunction('template')}\` + }); + } `); }); - it('errors on missing story props', async () => { - await expect(async () => - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - - - # Bad story - - - - - `) - ).rejects.toThrow('Expected a Story name, id, or story attribute'); - }); - - it("errors on story 'of' prop", async () => { - await expect(async () => - clean(dedent` - import * as MyStories from './My.stories'; - import { Story, Meta } from '@storybook/addon-docs'; - - - - # Bad story - - - `) - ).rejects.toThrow(`The 'of' prop is not supported in .stories.mdx files, only .mdx files. - See https://storybook.js.org/docs/7.0/react/writing-docs/mdx on how to write MDX files and stories separately.`); - }); - - it("errors on meta 'of' prop", async () => { - await expect(async () => - clean(dedent` - import * as MyStories from './My.stories'; - import { Meta } from '@storybook/addon-docs'; - - - `) - ).rejects.toThrow(`The 'of' prop is not supported in .stories.mdx files, only .mdx files. - See https://storybook.js.org/docs/7.0/react/writing-docs/mdx on how to write MDX files and stories separately.`); - }); - describe('csf3', () => { it('auto-title-docs-only.mdx', () => { expect( - clean(dedent` + clean( + compileSync(dedent` import { Meta } from '@storybook/addon-docs'; # Auto-title Docs Only - Spme **markdown** here! + Some **markdown** here! `) + ) ).toMatchInlineSnapshot(` - export const __page = () => { - throw new Error('Docs-only story'); - }; - __page.parameters = { - docsOnly: true, - }; - const componentMeta = { - tags: ['stories-mdx'], - includeStories: ['__page'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; + import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime"; + import {useMDXComponents as _provideComponents} from "@mdx-js/react"; + import {Meta} from '@storybook/addon-docs'; + function _createMdxContent(props) { + const _components = { + h1: "h1", + p: "p", + strong: "strong", + ..._provideComponents(), + ...props.components + }; + return _jsxs(_Fragment, { + children: [_jsx(Meta, {}), "\\n", _jsx(_components.h1, { + children: "Auto-title Docs Only" + }), "\\n", _jsxs(_components.p, { + children: ["Some ", _jsx(_components.strong, { + children: "markdown" + }), " here!"] + })] + }); + } `); }); it('auto-title.mdx', () => { expect( - clean(dedent` + clean( + compileSync(dedent` import { Button } from '@storybook/react/demo'; import { Story, Meta } from '@storybook/addon-docs'; - - - - - `) - ).toMatchInlineSnapshot(` - export const basic = () => - /*#__PURE__*/ _jsx(Button, { - children: 'Basic', - }); - basic.storyName = 'Basic'; - basic.parameters = { - storySource: { - source: '', - }, - }; - const componentMeta = { - component: Button, - tags: ['stories-mdx'], - includeStories: ['basic'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('default-render.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - - - - `) - ).toMatchInlineSnapshot(` - export const basic = {}; - basic.storyName = 'Basic'; - basic.parameters = { - storySource: { - source: '{}', - }, - }; - const componentMeta = { - title: 'Button', - component: Button, - tags: ['stories-mdx'], - includeStories: ['basic'], - }; - componentMeta.parameters = componentMeta.parameters || {}; - componentMeta.parameters.docs = { - ...(componentMeta.parameters.docs || {}), - page: MDXContent, - }; - export default componentMeta; - `); - }); - - it('component-render.mdx', () => { - expect( - clean(dedent` - import { Button } from '@storybook/react/demo'; - import { Story, Meta } from '@storybook/addon-docs'; - - + +
Open source software maintained by{' '} Chromatic and the{' '} From 79654375d4501805c4585a955fbab6426931a98b Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 1 Jan 2024 09:23:41 +0100 Subject: [PATCH 23/51] Fix alignment in tabs header --- code/ui/manager/src/settings/index.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/code/ui/manager/src/settings/index.tsx b/code/ui/manager/src/settings/index.tsx index eec87d2ae18e..0a3708744368 100644 --- a/code/ui/manager/src/settings/index.tsx +++ b/code/ui/manager/src/settings/index.tsx @@ -1,5 +1,5 @@ import { useStorybookApi, useStorybookState, types } from '@storybook/manager-api'; -import { IconButton, FlexBar, TabBar, TabButton, ScrollArea } from '@storybook/components'; +import { IconButton, TabBar, TabButton, ScrollArea } from '@storybook/components'; import { Location, Route } from '@storybook/router'; import { styled } from '@storybook/theming'; import { global } from '@storybook/global'; @@ -15,6 +15,16 @@ import { matchesModifiers, matchesKeyCode } from '../keybinding'; const { document } = global; +const Header = styled.div(({ theme }) => ({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + height: 40, + boxShadow: `${theme.appBorderColor} 0 -1px 0 0 inset`, + background: theme.barBg, + paddingRight: 8, +})); + const TabBarButton = React.memo(function TabBarButton({ changeTab, id, @@ -70,7 +80,7 @@ const Pages: FC<{ return ( - +
{enableWhatsNew && ( @@ -87,7 +97,7 @@ const Pages: FC<{ > - +
From 26d83b3663755e37baf3f3f35d9c10257e9c4b25 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 1 Jan 2024 09:30:50 +0100 Subject: [PATCH 24/51] Fix buttons in about footer --- code/ui/.storybook/main.ts | 1 + code/ui/manager/src/settings/whats_new.tsx | 46 +++++++--------------- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/code/ui/.storybook/main.ts b/code/ui/.storybook/main.ts index 4800dda1e181..aab89b2a2c0b 100644 --- a/code/ui/.storybook/main.ts +++ b/code/ui/.storybook/main.ts @@ -65,6 +65,7 @@ const config: StorybookConfig = { }, core: { disableTelemetry: true, + disableWhatsNewNotifications: false, }, viteFinal: (viteConfig, { configType }) => mergeConfig(viteConfig, { diff --git a/code/ui/manager/src/settings/whats_new.tsx b/code/ui/manager/src/settings/whats_new.tsx index ee6aba4e6c53..4b69aaa56ee4 100644 --- a/code/ui/manager/src/settings/whats_new.tsx +++ b/code/ui/manager/src/settings/whats_new.tsx @@ -1,7 +1,7 @@ import type { ComponentProps, FC } from 'react'; import React, { Fragment, useEffect, useState } from 'react'; import { styled, useTheme } from '@storybook/theming'; -import { Button, IconButton, Loader } from '@storybook/components'; +import { Button, Loader } from '@storybook/components'; import { useStorybookApi, useStorybookState } from '@storybook/manager-api'; import { global } from '@storybook/global'; import { EyeCloseIcon, EyeIcon, HeartIcon, AlertIcon as AlertIconSvg } from '@storybook/icons'; @@ -42,22 +42,6 @@ const Container = styled.div(({ theme }) => ({ justifyContent: 'space-between', })); -const ToggleNotificationButton = styled(IconButton)(({ theme }) => ({ - fontWeight: theme.typography.weight.regular, - color: theme.color.mediumdark, - margin: 0, -})); - -const CopyButton = styled(Button)(({ theme }) => ({ - '&&': { - fontSize: `13px`, - color: theme.color.defaultText, - margin: 0, - padding: 0, - borderRadius: 0, - }, -})); - export const WhatsNewFooter = ({ isNotificationsEnabled, onToggleNotifications, @@ -80,23 +64,21 @@ export const WhatsNewFooter = ({
Share this with your team.
- +
- - {isNotificationsEnabled ? ( - <> - -  Hide notifications - - ) : ( - <> - -  Show notifications - - )} - + {isNotificationsEnabled ? ( + + ) : ( + + )} ); }; From e723495665d3b55c77f40ad34845ea5db8abf3a6 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 1 Jan 2024 09:38:44 +0100 Subject: [PATCH 25/51] Update main.ts --- code/ui/.storybook/main.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/code/ui/.storybook/main.ts b/code/ui/.storybook/main.ts index aab89b2a2c0b..4800dda1e181 100644 --- a/code/ui/.storybook/main.ts +++ b/code/ui/.storybook/main.ts @@ -65,7 +65,6 @@ const config: StorybookConfig = { }, core: { disableTelemetry: true, - disableWhatsNewNotifications: false, }, viteFinal: (viteConfig, { configType }) => mergeConfig(viteConfig, { From b57c765b28323cdd277599b7c19b6722606d4e8c Mon Sep 17 00:00:00 2001 From: storybook-bot <32066757+storybook-bot@users.noreply.github.com> Date: Mon, 1 Jan 2024 16:13:52 +0000 Subject: [PATCH 26/51] Update CHANGELOG.md for v7.6.7 [skip ci] --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96041db16abb..a2458954ccd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 7.6.7 + +- Core: Skip no-framework error when ignorePreview=true - [#25286](https://github.com/storybookjs/storybook/pull/25286), thanks [@ndelangen](https://github.com/ndelangen)! +- Dependencies: Semver dependency fixes - [#25283](https://github.com/storybookjs/storybook/pull/25283), thanks [@ndelangen](https://github.com/ndelangen)! +- Vite: Fix pre-transform error in Vite 5 - [#25329](https://github.com/storybookjs/storybook/pull/25329), thanks [@yannbf](https://github.com/yannbf)! +- Vue3: Fix pnp by making compiler-core a dependency - [#25311](https://github.com/storybookjs/storybook/pull/25311), thanks [@shilman](https://github.com/shilman)! + ## 7.6.6 - SvelteKit: Support 2.0 modules with mocks - [#25244](https://github.com/storybookjs/storybook/pull/25244), thanks [@paoloricciuti](https://github.com/paoloricciuti)! From 2071832d8d47cc45fa852afc832ab1f783d1364d Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 08:30:49 -0300 Subject: [PATCH 27/51] remove jsxOptions from addon-docs --- MIGRATION.md | 4 ++-- code/addons/docs/README.md | 3 --- code/addons/docs/src/compiler/index.ts | 4 ++-- code/addons/docs/src/compiler/types.ts | 12 ------------ code/addons/docs/src/preset.ts | 3 +-- docs/essentials/index.md | 1 - ...ook-main-full-individual-essentials-config.js.mdx | 1 - ...ook-main-full-individual-essentials-config.ts.mdx | 1 - 8 files changed, 5 insertions(+), 24 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index fad5e550dee6..c78ed3febee7 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -392,10 +392,10 @@ Storybook now uses MDX3 under the hood. This change contains many improvements a #### Dropping support for *.stories.mdx (CSF in MDX) format -_Has automigration_ - In Storybook 7, we deprecated the ability of using MDX both for documentation and for defining stories in the same .stories.mdx file. It is now removed, and Storybook won't support .stories.mdx files anymore. We provide migration scripts to help you onto the new format. +Alongside with this change, the `jsxOptions` configuration was removed as it is not used anymore. + [More info here](https://storybook.js.org/docs/writing-docs/mdx#automigration). #### Dropping support for id, name and story in Story block diff --git a/code/addons/docs/README.md b/code/addons/docs/README.md index 379b23f2d8a1..9495cf2c1508 100644 --- a/code/addons/docs/README.md +++ b/code/addons/docs/README.md @@ -129,7 +129,6 @@ export default { { name: '@storybook/addon-docs', options: { - jsxOptions: {}, csfPluginOptions: null, mdxPluginOptions: {}, }, @@ -138,8 +137,6 @@ export default { }; ``` -`jsxOptions` are options that will be passed to `@babel/preset-react` for `.md` and `.mdx` files. - `csfPluginOptions` is an object for configuring `@storybook/csf-plugin`. When set to `null` it tells docs not to run the `csf-plugin` at all, which can be used as an optimization, or if you're already using `csf-plugin` in your `main.js`. > With the release of version 7.0, it is no longer possible to import `.md` files directly into Storybook using the `transcludeMarkdown` [option](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#importing-plain-markdown-files-with-transcludemarkdown-has-changed). Instead, we recommend using the [`Markdown`](https://storybook.js.org/docs/react/api/doc-block-markdown) Doc Block for importing Markdown files into your Storybook documentation. diff --git a/code/addons/docs/src/compiler/index.ts b/code/addons/docs/src/compiler/index.ts index f71159e5081e..79af50d3fb18 100644 --- a/code/addons/docs/src/compiler/index.ts +++ b/code/addons/docs/src/compiler/index.ts @@ -1,8 +1,8 @@ import { compile as mdxCompile, compileSync as mdxCompileSync } from '@mdx-js/mdx'; -import type { CompileOptions, MdxCompileOptions, JSXOptions } from './types'; +import type { CompileOptions, MdxCompileOptions } from './types'; -export type { CompileOptions, MdxCompileOptions, JSXOptions }; +export type { CompileOptions, MdxCompileOptions }; export const compile = async (input: string, { mdxCompileOptions = {} }: CompileOptions = {}) => { const options = getCompilerOptions(mdxCompileOptions); diff --git a/code/addons/docs/src/compiler/types.ts b/code/addons/docs/src/compiler/types.ts index 654368239392..9ef068b0aeed 100644 --- a/code/addons/docs/src/compiler/types.ts +++ b/code/addons/docs/src/compiler/types.ts @@ -1,19 +1,7 @@ import type { compile as mdxCompile } from '@mdx-js/mdx'; -import type { transformAsync } from '@babel/core'; - -export interface JSXOptions { - pragma?: string; - pragmaFrag?: string; - throwIfNamespace?: false; - runtime?: 'classic' | 'automatic'; - importSource?: string; -} export type MdxCompileOptions = Parameters[1]; -export type BabelOptions = Parameters[1]; export interface CompileOptions { - skipCsf?: boolean; mdxCompileOptions?: MdxCompileOptions; - jsxOptions?: JSXOptions; } diff --git a/code/addons/docs/src/preset.ts b/code/addons/docs/src/preset.ts index b6b0cc767751..8d623fe5b97f 100644 --- a/code/addons/docs/src/preset.ts +++ b/code/addons/docs/src/preset.ts @@ -5,7 +5,7 @@ import remarkExternalLinks from 'remark-external-links'; import type { DocsOptions, Options, PresetProperty } from '@storybook/types'; import type { CsfPluginOptions } from '@storybook/csf-plugin'; import { logger } from '@storybook/node-logger'; -import type { CompileOptions, JSXOptions } from './compiler'; +import type { CompileOptions } from './compiler'; /** * Get the resolvedReact preset, which points either to @@ -31,7 +31,6 @@ async function webpack( webpackConfig: any = {}, options: Options & { csfPluginOptions: CsfPluginOptions | null; - jsxOptions?: JSXOptions; mdxPluginOptions?: CompileOptions; } /* & Parameters< typeof createCompiler diff --git a/docs/essentials/index.md b/docs/essentials/index.md index 4cddae864fee..2ef9254bfab7 100644 --- a/docs/essentials/index.md +++ b/docs/essentials/index.md @@ -92,7 +92,6 @@ Below is an abridged configuration and table with all the available options for | `@storybook/addon-actions` | N/A | N/A | | `@storybook/addon-viewport` | N/A | N/A | | `@storybook/addon-docs` | `csfPluginOptions` | Provides additional configuration for Storybook's CSF plugin. Can be disabled with `null`. | -| | `jsxOptions` | Extends the default Babel configuration options for processing Markdown and MDX files. | | | `mdxPluginOptions` | Provides additional configuration options and plugin configuration for [MDX documentation](../writing-docs/mdx.md#lack-of-github-flavored-markdown-gfm). | | `@storybook/addon-controls` | N/A | N/A | | `@storybook/addon-backgrounds` | N/A | N/A | diff --git a/docs/snippets/common/storybook-main-full-individual-essentials-config.js.mdx b/docs/snippets/common/storybook-main-full-individual-essentials-config.js.mdx index 07391e43ad0b..0c11bf383b6f 100644 --- a/docs/snippets/common/storybook-main-full-individual-essentials-config.js.mdx +++ b/docs/snippets/common/storybook-main-full-individual-essentials-config.js.mdx @@ -13,7 +13,6 @@ export default { name: '@storybook/addon-docs', options: { csfPluginOptions: null, - jsxOptions: {}, mdxPluginOptions: { mdxCompileOptions: { remarkPlugins: [], diff --git a/docs/snippets/common/storybook-main-full-individual-essentials-config.ts.mdx b/docs/snippets/common/storybook-main-full-individual-essentials-config.ts.mdx index b2407522632b..5ddd5f067d6b 100644 --- a/docs/snippets/common/storybook-main-full-individual-essentials-config.ts.mdx +++ b/docs/snippets/common/storybook-main-full-individual-essentials-config.ts.mdx @@ -15,7 +15,6 @@ const config: StorybookConfig = { name: '@storybook/addon-docs', options: { csfPluginOptions: null, - jsxOptions: {}, mdxPluginOptions: { mdxCompileOptions: { remarkPlugins: [], From ca6f060fbc7c5ba8252cc653e9146671bfedb042 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 08:31:12 -0300 Subject: [PATCH 28/51] refactor mdx-loader logic --- code/addons/docs/src/mdx-loader.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/code/addons/docs/src/mdx-loader.ts b/code/addons/docs/src/mdx-loader.ts index e075ab72683f..639fb0c70f0d 100644 --- a/code/addons/docs/src/mdx-loader.ts +++ b/code/addons/docs/src/mdx-loader.ts @@ -6,7 +6,6 @@ export type MdxCompileOptions = Parameters[1]; export type BabelOptions = Parameters[1]; export interface CompileOptions { - skipCsf?: boolean; mdxCompileOptions?: MdxCompileOptions; } @@ -30,16 +29,14 @@ async function loader(this: LoaderContext, content: string): Promise { const callback = this.async(); const options = { ...this.getOptions(), filepath: this.resourcePath }; - let result: string; try { - result = await compile(content, options); + const result = await compile(content, options); + const code = `${DEFAULT_RENDERER}\n${result}`; + return callback(null, code); } catch (err: any) { console.error('Error loading:', this.resourcePath); return callback(err); } - - const code = `${DEFAULT_RENDERER}\n${result}`; - return callback(null, code); } export default loader; From 7c4e18ec1cbc2b8bb58e93733dd42dc95eedcc92 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 09:43:32 -0300 Subject: [PATCH 29/51] upgrade docs-mdx --- code/lib/core-server/package.json | 2 +- code/yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index da55fcfa5e1d..c7a08287b5d4 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -68,7 +68,7 @@ "@storybook/core-events": "workspace:*", "@storybook/csf": "^0.1.2", "@storybook/csf-tools": "workspace:*", - "@storybook/docs-mdx": "0.1.1-next.3", + "@storybook/docs-mdx": "3.0.0", "@storybook/global": "^5.0.0", "@storybook/manager": "workspace:*", "@storybook/node-logger": "workspace:*", diff --git a/code/yarn.lock b/code/yarn.lock index e09c14b5bf61..e89fe99af274 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -5491,7 +5491,7 @@ __metadata: "@storybook/core-events": "workspace:*" "@storybook/csf": "npm:^0.1.2" "@storybook/csf-tools": "workspace:*" - "@storybook/docs-mdx": "npm:0.1.1-next.3" + "@storybook/docs-mdx": "npm:3.0.0" "@storybook/global": "npm:^5.0.0" "@storybook/manager": "workspace:*" "@storybook/node-logger": "workspace:*" @@ -5624,10 +5624,10 @@ __metadata: languageName: node linkType: hard -"@storybook/docs-mdx@npm:0.1.1-next.3": - version: 0.1.1-next.3 - resolution: "@storybook/docs-mdx@npm:0.1.1-next.3" - checksum: 39a0652cee247fe04e52681dd60ba00dee8a39b1f2919566c9fdaf916e493e5ba892ed6c73386b395909b38ea7ad67f0c4150965c4745ebcabada8a9e2b35ce5 +"@storybook/docs-mdx@npm:3.0.0": + version: 3.0.0 + resolution: "@storybook/docs-mdx@npm:3.0.0" + checksum: 4f4242fc05b57e8dc239204c71fd0d1481c9abbf20d12dd0f3dace74f77a7ff7cbe0bd07d7d785873b45747be64cad273423d3dc0cf89b52e9f117592a4b054f languageName: node linkType: hard From 281856e45c29897b94958fdc5e0c20faa1978d76 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 2 Jan 2024 15:11:35 +0100 Subject: [PATCH 30/51] Fix menu icon styles --- .../src/components/sidebar/Menu.stories.tsx | 11 +- .../manager/src/components/sidebar/Menu.tsx | 112 ++++++------------ 2 files changed, 43 insertions(+), 80 deletions(-) diff --git a/code/ui/manager/src/components/sidebar/Menu.stories.tsx b/code/ui/manager/src/components/sidebar/Menu.stories.tsx index e04811e76bf8..ebc234f75efc 100644 --- a/code/ui/manager/src/components/sidebar/Menu.stories.tsx +++ b/code/ui/manager/src/components/sidebar/Menu.stories.tsx @@ -8,7 +8,7 @@ import { styled } from '@storybook/theming'; import { screen, userEvent, within } from '@storybook/testing-library'; import type { State } from '@storybook/manager-api'; import { LinkIcon } from '@storybook/icons'; -import { SidebarMenu, ToolbarMenu } from './Menu'; +import { SidebarMenu } from './Menu'; import { useMenu } from '../../container/Menu'; import { LayoutProvider } from '../layout/LayoutProvider'; @@ -34,11 +34,10 @@ export const Items: Story = { }; export const Real: Story = { - render: () => , -}; - -export const Toolbar = { - render: () => , + args: { + isHighlighted: true, + }, + render: (args) => , }; const DoubleThemeRenderingHack = styled.div({ diff --git a/code/ui/manager/src/components/sidebar/Menu.tsx b/code/ui/manager/src/components/sidebar/Menu.tsx index 95290acbc093..1765c6e13a62 100644 --- a/code/ui/manager/src/components/sidebar/Menu.tsx +++ b/code/ui/manager/src/components/sidebar/Menu.tsx @@ -22,48 +22,42 @@ const Icon = styled(Icons)(sharedStyles, ({ theme }) => ({ color: theme.color.secondary, })); -export const SidebarIconButton: FC< - ComponentProps & { highlighted: boolean; active: boolean } -> = styled(IconButton)< - ComponentProps & { - highlighted: boolean; - active: boolean; - } ->(({ highlighted, active, theme }) => ({ - position: 'relative', - overflow: 'visible', - color: theme.textMutedColor, - marginTop: 0, - zIndex: 1, - - ...(highlighted && { - '&:before, &:after': { - content: '""', - position: 'absolute', - top: 6, - right: 6, - width: 5, - height: 5, - zIndex: 2, - borderRadius: '50%', - background: theme.background.app, - border: `1px solid ${theme.background.app}`, - boxShadow: `0 0 0 2px ${theme.background.app}`, - }, - '&:after': { - background: theme.color.positive, - border: `1px solid rgba(0, 0, 0, 0.1)`, - boxShadow: `0 0 0 2px ${theme.background.app}`, - }, - - '&:hover:after, &:focus-visible:after': { - boxShadow: `0 0 0 2px ${transparentize(0.88, theme.color.secondary)}`, - }, - }), - ...(active && { - color: theme.color.secondary, - }), -})); +export const SidebarIconButton: FC & { highlighted: boolean }> = + styled(IconButton)< + ComponentProps & { + highlighted: boolean; + } + >(({ highlighted, theme }) => ({ + position: 'relative', + overflow: 'visible', + marginTop: 0, + zIndex: 1, + + ...(highlighted && { + '&:before, &:after': { + content: '""', + position: 'absolute', + top: 6, + right: 6, + width: 5, + height: 5, + zIndex: 2, + borderRadius: '50%', + background: theme.background.app, + border: `1px solid ${theme.background.app}`, + boxShadow: `0 0 0 2px ${theme.background.app}`, + }, + '&:after': { + background: theme.color.positive, + border: `1px solid rgba(0, 0, 0, 0.1)`, + boxShadow: `0 0 0 2px ${theme.background.app}`, + }, + + '&:hover:after, &:focus-visible:after': { + boxShadow: `0 0 0 2px ${transparentize(0.88, theme.color.secondary)}`, + }, + }), + })); const MenuButtonGroup = styled.div({ display: 'flex', @@ -134,13 +128,13 @@ export const SidebarMenu: FC = ({ menu, isHighlighted, onClick > - setMobileMenuOpen(false)} > - + ); } @@ -163,33 +157,3 @@ export const SidebarMenu: FC = ({ menu, isHighlighted, onClick ); }; - -export const ToolbarMenu: FC<{ - menu: MenuList; -}> = ({ menu }) => { - return ( - } - > - - - - - ); -}; - -// We should not have to reset the margin-top here -// TODO: remove this once we have a the new IconButton component -const CloseIconButton = styled(IconButton)({ - marginTop: 0, -}); From b892c7ee506c105e5af7d8a751c62c5e8567a4f5 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 11:30:56 -0300 Subject: [PATCH 31/51] remove unused import --- code/ui/manager/src/components/sidebar/Menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ui/manager/src/components/sidebar/Menu.tsx b/code/ui/manager/src/components/sidebar/Menu.tsx index 1765c6e13a62..9dadfa2b156e 100644 --- a/code/ui/manager/src/components/sidebar/Menu.tsx +++ b/code/ui/manager/src/components/sidebar/Menu.tsx @@ -5,7 +5,7 @@ import { styled } from '@storybook/theming'; import { transparentize } from 'polished'; import type { Button, TooltipLinkListLink } from '@storybook/components'; import { WithTooltip, TooltipLinkList, Icons, IconButton } from '@storybook/components'; -import { CloseIcon, CogIcon, MenuIcon } from '@storybook/icons'; +import { CloseIcon, CogIcon } from '@storybook/icons'; import { useLayout } from '../layout/LayoutProvider'; export type MenuList = ComponentProps['links']; From 2a4413bfc93c48d5ec0113b3244c5d9c00659dd3 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 27 Dec 2023 14:14:22 -0300 Subject: [PATCH 32/51] CLI: Add Storyshots migration notice --- README.md | 6 +- code/addons/docs/README.md | 14 ----- code/lib/cli/src/automigrate/fixes/index.ts | 2 + .../fixes/storyshots-migration.test.ts | 60 +++++++++++++++++++ .../automigrate/fixes/storyshots-migration.ts | 30 ++++++++++ docs/configure/frameworks-feature-support.md | 2 +- docs/writing-tests/snapshot-testing.md | 2 +- 7 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 code/lib/cli/src/automigrate/fixes/storyshots-migration.test.ts create mode 100644 code/lib/cli/src/automigrate/fixes/storyshots-migration.ts diff --git a/README.md b/README.md index 7c174bdcc250..263ee639e993 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ For additional help, share your issue in [the repo's GitHub Discussions](https:/ See [Addon / Framework Support Table](https://storybook.js.org/docs/react/api/frameworks-feature-support) -### Deprecated Addons +### Deprecated/Removed Addons | Addons | | | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | @@ -147,12 +147,14 @@ See [Addon / Framework Support Table](https://storybook.js.org/docs/react/api/fr | [options](https://www.npmjs.com/package/@storybook/addon-options) | Customize the Storybook UI in code | | [storyshots](https://github.com/storybookjs/storybook/tree/main/code/addons/storyshots-core) | Snapshot testing for components in Storybook | -To continue improving your experience, we have to eventually deprecate certain addons in favor of new and better tools. +To continue improving your experience, we have to eventually deprecate or remove certain addons in favor of new and better tools. If you're using info/notes, we highly recommend you migrate to [docs](code/addons/docs/) instead, and [here is a guide](code/addons/docs/docs/recipes.md#migrating-from-notesinfo-addons) to help you. If you're using contexts, we highly recommend you migrate to [toolbars](https://github.com/storybookjs/storybook/tree/next/code/addons/toolbars) and [here is a guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-addon-contexts) to help you. +If you're using addon-storyshots, we highly recommend you migrate to the Storybook [test-runner](https://github.com/storybookjs/test-runner) and [here is a guide](https://storybook.js.org/docs/writing-tests/storyshots-migration-guide) to help you. + ## Badges & Presentation materials We have a badge! Link it to your live Storybook example. diff --git a/code/addons/docs/README.md b/code/addons/docs/README.md index 9a9a3debad2a..379b23f2d8a1 100644 --- a/code/addons/docs/README.md +++ b/code/addons/docs/README.md @@ -110,20 +110,6 @@ export default { }; ``` -If using in conjunction with the [storyshots add-on](https://github.com/storybookjs/storybook/blob/next/code/addons/storyshots-core/README.md), you will need to -configure Jest to transform MDX stories into something Storyshots can understand: - -Add the following to your Jest configuration: - -```json -{ - "transform": { - "^.+\\.[tj]sx?$": "babel-jest", - "^.+\\.mdx$": "@storybook/addon-docs/jest-transform-mdx" - } -} -``` - ### Be sure to check framework specific installation needs - [React](https://github.com/storybookjs/storybook/tree/next/code/addons/docs/react) (covered here) diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index bd33074805d8..0c6202f24264 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -19,6 +19,7 @@ import { incompatibleAddons } from './incompatible-addons'; import { angularBuildersMultiproject } from './angular-builders-multiproject'; import { wrapRequire } from './wrap-require'; import { reactDocgen } from './react-docgen'; +import { storyshotsMigration } from './storyshots-migration'; export * from '../types'; @@ -42,6 +43,7 @@ export const allFixes: Fix[] = [ angularBuilders, wrapRequire, reactDocgen, + storyshotsMigration, ]; export const initFixes: Fix[] = [missingBabelRc, eslintPlugin]; diff --git a/code/lib/cli/src/automigrate/fixes/storyshots-migration.test.ts b/code/lib/cli/src/automigrate/fixes/storyshots-migration.test.ts new file mode 100644 index 000000000000..4a7ccc9d335a --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/storyshots-migration.test.ts @@ -0,0 +1,60 @@ +import { describe, afterEach, it, expect, vi } from 'vitest'; + +import type { StorybookConfig } from '@storybook/types'; +import { storyshotsMigration } from './storyshots-migration'; +import type { JsPackageManager } from '../../js-package-manager'; + +const check = async ({ + packageManager, + main: mainConfig = {}, + storybookVersion = '8.0.0', +}: { + packageManager: Partial; + main?: Partial & Record; + storybookVersion?: string; +}) => { + return storyshotsMigration.check({ + packageManager: packageManager as any, + configDir: '', + mainConfig: mainConfig as any, + storybookVersion, + }); +}; + +describe('storyshots-migration fix', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should detect storyshots registered in main.js', async () => { + await expect( + check({ + packageManager: { + getAllDependencies: async () => ({}), + }, + main: { addons: ['@storybook/addon-storyshots'] }, + }) + ).resolves.toBeTruthy(); + }); + + it('should detect storyshots in package.json', async () => { + await expect( + check({ + packageManager: { + getAllDependencies: async () => ({ '@storybook/addon-storyshots': '7.0.0' }), + }, + }) + ).resolves.toBeTruthy(); + }); + + it('no-op when storyshots is not present', async () => { + await expect( + check({ + packageManager: { + getAllDependencies: async () => ({}), + }, + main: { addons: ['@storybook/essentials'] }, + }) + ).resolves.toBeNull(); + }); +}); diff --git a/code/lib/cli/src/automigrate/fixes/storyshots-migration.ts b/code/lib/cli/src/automigrate/fixes/storyshots-migration.ts new file mode 100644 index 000000000000..6d047f88449f --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/storyshots-migration.ts @@ -0,0 +1,30 @@ +import chalk from 'chalk'; +import dedent from 'ts-dedent'; +import type { Fix } from '../types'; + +export const storyshotsMigration: Fix = { + id: 'storyshots-migration', + promptOnly: true, + + async check({ mainConfig, packageManager }) { + const allDeps = await packageManager.getAllDependencies(); + const hasStoryshots = + allDeps['@storybook/addon-storyshots'] || + mainConfig.addons?.find((addon) => { + const addonName = typeof addon === 'string' ? addon : addon.name; + return addonName.includes('@storybook/addon-storyshots'); + }); + + return hasStoryshots ?? null; + }, + prompt() { + return dedent` + ${chalk.bold( + 'Attention' + )}: Storyshots is now officially deprecated, is no longer being maintained, and was removed in Storybook 8. + + We recommend following the migration guide we've prepared to help you during this transition period: + ${chalk.yellow('https://storybook.js.org/docs/writing-tests/storyshots-migration-guide')} + `; + }, +}; diff --git a/docs/configure/frameworks-feature-support.md b/docs/configure/frameworks-feature-support.md index 306ee9e94160..498d984cabec 100644 --- a/docs/configure/frameworks-feature-support.md +++ b/docs/configure/frameworks-feature-support.md @@ -113,5 +113,5 @@ To align the Storybook ecosystem with the current state of frontend development, | Feature | Status | | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Knobs](https://github.com/storybookjs/addon-knobs) | The Knobs addon was officially deprecated with the release of Storybook 6.3 and is no longer actively maintained. We recommend using the [controls](../essentials/controls.md) instead. | -| [Storyshots](../writing-tests/snapshot-testing.md) | The Storyshots addon was officially deprecated with the release of Storybook 7.6 and is no longer actively maintained. See the [migration guide](../writing-tests/storyshots-migration-guide.md) for the available alternatives. | +| [Storyshots](../writing-tests/snapshot-testing.md) | The Storyshots addon was officially deprecated with the release of Storybook 7.6, is no longer actively maintained and was removed in Storybook 8. See the [migration guide](../writing-tests/storyshots-migration-guide.md) for the available alternatives. | | [`StoriesOf`](https://github.com/storybookjs/storybook/blob/next/code/lib/preview-api/docs/storiesOf.md) | The `storiesOf` API was officially deprecated with the release of Storybook 7.5 and is no longer actively maintained. We recommend using the [CSF API](../api/csf.md) instead for writing stories.
See the [migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#storystorev6-and-storiesof-is-deprecated) for more information. | diff --git a/docs/writing-tests/snapshot-testing.md b/docs/writing-tests/snapshot-testing.md index 8570dd376179..438258b36adb 100644 --- a/docs/writing-tests/snapshot-testing.md +++ b/docs/writing-tests/snapshot-testing.md @@ -16,7 +16,7 @@ The Storyshots addon was the original testing solution for Storybook, offering a -The Storyshots addon has been deprecated and will be removed in a future release of Storybook. See the [migration guide](./storyshots-migration-guide.md) for more information. +The Storyshots addon was deprecated and has been removed in Storybook 8. See the [migration guide](./storyshots-migration-guide.md) for more information. From f347c154214ac1e0c6ef024dc749e304db481579 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 27 Dec 2023 16:00:16 -0300 Subject: [PATCH 33/51] add test timeout --- .../src/modules/preview-web/PreviewWeb.integration.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts index b3d7aa04bde9..494ceec4c7ae 100644 --- a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts +++ b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts @@ -111,7 +111,9 @@ describe('PreviewWeb', () => { await waitForRender(); expect(docsRoot.outerHTML).toMatchInlineSnapshot('"
INSIDE
"'); - }); + // Extended timeout to try and avoid + // Error: Event was not emitted in time: storyRendered,docsRendered,storyThrewException,storyErrored,storyMissing + }, 10_000); // TODO @tmeasday please help fixing this test it.skip('sends docs rendering exceptions to showException', async () => { From ea26963386635645c765654ab0b26b96dfaf281a Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 09:59:20 -0300 Subject: [PATCH 34/51] add storyshots migration guide to migration notes --- MIGRATION.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index c69c72a1fc66..f5e956711c63 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -407,22 +407,24 @@ Addon authors are advised to upgrade to react v18. #### Storyshots has been removed -Storyshots was an addon for storybook which allowed users to turn their stories into automated snapshot-tests. +Storyshots was an addon for Storybook which allowed users to turn their stories into automated snapshot tests. -Every story would automatically be taken into account and created a snapshot-file for. +Every story would automatically be taken into account and create a snapshot file. -Snapshot-testing has since fallen out of favor and is no longer recommended. +Snapshot testing has since fallen out of favor and is no longer recommended. -In addition to it's limited use, and high chance of false-positives, storyshots ran code developed to run in the browser in NodeJS via JSDOM. -JSDOM has limitations and is not a perfect emulation of the browser environment; therefore storyshots was always a pain to setup and maintain. +In addition to its limited use, and high chance of false positives, Storyshots ran code developed to run in the browser in NodeJS via JSDOM. +JSDOM has limitations and is not a perfect emulation of the browser environment; therefore, Storyshots was always a pain to set up and maintain. -The storybook team has build the test-runner as a direct replacement, which utilizes playwright to connect to an actual browser where storybook runs the code. +The Storybook team has built the test-runner as a direct replacement, which utilizes Playwright to connect to an actual browser where Storybook runs the code. -In addition CSF has expanded to allow for play-function to be defined on stories, which allows for more complex testing scenarios, fully integrated within storybook itself (and supported by the test-runner, and not storyshots). +In addition, CSF has expanded to allow for play functions to be defined on stories, which allows for more complex testing scenarios, fully integrated within Storybook itself (and supported by the test-runner, and not Storyshots). -Finally `storyStoreV7: true` (the default and only options in storybook 8), was not supported by storyshots. +Finally, storyStoreV7: true (the default and only option in Storybook 8), was not supported by Storyshots. -By removing storyshots, the storybook team was unblocked from moving (eventually) to an ESM-only storybook, which is a big step towards a more modern storybook. +By removing Storyshots, the Storybook team was unblocked from moving (eventually) to an ESM-only Storybook, which is a big step towards a more modern Storybook. + +Please check the [migration guide](https://storybook.js.org/docs/writing-tests/storyshots-migration-guide) that we prepared. #### UI layout state has changed shape From 6db8c1b3e42ac2b03e1b0b42de9a6bd4279acf56 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 14:55:34 -0300 Subject: [PATCH 35/51] add comment to deprecation notice --- .../src/components/Button/Button.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/ui/components/src/components/Button/Button.tsx b/code/ui/components/src/components/Button/Button.tsx index 5045f0621ed2..37b64a786493 100644 --- a/code/ui/components/src/components/Button/Button.tsx +++ b/code/ui/components/src/components/Button/Button.tsx @@ -15,23 +15,23 @@ export interface ButtonProps extends ButtonHTMLAttributes { active?: boolean; animation?: 'none' | 'rotate360' | 'glow' | 'jiggle'; - /** @deprecated Use {@link asChild} instead */ + /** @deprecated Use {@link asChild} instead. This will be removed in Storybook 9.0 */ isLink?: boolean; - /** @deprecated Use {@link variant} instead */ + /** @deprecated Use {@link variant} instead. This will be removed in Storybook 9.0 */ primary?: boolean; - /** @deprecated Use {@link variant} instead */ + /** @deprecated Use {@link variant} instead. This will be removed in Storybook 9.0 */ secondary?: boolean; - /** @deprecated Use {@link variant} instead */ + /** @deprecated Use {@link variant} instead. This will be removed in Storybook 9.0 */ tertiary?: boolean; - /** @deprecated Use {@link variant} instead */ + /** @deprecated Use {@link variant} instead. This will be removed in Storybook 9.0 */ gray?: boolean; - /** @deprecated Use {@link variant} instead */ + /** @deprecated Use {@link variant} instead. This will be removed in Storybook 9.0 */ inForm?: boolean; - /** @deprecated Use {@link size} instead */ + /** @deprecated Use {@link size} instead. This will be removed in Storybook 9.0 */ small?: boolean; - /** @deprecated Use {@link variant} instead */ + /** @deprecated Use {@link variant} instead. This will be removed in Storybook 9.0 */ outline?: boolean; - /** @deprecated Add your icon as a child directly */ + /** @deprecated Add your icon as a child directly. This will be removed in Storybook 9.0 */ containsIcon?: boolean; } From 6bf2bce9d42c25d162042f684dc54fa467257eb0 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 17:20:55 -0300 Subject: [PATCH 36/51] Core: Remove unused warnOnLegacyHierarchySeparator type --- code/lib/core-server/src/presets/common-preset.ts | 1 - code/lib/core-server/src/utils/getStoryIndexGenerator.ts | 1 - code/lib/types/src/modules/core-common.ts | 6 ------ 3 files changed, 8 deletions(-) diff --git a/code/lib/core-server/src/presets/common-preset.ts b/code/lib/core-server/src/presets/common-preset.ts index 350872f38891..e1248f1f8dd1 100644 --- a/code/lib/core-server/src/presets/common-preset.ts +++ b/code/lib/core-server/src/presets/common-preset.ts @@ -187,7 +187,6 @@ export const previewAnnotations = async (base: any, options: Options) => { export const features: PresetProperty<'features'> = async (existing) => ({ ...existing, - warnOnLegacyHierarchySeparator: true, buildStoriesJson: false, storyStoreV7: true, argTypeTargetsV7: true, diff --git a/code/lib/core-server/src/utils/getStoryIndexGenerator.ts b/code/lib/core-server/src/utils/getStoryIndexGenerator.ts index 74401020256e..810b95244c72 100644 --- a/code/lib/core-server/src/utils/getStoryIndexGenerator.ts +++ b/code/lib/core-server/src/utils/getStoryIndexGenerator.ts @@ -10,7 +10,6 @@ export async function getStoryIndexGenerator( buildStoriesJson?: boolean; storyStoreV7?: boolean; argTypeTargetsV7?: boolean; - warnOnLegacyHierarchySeparator?: boolean; }, options: Options, serverChannel: ServerChannel diff --git a/code/lib/types/src/modules/core-common.ts b/code/lib/types/src/modules/core-common.ts index 8f848909d8ed..1affaa649a9b 100644 --- a/code/lib/types/src/modules/core-common.ts +++ b/code/lib/types/src/modules/core-common.ts @@ -375,12 +375,6 @@ export interface StorybookConfigRaw { */ argTypeTargetsV7?: boolean; - /** - * Warn when there is a pre-6.0 hierarchy separator ('.' / '|') in the story title. - * Will be removed in 7.0. - */ - warnOnLegacyHierarchySeparator?: boolean; - /** * Use legacy MDX1, to help smooth migration to 7.0 */ From fe7297ae396bf4a12cacaf124b5e36e22104f8ab Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Wed, 3 Jan 2024 12:37:43 +0800 Subject: [PATCH 37/51] Simplify viewports logic --- code/addons/viewport/src/Tool.tsx | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/code/addons/viewport/src/Tool.tsx b/code/addons/viewport/src/Tool.tsx index 229f5e21bafa..8a2f97c6b1a3 100644 --- a/code/addons/viewport/src/Tool.tsx +++ b/code/addons/viewport/src/Tool.tsx @@ -116,8 +116,8 @@ export const ViewportTool: FC = memo( const { viewports = MINIMAL_VIEWPORTS, - defaultOrientation = 'portrait', - defaultViewport = globals.viewport || responsiveViewport.id, + defaultOrientation, + defaultViewport, disable, } = useParameter(PARAM_KEY, {}); @@ -125,7 +125,7 @@ export const ViewportTool: FC = memo( const api = useStorybookApi(); const [isTooltipVisible, setIsTooltipVisible] = useState(false); - if (!list.find((i) => i.id === defaultViewport)) { + if (defaultViewport && !list.find((i) => i.id === defaultViewport)) { // eslint-disable-next-line no-console console.warn( `Cannot find "defaultViewport" of "${defaultViewport}" in addon-viewport configs, please check the "viewports" setting in the configuration.` @@ -134,18 +134,21 @@ export const ViewportTool: FC = memo( useEffect(() => { registerShortcuts(api, globals, updateGlobals, Object.keys(viewports)); - }, [viewports, globals.viewport]); + }, [viewports]); useEffect(() => { - updateGlobals({ - viewport: - defaultViewport || - (globals.viewport && viewports[globals.viewport] - ? globals.viewport - : responsiveViewport.id), - viewportRotated: defaultOrientation === 'landscape', - }); - }, [defaultOrientation, defaultViewport]); + const defaultRotated = defaultOrientation === 'landscape'; + + if ( + (defaultViewport && globals.viewport !== defaultViewport) || + (defaultOrientation && globals.viewportRotated !== defaultRotated) + ) { + updateGlobals({ + viewport: defaultViewport, + viewportRotated: defaultRotated, + }); + } + }, [defaultOrientation, defaultViewport, globals, updateGlobals]); const item = list.find((i) => i.id === globals.viewport) || From bd8236d9a364f5c837b77bba1f1bf226aeec7134 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Wed, 3 Jan 2024 10:02:14 +0100 Subject: [PATCH 38/51] restructure migration deprecations, add svelte 4 section --- MIGRATION.md | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index c69c72a1fc66..467fc0e5969d 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -10,12 +10,17 @@ - [UI layout state has changed shape](#ui-layout-state-has-changed-shape) - [New UI and props for Button and IconButton components](#new-ui-and-props-for-button-and-iconbutton-components) - [Icons is deprecated](#icons-is-deprecated) - - [React-docgen component analysis by default](#react-docgen-component-analysis-by-default) - [Removed postinstall](#removed-postinstall) - [Removed stories.json](#removed-storiesjson) - [Framework-specific changes](#framework-specific-changes) - - [Angular: Drop support for Angular \< 15](#angular-drop-support-for-angular--15) - - [Next.js: Drop support for version \< 13.5](#nextjs-drop-support-for-version--135) + - [React](#react) + - [`react-docgen` component analysis by default](#react-docgen-component-analysis-by-default) + - [Next.js](#nextjs) + - [Require Next.js 13.5 and up](#require-nextjs-135-and-up) + - [Angular](#angular) + - [Require Angular 15 and up](#require-angular-15-and-up) + - [Svelte](#svelte) + - [Require Svelte 4 and up](#require-svelte-4-and-up) - [From version 7.5.0 to 7.6.0](#from-version-750-to-760) - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) @@ -454,7 +459,21 @@ The `IconButton` doesn't have any deprecated props but it now uses the new `Butt In Storybook 8.0 we are introducing a new icon library available with `@storybook/icons`. We are deprecating the `Icons` component in `@storybook/components` and recommend that addon creators and Storybook maintainers use the new `@storybook/icons` component instead. -#### React-docgen component analysis by default +#### Removed postinstall + +We removed the `@storybook/postinstall` package, which provided some utilities for addons to programmatically modify user configuration files on install. This package was years out of date, so this should be a non-disruptive change. If your addon used the package, you can view the old source code [here](https://github.com/storybookjs/storybook/tree/release-7-5/code/lib/postinstall) and adapt it into your addon. + +#### Removed stories.json + +In addition to the built storybook, `storybook build` generates two files, `index.json` and `stories.json`, that list out the contents of the Storybook. `stories.json` is a legacy format and we included it for backwards compatibility. As of 8.0 we no longer build `stories.json` by default, and we will remove it completely in 9.0. + +In the meantime if you have code that relies on `stories.json`, you can find code that transforms the "v4" `index.json` to the "v3" `stories.json` format (and their respective TS types): https://github.com/storybookjs/storybook/blob/release-7-5/code/lib/core-server/src/utils/stories-json.ts#L71-L91 + +### Framework-specific changes + +#### React + +##### `react-docgen` component analysis by default In Storybook 7, we used `react-docgen-typescript` to analyze React component props and auto-generate controls. In Storybook 8, we have moved to `react-docgen` as the new default. `react-docgen` is dramatically more efficient, shaving seconds off of dev startup times. However, it only analyzes basic TypeScript constructs. @@ -470,25 +489,23 @@ export default { For more information see: https://storybook.js.org/docs/react/api/main-config-typescript#reactdocgen -#### Removed postinstall - -We removed the `@storybook/postinstall` package, which provided some utilities for addons to programmatically modify user configuration files on install. This package was years out of date, so this should be a non-disruptive change. If your addon used the package, you can view the old source code [here](https://github.com/storybookjs/storybook/tree/release-7-5/code/lib/postinstall) and adapt it into your addon. +#### Next.js -#### Removed stories.json +##### Require Next.js 13.5 and up -In addition to the built storybook, `storybook build` generates two files, `index.json` and `stories.json`, that list out the contents of the Storybook. `stories.json` is a legacy format and we included it for backwards compatibility. As of 8.0 we no longer build `stories.json` by default, and we will remove it completely in 9.0. +Starting in 8.0, Storybook requires Next.js 13.5 and up. -In the meantime if you have code that relies on `stories.json`, you can find code that transforms the "v4" `index.json` to the "v3" `stories.json` format (and their respective TS types): https://github.com/storybookjs/storybook/blob/release-7-5/code/lib/core-server/src/utils/stories-json.ts#L71-L91 +#### Angular -### Framework-specific changes +##### Require Angular 15 and up -#### Angular: Drop support for Angular \< 15 +Starting in 8.0, Storybook requires Angular 15 and up. -Starting in 8.0, we drop support for Angular < 15 +#### Svelte -#### Next.js: Drop support for version \< 13.5 +##### Require Svelte 4 and up -Starting in 8.0, we drop support for Next.js < 13.5. +Starting in 8.0, Storybook requires Svelte 4 and up. ## From version 7.5.0 to 7.6.0 From 64eef7cb3f4a3902279c0b700095a23648689b29 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 3 Jan 2024 11:30:02 +0100 Subject: [PATCH 39/51] Remove vite plugins and drop Vite 3 support --- code/builders/builder-vite/package.json | 6 +- code/frameworks/preact-vite/package.json | 3 +- code/frameworks/preact-vite/src/preset.ts | 10 -- code/frameworks/react-vite/package.json | 3 +- code/frameworks/react-vite/src/preset.ts | 7 - code/frameworks/svelte-vite/package.json | 5 +- code/frameworks/svelte-vite/src/preset.ts | 8 +- code/frameworks/vue3-vite/package.json | 3 +- code/frameworks/vue3-vite/src/preset.ts | 7 - code/yarn.lock | 156 ++-------------------- 10 files changed, 22 insertions(+), 186 deletions(-) diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index 081fcf17090c..59bb5dc7e3fc 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -57,14 +57,12 @@ "express": "^4.17.3", "find-cache-dir": "^3.0.0", "fs-extra": "^11.1.0", - "magic-string": "^0.30.0", - "rollup": "^2.25.0 || ^3.3.0" + "magic-string": "^0.30.0" }, "devDependencies": { "@types/express": "^4.17.13", "@types/node": "^18.0.0", "glob": "^10.0.0", - "rollup": "^3.20.1", "slash": "^5.0.0", "typescript": "^5.3.2", "vite": "^4.0.4" @@ -72,7 +70,7 @@ "peerDependencies": { "@preact/preset-vite": "*", "typescript": ">= 4.3.x", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0", + "vite": "^4.0.0 || ^5.0.0", "vite-plugin-glimmerx": "*" }, "peerDependenciesMeta": { diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index caad949fb1a4..96c6e744dcf6 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -47,7 +47,6 @@ "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@preact/preset-vite": "^2.0.0", "@storybook/builder-vite": "workspace:*", "@storybook/preact": "workspace:*" }, @@ -58,7 +57,7 @@ }, "peerDependencies": { "preact": ">=10", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "vite": "^4.0.0 || ^5.0.0" }, "engines": { "node": ">=16" diff --git a/code/frameworks/preact-vite/src/preset.ts b/code/frameworks/preact-vite/src/preset.ts index 2d4e18d77e90..4002182ea926 100644 --- a/code/frameworks/preact-vite/src/preset.ts +++ b/code/frameworks/preact-vite/src/preset.ts @@ -1,6 +1,4 @@ -import { hasVitePlugins } from '@storybook/builder-vite'; import type { PresetProperty } from '@storybook/types'; -import preact from '@preact/preset-vite'; import { dirname, join } from 'path'; import type { StorybookConfig } from './types'; @@ -13,14 +11,6 @@ export const core: PresetProperty<'core', StorybookConfig> = { }; export const viteFinal: StorybookConfig['viteFinal'] = async (config) => { - const { plugins = [] } = config; - - // Add Preact plugin if not present - if (!(await hasVitePlugins(plugins, ['vite:preact-jsx']))) { - plugins.push(preact()); - } - // TODO: Add docgen plugin per issue https://github.com/storybookjs/storybook/issues/19739 - return config; }; diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index d06ab648e3ce..a5c9895676ab 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -51,7 +51,6 @@ "@rollup/pluginutils": "^5.0.2", "@storybook/builder-vite": "workspace:*", "@storybook/react": "workspace:*", - "@vitejs/plugin-react": "^3.0.1", "magic-string": "^0.30.0", "react-docgen": "^7.0.0" }, @@ -63,7 +62,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "vite": "^4.0.0 || ^5.0.0" }, "engines": { "node": ">=16" diff --git a/code/frameworks/react-vite/src/preset.ts b/code/frameworks/react-vite/src/preset.ts index 207f60988ebc..0defee003966 100644 --- a/code/frameworks/react-vite/src/preset.ts +++ b/code/frameworks/react-vite/src/preset.ts @@ -1,6 +1,5 @@ /* eslint-disable global-require */ import type { PresetProperty } from '@storybook/types'; -import { hasVitePlugins } from '@storybook/builder-vite'; import { dirname, join } from 'path'; import type { StorybookConfig } from './types'; @@ -15,12 +14,6 @@ export const core: PresetProperty<'core', StorybookConfig> = { export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => { const { plugins = [] } = config; - // Add react plugin if not present - if (!(await hasVitePlugins(plugins, ['vite:react-babel', 'vite:react-swc']))) { - const { default: react } = await import('@vitejs/plugin-react'); - plugins.push(react()); - } - // Add docgen plugin const { reactDocgen: reactDocgenOption, reactDocgenTypescriptOptions } = await presets.apply( 'typescript', diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 22357db9e547..654cca9a9e0c 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -50,21 +50,22 @@ "@storybook/builder-vite": "workspace:*", "@storybook/node-logger": "workspace:*", "@storybook/svelte": "workspace:*", - "@sveltejs/vite-plugin-svelte": "^2.4.2", "magic-string": "^0.30.0", "svelte-preprocess": "^5.1.1", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.2.0" }, "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^3.0.1", "@types/node": "^18.0.0", "svelte": "^5.0.0-next.16", "typescript": "^5.3.2", "vite": "^4.0.0" }, "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^2.0.0 || ^3.0.0", "svelte": "^4.0.0 || ^5.0.0-next.16", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "vite": "^4.0.0 || ^5.0.0" }, "engines": { "node": "^14.18 || >=16" diff --git a/code/frameworks/svelte-vite/src/preset.ts b/code/frameworks/svelte-vite/src/preset.ts index 220812cf7c5a..95966bd3f9ca 100644 --- a/code/frameworks/svelte-vite/src/preset.ts +++ b/code/frameworks/svelte-vite/src/preset.ts @@ -1,4 +1,3 @@ -import { hasVitePlugins } from '@storybook/builder-vite'; import type { PresetProperty } from '@storybook/types'; import { dirname, join } from 'path'; import type { StorybookConfig } from './types'; @@ -17,14 +16,9 @@ export const viteFinal: NonNullable = async (confi const { plugins = [] } = config; // TODO: set up eslint import to use typescript resolver // eslint-disable-next-line import/no-unresolved - const { svelte, loadSvelteConfig } = await import('@sveltejs/vite-plugin-svelte'); + const { loadSvelteConfig } = await import('@sveltejs/vite-plugin-svelte'); const svelteConfig = await loadSvelteConfig(); - // Add svelte plugin if the user does not have a Vite config of their own - if (!(await hasVitePlugins(plugins, ['vite-plugin-svelte']))) { - plugins.push(svelte()); - } - // Add docgen plugin plugins.push(svelteDocgen(svelteConfig)); diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index b2793bc7be19..28eeb77722e1 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -50,7 +50,6 @@ "@storybook/builder-vite": "workspace:*", "@storybook/core-server": "workspace:*", "@storybook/vue3": "workspace:*", - "@vitejs/plugin-vue": "^4.0.0", "magic-string": "^0.30.0", "vue-docgen-api": "^4.40.0" }, @@ -60,7 +59,7 @@ "vite": "^4.0.0" }, "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "vite": "^4.0.0 || ^5.0.0" }, "engines": { "node": "^14.18 || >=16" diff --git a/code/frameworks/vue3-vite/src/preset.ts b/code/frameworks/vue3-vite/src/preset.ts index c0d97bd8da87..2fb65169d339 100644 --- a/code/frameworks/vue3-vite/src/preset.ts +++ b/code/frameworks/vue3-vite/src/preset.ts @@ -1,4 +1,3 @@ -import { hasVitePlugins } from '@storybook/builder-vite'; import type { PresetProperty } from '@storybook/types'; import { mergeConfig, type PluginOption } from 'vite'; import { dirname, join } from 'path'; @@ -16,12 +15,6 @@ export const core: PresetProperty<'core'> = { export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => { const plugins: PluginOption[] = []; - // Add vue plugin if not present - if (!(config.plugins && (await hasVitePlugins(config.plugins, ['vite:vue'])))) { - const { default: vue } = await import('@vitejs/plugin-vue'); - plugins.push(vue()); - } - // Add docgen plugin plugins.push(vueDocgen()); diff --git a/code/yarn.lock b/code/yarn.lock index 1a55377378c9..16eded012b95 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -4130,64 +4130,6 @@ __metadata: languageName: node linkType: hard -"@preact/preset-vite@npm:^2.0.0": - version: 2.7.0 - resolution: "@preact/preset-vite@npm:2.7.0" - dependencies: - "@babel/plugin-transform-react-jsx": "npm:^7.22.15" - "@babel/plugin-transform-react-jsx-development": "npm:^7.22.5" - "@prefresh/vite": "npm:^2.4.1" - "@rollup/pluginutils": "npm:^4.1.1" - babel-plugin-transform-hook-names: "npm:^1.0.2" - debug: "npm:^4.3.4" - kolorist: "npm:^1.8.0" - resolve: "npm:^1.22.8" - peerDependencies: - "@babel/core": 7.x - vite: 2.x || 3.x || 4.x || 5.x - checksum: 95a5a87d804d9f33d98f7c8db93fe27de0d626b2794e745734bcad7a7d89db5a3ad37712feb188f1857d834658de33167f524b3040e8cea48ef422da6a1e74db - languageName: node - linkType: hard - -"@prefresh/babel-plugin@npm:0.5.1": - version: 0.5.1 - resolution: "@prefresh/babel-plugin@npm:0.5.1" - checksum: f9153c210427adbddb4403502f8fa845f6207516de2d162f5d550683a87173dc3eaabc6be2bb4f1206b882cdd23339f2092567be8d09794a3d06a5626942b1e4 - languageName: node - linkType: hard - -"@prefresh/core@npm:^1.5.1": - version: 1.5.2 - resolution: "@prefresh/core@npm:1.5.2" - peerDependencies: - preact: ^10.0.0 - checksum: 53d1ce714ed098ccc11f3a8e2826ff6b90237445c24df6281eb162791b534d1d7626a43c0c1c7427139d2ade658e1ba7020963c001135bbdbeeb15073008529b - languageName: node - linkType: hard - -"@prefresh/utils@npm:^1.2.0": - version: 1.2.0 - resolution: "@prefresh/utils@npm:1.2.0" - checksum: 38cdc6cbb5e18df36996161214eb1097db3361cb0b6402a8012cbe500ba8fb5bcbdc39a687d3b6d67e99f6c340ed77d59f27ab167dfc1655eb4d783740d87d52 - languageName: node - linkType: hard - -"@prefresh/vite@npm:^2.4.1": - version: 2.4.4 - resolution: "@prefresh/vite@npm:2.4.4" - dependencies: - "@babel/core": "npm:^7.22.1" - "@prefresh/babel-plugin": "npm:0.5.1" - "@prefresh/core": "npm:^1.5.1" - "@prefresh/utils": "npm:^1.2.0" - "@rollup/pluginutils": "npm:^4.2.1" - peerDependencies: - preact: ^10.4.0 - vite: ">=2.0.0" - checksum: 31c3fcdcfbfd31921d41f01ca027515d4411f4169c2d3810578bf87b61609d155a1a410c977f098839982adb8da2d88674382cc4a5e55b6fe249a59be60a2483 - languageName: node - linkType: hard - "@radix-ui/number@npm:1.0.1": version: 1.0.1 resolution: "@radix-ui/number@npm:1.0.1" @@ -4366,16 +4308,6 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.1": - version: 4.2.1 - resolution: "@rollup/pluginutils@npm:4.2.1" - dependencies: - estree-walker: "npm:^2.0.1" - picomatch: "npm:^2.2.2" - checksum: 3ee56b2c8f1ed8dfd0a92631da1af3a2dfdd0321948f089b3752b4de1b54dc5076701eadd0e5fc18bd191b77af594ac1db6279e83951238ba16bf8a414c64c48 - languageName: node - linkType: hard - "@rollup/pluginutils@npm:^5.0.2": version: 5.1.0 resolution: "@rollup/pluginutils@npm:5.1.0" @@ -5172,14 +5104,13 @@ __metadata: fs-extra: "npm:^11.1.0" glob: "npm:^10.0.0" magic-string: "npm:^0.30.0" - rollup: "npm:^3.20.1" slash: "npm:^5.0.0" typescript: "npm:^5.3.2" vite: "npm:^4.0.4" peerDependencies: "@preact/preset-vite": "*" typescript: ">= 4.3.x" - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + vite: ^4.0.0 || ^5.0.0 vite-plugin-glimmerx: "*" peerDependenciesMeta: "@preact/preset-vite": @@ -5941,7 +5872,6 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/preact-vite@workspace:frameworks/preact-vite" dependencies: - "@preact/preset-vite": "npm:^2.0.0" "@storybook/builder-vite": "workspace:*" "@storybook/preact": "workspace:*" "@types/node": "npm:^18.0.0" @@ -5949,7 +5879,7 @@ __metadata: vite: "npm:^4.0.0" peerDependencies: preact: ">=10" - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + vite: ^4.0.0 || ^5.0.0 languageName: unknown linkType: soft @@ -6224,7 +6154,6 @@ __metadata: "@storybook/builder-vite": "workspace:*" "@storybook/react": "workspace:*" "@types/node": "npm:^18.0.0" - "@vitejs/plugin-react": "npm:^3.0.1" magic-string: "npm:^0.30.0" react-docgen: "npm:^7.0.0" typescript: "npm:^5.3.2" @@ -6232,7 +6161,7 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + vite: ^4.0.0 || ^5.0.0 languageName: unknown linkType: soft @@ -6536,7 +6465,7 @@ __metadata: "@storybook/builder-vite": "workspace:*" "@storybook/node-logger": "workspace:*" "@storybook/svelte": "workspace:*" - "@sveltejs/vite-plugin-svelte": "npm:^2.4.2" + "@sveltejs/vite-plugin-svelte": "npm:^3.0.1" "@types/node": "npm:^18.0.0" magic-string: "npm:^0.30.0" svelte: "npm:^5.0.0-next.16" @@ -6546,8 +6475,9 @@ __metadata: typescript: "npm:^5.3.2" vite: "npm:^4.0.0" peerDependencies: + "@sveltejs/vite-plugin-svelte": ^2.0.0 || ^3.0.0 svelte: ^4.0.0 || ^5.0.0-next.16 - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + vite: ^4.0.0 || ^5.0.0 languageName: unknown linkType: soft @@ -6723,13 +6653,12 @@ __metadata: "@storybook/core-server": "workspace:*" "@storybook/vue3": "workspace:*" "@types/node": "npm:^18.0.0" - "@vitejs/plugin-vue": "npm:^4.0.0" magic-string: "npm:^0.30.0" typescript: "npm:^5.3.2" vite: "npm:^4.0.0" vue-docgen-api: "npm:^4.40.0" peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + vite: ^4.0.0 || ^5.0.0 languageName: unknown linkType: soft @@ -6838,19 +6767,6 @@ __metadata: languageName: node linkType: hard -"@sveltejs/vite-plugin-svelte-inspector@npm:^1.0.4": - version: 1.0.4 - resolution: "@sveltejs/vite-plugin-svelte-inspector@npm:1.0.4" - dependencies: - debug: "npm:^4.3.4" - peerDependencies: - "@sveltejs/vite-plugin-svelte": ^2.2.0 - svelte: ^3.54.0 || ^4.0.0 - vite: ^4.0.0 - checksum: f21cb6bde0d8cce505c558dcb786d00e514c270848d9ff21dca12bc8335588e1bd05215fe3cd7478c8a6779bae7a75629b68d484fcdf309d759f25ee58ea771e - languageName: node - linkType: hard - "@sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0-next.0 || ^2.0.0": version: 2.0.0 resolution: "@sveltejs/vite-plugin-svelte-inspector@npm:2.0.0" @@ -6864,24 +6780,6 @@ __metadata: languageName: node linkType: hard -"@sveltejs/vite-plugin-svelte@npm:^2.4.2": - version: 2.5.3 - resolution: "@sveltejs/vite-plugin-svelte@npm:2.5.3" - dependencies: - "@sveltejs/vite-plugin-svelte-inspector": "npm:^1.0.4" - debug: "npm:^4.3.4" - deepmerge: "npm:^4.3.1" - kleur: "npm:^4.1.5" - magic-string: "npm:^0.30.3" - svelte-hmr: "npm:^0.15.3" - vitefu: "npm:^0.2.4" - peerDependencies: - svelte: ^3.54.0 || ^4.0.0 || ^5.0.0-next.0 - vite: ^4.0.0 - checksum: 613a4ad18a946ddee7b82cae0d892040a9459a5ac5137cbaa91a4b7b67d504409b5dbc02d268136a740b09e42531b7516f80a0f687ca4fe2b0d99e6e483c5d06 - languageName: node - linkType: hard - "@sveltejs/vite-plugin-svelte@npm:^3.0.1": version: 3.0.1 resolution: "@sveltejs/vite-plugin-svelte@npm:3.0.1" @@ -8523,7 +8421,7 @@ __metadata: languageName: node linkType: hard -"@vitejs/plugin-vue@npm:^4.0.0, @vitejs/plugin-vue@npm:^4.4.0": +"@vitejs/plugin-vue@npm:^4.4.0": version: 4.5.2 resolution: "@vitejs/plugin-vue@npm:4.5.2" peerDependencies: @@ -10208,15 +10106,6 @@ __metadata: languageName: node linkType: hard -"babel-plugin-transform-hook-names@npm:^1.0.2": - version: 1.0.2 - resolution: "babel-plugin-transform-hook-names@npm:1.0.2" - peerDependencies: - "@babel/core": ^7.12.10 - checksum: 517b85fe0611d742b3fffad5d0e119fcbd29bf69f95c6970b9ede4cb66453c7106a2d3bf048b35255b78a9d6a9565ad37e73b46c0be1fe557e941c792fad79f0 - languageName: node - linkType: hard - "babel-preset-current-node-syntax@npm:^1.0.0": version: 1.0.1 resolution: "babel-preset-current-node-syntax@npm:1.0.1" @@ -18654,13 +18543,6 @@ __metadata: languageName: node linkType: hard -"kolorist@npm:^1.8.0": - version: 1.8.0 - resolution: "kolorist@npm:1.8.0" - checksum: 73075db44a692bf6c34a649f3b4b3aea4993b84f6b754cbf7a8577e7c7db44c0bad87752bd23b0ce533f49de2244ce2ce03b7b1b667a85ae170a94782cc50f9b - languageName: node - linkType: hard - "language-subtag-registry@npm:~0.3.2": version: 0.3.22 resolution: "language-subtag-registry@npm:0.3.22" @@ -19314,7 +19196,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:0.30.5, magic-string@npm:^0.30.0, magic-string@npm:^0.30.3, magic-string@npm:^0.30.4, magic-string@npm:^0.30.5": +"magic-string@npm:0.30.5, magic-string@npm:^0.30.0, magic-string@npm:^0.30.4, magic-string@npm:^0.30.5": version: 0.30.5 resolution: "magic-string@npm:0.30.5" dependencies: @@ -22429,7 +22311,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.2.3, picomatch@npm:^2.3.0, picomatch@npm:^2.3.1": +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3, picomatch@npm:^2.3.0, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be @@ -24666,7 +24548,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.8, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.13.1, resolve@npm:^1.14.2, resolve@npm:^1.15.1, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:^1.22.8, resolve@npm:^1.4.0": +"resolve@npm:1.22.8, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.13.1, resolve@npm:^1.14.2, resolve@npm:^1.15.1, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:^1.4.0": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -24692,7 +24574,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.13.1#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.15.1#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.4.0#optional!builtin": +"resolve@patch:resolve@npm%3A1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.13.1#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.15.1#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.4.0#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -24845,7 +24727,7 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^3.20.1, rollup@npm:^3.27.1": +"rollup@npm:^3.27.1": version: 3.29.4 resolution: "rollup@npm:3.29.4" dependencies: @@ -28485,18 +28367,6 @@ __metadata: languageName: node linkType: hard -"vitefu@npm:^0.2.4": - version: 0.2.4 - resolution: "vitefu@npm:0.2.4" - peerDependencies: - vite: ^3.0.0 || ^4.0.0 - peerDependenciesMeta: - vite: - optional: true - checksum: 78d5e7071c0c4fdfc010f15a3e5bac2d31090ddd48789446fce5b7d0f01496fc6a041b65d3add904365bb0ac6576bb93635f700971c16ffd27cd7c0bee9eb1ae - languageName: node - linkType: hard - "vitefu@npm:^0.2.5": version: 0.2.5 resolution: "vitefu@npm:0.2.5" From acc9f4814a8bf0e924bc997c0deecd94a119118f Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 3 Jan 2024 12:29:55 +0100 Subject: [PATCH 40/51] Add migration note --- MIGRATION.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index c69c72a1fc66..9459baa398a9 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -331,6 +331,21 @@ ## From version 7.x to 8.0.0 +### Framework specific vite plugins have to be explicitly added + +In Storybook 7 we would automatically add frameworks specific vite plugins, e.g. `@vitejs/plugin-react`, if they were not installed. +In Storybook 8 those plugins have to be added explicitly in the user's `vite.config.ts`: + +```ts +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); +``` + ### Implicit actions can not be used during rendering (for example in the play function) In Storybook 7, we inferred if the component accepts any action props, From e70b3d473873a359e8c1dfbe7597198f8424b9bd Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 3 Jan 2024 12:31:15 +0100 Subject: [PATCH 41/51] Add link to migration note --- MIGRATION.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MIGRATION.md b/MIGRATION.md index 1c1e1d92408c..26567a230b61 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,6 +1,7 @@

Migration

- [From version 7.x to 8.0.0](#from-version-7x-to-800) + - [Framework specific vite plugins have to be explicitly added](#framework-specific-vite-plugins-have-to-be-explicitly-added) - [Implicit actions can not be used during rendering (for example in the play function)](#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function) - [Core changes](#core-changes) - [Dropping support for Node.js 16](#dropping-support-for-nodejs-16) From 3251604e2d5a01737e135f0d4b1987cde05c9d70 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 3 Jan 2024 12:47:36 +0100 Subject: [PATCH 42/51] Update MIGRATION.md Co-authored-by: Valentin Palkovic --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index 26567a230b61..c983fde43908 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -337,7 +337,7 @@ ## From version 7.x to 8.0.0 -### Framework specific vite plugins have to be explicitly added +### Framework-specific Vite plugins have to be explicitly added In Storybook 7 we would automatically add frameworks specific vite plugins, e.g. `@vitejs/plugin-react`, if they were not installed. In Storybook 8 those plugins have to be added explicitly in the user's `vite.config.ts`: From 2fd026c05faa1db1fd8b3d64f382b961a9632284 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 3 Jan 2024 12:47:44 +0100 Subject: [PATCH 43/51] Update MIGRATION.md Co-authored-by: Valentin Palkovic --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index c983fde43908..9a5a8858585a 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -339,7 +339,7 @@ ### Framework-specific Vite plugins have to be explicitly added -In Storybook 7 we would automatically add frameworks specific vite plugins, e.g. `@vitejs/plugin-react`, if they were not installed. +In Storybook 7, we would automatically add frameworks-specific Vite plugins, e.g. `@vitejs/plugin-react` if not installed. In Storybook 8 those plugins have to be added explicitly in the user's `vite.config.ts`: ```ts From a88b242f0cbda0390de24491a0d5d5b59273515b Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 3 Jan 2024 12:56:20 +0100 Subject: [PATCH 44/51] Remove unneeded mergeConfig --- code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts index 58855bbd9dfb..32f6eb0c41b0 100644 --- a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts +++ b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts @@ -2,7 +2,6 @@ import { resolve } from 'node:path'; import type { Plugin } from 'vite'; export async function mockSveltekitStores() { - const { mergeConfig } = await import('vite'); return { name: 'storybook:sveltekit-mock-stores', config: () => ({ From d6d5c7af0e2ea41231d5c7ba6dc9d5c3b58707eb Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 2 Jan 2024 17:02:06 -0300 Subject: [PATCH 45/51] remove --use-npm flag from CLI --- MIGRATION.md | 8 ++++++++ code/lib/cli/src/add.ts | 15 ++++----------- code/lib/cli/src/automigrate/index.ts | 12 +----------- code/lib/cli/src/automigrate/types.ts | 1 - code/lib/cli/src/generate.ts | 4 ---- code/lib/cli/src/generators/types.ts | 1 - code/lib/cli/src/initiate.ts | 9 ++------- .../cli/src/js-package-manager/deprecations.ts | 8 -------- code/lib/cli/src/js-package-manager/index.ts | 2 -- code/lib/cli/src/upgrade.ts | 9 +-------- 10 files changed, 16 insertions(+), 53 deletions(-) delete mode 100644 code/lib/cli/src/js-package-manager/deprecations.ts diff --git a/MIGRATION.md b/MIGRATION.md index 467fc0e5969d..5ffcc0e6116c 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -21,6 +21,8 @@ - [Require Angular 15 and up](#require-angular-15-and-up) - [Svelte](#svelte) - [Require Svelte 4 and up](#require-svelte-4-and-up) + - [Deprecations which are now removed](#deprecations-which-are-now-removed) + - [--use-npm flag in storybook CLI](#--use-npm-flag-in-storybook-cli) - [From version 7.5.0 to 7.6.0](#from-version-750-to-760) - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) @@ -507,6 +509,12 @@ Starting in 8.0, Storybook requires Angular 15 and up. Starting in 8.0, Storybook requires Svelte 4 and up. +### Deprecations which are now removed + +#### --use-npm flag in storybook CLI + +The `--use-npm` is now removed. Use `--package-manager=npm` instead. [More info here](#cli-option---use-npm-deprecated). + ## From version 7.5.0 to 7.6.0 #### CommonJS with Vite is deprecated diff --git a/code/lib/cli/src/add.ts b/code/lib/cli/src/add.ts index 20e1c42bc811..3c730d68da5a 100644 --- a/code/lib/cli/src/add.ts +++ b/code/lib/cli/src/add.ts @@ -4,11 +4,7 @@ import { isAbsolute, join } from 'path'; import SemVer from 'semver'; import dedent from 'ts-dedent'; -import { - JsPackageManagerFactory, - useNpmWarning, - type PackageManagerName, -} from './js-package-manager'; +import { JsPackageManagerFactory, type PackageManagerName } from './js-package-manager'; import { getStorybookVersion, isCorePackage } from './utils'; const logger = console; @@ -71,13 +67,10 @@ const checkInstalled = (addonName: string, main: any) => { */ export async function add( addon: string, - options: { useNpm: boolean; packageManager: PackageManagerName; skipPostinstall: boolean } + options: { packageManager: PackageManagerName; skipPostinstall: boolean } ) { - let { packageManager: pkgMgr } = options; - if (options.useNpm) { - useNpmWarning(); - pkgMgr = 'npm'; - } + const { packageManager: pkgMgr } = options; + const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr }); const packageJson = await packageManager.retrievePackageJson(); const { mainConfig, configDir } = getStorybookInfo(packageJson); diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 1ef8ec9ce1a2..3fd322e724d0 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -9,7 +9,7 @@ import dedent from 'ts-dedent'; import { join } from 'path'; import { getStorybookInfo, loadMainConfig } from '@storybook/core-common'; import invariant from 'tiny-invariant'; -import { JsPackageManagerFactory, useNpmWarning } from '../js-package-manager'; +import { JsPackageManagerFactory } from '../js-package-manager'; import type { PackageManagerName } from '../js-package-manager'; import type { Fix, FixId, FixOptions, FixSummary } from './fixes'; @@ -55,7 +55,6 @@ export const automigrate = async ({ fixes: inputFixes, dryRun, yes, - useNpm, packageManager: pkgMgr, list, configDir: userSpecifiedConfigDir, @@ -86,7 +85,6 @@ export const automigrate = async ({ const { fixResults, fixSummary, preCheckFailure } = await runFixes({ fixes, - useNpm, pkgMgr, userSpecifiedConfigDir, rendererPackage, @@ -129,7 +127,6 @@ export async function runFixes({ fixes, dryRun, yes, - useNpm, pkgMgr, userSpecifiedConfigDir, rendererPackage, @@ -138,7 +135,6 @@ export async function runFixes({ fixes: Fix[]; yes?: boolean; dryRun?: boolean; - useNpm?: boolean; pkgMgr?: PackageManagerName; userSpecifiedConfigDir?: string; rendererPackage?: string; @@ -148,12 +144,6 @@ export async function runFixes({ fixResults: Record; fixSummary: FixSummary; }> { - if (useNpm) { - useNpmWarning(); - // eslint-disable-next-line no-param-reassign - pkgMgr = 'npm'; - } - const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr }); const fixResults = {} as Record; diff --git a/code/lib/cli/src/automigrate/types.ts b/code/lib/cli/src/automigrate/types.ts index 1befb24bf22c..5949d70db98e 100644 --- a/code/lib/cli/src/automigrate/types.ts +++ b/code/lib/cli/src/automigrate/types.ts @@ -41,7 +41,6 @@ export interface FixOptions { fixes?: Fix[]; yes?: boolean; dryRun?: boolean; - useNpm?: boolean; packageManager?: PackageManagerName; configDir?: string; renderer?: string; diff --git a/code/lib/cli/src/generate.ts b/code/lib/cli/src/generate.ts index c964767da543..5ee5c9d89abf 100644 --- a/code/lib/cli/src/generate.ts +++ b/code/lib/cli/src/generate.ts @@ -48,7 +48,6 @@ command('init') .option('-f --force', 'Force add Storybook') .option('-s --skip-install', 'Skip installing deps') .option('--package-manager ', 'Force package manager for installing deps') - .option('-N --use-npm', 'Use npm to install deps (deprecated)') .option('--use-pnp', 'Enable pnp mode for Yarn 2+') .option('-p --parser ', 'jscodeshift parser') .option('-t --type ', 'Add Storybook for a specific project type') @@ -65,7 +64,6 @@ command('add ') '--package-manager ', 'Force package manager for installing dependencies' ) - .option('-N --use-npm', 'Use NPM to install dependencies (deprecated)') .option('-s --skip-postinstall', 'Skip package specific postinstall config modifications') .action((addonName: string, options: any) => add(addonName, options)); @@ -79,7 +77,6 @@ command('upgrade') '--package-manager ', 'Force package manager for installing dependencies' ) - .option('-N --use-npm', 'Use NPM to install dependencies (deprecated)') .option('-y --yes', 'Skip prompting the user') .option('-n --dry-run', 'Only check for upgrades, do not install') .option('-t --tag ', 'Upgrade to a certain npm dist-tag (e.g. next, prerelease)') @@ -167,7 +164,6 @@ command('automigrate [fixId]') .option('-y --yes', 'Skip prompting the user') .option('-n --dry-run', 'Only check for fixes, do not actually run them') .option('--package-manager ', 'Force package manager') - .option('-N --use-npm', 'Use npm as package manager (deprecated)') .option('-l --list', 'List available migrations') .option('-c, --config-dir ', 'Directory of Storybook configurations to migrate') .option('-s --skip-install', 'Skip installing deps') diff --git a/code/lib/cli/src/generators/types.ts b/code/lib/cli/src/generators/types.ts index 2f97a34df126..85ed0dbc600c 100644 --- a/code/lib/cli/src/generators/types.ts +++ b/code/lib/cli/src/generators/types.ts @@ -41,7 +41,6 @@ export type Generator = ( export type CommandOptions = { packageManager: PackageManagerName; - useNpm?: boolean; usePnp?: boolean; type?: ProjectType; force?: any; diff --git a/code/lib/cli/src/initiate.ts b/code/lib/cli/src/initiate.ts index 5217bca197aa..c0dbf5a3c7b3 100644 --- a/code/lib/cli/src/initiate.ts +++ b/code/lib/cli/src/initiate.ts @@ -29,7 +29,7 @@ import svelteKitGenerator from './generators/SVELTEKIT'; import solidGenerator from './generators/SOLID'; import serverGenerator from './generators/SERVER'; import type { JsPackageManager } from './js-package-manager'; -import { JsPackageManagerFactory, useNpmWarning } from './js-package-manager'; +import { JsPackageManagerFactory } from './js-package-manager'; import type { NpmOptions } from './NpmOptions'; import type { CommandOptions, GeneratorOptions } from './generators/types'; import { HandledError } from './HandledError'; @@ -235,12 +235,7 @@ async function doInitiate( } | { shouldRunDev: false } > { - let { packageManager: pkgMgr } = options; - if (options.useNpm) { - useNpmWarning(); - - pkgMgr = 'npm'; - } + const { packageManager: pkgMgr } = options; const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr, diff --git a/code/lib/cli/src/js-package-manager/deprecations.ts b/code/lib/cli/src/js-package-manager/deprecations.ts deleted file mode 100644 index 5883fad3a294..000000000000 --- a/code/lib/cli/src/js-package-manager/deprecations.ts +++ /dev/null @@ -1,8 +0,0 @@ -import deprecate from 'util-deprecate'; - -export const useNpmWarning = deprecate( - () => {}, - `\`--use-npm\` is deprecated and will be removed in Storybook 8.0. -Please use the \`--package-manager=npm\` option instead. -Read more at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#cli-option---use-npm-deprecated` -); diff --git a/code/lib/cli/src/js-package-manager/index.ts b/code/lib/cli/src/js-package-manager/index.ts index d9849cbff268..f95d6f9659ba 100644 --- a/code/lib/cli/src/js-package-manager/index.ts +++ b/code/lib/cli/src/js-package-manager/index.ts @@ -1,5 +1,3 @@ -export * from './deprecations'; - export * from './JsPackageManagerFactory'; export * from './JsPackageManager'; diff --git a/code/lib/cli/src/upgrade.ts b/code/lib/cli/src/upgrade.ts index aefd6bc8bc07..1938e18ba335 100644 --- a/code/lib/cli/src/upgrade.ts +++ b/code/lib/cli/src/upgrade.ts @@ -5,7 +5,7 @@ import { logger } from '@storybook/node-logger'; import { withTelemetry } from '@storybook/core-server'; import type { PackageJsonWithMaybeDeps, PackageManagerName } from './js-package-manager'; -import { getPackageDetails, JsPackageManagerFactory, useNpmWarning } from './js-package-manager'; +import { getPackageDetails, JsPackageManagerFactory } from './js-package-manager'; import { coerceSemver, commandLog } from './helpers'; import { automigrate } from './automigrate'; import { isCorePackage } from './utils'; @@ -135,7 +135,6 @@ export interface UpgradeOptions { tag: string; prerelease: boolean; skipCheck: boolean; - useNpm: boolean; packageManager: PackageManagerName; dryRun: boolean; yes: boolean; @@ -147,18 +146,12 @@ export const doUpgrade = async ({ tag, prerelease, skipCheck, - useNpm, packageManager: pkgMgr, dryRun, configDir, yes, ...options }: UpgradeOptions) => { - if (useNpm) { - useNpmWarning(); - // eslint-disable-next-line no-param-reassign - pkgMgr = 'npm'; - } const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr }); const beforeVersion = await getStorybookCoreVersion(); From 85af265d3a761b762281a4fec32ae1ef4e9c1a28 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 3 Jan 2024 10:08:09 -0300 Subject: [PATCH 46/51] Update MIGRATION.md --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index c78ed3febee7..76f884a0fb29 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -396,7 +396,7 @@ In Storybook 7, we deprecated the ability of using MDX both for documentation an Alongside with this change, the `jsxOptions` configuration was removed as it is not used anymore. -[More info here](https://storybook.js.org/docs/writing-docs/mdx#automigration). +[More info here](https://storybook.js.org/docs/migration-guide#storiesmdx-to-mdxcsf). #### Dropping support for id, name and story in Story block From 2c6afe2fff16f4dae18ffc70ffd46eca11051556 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 3 Jan 2024 10:08:45 -0300 Subject: [PATCH 47/51] Update MIGRATION.md --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index 76f884a0fb29..74c009340d0b 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -388,7 +388,7 @@ To summarize: #### MDX is upgraded to v3 -Storybook now uses MDX3 under the hood. This change contains many improvements and a few small breaking changes that possibly won't affect you. However we recommend checking the [migration notes from MDX here](https://mdxjs.com/blog/v3/). +Storybook now uses MDX3 under the hood. This change contains many improvements and a few small breaking changes that probably won't affect you. However we recommend checking the [migration notes from MDX here](https://mdxjs.com/blog/v3/). #### Dropping support for *.stories.mdx (CSF in MDX) format From d43f6c5b5ae7905b16b4cbdbedf2e2b2a5a0039d Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Wed, 3 Jan 2024 22:41:09 +0800 Subject: [PATCH 48/51] Viewport: Fix keyboard shortcut --- code/addons/viewport/src/Tool.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/addons/viewport/src/Tool.tsx b/code/addons/viewport/src/Tool.tsx index 8a2f97c6b1a3..f365fb65d040 100644 --- a/code/addons/viewport/src/Tool.tsx +++ b/code/addons/viewport/src/Tool.tsx @@ -134,7 +134,7 @@ export const ViewportTool: FC = memo( useEffect(() => { registerShortcuts(api, globals, updateGlobals, Object.keys(viewports)); - }, [viewports]); + }, [viewports, globals.viewport]); useEffect(() => { const defaultRotated = defaultOrientation === 'landscape'; From 70f85f67f35e48d235a54e6595f21f20d7fe12fc Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Wed, 3 Jan 2024 15:49:36 +0100 Subject: [PATCH 49/51] add migration notes about the removal of the shim packages --- MIGRATION.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index 8d6310ddce12..6b7050f4f5fb 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,7 +1,8 @@

Migration

- [From version 7.x to 8.0.0](#from-version-7x-to-800) - - [Framework specific vite plugins have to be explicitly added](#framework-specific-vite-plugins-have-to-be-explicitly-added) + - [Removed deprecated shim packages](#removed-deprecated-shim-packages) + - [Framework-specific Vite plugins have to be explicitly added](#framework-specific-vite-plugins-have-to-be-explicitly-added) - [Implicit actions can not be used during rendering (for example in the play function)](#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function) - [Core changes](#core-changes) - [Dropping support for Node.js 16](#dropping-support-for-nodejs-16) @@ -339,6 +340,21 @@ ## From version 7.x to 8.0.0 +### Removed deprecated shim packages + +In Storybook 7, these packages existed for backwards compatibility, but were marked as deprecated: + +- `@storybook/addons` - this package has been split into 2 packages: `@storybook/preview-api` and `@storybook/manager-api`, see more here: [New Addons API](#new-addons-api). +- `@storybook/channel-postmessage` - this package has been merged into `@storybook/channel`. +- `@storybook/channel-websocket` - this package has been merged into `@storybook/channel`. +- `@storybook/client-api` - this package has been merged into `@storybook/preview-api`. +- `@storybook/core-client` - this package has been merged into `@storybook/preview-api`. +- `@storybook/preview-web` - this package has been merged into `@storybook/preview-api`. +- `@storybook/store` - this package has been merged into `@storybook/preview-api`. +- `@storybook/api` - this package has been replaced with `@storybook/manager-api`. + +This section explains the rationale, and the required changed you might have to make: [New Addons API](#new-addons-api) + ### Framework-specific Vite plugins have to be explicitly added In Storybook 7, we would automatically add frameworks-specific Vite plugins, e.g. `@vitejs/plugin-react` if not installed. From 97ae40467cecacccf9face24edc8b93785d6845d Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 3 Jan 2024 11:56:44 -0300 Subject: [PATCH 50/51] remove legacy mdx 1 feature documentation --- MIGRATION.md | 6 ++++-- .../docs/src/plugins/mdx-plugin.types.d.ts | 1 - docs/api/main-config-features.md | 17 ---------------- docs/configure/index.md | 1 - docs/migration-guide.md | 20 ------------------- .../storybook-fallback-mdx-install.npm.js.mdx | 3 --- ...storybook-fallback-mdx-install.pnpm.js.mdx | 3 --- ...storybook-fallback-mdx-install.yarn.js.mdx | 3 --- scripts/verdaccio.yaml | 8 -------- 9 files changed, 4 insertions(+), 58 deletions(-) delete mode 100644 code/addons/docs/src/plugins/mdx-plugin.types.d.ts delete mode 100644 docs/snippets/common/storybook-fallback-mdx-install.npm.js.mdx delete mode 100644 docs/snippets/common/storybook-fallback-mdx-install.pnpm.js.mdx delete mode 100644 docs/snippets/common/storybook-fallback-mdx-install.yarn.js.mdx diff --git a/MIGRATION.md b/MIGRATION.md index 74c009340d0b..2708d5e0e19c 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -4,7 +4,7 @@ - [Implicit actions can not be used during rendering (for example in the play function)](#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function) - [MDX related changes](#mdx-related-changes) - [MDX is upgraded to v3](#mdx-is-upgraded-to-v3) - - [Dropping support for \*.stories.mdx (CSF in MDX) format](#dropping-support-for-storiesmdx-csf-in-mdx-format) + - [Dropping support for \*.stories.mdx (CSF in MDX) format and MDX1 support](#dropping-support-for-storiesmdx-csf-in-mdx-format-and-mdx1-support) - [Dropping support for id, name and story in Story block](#dropping-support-for-id-name-and-story-in-story-block) - [Core changes](#core-changes) - [Dropping support for Node.js 16](#dropping-support-for-nodejs-16) @@ -390,10 +390,12 @@ To summarize: Storybook now uses MDX3 under the hood. This change contains many improvements and a few small breaking changes that probably won't affect you. However we recommend checking the [migration notes from MDX here](https://mdxjs.com/blog/v3/). -#### Dropping support for *.stories.mdx (CSF in MDX) format +#### Dropping support for *.stories.mdx (CSF in MDX) format and MDX1 support In Storybook 7, we deprecated the ability of using MDX both for documentation and for defining stories in the same .stories.mdx file. It is now removed, and Storybook won't support .stories.mdx files anymore. We provide migration scripts to help you onto the new format. +If you were using the [legacy MDX1 format](#legacy-mdx1-support), you will have to remove the `legacyMdx1` main.js feature flag and the `@storybook/mdx1-csf` package. + Alongside with this change, the `jsxOptions` configuration was removed as it is not used anymore. [More info here](https://storybook.js.org/docs/migration-guide#storiesmdx-to-mdxcsf). diff --git a/code/addons/docs/src/plugins/mdx-plugin.types.d.ts b/code/addons/docs/src/plugins/mdx-plugin.types.d.ts deleted file mode 100644 index fea94f85dc25..000000000000 --- a/code/addons/docs/src/plugins/mdx-plugin.types.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module '@storybook/mdx1-csf'; diff --git a/docs/api/main-config-features.md b/docs/api/main-config-features.md index 81a80502a7bc..f92ae24139a1 100644 --- a/docs/api/main-config-features.md +++ b/docs/api/main-config-features.md @@ -54,23 +54,6 @@ Apply decorators from preview.js before decorators from addons or frameworks. [M -## `legacyMdx1` - -Type: `boolean` - -Enables support for MDX version 1 as a fallback. Requires [@storybook/mdx1-csf](https://github.com/storybookjs/mdx1-csf) to be installed. - - - - - - - ## `storyStoreV7` Type: `boolean` diff --git a/docs/configure/index.md b/docs/configure/index.md index ee38fd9a4569..f8c904c925d3 100644 --- a/docs/configure/index.md +++ b/docs/configure/index.md @@ -56,7 +56,6 @@ Additionally, you can also provide additional feature flags to your Storybook co | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `storyStoreV7` | Configures Storybook to load stories [on demand](#on-demand-story-loading), rather than during boot up (defaults to `true` as of `v7.0`)
`features: { storyStoreV7: true }` | | `buildStoriesJson` | Generates `index.json` and `stories.json` files to help story loading with the on-demand mode (defaults to `true` when `storyStoreV7` is `true`)
`features: { buildStoriesJson: true }` | -| `legacyMdx1` | Enables support for MDX version 1 as a fallback. Requires [`@storybook/mdx1-csf`](https://github.com/storybookjs/mdx1-csf)
`features: { legacyMdx1: true }` | ## Configure story loading diff --git a/docs/migration-guide.md b/docs/migration-guide.md index e0cf30691b06..c2a40c5968fe 100644 --- a/docs/migration-guide.md +++ b/docs/migration-guide.md @@ -94,26 +94,6 @@ This shows the errors visually in your editor, which speeds things up a lot. Her ![MDX errors showing in VS Code](./assets/mdx-vs-code-extension-errors.gif) -#### MDX1 as fallback - -If, for some reason, you are unable to get MDX2 working, we’ve implemented legacy MDX1 support as a last resort. MDX1 is deprecated and opt-in, and we recommend against it unless you really need it. - -To use MDX1: - -1. Install `@storybook/mdx1-csf` as a dev dependency -2. Add the `legacyMdx1` feature flag to your `.storybook/main.js`: - - - - - - - ### storiesOf support discontinued by default If you use Storybook’s legacy `storiesOf` API, it is no longer supported by default in Storybook 7. diff --git a/docs/snippets/common/storybook-fallback-mdx-install.npm.js.mdx b/docs/snippets/common/storybook-fallback-mdx-install.npm.js.mdx deleted file mode 100644 index bb7ce17277ed..000000000000 --- a/docs/snippets/common/storybook-fallback-mdx-install.npm.js.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```shell -npm install @storybook/mdx1-csf --save-dev -``` diff --git a/docs/snippets/common/storybook-fallback-mdx-install.pnpm.js.mdx b/docs/snippets/common/storybook-fallback-mdx-install.pnpm.js.mdx deleted file mode 100644 index 624f84077d48..000000000000 --- a/docs/snippets/common/storybook-fallback-mdx-install.pnpm.js.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```shell -pnpm add --save-dev @storybook/mdx1-csf -``` diff --git a/docs/snippets/common/storybook-fallback-mdx-install.yarn.js.mdx b/docs/snippets/common/storybook-fallback-mdx-install.yarn.js.mdx deleted file mode 100644 index 02fadab47356..000000000000 --- a/docs/snippets/common/storybook-fallback-mdx-install.yarn.js.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```shell -yarn add --dev @storybook/mdx1-csf -``` diff --git a/scripts/verdaccio.yaml b/scripts/verdaccio.yaml index e0139f305f0b..6ab5ce649186 100644 --- a/scripts/verdaccio.yaml +++ b/scripts/verdaccio.yaml @@ -87,14 +87,6 @@ packages: access: $all publish: $all proxy: npmjs - '@storybook/mdx1-csf': - access: $all - publish: $all - proxy: npmjs - '@storybook/mdx2-csf': - access: $all - publish: $all - proxy: npmjs '@storybook/expect': access: $all publish: $all From 303eb6377775f92cca66992b0c47dc9a6590e352 Mon Sep 17 00:00:00 2001 From: storybook-bot <32066757+storybook-bot@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:44:17 +0000 Subject: [PATCH 51/51] Write changelog for 8.0.0-alpha.7 [skip ci] --- CHANGELOG.prerelease.md | 13 +++++++++++++ code/package.json | 3 ++- docs/versions/next.json | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 0930b04e6a74..077e70147763 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,16 @@ +## 8.0.0-alpha.7 + +- Addon-Docs: Upgrade to MDX3 - [#25303](https://github.com/storybookjs/storybook/pull/25303), thanks [@yannbf](https://github.com/yannbf)! +- CLI: Add Storyshots migration notice - [#25327](https://github.com/storybookjs/storybook/pull/25327), thanks [@yannbf](https://github.com/yannbf)! +- CLI: Fix regex used in upgrade command - [#25284](https://github.com/storybookjs/storybook/pull/25284), thanks [@yannbf](https://github.com/yannbf)! +- CLI: Remove --use-npm flag - [#25414](https://github.com/storybookjs/storybook/pull/25414), thanks [@yannbf](https://github.com/yannbf)! +- Core: Remove unused warnOnLegacyHierarchySeparator type - [#25416](https://github.com/storybookjs/storybook/pull/25416), thanks [@yannbf](https://github.com/yannbf)! +- Core: Remove vite plugins and drop Vite 3 support - [#25427](https://github.com/storybookjs/storybook/pull/25427), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Maintenance: Add comment to deprecation notice in Button component - [#25411](https://github.com/storybookjs/storybook/pull/25411), thanks [@yannbf](https://github.com/yannbf)! +- UI: Fix about page layout - [#25396](https://github.com/storybookjs/storybook/pull/25396), thanks [@cdedreuille](https://github.com/cdedreuille)! +- Viewport: Store viewport, rotation in globals - [#25423](https://github.com/storybookjs/storybook/pull/25423), thanks [@shilman](https://github.com/shilman)! +- Vite: Fix Vite 5 CJS warnings - [#25005](https://github.com/storybookjs/storybook/pull/25005), thanks [@JReinhold](https://github.com/JReinhold)! + ## 8.0.0-alpha.6 - NextJS: Autoconfigure public directory for new projects - [#25279](https://github.com/storybookjs/storybook/pull/25279), thanks [@shilman](https://github.com/shilman)! diff --git a/code/package.json b/code/package.json index dfb9615ac3fe..6d32eef356b0 100644 --- a/code/package.json +++ b/code/package.json @@ -308,5 +308,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "8.0.0-alpha.7" } diff --git a/docs/versions/next.json b/docs/versions/next.json index 9731c646282b..fcd9f1cce99a 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.0.0-alpha.6","info":{"plain":"- NextJS: Autoconfigure public directory for new projects - [#25279](https://github.com/storybookjs/storybook/pull/25279), thanks [@shilman](https://github.com/shilman)!\n- Vite: Fix pre-transform error in Vite 5 - [#25329](https://github.com/storybookjs/storybook/pull/25329), thanks [@yannbf](https://github.com/yannbf)!\n- Vue3: Fix pnp by making compiler-core a dependency - [#25311](https://github.com/storybookjs/storybook/pull/25311), thanks [@shilman](https://github.com/shilman)!"}} +{"version":"8.0.0-alpha.7","info":{"plain":"- Addon-Docs: Upgrade to MDX3 - [#25303](https://github.com/storybookjs/storybook/pull/25303), thanks [@yannbf](https://github.com/yannbf)!\n- CLI: Add Storyshots migration notice - [#25327](https://github.com/storybookjs/storybook/pull/25327), thanks [@yannbf](https://github.com/yannbf)!\n- CLI: Fix regex used in upgrade command - [#25284](https://github.com/storybookjs/storybook/pull/25284), thanks [@yannbf](https://github.com/yannbf)!\n- CLI: Remove --use-npm flag - [#25414](https://github.com/storybookjs/storybook/pull/25414), thanks [@yannbf](https://github.com/yannbf)!\n- Core: Remove unused warnOnLegacyHierarchySeparator type - [#25416](https://github.com/storybookjs/storybook/pull/25416), thanks [@yannbf](https://github.com/yannbf)!\n- Core: Remove vite plugins and drop Vite 3 support - [#25427](https://github.com/storybookjs/storybook/pull/25427), thanks [@kasperpeulen](https://github.com/kasperpeulen)!\n- Maintenance: Add comment to deprecation notice in Button component - [#25411](https://github.com/storybookjs/storybook/pull/25411), thanks [@yannbf](https://github.com/yannbf)!\n- UI: Fix about page layout - [#25396](https://github.com/storybookjs/storybook/pull/25396), thanks [@cdedreuille](https://github.com/cdedreuille)!\n- Viewport: Store viewport, rotation in globals - [#25423](https://github.com/storybookjs/storybook/pull/25423), thanks [@shilman](https://github.com/shilman)!\n- Vite: Fix Vite 5 CJS warnings - [#25005](https://github.com/storybookjs/storybook/pull/25005), thanks [@JReinhold](https://github.com/JReinhold)!"}}