From f826fb33c42cb860e7226244b74f766aa5850dee Mon Sep 17 00:00:00 2001 From: Maksim Kachurin Date: Tue, 9 Sep 2025 17:03:50 -0700 Subject: [PATCH 1/5] Storybook 10 beta support. Release 10.0.0-beta.0 with ESM, node entry, and docgen opts refactoring Major update to 10.0.0-beta.0. Switches to ESM-only output, adds a new node entry point, updates exports and type definitions, and improves docgen support with configurable options. Refactors preset and renderer logic for better compatibility and maintainability. --- package.json | 34 +++++++++++++--------------- preset.js | 2 +- src/node/index.ts | 5 +++++ src/preset.ts | 42 +++++++++++++---------------------- src/renderer/entry-preview.ts | 4 ++-- src/renderer/preset.ts | 17 +++++++++----- src/types.ts | 5 ++++- tsup.config.ts | 7 ++++-- 8 files changed, 60 insertions(+), 56 deletions(-) create mode 100644 src/node/index.ts diff --git a/package.json b/package.json index 213c9e1..c3e976c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "storybook-solidjs-vite", - "version": "9.0.2", + "version": "10.0.0-beta.0", "description": "SolidJS integration with Storybook", "private": false, "keywords": [ @@ -27,41 +27,39 @@ "url": "https://github.com/solidjs-community/storybook.git", "directory": "packages/storybook-solid-vite" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, "license": "MIT", + "type": "module", "exports": { - "./package.json": "./package.json", - "./renderer/package.json": "./renderer/package.json", ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" + "default": "./dist/index.js" }, + "./package.json": "./package.json", "./preset": { "types": "./dist/preset.d.ts", - "require": "./dist/preset.js", - "import": "./dist/preset.mjs" + "default": "./dist/preset.js" + }, + "./node": { + "types": "./dist/node/index.d.ts", + "default": "./dist/node/index.js" }, + "./renderer": { "types": "./dist/renderer/index.d.ts", - "import": "./dist/renderer/index.mjs", - "require": "./dist/renderer/index.js" + "default": "./dist/renderer/index.js" }, + "./renderer/package.json": "./renderer/package.json", "./renderer/preset": "./dist/renderer/preset.js", - "./renderer/entry-preview.mjs": "./dist/renderer/entry-preview.mjs", - "./renderer/entry-preview-docs.mjs": "./dist/renderer/entry-preview-docs.mjs" + "./renderer/entry-preview": "./dist/renderer/entry-preview.js", + "./renderer/entry-preview-argtypes": "./dist/renderer/entry-preview-argtypes.js", + "./renderer/entry-preview-docs": "./dist/renderer/entry-preview-docs.js" }, "main": "dist/index.js", - "module": "dist/index.mjs", "types": "dist/index.d.ts", "files": [ "dist/**/*", "bin/**/*", "README.md", - "preset.js", "**/*.d.ts" ], "scripts": { @@ -71,7 +69,7 @@ "postbuild": "bun run types", "types": "tsc -b tsconfig.build.json", "clean": "rm -rf dist && rm -rf .turbo && rm -rf node_modules", - "version-packages": "changeset version", + "version": "changeset version", "release": "changeset publish" }, "dependencies": { diff --git a/preset.js b/preset.js index a83f952..4bd63d3 100644 --- a/preset.js +++ b/preset.js @@ -1 +1 @@ -module.exports = require('./dist/preset'); +export * from './dist/preset.js'; diff --git a/src/node/index.ts b/src/node/index.ts new file mode 100644 index 0000000..93ec16c --- /dev/null +++ b/src/node/index.ts @@ -0,0 +1,5 @@ +import type { StorybookConfig } from '../types'; + +export function defineMain(config: StorybookConfig) { + return config; +} diff --git a/src/preset.ts b/src/preset.ts index 1560aaa..934f646 100644 --- a/src/preset.ts +++ b/src/preset.ts @@ -1,6 +1,3 @@ -import { hasVitePlugins } from '@storybook/builder-vite'; -import { dirname } from 'path'; - /** * A preset is a configuration that enables developers to quickly set up and * customize their environment with a specific set of features, functionalities, or integrations. @@ -8,21 +5,19 @@ import { dirname } from 'path'; * @see https://storybook.js.org/docs/addons/writing-presets * @see https://storybook.js.org/docs/api/main-config/main-config */ +import { hasVitePlugins } from '@storybook/builder-vite'; -import type { StorybookConfig } from './types'; +import type { FrameworkOptions, StorybookConfig } from './types'; import type { PresetProperty } from 'storybook/internal/types'; -// Helper for getting the location of dependencies. -const getAbsolutePath = (input: string): string => dirname(require.resolve(input)); - /** * Configures Storybook's internal features. * * @see https://storybook.js.org/docs/api/main-config/main-config-core */ export const core: PresetProperty<'core', StorybookConfig> = { - builder: getAbsolutePath('@storybook/builder-vite'), - renderer: getAbsolutePath('storybook-solidjs-vite/renderer'), + builder: import.meta.resolve('@storybook/builder-vite'), + renderer: import.meta.resolve('./renderer'), }; /** @@ -31,38 +26,31 @@ export const core: PresetProperty<'core', StorybookConfig> = { * @see https://storybook.js.org/docs/api/main-config/main-config-vite-final */ export const viteFinal: StorybookConfig['viteFinal'] = async(config, { presets }) => { - const { plugins = [] } = config; + const plugins = [...(config?.plugins ?? [])]; // Add docgen plugin - const { reactDocgen: reactDocgenOption, reactDocgenTypescriptOptions } = await presets.apply('typescript', {}); + const framework = await presets.apply('framework'); + const frameworkOptions: FrameworkOptions = (typeof framework === 'string') ? {} : (framework.options ?? {}); - let typescriptPresent = false; - - try { - require.resolve('typescript'); - typescriptPresent = true; - } - catch (e) {} - // Use vite-plugin-react-docgen-typescript for docgen - if (reactDocgenOption === 'react-docgen-typescript' && typescriptPresent) { - const { default: reactDocgenTypescriptPlugin } = await import('@joshwooding/vite-plugin-react-docgen-typescript'); + if (frameworkOptions.docgen !== false) { + const reactDocgenTypescriptPlugin = await import('@joshwooding/vite-plugin-react-docgen-typescript').then(module => module.default); plugins.push( reactDocgenTypescriptPlugin({ - ...reactDocgenTypescriptOptions, // We *need* this set so that RDT returns default values in the same format as react-docgen savePropValueAsString: true, + shouldExtractLiteralValuesFromEnum: true, + propFilter: (prop: any) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true), + ...frameworkOptions.docgenOptions, }) ); } // Add solid plugin if not present - if (!(await hasVitePlugins(plugins, ['vite-plugin-solid']))) { - const { default: solidPlugin } = await import('vite-plugin-solid'); - - plugins.push( - solidPlugin() + if (!(await hasVitePlugins(plugins, ['solid']))) { + plugins.unshift( + await import('vite-plugin-solid').then(module => module.default()) ); } diff --git a/src/renderer/entry-preview.ts b/src/renderer/entry-preview.ts index 36b887e..ce260c1 100644 --- a/src/renderer/entry-preview.ts +++ b/src/renderer/entry-preview.ts @@ -1,6 +1,8 @@ /* Configuration for default renderer. */ import { enhanceArgTypes } from 'storybook/internal/docs-tools'; +import { configure } from 'storybook/test'; + import { solidReactivityDecorator } from './renderToCanvas'; import type { Decorator } from './public-types'; @@ -17,8 +19,6 @@ export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes]; export const beforeAll = async() => { try { - const { configure } = await import('storybook/test'); - configure({ unstable_advanceTimersWrapper: (cb: () => any) => cb(), asyncWrapper: async(cb: () => any) => { diff --git a/src/renderer/preset.ts b/src/renderer/preset.ts index e2d14c9..9a33538 100644 --- a/src/renderer/preset.ts +++ b/src/renderer/preset.ts @@ -5,8 +5,7 @@ * @see https://storybook.js.org/docs/addons/writing-presets * @see https://storybook.js.org/docs/api/main-config/main-config */ - -import { join } from 'path'; +import { fileURLToPath } from 'node:url'; import type { PresetProperty } from 'storybook/internal/types'; @@ -25,7 +24,15 @@ export const previewAnnotations: PresetProperty<'previewAnnotations'> = async( return result .concat(input) - .concat([join(__dirname, 'entry-preview.mjs')]) - .concat([join(__dirname, 'entry-preview-argtypes.mjs')]) - .concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []); + .concat([ + fileURLToPath(import.meta.resolve('storybook-solidjs-vite/renderer/entry-preview')), + fileURLToPath(import.meta.resolve('storybook-solidjs-vite/renderer/entry-preview-argtypes')), + ]) + .concat( + docsEnabled + ? [ + fileURLToPath(import.meta.resolve('storybook-solidjs-vite/renderer/entry-preview-docs')), + ] + : [] + ); }; diff --git a/src/types.ts b/src/types.ts index 46ca9a3..456a13b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,15 +1,18 @@ import type { BuilderOptions, StorybookConfigVite } from '@storybook/builder-vite'; +import type { ParserOptions } from 'react-docgen-typescript'; import type { CompatibleString, StorybookConfig as StorybookConfigBase, } from 'storybook/internal/types'; -type FrameworkName = CompatibleString<'@storybook/html-vite'>; +type FrameworkName = CompatibleString<'storybook-solidjs-vite'>; type BuilderName = CompatibleString<'@storybook/builder-vite'>; export type FrameworkOptions = { builder?: BuilderOptions; + docgen?: boolean; + docgenOptions?: ParserOptions; }; type StorybookConfigFramework = { diff --git a/tsup.config.ts b/tsup.config.ts index cdeedfd..a906e72 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -4,15 +4,18 @@ import { defineConfig } from 'tsup'; export default defineConfig((options) => { return { entry: [ + // framework 'src/index.ts', 'src/preset.ts', + 'src/node/index.ts', + // renderer 'src/renderer/index.ts', 'src/renderer/preset.ts', 'src/renderer/entry-preview.ts', - 'src/renderer/entry-preview-docs.ts', 'src/renderer/entry-preview-argtypes.ts', + 'src/renderer/entry-preview-docs.ts', ], - format: ['esm', 'cjs'], + format: ['esm'], outDir: 'dist', dts: false, external: [ From 269bdcc4db424ee6b185f9d1dd7cbfdb42d3abe9 Mon Sep 17 00:00:00 2001 From: Maksim Kachurin Date: Tue, 9 Sep 2025 17:30:01 -0700 Subject: [PATCH 2/5] Next tag --- CHANGELOG.md | 8 ++++++++ MIGRATION.md | 1 + README.md | 27 ++++++++++++++++++--------- package.json | 3 ++- src/preset.ts | 13 +++++++++---- src/types.ts | 7 +------ 6 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 MIGRATION.md diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c698f..c41084f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # storybook-solidjs-vite +## 10.0.0-beta.0 + +### Minor Changes + +- Support for Storybook 10 beta.2 +- Package now builds only in ESM format +- Simplified configuration for docgen + ## 9.0.2 ### Patch Changes diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..d6c1896 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1 @@ +# Migration Guide: Version 9 to 10 diff --git a/README.md b/README.md index 7752bf9..bd89233 100644 --- a/README.md +++ b/README.md @@ -9,20 +9,22 @@ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](./LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/solidjs-community/storybook/pulls) - Community supported [Storybook](https://storybook.js.org/) **framework adapter** for [SolidJS](https://solidjs.com/), using Vite as the bundler. --- ## 📋 Table of Contents -- [Features](#features) -- [Installation](#installation) -- [Quick Start](#quick-start) -- [Configuration](#configuration) -- [Contributing](#contributing) -- [License](#license) -- [Maintainer](#maintainer) +- [Storybook for SolidJS](#storybook-for-solidjs) + - [📋 Table of Contents](#-table-of-contents) + - [✨ Features](#-features) + - [🚀 Getting Started](#-getting-started) + - [📦 Manual Installation](#-manual-installation) + - [⚙️ Configuration](#️-configuration) + - [🔄 Migration Guide](#-migration-guide) + - [🤝 Contributing](#-contributing) + - [👤 Maintainer](#-maintainer) + - [📖 License](#-license) --- @@ -41,7 +43,6 @@ Community supported [Storybook](https://storybook.js.org/) **framework adapter** --- - ## 🚀 Getting Started The fastest way to start using Storybook with SolidJS: @@ -64,8 +65,10 @@ Open the provided URL in your browser to view your Storybook instance. --- ## 📦 Manual Installation + You can set everything up manually. To do this: + 1. Copy the following files from [storybook-solid-template](https://github.com/kachurun/create-solid-storybook/tree/main/packages/storybook-solid-template) to your project: - `.storybook/**` @@ -104,6 +107,12 @@ npm run storybook --- +## 🔄 Migration Guide + +Migrating from version 9 to 10? Check out our [Migration Guide](./MIGRATION.md) for step-by-step instructions and breaking changes. + +--- + ## 🤝 Contributing Contributions, issues and feature requests are welcome! Feel free to [open an issue](https://github.com/solidjs-community/storybook/issues) or submit a PR. diff --git a/package.json b/package.json index c3e976c..8db9d79 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ } }, "publishConfig": { - "access": "public" + "access": "public", + "tag": "next" } } diff --git a/src/preset.ts b/src/preset.ts index 934f646..5dd8bef 100644 --- a/src/preset.ts +++ b/src/preset.ts @@ -7,6 +7,8 @@ */ import { hasVitePlugins } from '@storybook/builder-vite'; +import { mergeConfig } from 'vite'; + import type { FrameworkOptions, StorybookConfig } from './types'; import type { PresetProperty } from 'storybook/internal/types'; @@ -26,7 +28,8 @@ export const core: PresetProperty<'core', StorybookConfig> = { * @see https://storybook.js.org/docs/api/main-config/main-config-vite-final */ export const viteFinal: StorybookConfig['viteFinal'] = async(config, { presets }) => { - const plugins = [...(config?.plugins ?? [])]; + const existPlugins = [...(config?.plugins ?? [])]; + const plugins = []; // Add docgen plugin const framework = await presets.apply('framework'); @@ -48,11 +51,13 @@ export const viteFinal: StorybookConfig['viteFinal'] = async(config, { presets } } // Add solid plugin if not present - if (!(await hasVitePlugins(plugins, ['solid']))) { - plugins.unshift( + if (!(await hasVitePlugins(existPlugins, ['solid']))) { + plugins.push( await import('vite-plugin-solid').then(module => module.default()) ); } - return config; + return mergeConfig(config, { + plugins, + }); }; diff --git a/src/types.ts b/src/types.ts index 456a13b..26f03f7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -33,9 +33,4 @@ type StorybookConfigFramework = { }; /** The interface for Storybook configuration in `main.ts` files. */ -export type StorybookConfig = Omit< - StorybookConfigBase, - keyof StorybookConfigVite | keyof StorybookConfigFramework -> & -StorybookConfigVite & -StorybookConfigFramework; +export type StorybookConfig = Omit & StorybookConfigVite & StorybookConfigFramework; From a2ab26f5d9776a7309b88e29ad081228af872909 Mon Sep 17 00:00:00 2001 From: Maksim Kachurin Date: Tue, 9 Sep 2025 17:46:17 -0700 Subject: [PATCH 3/5] Migration guide --- MIGRATION.md | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index d6c1896..b260063 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1 +1,152 @@ # Migration Guide: Version 9 to 10 + +## Important Core Changes + +Before migrating your `storybook-solidjs-vite` configuration, be aware of these critical Storybook 10 core changes: + +### Node.js Requirements + +- **Node.js 20.19+ or 22.12+** is now required +- Storybook 10 requires these versions for ESM support without flags + +### ESM Requirements + +- **`.storybook/main.*` and `vite.config.ts` files must be valid ESM** - CJS constants (`require`, `__dirname`, `__filename`) are no longer defined +- If you need CJS constants, define them manually: + + ```typescript + import { createRequire } from "node:module"; + import { dirname } from "node:path"; + import { fileURLToPath } from "node:url"; + + const __filename = fileURLToPath(import.meta.url); + const __dirname = dirname(__filename); + const require = createRequire(import.meta.url); + ``` + +### TypeScript Configuration + +- **Update `tsconfig.json`** to use a `moduleResolution` that supports the `types` condition: + ```json + { + "compilerOptions": { + "moduleResolution": "bundler" // or "node16"/"nodenext" + } + } + ``` + +### Addon Path Resolution + +- **Local addons must be fully resolved** - relative paths like `"./my-addon.ts"` must become `import.meta.resolve("./my-addon.ts")` + +For complete details on all Storybook 10 changes, see the [official Storybook migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-9x-to-1000). + +--- + +## Configuration Changes + +### .storybook/main.ts Configuration + +The main configuration file has several important changes: + +#### 1. Docgen configuration + +**Before (v9):** + +```typescript +framework: 'storybook-solidjs-vite', +typescript: { + reactDocgen: 'react-docgen-typescript', + reactDocgenTypescriptOptions: { + shouldExtractLiteralValuesFromEnum: true, + propFilter: (prop: any) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true), + }, +}, +``` + +**After (v10):** + +```typescript +framework: { + name: 'storybook-solidjs-vite', + options: { + docgen: true, // Enable docgen (optional, defaults to true) + // docgenOptions: {}, // Optional react-docgen-typescript options + }, +}, +``` + +#### 2. Addon Path Resolution + +To ensure that addons are correctly resolved, you need to use the `getAbsolutePath` helper function. + +**Before (v9):** + +```typescript +addons: [ + '@storybook/addon-onboarding', + '@storybook/addon-docs', + '@storybook/addon-a11y', + '@storybook/addon-links', + { + name: '@storybook/addon-vitest', + options: { + cli: false, + }, + }, +], +``` + +**After (v10):** + +```typescript +// Add this helper function at the top +const getAbsolutePath = (packageName: string): string => + path.dirname(import.meta.resolve(path.join(packageName, 'package.json'))).replace(/^file:\/\//, ''); + +addons: [ + getAbsolutePath('@storybook/addon-onboarding'), + getAbsolutePath('@storybook/addon-docs'), + getAbsolutePath('@storybook/addon-a11y'), + getAbsolutePath('@storybook/addon-links'), + { + name: getAbsolutePath('@storybook/addon-vitest'), + options: { + cli: false, + }, + }, +], +``` + +#### 3. Removed Configuration Sections + +**Removed from v10:** + +- `typescript` docgen configuration section (moved to framework options) +- `viteFinal` function (moved to vite.config.ts) + +#### 4. Vite configuration + +**Before (v9):** + +```typescript +viteFinal: async (config) => { + return mergeConfig(config, { + plugins: [ + ... + ] + }); +}, +``` + +**After (v10):** +You can use the `viteFinal` function if you want but I do recommend using `vite.config.ts` instead. + +```typescript +// vite.config.ts +export default { + plugins: [ + ... + ] +}; +``` From 2f5468449241d4065dd487f3b88ad6d7fc4cf03f Mon Sep 17 00:00:00 2001 From: Maksim Kachurin Date: Tue, 9 Sep 2025 18:12:49 -0700 Subject: [PATCH 4/5] Fix storybook peer dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8db9d79..2dc62d1 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ }, "peerDependencies": { "solid-js": "^1.9.0", - "storybook": "^9.0.0", + "storybook": "next", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", "typescript": ">= 4.9.x" }, From b370048aed0eaee8c971e1a789feb74cf975953d Mon Sep 17 00:00:00 2001 From: Maksim Kachurin Date: Tue, 9 Sep 2025 18:19:12 -0700 Subject: [PATCH 5/5] Fix deps for next version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2dc62d1..48e21c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "storybook-solidjs-vite", - "version": "10.0.0-beta.0", + "version": "10.0.0-beta.2", "description": "SolidJS integration with Storybook", "private": false, "keywords": [ @@ -74,7 +74,7 @@ }, "dependencies": { "vite-plugin-solid": "^2.11.8", - "@storybook/builder-vite": "^9.1.1", + "@storybook/builder-vite": "next", "@joshwooding/vite-plugin-react-docgen-typescript": "^0.6.1", "@storybook/global": "^5.0.0" },