From 1ea65954ca397f911e2422beaa36322ab4a562f0 Mon Sep 17 00:00:00 2001 From: Brody McKee Date: Tue, 19 May 2020 10:36:36 +0300 Subject: [PATCH] feat: update types and defaults --- .../server/framework-preset-react-docgen.ts | 27 +++----- examples/react-ts/{main.js => main.ts} | 5 +- examples/react-ts/package.json | 1 + examples/react-ts/src/button.stories.tsx | 2 +- examples/react-ts/src/button.tsx | 6 +- examples/react-ts/src/emoji-button.js | 19 ++++++ examples/react-ts/src/emoji-button.stories.js | 8 +++ examples/react-ts/tsconfig.json | 6 +- lib/core/src/server/config.js | 3 +- lib/core/src/server/config/defaults.js | 4 ++ lib/core/src/server/manager/manager-config.js | 4 +- lib/core/types/index.ts | 63 ++++++++++++++++--- yarn.lock | 2 +- 13 files changed, 110 insertions(+), 40 deletions(-) rename examples/react-ts/{main.js => main.ts} (76%) create mode 100644 examples/react-ts/src/emoji-button.js create mode 100644 examples/react-ts/src/emoji-button.stories.js create mode 100644 lib/core/src/server/config/defaults.js diff --git a/app/react/src/server/framework-preset-react-docgen.ts b/app/react/src/server/framework-preset-react-docgen.ts index cf731c96525..a525c8d03f9 100644 --- a/app/react/src/server/framework-preset-react-docgen.ts +++ b/app/react/src/server/framework-preset-react-docgen.ts @@ -1,19 +1,9 @@ -import { TransformOptions } from '@babel/core'; -import { Configuration } from 'webpack'; +import type { TransformOptions } from '@babel/core'; +import type { Configuration } from 'webpack'; import type { StorybookOptions } from '@storybook/core/types'; -const DEFAULT_DOCGEN = 'react-docgen-typescript'; - -const getDocgen = (typescriptOptions: StorybookOptions['typescriptOptions']) => { - const docgen = typescriptOptions?.reactDocgen; - return typeof docgen === 'undefined' ? DEFAULT_DOCGEN : docgen; -}; - -export function babel( - config: TransformOptions, - { typescriptOptions }: StorybookOptions = { typescriptOptions: {} } -) { - const reactDocgen = getDocgen(typescriptOptions); +export function babel(config: TransformOptions, { typescriptOptions }: StorybookOptions) { + const { reactDocgen } = typescriptOptions; if (!reactDocgen) { return config; } @@ -35,11 +25,8 @@ export function babel( }; } -export function webpackFinal( - config: Configuration, - { typescriptOptions }: StorybookOptions = { typescriptOptions: {} } -) { - const reactDocgen = getDocgen(typescriptOptions); +export function webpackFinal(config: Configuration, { typescriptOptions }: StorybookOptions) { + const { reactDocgen, reactDocgenTypescriptOptions } = typescriptOptions; if (reactDocgen !== 'react-docgen-typescript') return config; return { ...config, @@ -53,7 +40,7 @@ export function webpackFinal( use: [ { loader: require.resolve('react-docgen-typescript-loader'), - options: typescriptOptions?.reactDocgenTypescriptOptions, + options: reactDocgenTypescriptOptions, }, ], }, diff --git a/examples/react-ts/main.js b/examples/react-ts/main.ts similarity index 76% rename from examples/react-ts/main.js rename to examples/react-ts/main.ts index e901e7decb6..17f75117a16 100644 --- a/examples/react-ts/main.js +++ b/examples/react-ts/main.ts @@ -1,12 +1,13 @@ +import type { StorybookConfig } from '@storybook/core/types'; + module.exports = { stories: ['./src/*.stories.*'], addons: ['@storybook/addon-essentials'], typescript: { check: true, checkOptions: {}, - reactDocgen: 'react-docgen-typescript', reactDocgenTypescriptOptions: { propFilter: (prop) => ['label', 'disabled'].includes(prop.name), }, }, -}; +} as StorybookConfig; diff --git a/examples/react-ts/package.json b/examples/react-ts/package.json index 6ab3104715d..0d31cc0c602 100644 --- a/examples/react-ts/package.json +++ b/examples/react-ts/package.json @@ -12,6 +12,7 @@ "@storybook/react": "6.0.0-beta.8", "@types/react": "^16.9.35", "@types/react-dom": "^16.9.8", + "prop-types": "15.7.2", "react": "^16.13.1", "react-dom": "^16.13.1", "typescript": "^3.9.2", diff --git a/examples/react-ts/src/button.stories.tsx b/examples/react-ts/src/button.stories.tsx index b2350a28722..4f6fa70cb1c 100644 --- a/examples/react-ts/src/button.stories.tsx +++ b/examples/react-ts/src/button.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { argsStory } from '@storybook/react'; import { Button } from './button'; -export default { component: Button, title: 'Examples/Button' }; +export default { component: Button, title: 'Examples / Button' }; export const WithArgs = argsStory({ label: 'With args' }); export const Basic = () => ); diff --git a/examples/react-ts/src/emoji-button.js b/examples/react-ts/src/emoji-button.js new file mode 100644 index 00000000000..716afa1238c --- /dev/null +++ b/examples/react-ts/src/emoji-button.js @@ -0,0 +1,19 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export const EmojiButton = ({ label, ...props }) => ( + +); + +EmojiButton.propTypes = { + /** + * A label to show on the button + */ + label: PropTypes.string, +}; + +EmojiButton.defaultProps = { + label: 'Hello', +}; diff --git a/examples/react-ts/src/emoji-button.stories.js b/examples/react-ts/src/emoji-button.stories.js new file mode 100644 index 00000000000..2721965b84c --- /dev/null +++ b/examples/react-ts/src/emoji-button.stories.js @@ -0,0 +1,8 @@ +import React from 'react'; +import { argsStory } from '@storybook/react'; +import { EmojiButton } from './emoji-button'; + +export default { component: EmojiButton, title: 'Examples / Emoji Button' }; + +export const WithArgs = argsStory({ label: 'With args' }); +export const Basic = () => ; diff --git a/examples/react-ts/tsconfig.json b/examples/react-ts/tsconfig.json index 8b8ebe54e83..5447ee7e4d8 100644 --- a/examples/react-ts/tsconfig.json +++ b/examples/react-ts/tsconfig.json @@ -1,10 +1,10 @@ { "compilerOptions": { "baseUrl": ".", - "skipLibCheck": true, - "jsx": "preserve", "esModuleInterop": true, + "jsx": "preserve", + "skipLibCheck": true, "strict": true }, - "include": ["src/*"] + "include": ["src/*", "main.ts"] } diff --git a/lib/core/src/server/config.js b/lib/core/src/server/config.js index 5aff0e31b29..7e5970bf30d 100644 --- a/lib/core/src/server/config.js +++ b/lib/core/src/server/config.js @@ -1,9 +1,10 @@ import { logger } from '@storybook/node-logger'; import loadPresets from './presets'; import loadCustomPresets from './common/custom-presets'; +import { typeScriptDefaults } from './config/defaults'; async function getPreviewWebpackConfig(options, presets) { - const typescriptOptions = await presets.apply('typescript', {}, options); + const typescriptOptions = await presets.apply('typescript', { ...typeScriptDefaults }, options); const babelOptions = await presets.apply('babel', {}, { ...options, typescriptOptions }); const entries = await presets.apply('entries', [], options); const stories = await presets.apply('stories', [], options); diff --git a/lib/core/src/server/config/defaults.js b/lib/core/src/server/config/defaults.js new file mode 100644 index 00000000000..28c4b29435c --- /dev/null +++ b/lib/core/src/server/config/defaults.js @@ -0,0 +1,4 @@ +export const typeScriptDefaults = { + check: false, + reactDocgen: 'react-docgen-typescript', +}; diff --git a/lib/core/src/server/manager/manager-config.js b/lib/core/src/server/manager/manager-config.js index 5c48a1a7589..ab8ff403868 100644 --- a/lib/core/src/server/manager/manager-config.js +++ b/lib/core/src/server/manager/manager-config.js @@ -5,6 +5,7 @@ import resolveFrom from 'resolve-from'; import loadPresets from '../presets'; import loadCustomPresets from '../common/custom-presets'; +import { typeScriptDefaults } from '../config/defaults'; const getAutoRefs = async (options) => { const location = await findUp('package.json', { cwd: options.configDir }); @@ -39,7 +40,8 @@ const toTitle = (input) => { }; async function getManagerWebpackConfig(options, presets) { - const babelOptions = await presets.apply('babel', {}, options); + const typescriptOptions = await presets.apply('typescript', { ...typeScriptDefaults }, options); + const babelOptions = await presets.apply('babel', {}, { ...options, typescriptOptions }); const autoRefs = await getAutoRefs(options); const refs = await presets.apply('refs', undefined, options); diff --git a/lib/core/types/index.ts b/lib/core/types/index.ts index ed98b6d293a..2edb4149737 100644 --- a/lib/core/types/index.ts +++ b/lib/core/types/index.ts @@ -1,10 +1,57 @@ -type ReactDocgen = 'react-docgen' | 'react-docgen-typescript' | false; +import type ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import type LoaderOptions from 'react-docgen-typescript-loader/dist/LoaderOptions'; -export interface StorybookOptions { - typescriptOptions?: { - reactDocgen?: ReactDocgen; - reactDocgenTypescriptOptions?: any; - check?: boolean; - checkOptions?: any; - }; +/** + * The interface for Storybook configuration in `main.js` files. + */ +export interface StorybookConfig { + /** + * Sets the addons you want to use with Storybook. + * + * @example `['@storybook/addon-essentials']` + */ + addons: string[]; + /** + * Tells Storybook where to find stories. + * + * @example `['./src/*.stories.(j|t)sx?']` + */ + stories: string[]; + /** + * Controls how Storybook hanldes TypeScript files. + */ + typescript?: Partial; +} + +/** + * The internal options object, used by Storybook frameworks and adddons. + */ +export interface StorybookOptions { + typescriptOptions: TypescriptOptions; +} + +/** + * Options for TypeScript usage within Storybook. + */ +export interface TypescriptOptions { + /** + * Enables type checking within Storybook. + * + * @defalt `false` + */ + check: boolean; + /** + * Configures `fork-ts-checker-webpack-plugin` + */ + checkOptions?: ForkTsCheckerWebpackPlugin['options']; + /** + * Sets the type of Docgen when working with React and TypeScript + * + * @default `'react-docgen-typescript'` + */ + reactDocgen: 'react-docgen-typescript' | 'react-docgen' | false; + /** + * Configures `react-docgen-typescript-loader` + */ + reactDocgenTypescriptOptions?: LoaderOptions; } diff --git a/yarn.lock b/yarn.lock index 3e7628aaed8..093170faf5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25182,7 +25182,7 @@ prop-types-exact@^1.2.0: object.assign "^4.1.0" reflect.ownkeys "^0.2.0" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==