storybook-addon-code-editor
用于实时编辑 Storybook stories 的插件。支持 React 和 TypeScript。
这是什么?
这是一个 Storybook 插件,支持实时编辑 React 组件并实时预览。可以把它想象成一个轻量级的 CodeSandbox,直接集成在 stories 或 MDX 页面中。
它使用 Monaco Editor(浏览器版 VS Code),提供卓越的 TypeScript 编辑体验。
开始使用
- 安装为开发依赖
npm install --save-dev storybook-addon-code-editor
# Or yarn:
yarn add --dev storybook-addon-code-editor
- 在你的
.storybook/main.ts
文件中添加storybook-addon-code-editor
,并确保staticDirs
、addons
和framework
字段包含以下内容
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite';
import { getCodeEditorStaticDirs } from 'storybook-addon-code-editor/getStaticDirs';
const config: StorybookConfig = {
staticDirs: [...getCodeEditorStaticDirs(__filename)],
addons: ['storybook-addon-code-editor'],
framework: {
name: '@storybook/react-vite',
options: {},
},
};
export default config;
staticDirs
设置了 Storybook 加载的静态文件目录列表。编辑器 (monaco-editor) 需要这些额外的静态文件在运行时可用。
可以使用 storybook-addon-code-editor/getStaticDirs
中的 getExtraStaticDir
助手函数添加额外的静态文件
// .storybook/main.ts
import {
getCodeEditorStaticDirs,
getExtraStaticDir,
} from 'storybook-addon-code-editor/getStaticDirs';
const config: StorybookConfig = {
staticDirs: [
...getCodeEditorStaticDirs(__filename),
// files will be available at: /monaco-editor/esm/*
getExtraStaticDir('monaco-editor/esm'),
重要提示
目前只支持 @storybook/react-vite
框架。
API
Playground
在 MDX 格式中使用 Playground
组件。
// MyComponent.stories.mdx
import { Playground } from 'storybook-addon-code-editor'
<Playground code="export default () => <h1>Hello</h1>" />
// MyComponent.stories.mdx
import { Playground } from 'storybook-addon-code-editor';
import \* as MyLibrary from './index';
import storyCode from './MyStory.source.tsx?raw';
// TypeScript might complain about not finding this import or
// importing things from .d.ts files wihtout `import type`.
// Ignore this, we need the string contents of this file.
// @ts-ignore
import MyLibraryTypes from '../dist/types.d.ts?raw';
<Playground
availableImports={{ 'my-library': MyLibrary }}
code={storyCode}
height="560px"
id="unique id used to save edited code until the page is reloaded"
modifyEditor={(monaco, editor) => {
// editor docs: https://msdocs.cn/monaco-editor/api/interfaces/monaco.editor.IStandaloneCodeEditor.html
// monaco docs: https://msdocs.cn/monaco-editor/api/modules/monaco.html
editor.getModel().updateOptions({ tabSize: 2 });
monaco.editor.setTheme('vs-dark');
monaco.languages.typescript.typescriptDefaults.addExtraLib(
MyLibraryTypes,
'file:///node_modules/my-library/index.d.ts',
);
}}
/>
Playground
属性
interface PlaygroundProps {
availableImports?: {
[importSpecifier: string]: {
[namedImport: string]: any;
};
};
code?: string;
defaultEditorOptions?: Monaco.editor.IEditorOptions;
height?: string;
id?: string | number | symbol;
modifyEditor?: (monaco: Monaco, editor: Monaco.editor.IStandaloneCodeEditor) => any;
}
如果 code
没有导入 React
,它会自动导入。如果 @types/react
可用,React TypeScript 定义也会自动加载。
makeLiveEditStory
在传统 stories 中使用 makeLiveEditStory
函数来显示代码编辑器面板
// MyComponent.stories.ts
import type { Meta, StoryObj } from '@storybook/react';
import { makeLiveEditStory } from 'storybook-addon-code-editor';
import * as MyLibrary from './index';
import storyCode from './MyStory.source.tsx?raw';
const meta = {
// Story defaults
} satisfies Meta<typeof MyLibrary.MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const MyStory: Story = {
// Story config
};
makeLiveEditStory(MyStory, {
availableImports: { 'my-library': MyLibrary },
code: storyCode,
});
makeLiveEditStory
选项
interface LiveEditStoryOptions {
availableImports?: {
[importSpecifier: string]: {
[namedImport: string]: any;
};
};
code: string;
modifyEditor?: (monaco: Monaco, editor: Monaco.editor.IStandaloneCodeEditor) => any;
defaultEditorOptions?: Monaco.editor.IEditorOptions;
}
setupMonaco
setupMonaco
允许自定义 monaco-editor
。
在你的 .storybook/preview.ts
中使用此函数来添加类型定义或集成。
查看具有不同配置的 monaco-editor
示例。
// .storybook/preview.ts
import { setupMonaco } from 'storybook-addon-code-editor';
setupMonaco({
// https://msdocs.cn/monaco-editor/typedoc/interfaces/Environment.html
monacoEnvironment: {
getWorker(moduleId, label) {
...
},
},
// onMonacoLoad is called when monaco is first loaded, before an editor instance is created.
onMonacoLoad(monaco) {
...
},
});
setupMonaco
选项
interface MonacoSetup {
monacoEnvironment?: Monaco.Environment;
onMonacoLoad?: (monaco: Monaco) => any;
}
贡献
安装依赖
npm install
运行示例
npm run start-example
当对库进行更改时,需要手动重启服务器。
运行测试
npm run test
格式化代码
npm run format
构建库
npm run build
提交
使用 Conventional Commits 允许自动版本发布。
fix:
表示 bug 修复,对应于 SemVer 的补丁版本。feat:
表示新功能,对应于 SemVer 的次版本。feat!:
,或fix!:
,refactor!:
等,表示破坏性更改(由 ! 标示),将导致 SemVer 的主版本升级。
发布
将自动化生成的指向主分支的 release-please PR 合并即可部署发布。