diff --git a/.babelrc.js b/.babelrc.js index c1e808c5983..cb85c9eb2b7 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -13,7 +13,10 @@ const withTests = { }; module.exports = { - ignore: ['./lib/codemod/src/transforms/__testfixtures__'], + ignore: [ + './lib/codemod/src/transforms/__testfixtures__', + './lib/postinstall/src/__testfixtures__', + ], presets: [ ['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage', corejs: '3' }], '@babel/preset-typescript', diff --git a/.eslintrc.js b/.eslintrc.js index 37080fa43ba..3c53e6faad7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,25 +1,21 @@ -const ignore = 0; -// const warn = 1; -const error = 2; - module.exports = { root: true, extends: ['@storybook/eslint-config-storybook'], rules: { 'import/extensions': [ - error, + 'error', 'never', { ignorePackages: true, md: 'always', svg: 'always', json: 'always', tag: 'always' }, ], - 'import/no-unresolved': [error, { ignore: ['@storybook'] }], - 'react/state-in-constructor': ignore, - 'react/static-property-placement': ignore, - 'react/jsx-props-no-spreading': ignore, - 'react/jsx-fragments': ignore, - '@typescript-eslint/ban-ts-ignore': ignore, - '@typescript-eslint/no-object-literal-type-assertion': ignore, + 'import/no-unresolved': ['error', { ignore: ['@storybook'] }], + 'react/state-in-constructor': 'off', + 'react/static-property-placement': 'off', + 'react/jsx-props-no-spreading': 'off', + 'react/jsx-fragments': 'off', + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/no-object-literal-type-assertion': 'off', 'react/sort-comp': [ - error, + 'error', { order: [ 'staticLifecycle', @@ -38,7 +34,7 @@ module.exports = { }, }, ], - 'max-classes-per-file': ignore, + 'max-classes-per-file': 'off', }, overrides: [ { @@ -51,30 +47,30 @@ module.exports = { 'docs/src/stories/**', ], rules: { - '@typescript-eslint/no-empty-function': ignore, - 'import/no-extraneous-dependencies': ignore, + '@typescript-eslint/no-empty-function': 'off', + 'import/no-extraneous-dependencies': 'off', }, }, - { files: '**/.storybook/config.js', rules: { 'global-require': ignore } }, + { files: '**/.storybook/config.js', rules: { 'global-require': 'off' } }, { files: ['**/*.stories.*'], rules: { - 'no-console': ignore, + 'no-console': 'off', }, }, { files: ['**/*.tsx', '**/*.ts'], rules: { - 'react/prop-types': ignore, // we should use types - 'no-dupe-class-members': ignore, // this is called overloads in typescript + 'react/prop-types': 'off', // we should use types + 'no-dupe-class-members': 'off', // this is called overloads in typescript }, }, { files: ['**/*.d.ts'], rules: { - 'vars-on-top': ignore, - 'no-var': ignore, // this is how typescript works - 'spaced-comment': ignore, + 'vars-on-top': 'off', + 'no-var': 'off', // this is how typescript works + 'spaced-comment': 'off', }, }, ], diff --git a/CHANGELOG.md b/CHANGELOG.md index cb0146a53dd..1f3c86d548f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,148 @@ +## 5.3.0-beta.2 (November 19, 2019) + +### Features + +* Addon-docs: Customizable DocPage doc blocks ([#8855](https://github.com/storybookjs/storybook/pull/8855)) + +### Bug Fixes + +* Addon-docs: Add back Props "exclude" support ([#8868](https://github.com/storybookjs/storybook/pull/8868)) +* Addon-docs: Fix MDX component permalinking ([#8872](https://github.com/storybookjs/storybook/pull/8872)) +* Addon-docs: Fix regression to @ignore in Props ([#8867](https://github.com/storybookjs/storybook/pull/8867)) + +### Maintenance + +* Addon-docs: Add tests for prop types default value ([#8869](https://github.com/storybookjs/storybook/pull/8869)) + +## 5.3.0-beta.1 (November 18, 2019) + +### Features + +* Addon-google-analytics: Add gaOption config ([#8859](https://github.com/storybookjs/storybook/pull/8859)) + +### Bug Fixes + +* Addon-docs: Fix props table props sorting for PropTypes ([#8857](https://github.com/storybookjs/storybook/pull/8857)) +* Fix layout of Preview container ([#8628](https://github.com/storybookjs/storybook/pull/8628)) + +## 5.3.0-beta.0 (November 16, 2019) + +Storybook 5.3 is in beta y'all 🔥🔥🔥 It includes: + +- 📝 Longform documentation in MDX +- 🎨 Multi-framework SB Docs (React, Vue, Angular, WC) +- 📦 Web-components framework support +- 🔼 Tri-config (experimental) + +See the [latest changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md) for a full list of changes. + +## 5.3.0-alpha.47 (November 16, 2019) + +### Features + +* Triconfig: Declarative story definition in main.js ([#8748](https://github.com/storybookjs/storybook/pull/8748)) +* Storyshots: Triconfig support ([#8765](https://github.com/storybookjs/storybook/pull/8765)) + +### Bug Fixes + +* Addon-viewports: Fix missing TypeScript types ([#8848](https://github.com/storybookjs/storybook/pull/8848)) + +### Dependency Upgrades + +* Dependency upgrades ([#8847](https://github.com/storybookjs/storybook/pull/8847)) + +## 5.3.0-alpha.46 (November 16, 2019) + +### Features + +* Core: allow uppercase path names in url query param ([#8516](https://github.com/storybookjs/storybook/pull/8516)) + +### Bug Fixes + +* Core: Fix null version check bug ([#8806](https://github.com/storybookjs/storybook/pull/8806)) +* Addon-notes: Fix anchor links ([#8132](https://github.com/storybookjs/storybook/pull/8132)) + +### Maintenance + +* Refactor: remove useless variables from eslint config ([#8843](https://github.com/storybookjs/storybook/pull/8843)) + +### Dependency Upgrades + +* Addon-docs: Replace `storybook-addon-vue-info` with `vue-docgen-loader` ([#8831](https://github.com/storybookjs/storybook/pull/8831)) + +## 5.3.0-alpha.45 (November 14, 2019) + +### Breaking Changes + +* CSF: Deprecate displayName parameter ([#8775](https://github.com/storybookjs/storybook/pull/8775)) + +### Features + +* Addon-docs: Rich prop tables ([#8826](https://github.com/storybookjs/storybook/pull/8826)) +* Core: Simplified hierarchy separators ([#8796](https://github.com/storybookjs/storybook/pull/8796)) +* CLI: Upgrade hierarchy separator codemod + examples ([#8818](https://github.com/storybookjs/storybook/pull/8818)) +* CLI: Addon postinstall hooks ([#8700](https://github.com/storybookjs/storybook/pull/8700)) +* CSF/MDX: Add component id for permalinks ([#8808](https://github.com/storybookjs/storybook/pull/8808)) +* Addon-knobs: Add object[] support for select ([#7957](https://github.com/storybookjs/storybook/pull/7957)) + +### Bug Fixes + +* Addon-A11y: Show errors, reset config properly ([#8779](https://github.com/storybookjs/storybook/pull/8779)) + +## 5.3.0-alpha.44 (November 13, 2019) + +### Features + +* React-native: Add theming to ondevice-addons ([#8738](https://github.com/storybookjs/storybook/pull/8738)) + +### Bug Fixes + +* UI: Store layout state in sessionStorage ([#8786](https://github.com/storybookjs/storybook/pull/8786)) +* Core: Use `stable` package to ensure story sorting is stable ([#8795](https://github.com/storybookjs/storybook/pull/8795)) + +### Maintenance + +* Svelte: Migrate @storybook/svelte to Typescript ([#8770](https://github.com/storybookjs/storybook/pull/8770)) + +## 5.3.0-alpha.43 (November 11, 2019) + +### Bug Fixes + +* Source-loader: Warn if applied to non-stories file ([#8773](https://github.com/storybookjs/storybook/pull/8773)) + +### Maintenance + +* Presets / Addon-docs: Cleanup framework-specific presets ([#8782](https://github.com/storybookjs/storybook/pull/8782)) +* Add @babel/runtime to workspace ([#8774](https://github.com/storybookjs/storybook/pull/8774)) + +## 5.2.6 (November 9, 2019) + +### Bug Fixes + +* Addon-info: Remove jsnext:main ([#8764](https://github.com/storybookjs/storybook/pull/8764)) +* Addon-info: Fix "The prop 'children' is marked as required in 'Td'" ([#8745](https://github.com/storybookjs/storybook/pull/8745)) +* UI: Fix unmount components on Canvas/Docs tab switch ([#8625](https://github.com/storybookjs/storybook/pull/8625)) +* Addon-docs: Fix code style inside LI ([#8708](https://github.com/storybookjs/storybook/pull/8708)) +* Remove min-height CSS rule from DocsPage wrapper ([#8366](https://github.com/storybookjs/storybook/pull/8366)) +* Core: Revert webpack rebuild changes in node_modules ([#8657](https://github.com/storybookjs/storybook/pull/8657)) +* Addon-notes: Add key to render function ([#8633](https://github.com/storybookjs/storybook/pull/8633)) +* Addon-docs: Fix story scroll-to heuristics ([#8629](https://github.com/storybookjs/storybook/pull/8629)) +* React-native-server: Changed default port to number in CLI options ([#8584](https://github.com/storybookjs/storybook/pull/8584)) +* Increase TooltipLinkList max-height to accommodate more links ([#8545](https://github.com/storybookjs/storybook/pull/8545)) +* Prevent form submission as search is done while typing ([#8546](https://github.com/storybookjs/storybook/pull/8546)) +* Ondevice-knobs: Fix peer dep ([#8644](https://github.com/storybookjs/storybook/pull/8644)) + +## 5.3.0-alpha.42 (November 9, 2019) + +### Bug Fixes + +* Addon-info: Remove jsnext:main ([#8764](https://github.com/storybookjs/storybook/pull/8764)) +* Addon-info: Fix "The prop 'children' is marked as required in 'Td'" ([#8745](https://github.com/storybookjs/storybook/pull/8745)) + +### Maintenance + +* React-native: Update compilation target - it was compiled for old browsers ([#8698](https://github.com/storybookjs/storybook/pull/8698)) + ## 5.3.0-alpha.41 (November 7, 2019) ### Features diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 638e1aade6f..5235cf76da4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -327,9 +327,7 @@ First we are going to install storybook, then we are going to link `@storybook/r You should now have a working storybook dev environment up and running. -> TODO: update this section (is already incorrect) - -Save and go to `http://localhost:9009` (or wherever storybook is running) +Save and go to `http://localhost:9011` (or wherever storybook is running) If you don't see the changes rerun `yarn storybook` again in your sandbox app diff --git a/MIGRATION.md b/MIGRATION.md index ed9ccef19fb..4795757e5e9 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -5,6 +5,9 @@ - [Create React App preset](#create-react-app-preset) - [Description doc block](#description-doc-block) - [React Native Async Storage](#react-native-async-storage) + - [Deprecate displayName parameter](#deprecate-displayname-parameter) + - [Unified docs preset](#unified-docs-preset) + - [Simplified hierarchy separators](#simplified-hierarchy-separators) - [From version 5.1.x to 5.2.x](#from-version-51x-to-52x) - [Source-loader](#source-loader) - [Default viewports](#default-viewports) @@ -97,17 +100,41 @@ To avoid that now you have to manually pass asyncStorage to React Native Storybo Solution: -- Use `require('@react-native-community/async-storage')` for React Native v0.59 and above. +- Use `require('@react-native-community/async-storage').AsyncStorage` for React Native v0.59 and above. - Use `require('react-native').AsyncStorage` for React Native v0.58 or below. - Use `null` to disable Async Storage completely. ```javascript getStorybookUI({ ... - asyncStorage: require('@react-native-community/async-storage') || require('react-native').AsyncStorage || null + asyncStorage: require('@react-native-community/async-storage').AsyncStorage || require('react-native').AsyncStorage || null }); ``` +### Deprecate displayName parameter + +In 5.2, the story parameter `displayName` was introduced as a publicly visible (but internal) API. Storybook's Component Story Format (CSF) loader used it to modify a story's display name independent of the story's `name`/`id` (which were coupled). + +In 5.3, the CSF loader decouples the story's `name`/`id`, which means that `displayName` is no longer necessary. Unfortunately, this is a breaking change for any code that uses the story `name` field. Storyshots relies on story `name`, and the appropriate migration is to simply update your snapshots. Apologies for the inconvenience! + +### Unified docs preset + +Addon-docs configuration gets simpler in 5.3. In 5.2, each framework had its own preset, e.g. `@storybook/addon-docs/react/preset`. Starting in 5.3, everybody should use `@storybook/addon-docs/preset`. + +### Simplified hierarchy separators + +We've deprecated the ability to specify the hierarchy separators (how you control the grouping of story kinds in the sidebar). From Storybook 6.0 we will have a single separator `/`, which cannot be configured. + +If you are currently using using custom separators, we encourage you to migrate to using `/` as the sole separator. If you are using `|` or `.` as a separator currently, (we will soon provide) a codemod that can be used to rename all your components. + +If you were using `|` and wish to keep the "root" behaviour, use the `showRoots: true` option to re-enable roots: + +```js +addParameters({ options: { showRoots: true } }); +``` + +NOTE: it is no longer possible to have some stories with roots and others without. If you want to keep the old behaviour, simply add a root called "Others" to all your previously unrooted stories. + ## From version 5.1.x to 5.2.x ### Source-loader diff --git a/addons/a11y/README.md b/addons/a11y/README.md index 584e49f6702..d4d2638a9e6 100755 --- a/addons/a11y/README.md +++ b/addons/a11y/README.md @@ -56,7 +56,6 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y) addParameters({ a11y: { - // ... axe options element: '#root', // optional selector which element to inspect config: {}, // axe-core configurationOptions (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#parameters-1) options: {} // axe-core optionsParameter (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter) diff --git a/addons/a11y/package.json b/addons/a11y/package.json index 7625a213231..ac52a597640 100644 --- a/addons/a11y/package.json +++ b/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "a11y addon for storybook", "keywords": [ "a11y", @@ -33,12 +33,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "axe-core": "^3.3.2", "core-js": "^3.0.1", "global": "^4.3.2", diff --git a/addons/a11y/src/components/A11YPanel.test.js b/addons/a11y/src/components/A11YPanel.test.js index 5c57664c573..2f84b31afd3 100644 --- a/addons/a11y/src/components/A11YPanel.test.js +++ b/addons/a11y/src/components/A11YPanel.test.js @@ -63,7 +63,7 @@ function ThemedA11YPanel(props) { } describe('A11YPanel', () => { - it('should register STORY_RENDERED and RESULT updater on mount', () => { + it('should register STORY_RENDERED, RESULT and ERROR updater on mount', () => { // given const api = createApi(); expect(api.on).not.toHaveBeenCalled(); @@ -72,9 +72,10 @@ describe('A11YPanel', () => { mount(); // then - expect(api.on.mock.calls.length).toBe(2); + expect(api.on.mock.calls.length).toBe(3); expect(api.on.mock.calls[0][0]).toBe(STORY_RENDERED); expect(api.on.mock.calls[1][0]).toBe(EVENTS.RESULT); + expect(api.on.mock.calls[2][0]).toBe(EVENTS.ERROR); }); it('should request a run on tab activation', () => { @@ -93,7 +94,7 @@ describe('A11YPanel', () => { expect(wrapper.find(ScrollArea).length).toBe(0); }); - it('should deregister STORY_RENDERED and RESULT updater on unmount', () => { + it('should deregister STORY_RENDERED, RESULT and ERROR updater on unmount', () => { // given const api = createApi(); const wrapper = mount(); @@ -103,9 +104,10 @@ describe('A11YPanel', () => { wrapper.unmount(); // then - expect(api.off.mock.calls.length).toBe(2); + expect(api.off.mock.calls.length).toBe(3); expect(api.off.mock.calls[0][0]).toBe(STORY_RENDERED); expect(api.off.mock.calls[1][0]).toBe(EVENTS.RESULT); + expect(api.off.mock.calls[2][0]).toBe(EVENTS.ERROR); }); it('should update run result', () => { diff --git a/addons/a11y/src/components/A11YPanel.tsx b/addons/a11y/src/components/A11YPanel.tsx index 5f0c1fffb61..194acca7be6 100644 --- a/addons/a11y/src/components/A11YPanel.tsx +++ b/addons/a11y/src/components/A11YPanel.tsx @@ -46,26 +46,35 @@ const Incomplete = styled.span<{}>(({ theme }) => ({ color: theme.color.warning, })); +const centeredStyle = { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: '100%', +}; + const Loader = styled(({ className }) => (
Please wait while the accessibility scan is running ...
-))({ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: '100%', -}); +))(centeredStyle); Loader.displayName = 'Loader'; -interface A11YPanelState { - status: string; +interface A11YPanelNormalState { + status: 'ready' | 'ran' | 'running'; passes: Result[]; violations: Result[]; incomplete: Result[]; } +interface A11YPanelErrorState { + status: 'error'; + error: unknown; +} + +type A11YPanelState = A11YPanelNormalState | A11YPanelErrorState; + interface A11YPanelProps { active: boolean; api: API; @@ -84,6 +93,7 @@ export class A11YPanel extends Component { api.on(STORY_RENDERED, this.request); api.on(EVENTS.RESULT, this.onUpdate); + api.on(EVENTS.ERROR, this.onError); } componentDidUpdate(prevProps: A11YPanelProps) { @@ -101,6 +111,7 @@ export class A11YPanel extends Component { const { api } = this.props; api.off(STORY_RENDERED, this.request); api.off(EVENTS.RESULT, this.onUpdate); + api.off(EVENTS.ERROR, this.onError); } onUpdate = ({ passes, violations, incomplete }: AxeResults) => { @@ -124,6 +135,13 @@ export class A11YPanel extends Component { ); }; + onError = (error: unknown) => { + this.setState({ + status: 'error', + error, + }); + }; + request = () => { const { api, active } = this.props; @@ -142,8 +160,22 @@ export class A11YPanel extends Component { }; render() { - const { passes, violations, incomplete, status } = this.state; const { active } = this.props; + if (!active) return null; + + // eslint-disable-next-line react/destructuring-assignment + if (this.state.status === 'error') { + const { error } = this.state; + return ( +
+ The accessibility scan encountered an error. +
+ {error} +
+ ); + } + + const { passes, violations, incomplete, status } = this.state; let actionTitle; if (status === 'ready') { @@ -162,7 +194,7 @@ export class A11YPanel extends Component { ); } - return active ? ( + return ( {status === 'running' ? ( @@ -218,6 +250,6 @@ export class A11YPanel extends Component { /> - ) : null; + ); } } diff --git a/addons/a11y/src/components/Report/HighlightToggle.tsx b/addons/a11y/src/components/Report/HighlightToggle.tsx index 5d075d8e075..2aa554641e3 100644 --- a/addons/a11y/src/components/Report/HighlightToggle.tsx +++ b/addons/a11y/src/components/Report/HighlightToggle.tsx @@ -185,7 +185,4 @@ class HighlightToggle extends Component { } } -export default connect( - mapStateToProps, - mapDispatchToProps -)(HighlightToggle); +export default connect(mapStateToProps, mapDispatchToProps)(HighlightToggle); diff --git a/addons/a11y/src/components/Report/__snapshots__/HighlightToggle.test.js.snap b/addons/a11y/src/components/Report/__snapshots__/HighlightToggle.test.js.snap index bdef5cabcc0..e0c37bf518c 100644 --- a/addons/a11y/src/components/Report/__snapshots__/HighlightToggle.test.js.snap +++ b/addons/a11y/src/components/Report/__snapshots__/HighlightToggle.test.js.snap @@ -84,6 +84,7 @@ exports[`HighlightToggle component should match snapshot 1`] = ` "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBd0NxQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", "name": "1o7rzh8-hoverable", "styles": "transition:all 150ms ease-out;transform:translate3d(0,0,0);&:hover{transform:translate3d(0,-2px,0);}&:active{transform:translate3d(0,0,0);};label:hoverable;", + "toString": [Function], }, "inlineGlow": Object { "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUNzQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", diff --git a/addons/a11y/src/components/__snapshots__/A11YPanel.test.js.snap b/addons/a11y/src/components/__snapshots__/A11YPanel.test.js.snap index 24e12e70404..2ac873d4753 100644 --- a/addons/a11y/src/components/__snapshots__/A11YPanel.test.js.snap +++ b/addons/a11y/src/components/__snapshots__/A11YPanel.test.js.snap @@ -177,6 +177,10 @@ exports[`A11YPanel should render report 1`] = ` "storybook/a11y/result", [Function], ], + Array [ + "storybook/a11y/error", + [Function], + ], ], "results": Array [ Object { @@ -187,6 +191,10 @@ exports[`A11YPanel should render report 1`] = ` "type": "return", "value": undefined, }, + Object { + "type": "return", + "value": undefined, + }, ], }, } diff --git a/addons/a11y/src/constants.ts b/addons/a11y/src/constants.ts index d5b15398646..efabac7a268 100755 --- a/addons/a11y/src/constants.ts +++ b/addons/a11y/src/constants.ts @@ -6,5 +6,6 @@ export const ADD_ELEMENT = 'ADD_ELEMENT'; export const CLEAR_ELEMENTS = 'CLEAR_ELEMENTS'; const RESULT = `${ADDON_ID}/result`; const REQUEST = `${ADDON_ID}/request`; +const ERROR = `${ADDON_ID}/error`; -export const EVENTS = { RESULT, REQUEST }; +export const EVENTS = { RESULT, REQUEST, ERROR }; diff --git a/addons/a11y/src/index.ts b/addons/a11y/src/index.ts index 20c8fc71726..a7f53ec29a7 100644 --- a/addons/a11y/src/index.ts +++ b/addons/a11y/src/index.ts @@ -39,7 +39,8 @@ const run = (element: ElementContext, config: Spec, options: RunOptions) => { restoreScroll: true, } as RunOptions) // cast to RunOptions is necessary because axe types are not up to date ) - .then(report); + .then(report) + .catch(error => addons.getChannel().emit(EVENTS.ERROR, String(error))); }); }; @@ -47,12 +48,20 @@ if (module && module.hot && module.hot.decline) { module.hot.decline(); } +let storedDefaultSetup: Setup | null = null; + export const withA11y = makeDecorator({ name: 'withA11Y', parameterName: PARAM_KEY, wrapper: (getStory, context, { parameters }) => { if (parameters) { - setup = parameters as Setup; + if (storedDefaultSetup === null) { + storedDefaultSetup = { ...setup }; + } + Object.assign(setup, parameters as Setup); + } else if (storedDefaultSetup !== null) { + Object.assign(setup, storedDefaultSetup); + storedDefaultSetup = null; } addons.getChannel().on(EVENTS.REQUEST, () => run(setup.element, setup.config, setup.options)); diff --git a/addons/actions/package.json b/addons/actions/package.json index ff035ada7ec..3724baae7f5 100644 --- a/addons/actions/package.json +++ b/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Action Logger addon for storybook", "keywords": [ "storybook" @@ -28,12 +28,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "fast-deep-equal": "^2.0.1", "global": "^4.3.2", diff --git a/addons/backgrounds/package.json b/addons/backgrounds/package.json index 552703b630e..50f2cec189f 100644 --- a/addons/backgrounds/package.json +++ b/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "A storybook addon to show different backgrounds for your preview", "keywords": [ "addon", @@ -32,12 +32,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "memoizerific": "^1.11.3", "react": "^16.8.3", diff --git a/addons/centered/package.json b/addons/centered/package.json index b59c6b93289..7d8c78f7b21 100644 --- a/addons/centered/package.json +++ b/addons/centered/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-centered", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook decorator to center components", "keywords": [ "addon", @@ -29,7 +29,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "util-deprecate": "^1.0.2" diff --git a/addons/contexts/package.json b/addons/contexts/package.json index b548e52492f..2014f7a96e1 100644 --- a/addons/contexts/package.json +++ b/addons/contexts/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-contexts", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook Addon Contexts", "keywords": [ "preact", @@ -27,10 +27,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "qs": "^6.6.0" diff --git a/addons/contexts/src/manager/components/ToolBar.test.tsx b/addons/contexts/src/manager/components/ToolBar.test.tsx index b5a09c187e1..35caba83f2c 100644 --- a/addons/contexts/src/manager/components/ToolBar.test.tsx +++ b/addons/contexts/src/manager/components/ToolBar.test.tsx @@ -27,7 +27,10 @@ describe('Tests on addon-contexts component: ToolBar', () => { icon: 'box' as const, nodeId: 'Some Context B', options: { cancelable: true, deep: false, disable: false }, - params: [{ name: 'Some Param X', props: {} }, { name: 'Some Param Y', props: {} }], + params: [ + { name: 'Some Param X', props: {} }, + { name: 'Some Param Y', props: {} }, + ], title: 'Some Context B', }, ]; diff --git a/addons/contexts/src/manager/components/ToolBarControl.test.tsx b/addons/contexts/src/manager/components/ToolBarControl.test.tsx index c0131fd4a47..975f420dc27 100644 --- a/addons/contexts/src/manager/components/ToolBarControl.test.tsx +++ b/addons/contexts/src/manager/components/ToolBarControl.test.tsx @@ -9,7 +9,10 @@ describe('Tests on addon-contexts component: ToolBarControl', () => { icon: 'box' as const, nodeId: 'Some Context', options: { cancelable: true, deep: false, disable: false }, - params: [{ name: 'A', props: {} }, { name: 'B', props: {} }], + params: [ + { name: 'A', props: {} }, + { name: 'B', props: {} }, + ], title: 'Some Context', selected: '', setSelected: jest.fn, diff --git a/addons/contexts/src/preview/libs/getContextNodes.test.ts b/addons/contexts/src/preview/libs/getContextNodes.test.ts index cf6b1c2e20f..d6bbb23c24e 100644 --- a/addons/contexts/src/preview/libs/getContextNodes.test.ts +++ b/addons/contexts/src/preview/libs/getContextNodes.test.ts @@ -22,7 +22,10 @@ describe('Test on the merging result of a pair of settings', () => { icon: 'box' as const, title: 'Some Context', components: ['div'], - params: [{ name: 'T1', props: {} }, { name: 'T2', props: {} }], + params: [ + { name: 'T1', props: {} }, + { name: 'T2', props: {} }, + ], options: { cancelable: true, disable: true, @@ -32,7 +35,10 @@ describe('Test on the merging result of a pair of settings', () => { icon: 'box' as const, title: 'Some Context', components: ['span'], - params: [{ name: 'S1', props: {} }, { name: 'S2', props: {} }], + params: [ + { name: 'S1', props: {} }, + { name: 'S2', props: {} }, + ], options: { deep: true, disable: false, @@ -106,7 +112,10 @@ describe('Test on reconciliation of settings', () => { icon: 'box', nodeId: 'Some Context', options: { cancelable: false, deep: false, disable: false }, - params: [{ name: 'T1', props: {} }, { name: 'S2', props: {}, default: true }], + params: [ + { name: 'T1', props: {} }, + { name: 'S2', props: {}, default: true }, + ], title: 'Some Context', }, { diff --git a/addons/contexts/src/preview/libs/getPropsMap.test.ts b/addons/contexts/src/preview/libs/getPropsMap.test.ts index 130cba8df63..321d926e38b 100644 --- a/addons/contexts/src/preview/libs/getPropsMap.test.ts +++ b/addons/contexts/src/preview/libs/getPropsMap.test.ts @@ -2,7 +2,10 @@ import { _getPropsByParamName, getPropsMap } from './getPropsMap'; import { OPT_OUT } from '../../shared/constants'; describe('Test on behaviors from collecting the propsMap', () => { - const someParams = [{ name: 'A', props: {} }, { name: 'B', props: {} }]; + const someParams = [ + { name: 'A', props: {} }, + { name: 'B', props: {} }, + ]; it('should return "null" when params in 0 length', () => { const result = _getPropsByParamName([]); @@ -44,7 +47,10 @@ describe('Test on the integrity of the method to get the propMaps', () => { icon: 'box' as const, nodeId: 'Some Context', options: { cancelable: false, deep: false, disable: false }, - params: [{ name: 'A1', props: { a: 1 } }, { name: 'A2', props: { a: 2 }, default: true }], + params: [ + { name: 'A1', props: { a: 1 } }, + { name: 'A2', props: { a: 2 }, default: true }, + ], title: 'Some Context', }, { diff --git a/addons/cssresources/package.json b/addons/cssresources/package.json index 766c45e7823..d604b25772c 100644 --- a/addons/cssresources/package.json +++ b/addons/cssresources/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-cssresources", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "A storybook addon to switch between css resources at runtime for your story", "keywords": [ "addon", @@ -32,10 +32,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3" diff --git a/addons/design-assets/package.json b/addons/design-assets/package.json index dd57c2b0726..fbc3408b04f 100644 --- a/addons/design-assets/package.json +++ b/addons/design-assets/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-design-assets", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Design asset preview for storybook", "keywords": [ "addon", @@ -34,12 +34,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3", diff --git a/addons/docs/README.md b/addons/docs/README.md index 6008ed2cffb..ed73384d36f 100644 --- a/addons/docs/README.md +++ b/addons/docs/README.md @@ -47,7 +47,7 @@ Here's an example file: import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { Checkbox } from './Checkbox'; - + # Checkbox @@ -77,16 +77,16 @@ For more information on `MDX`, see the [`MDX` reference](./docs/mdx.md). Storybook Docs supports all view layers that Storybook supports except for React Native (currently). There are some framework-specific features as well, such as props tables and inline story rendering. This chart captures the current state of support: -| | React | Vue | Angular | HTML | [Web Components](./web-components) | Svelte | Polymer | Marko | Mithril | Riot | Ember | Preact | -| ----------------- | :---: | :---: | :-----: | :---: | :--------------------------------: | :----: | :-----: | :---: | :-----: | :---: | :---: | :----: | -| MDX stories | + | + | + | + | + | + | + | + | + | + | + | + | -| CSF stories | + | + | + | + | + | + | + | + | + | + | + | + | -| StoriesOf stories | + | + | + | + | + | + | + | + | + | + | + | + | -| Source | + | + | + | + | + | + | + | + | + | + | + | + | -| Notes / Info | + | + | + | + | + | + | + | + | + | + | + | + | -| Props table | + | + | # | | + | | | | | | | | -| Description | + | + | # | | + | | | | | | | | -| Inline stories | + | + | | | + | | | | | | | | +| | React | Vue | Angular | HTML | [Web Components](./web-components) | Svelte | Polymer | Marko | Mithril | Riot | Ember | Preact | +| ----------------- | :---: | :-: | :-----: | :--: | :--------------------------------: | :----: | :-----: | :---: | :-----: | :--: | :---: | :----: | +| MDX stories | + | + | + | + | + | + | + | + | + | + | + | + | +| CSF stories | + | + | + | + | + | + | + | + | + | + | + | + | +| StoriesOf stories | + | + | + | + | + | + | + | + | + | + | + | + | +| Source | + | + | + | + | + | + | + | + | + | + | + | + | +| Notes / Info | + | + | + | + | + | + | + | + | + | + | + | + | +| Props table | + | + | # | | + | | | | | | | | +| Description | + | + | # | | + | | | | | | | | +| Inline stories | + | + | | | + | | | | | | | | **Note:** `#` = WIP support @@ -109,11 +109,9 @@ yarn add -D react react-is babel-loader Then add the following to your `.storybook/presets.js` exports: ```js -module.exports = ['@storybook/addon-docs/react/preset']; +module.exports = ['@storybook/addon-docs/preset']; ``` -If you're not using `react`, replace it with your framework of choice corresponding to the Storybook package name, e.g. `angular` for `@storybook/angular` etc. - **Configure.** If you're migrating from an earlier version of Storybook and want to use `MDX`, you need to upgrade your Storybook config: ```js diff --git a/addons/docs/angular/README.md b/addons/docs/angular/README.md index 6a8de67eae4..3648eda1204 100644 --- a/addons/docs/angular/README.md +++ b/addons/docs/angular/README.md @@ -25,7 +25,7 @@ yarn add -D @storybook/addon-docs@next Then add the following to your `.storybook/presets.js` exports: ```js -module.exports = ['@storybook/addon-docs/angular/preset']; +module.exports = ['@storybook/addon-docs/preset']; ``` ## DocsPage diff --git a/addons/docs/angular/config.js b/addons/docs/angular/config.js deleted file mode 100644 index 52f6248698b..00000000000 --- a/addons/docs/angular/config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../dist/frameworks/angular/config'); diff --git a/addons/docs/docs/mdx.md b/addons/docs/docs/mdx.md index 8eb3ec708d9..fe8f4659213 100644 --- a/addons/docs/docs/mdx.md +++ b/addons/docs/docs/mdx.md @@ -25,7 +25,7 @@ Let's get started with an example that combines markdown with a single story: import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { Checkbox } from './Checkbox'; - + # Checkbox @@ -64,7 +64,7 @@ For example, here's the story from `Checkbox` example above, rewritten in CSF: ```js import React from 'react'; import { Checkbox } from './Checkbox'; -export default { title: "MDX|Checkbox" component: Checkbox }; +export default { title: "MDX/Checkbox" component: Checkbox }; export const allCheckboxes = () => (
@@ -86,7 +86,7 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { Badge } from './Badge'; import { Icon } from './Icon'; - + # Badge diff --git a/addons/docs/docs/recipes.md b/addons/docs/docs/recipes.md index d8074274392..79d33d802f0 100644 --- a/addons/docs/docs/recipes.md +++ b/addons/docs/docs/recipes.md @@ -66,7 +66,7 @@ import { SomeComponent } from 'path/to/SomeComponent'; I can define a story with the function imported from CSF: -{stories.basic} +{stories.basic()} And I can also embed arbitrary markdown & JSX in this file. diff --git a/addons/docs/package.json b/addons/docs/package.json index 07565121ce2..137f674408b 100644 --- a/addons/docs/package.json +++ b/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Superior documentation for your components", "keywords": [ "addon", @@ -23,6 +23,7 @@ "angular/**/*", "common/**/*", "html/**/*", + "postinstall/**/*", "react/**/*", "vue/**/*", "web-components/**/*", @@ -44,20 +45,28 @@ "@mdx-js/loader": "^1.1.0", "@mdx-js/mdx": "^1.1.0", "@mdx-js/react": "^1.0.27", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/router": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/postinstall": "5.3.0-beta.2", + "@storybook/router": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "acorn-walk": "^7.0.0", "core-js": "^3.0.1", "doctrine": "^3.0.0", + "escodegen": "^1.12.0", "global": "^4.3.2", + "html-tags": "^3.1.0", "js-string-escape": "^1.0.1", "lodash": "^4.17.15", "prop-types": "^15.7.2", - "storybook-addon-vue-info": "^1.2.1", - "ts-dedent": "^1.1.0" + "ts-dedent": "^1.1.0", + "util-deprecate": "^1.0.2", + "vue-docgen-api": "^3.26.0", + "vue-docgen-loader": "^1.0.1" }, "devDependencies": { "@types/doctrine": "^0.0.3", @@ -65,7 +74,8 @@ "@types/jest": "^24.0.11", "@types/prop-types": "^15.5.9", "@types/util-deprecate": "^1.0.0", - "@types/webpack-env": "^1.14.0" + "@types/webpack-env": "^1.14.0", + "jest-specific-snapshot": "^2.0.0" }, "peerDependencies": { "babel-loader": "^8.0.0", diff --git a/addons/docs/postinstall/presets.js b/addons/docs/postinstall/presets.js new file mode 100644 index 00000000000..a8feae9101e --- /dev/null +++ b/addons/docs/postinstall/presets.js @@ -0,0 +1,39 @@ +import fs from 'fs'; +import { presetsAddPreset, getFrameworks } from '@storybook/postinstall'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { logger } from '@storybook/node-logger'; + +export default function transformer(file, api) { + const packageJson = JSON.parse(fs.readFileSync('./package.json')); + const frameworks = getFrameworks(packageJson); + + let err = null; + let framework = null; + let presetOptions = null; + if (frameworks.length !== 1) { + err = `${frameworks.length === 0 ? 'No' : 'Multiple'} frameworks found: ${frameworks}`; + logger.error(`${err}, please configure '@storybook/addon-docs' manually.`); + return file.source; + } + + // eslint-disable-next-line prefer-destructuring + framework = frameworks[0]; + + const { dependencies, devDependencies } = packageJson; + if ( + framework === 'react' && + ((dependencies && dependencies['react-scripts']) || + (devDependencies && devDependencies['react-scripts'])) + ) { + presetOptions = { + configureJSX: true, + }; + } + + const j = api.jscodeshift; + const root = j(file.source); + + presetsAddPreset(`@storybook/addon-docs/preset`, presetOptions, { root, api }); + + return root.toSource({ quote: 'single' }); +} diff --git a/addons/docs/preset.js b/addons/docs/preset.js new file mode 100644 index 00000000000..a83f95279e7 --- /dev/null +++ b/addons/docs/preset.js @@ -0,0 +1 @@ +module.exports = require('./dist/preset'); diff --git a/addons/docs/src/blocks/Description.tsx b/addons/docs/src/blocks/Description.tsx index 5858bf8eba9..5fa8852a375 100644 --- a/addons/docs/src/blocks/Description.tsx +++ b/addons/docs/src/blocks/Description.tsx @@ -1,8 +1,8 @@ -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useContext } from 'react'; import { Description, DescriptionProps as PureDescriptionProps } from '@storybook/components'; import { DocsContext, DocsContextProps } from './DocsContext'; -import { Component, CURRENT_SELECTION } from './shared'; -import { str } from '../lib/docgenUtils'; +import { Component, CURRENT_SELECTION, DescriptionSlot } from './shared'; +import { str } from '../lib/docgen/utils'; export enum DescriptionType { INFO = 'info', @@ -16,24 +16,26 @@ type Notes = string | any; type Info = string | any; interface DescriptionProps { + slot?: DescriptionSlot; of?: '.' | Component; type?: DescriptionType; markdown?: string; + children?: string; } -export const getNotes = (notes?: Notes) => +const getNotes = (notes?: Notes) => notes && (typeof notes === 'string' ? notes : str(notes.markdown) || str(notes.text)); -export const getInfo = (info?: Info) => info && (typeof info === 'string' ? info : str(info.text)); +const getInfo = (info?: Info) => info && (typeof info === 'string' ? info : str(info.text)); const noDescription = (component?: Component): string | null => null; export const getDescriptionProps = ( - { of, type, markdown }: DescriptionProps, + { of, type, markdown, children }: DescriptionProps, { parameters }: DocsContextProps ): PureDescriptionProps => { - if (markdown) { - return { markdown }; + if (children || markdown) { + return { markdown: children || markdown }; } const { component, notes, info, docs } = parameters; const { extractComponentDescription = noDescription } = docs || {}; @@ -59,13 +61,19 @@ ${extractComponentDescription(target) || ''} } }; -const DescriptionContainer: FunctionComponent = props => ( - - {context => { - const { markdown } = getDescriptionProps(props, context); - return markdown && ; - }} - -); +const DescriptionContainer: FunctionComponent = props => { + const context = useContext(DocsContext); + const { slot } = props; + let { markdown } = getDescriptionProps(props, context); + if (slot) { + markdown = slot(markdown, context); + } + return markdown ? : null; +}; + +// since we are in the docs blocks, assume default description if for primary component story +DescriptionContainer.defaultProps = { + of: '.', +}; export { DescriptionContainer as Description }; diff --git a/addons/docs/src/blocks/DocsPage.test.ts b/addons/docs/src/blocks/DocsPage.test.ts new file mode 100644 index 00000000000..11294b76bb7 --- /dev/null +++ b/addons/docs/src/blocks/DocsPage.test.ts @@ -0,0 +1,18 @@ +import { defaultTitleSlot } from './Title'; + +describe('defaultTitleSlot', () => { + it('showRoots', () => { + const parameters = { + options: { showRoots: true }, + }; + expect(defaultTitleSlot({ selectedKind: 'a/b/c', parameters })).toBe('c'); + expect(defaultTitleSlot({ selectedKind: 'a|b', parameters })).toBe('a|b'); + expect(defaultTitleSlot({ selectedKind: 'a/b/c.d', parameters })).toBe('c.d'); + }); + it('no showRoots', () => { + const parameters = {}; + expect(defaultTitleSlot({ selectedKind: 'a/b/c', parameters })).toBe('c'); + expect(defaultTitleSlot({ selectedKind: 'a|b', parameters })).toBe('b'); + expect(defaultTitleSlot({ selectedKind: 'a/b/c.d', parameters })).toBe('d'); + }); +}); diff --git a/addons/docs/src/blocks/DocsPage.tsx b/addons/docs/src/blocks/DocsPage.tsx index 1187288d962..a19a7038867 100644 --- a/addons/docs/src/blocks/DocsPage.tsx +++ b/addons/docs/src/blocks/DocsPage.tsx @@ -1,140 +1,26 @@ import React, { FunctionComponent } from 'react'; - -import { parseKind } from '@storybook/router'; -import { DocsPage as PureDocsPage, PropsTable, PropsTableProps } from '@storybook/components'; -import { H2, H3 } from '@storybook/components/html'; -import { DocsContext } from './DocsContext'; +import { DocsPageProps } from './shared'; +import { Title } from './Title'; +import { Subtitle } from './Subtitle'; import { Description } from './Description'; -import { Story } from './Story'; -import { Preview } from './Preview'; -import { Anchor } from './Anchor'; -import { getPropsTableProps } from './Props'; - -export interface SlotContext { - id?: string; - selectedKind?: string; - selectedStory?: string; - parameters?: any; - storyStore?: any; -} - -export type StringSlot = (context: SlotContext) => string | void; -export type PropsSlot = (context: SlotContext) => PropsTableProps | void; -export type StorySlot = (stories: StoryData[], context: SlotContext) => DocsStoryProps | void; -export type StoriesSlot = (stories: StoryData[], context: SlotContext) => DocsStoryProps[] | void; - -export interface DocsPageProps { - titleSlot: StringSlot; - subtitleSlot: StringSlot; - descriptionSlot: StringSlot; - primarySlot: StorySlot; - propsSlot: PropsSlot; - storiesSlot: StoriesSlot; -} - -interface DocsStoryProps { - id: string; - name: string; - expanded?: boolean; - withToolbar?: boolean; - parameters?: any; -} - -interface StoryData { - id: string; - kind: string; - name: string; - parameters?: any; -} - -const defaultTitleSlot: StringSlot = ({ selectedKind, parameters }) => { - const { - hierarchyRootSeparator: rootSeparator, - hierarchySeparator: groupSeparator, - } = (parameters && parameters.options) || { - hierarchyRootSeparator: '|', - hierarchySeparator: /\/|\./, - }; - const { groups } = parseKind(selectedKind, { rootSeparator, groupSeparator }); - return (groups && groups[groups.length - 1]) || selectedKind; -}; - -const defaultSubtitleSlot: StringSlot = ({ parameters }) => - parameters && parameters.componentSubtitle; - -const defaultPropsSlot: PropsSlot = context => getPropsTableProps({ of: '.' }, context); - -const defaultDescriptionSlot: StringSlot = ({ parameters }) => { - const { component, docs } = parameters; - if (!component) { - return null; - } - const { extractComponentDescription } = docs || {}; - return extractComponentDescription && extractComponentDescription(component, parameters); -}; - -const defaultPrimarySlot: StorySlot = stories => stories && stories[0]; -const defaultStoriesSlot: StoriesSlot = stories => { - if (stories && stories.length > 1) { - const [first, ...rest] = stories; - return rest; - } - return null; -}; - -const StoriesHeading = H2; -const StoryHeading = H3; - -const DocsStory: FunctionComponent = ({ - id, - name, - expanded = true, - withToolbar = false, - parameters, -}) => ( - - {expanded && {(parameters && parameters.displayName) || name}} - {expanded && parameters && parameters.docs && parameters.docs.storyDescription && ( - - )} - - - - -); +import { Primary } from './Primary'; +import { Props } from './Props'; +import { Stories } from './Stories'; export const DocsPage: FunctionComponent = ({ - titleSlot = defaultTitleSlot, - subtitleSlot = defaultSubtitleSlot, - descriptionSlot = defaultDescriptionSlot, - primarySlot = defaultPrimarySlot, - propsSlot = defaultPropsSlot, - storiesSlot = defaultStoriesSlot, + titleSlot, + subtitleSlot, + descriptionSlot, + primarySlot, + propsSlot, + storiesSlot, }) => ( - - {context => { - const title = titleSlot(context) || ''; - const subtitle = subtitleSlot(context) || ''; - const description = descriptionSlot(context) || ''; - const propsTableProps = propsSlot(context); - - const { selectedKind, storyStore } = context; - const componentStories = storyStore - .getStoriesForKind(selectedKind) - .filter((s: any) => !(s.parameters && s.parameters.docs && s.parameters.docs.disable)); - const primary = primarySlot(componentStories, context); - const stories = storiesSlot(componentStories, context); - - return ( - - - {primary && } - {propsTableProps && } - {stories && stories.length > 0 && Stories} - {stories && - stories.map(story => story && )} - - ); - }} - + <> + + <Subtitle slot={subtitleSlot} /> + <Description slot={descriptionSlot} /> + <Primary slot={primarySlot} /> + <Props slot={propsSlot} /> + <Stories slot={storiesSlot} /> + </> ); diff --git a/addons/docs/src/blocks/DocsStory.tsx b/addons/docs/src/blocks/DocsStory.tsx new file mode 100644 index 00000000000..ca6640ad183 --- /dev/null +++ b/addons/docs/src/blocks/DocsStory.tsx @@ -0,0 +1,25 @@ +import React, { FunctionComponent } from 'react'; +import { Subheading } from './Subheading'; +import { DocsStoryProps } from './shared'; +import { Anchor } from './Anchor'; +import { Description } from './Description'; +import { Story } from './Story'; +import { Preview } from './Preview'; + +export const DocsStory: FunctionComponent<DocsStoryProps> = ({ + id, + name, + expanded = true, + withToolbar = false, + parameters, +}) => ( + <Anchor storyId={id}> + {expanded && <Subheading>{name}</Subheading>} + {expanded && parameters && parameters.docs && parameters.docs.storyDescription && ( + <Description markdown={parameters.docs.storyDescription} /> + )} + <Preview withToolbar={withToolbar}> + <Story id={id} /> + </Preview> + </Anchor> +); diff --git a/addons/docs/src/blocks/Heading.tsx b/addons/docs/src/blocks/Heading.tsx new file mode 100644 index 00000000000..13aefc91fe6 --- /dev/null +++ b/addons/docs/src/blocks/Heading.tsx @@ -0,0 +1,7 @@ +import React, { FunctionComponent } from 'react'; +import { H2 } from '@storybook/components/html'; + +interface HeadingProps { + children: JSX.Element | string; +} +export const Heading: FunctionComponent<HeadingProps> = ({ children }) => <H2>{children}</H2>; diff --git a/addons/docs/src/blocks/Primary.tsx b/addons/docs/src/blocks/Primary.tsx new file mode 100644 index 00000000000..fe2b764fcaa --- /dev/null +++ b/addons/docs/src/blocks/Primary.tsx @@ -0,0 +1,16 @@ +import React, { useContext, FunctionComponent } from 'react'; +import { DocsContext } from './DocsContext'; +import { DocsStory } from './DocsStory'; +import { getDocsStories } from './utils'; +import { StorySlot } from './shared'; + +interface PrimaryProps { + slot?: StorySlot; +} + +export const Primary: FunctionComponent<PrimaryProps> = ({ slot }) => { + const context = useContext(DocsContext); + const componentStories = getDocsStories(context); + const story = slot ? slot(componentStories, context) : componentStories && componentStories[0]; + return story ? <DocsStory {...story} expanded={false} withToolbar /> : null; +}; diff --git a/addons/docs/src/blocks/Props.tsx b/addons/docs/src/blocks/Props.tsx index 1656af59904..48a31a9ff22 100644 --- a/addons/docs/src/blocks/Props.tsx +++ b/addons/docs/src/blocks/Props.tsx @@ -1,15 +1,28 @@ -import React, { FunctionComponent } from 'react'; -import { PropsTable, PropsTableError, PropsTableProps } from '@storybook/components'; -import { DocsContext, DocsContextProps } from './DocsContext'; -import { Component, CURRENT_SELECTION } from './shared'; +import React, { FunctionComponent, useContext } from 'react'; +import { isNil } from 'lodash'; -import { PropsExtractor } from '../lib/docgenUtils'; +import { + PropsTable, + PropsTableError, + PropsTableProps, + PropDef, + TabsState, +} from '@storybook/components'; +import { DocsContext, DocsContextProps } from './DocsContext'; +import { Component, PropsSlot, CURRENT_SELECTION } from './shared'; +import { getComponentName } from './utils'; + +import { PropsExtractor } from '../lib/docgen/types'; import { extractProps as reactExtractProps } from '../frameworks/react/extractProps'; import { extractProps as vueExtractProps } from '../frameworks/vue/extractProps'; interface PropsProps { exclude?: string[]; - of: '.' | Component; + of?: '.' | Component; + components?: { + [label: string]: Component; + }; + slot?: PropsSlot; } // FIXME: remove in SB6.0 & require config @@ -24,36 +37,97 @@ const inferPropsExtractor = (framework: string): PropsExtractor | null => { } }; -export const getPropsTableProps = ( - { exclude, of }: PropsProps, +export const getComponentProps = ( + component: Component, + { exclude }: PropsProps, { parameters }: DocsContextProps ): PropsTableProps => { + if (!component) { + return null; + } try { const params = parameters || {}; - const { component, framework = null } = params; - - const target = of === CURRENT_SELECTION ? component : of; - if (!target) { - throw new Error(PropsTableError.NO_COMPONENT); - } + const { framework = null } = params; const { extractProps = inferPropsExtractor(framework) } = params.docs || {}; if (!extractProps) { throw new Error(PropsTableError.PROPS_UNSUPPORTED); } - return extractProps(target, { exclude }); + let { rows } = extractProps(component); + if (!isNil(exclude)) { + rows = rows.filter((row: PropDef) => !exclude.includes(row.name)); + } + + return { rows }; } catch (err) { return { error: err.message }; } }; -const PropsContainer: FunctionComponent<PropsProps> = props => ( - <DocsContext.Consumer> - {context => { - const propsTableProps = getPropsTableProps(props, context); - return <PropsTable {...propsTableProps} />; - }} - </DocsContext.Consumer> -); +export const getComponent = (props: PropsProps = {}, context: DocsContextProps): Component => { + const { of } = props; + const { parameters = {} } = context; + const { component } = parameters; + + const target = of === CURRENT_SELECTION ? component : of; + if (!target) { + if (of === CURRENT_SELECTION) { + return null; + } + throw new Error(PropsTableError.NO_COMPONENT); + } + return target; +}; + +const PropsContainer: FunctionComponent<PropsProps> = props => { + const context = useContext(DocsContext); + const { slot, components } = props; + const { + parameters: { subcomponents }, + } = context; + + let allComponents = components; + if (!allComponents) { + const main = getComponent(props, context); + const mainLabel = getComponentName(main); + const mainProps = slot ? slot(context, main) : getComponentProps(main, props, context); + + if (!subcomponents || typeof subcomponents !== 'object') { + return mainProps && <PropsTable {...mainProps} />; + } + + allComponents = { [mainLabel]: main, ...subcomponents }; + } + + const tabs: { label: string; table: PropsTableProps }[] = []; + Object.entries(allComponents).forEach(([label, component]) => { + tabs.push({ + label, + table: slot ? slot(context, component) : getComponentProps(component, props, context), + }); + }); + + return ( + <TabsState> + {tabs.map(({ label, table }) => { + if (!table) { + return null; + } + const id = `prop_table_div_${label}`; + return ( + <div key={id} id={id} title={label}> + {({ active }: { active: boolean }) => + active ? <PropsTable key={`prop_table_${label}`} {...table} /> : null + } + </div> + ); + })} + </TabsState> + ); +}; + +PropsContainer.defaultProps = { + of: '.', +}; export { PropsContainer as Props }; diff --git a/addons/docs/src/blocks/Stories.tsx b/addons/docs/src/blocks/Stories.tsx new file mode 100644 index 00000000000..c1b585e82db --- /dev/null +++ b/addons/docs/src/blocks/Stories.tsx @@ -0,0 +1,33 @@ +import React, { useContext, FunctionComponent } from 'react'; +import { DocsContext } from './DocsContext'; +import { DocsStory } from './DocsStory'; +import { Heading } from './Heading'; +import { getDocsStories } from './utils'; +import { StoriesSlot, DocsStoryProps } from './shared'; + +interface StoriesProps { + slot?: StoriesSlot; + title?: JSX.Element | string; +} + +export const Stories: FunctionComponent<StoriesProps> = ({ slot, title }) => { + const context = useContext(DocsContext); + const componentStories = getDocsStories(context); + + const stories: DocsStoryProps[] = slot + ? slot(componentStories, context) + : componentStories && componentStories.slice(1); + if (!stories) { + return null; + } + return ( + <> + <Heading>{title}</Heading> + {stories.map(story => story && <DocsStory key={story.id} {...story} expanded />)} + </> + ); +}; + +Stories.defaultProps = { + title: 'Stories', +}; diff --git a/addons/docs/src/blocks/Subheading.tsx b/addons/docs/src/blocks/Subheading.tsx new file mode 100644 index 00000000000..0cda996ffc2 --- /dev/null +++ b/addons/docs/src/blocks/Subheading.tsx @@ -0,0 +1,7 @@ +import React, { FunctionComponent } from 'react'; +import { H3 } from '@storybook/components/html'; + +interface SubheadingProps { + children: JSX.Element | string; +} +export const Subheading: FunctionComponent<SubheadingProps> = ({ children }) => <H3>{children}</H3>; diff --git a/addons/docs/src/blocks/Subtitle.tsx b/addons/docs/src/blocks/Subtitle.tsx new file mode 100644 index 00000000000..595bac6452f --- /dev/null +++ b/addons/docs/src/blocks/Subtitle.tsx @@ -0,0 +1,19 @@ +import React, { useContext, FunctionComponent } from 'react'; +import { Subtitle as PureSubtitle } from '@storybook/components'; +import { DocsContext } from './DocsContext'; +import { StringSlot } from './shared'; + +interface SubtitleProps { + slot?: StringSlot; + children?: JSX.Element | string; +} + +export const Subtitle: FunctionComponent<SubtitleProps> = ({ slot, children }) => { + const context = useContext(DocsContext); + const { parameters } = context; + let text: JSX.Element | string = children; + if (!text) { + text = slot ? slot(context) : parameters && parameters.componentSubtitle; + } + return text ? <PureSubtitle className="sbdocs-subtitle">{text}</PureSubtitle> : null; +}; diff --git a/addons/docs/src/blocks/Title.tsx b/addons/docs/src/blocks/Title.tsx new file mode 100644 index 00000000000..a670600d6e2 --- /dev/null +++ b/addons/docs/src/blocks/Title.tsx @@ -0,0 +1,48 @@ +import React, { useContext, FunctionComponent } from 'react'; +import { parseKind } from '@storybook/router'; +import { Title as PureTitle } from '@storybook/components'; +import { DocsContext } from './DocsContext'; +import { StringSlot } from './shared'; + +interface TitleProps { + slot?: StringSlot; + children?: JSX.Element | string; +} +export const defaultTitleSlot: StringSlot = ({ selectedKind, parameters }) => { + const { + showRoots, + hierarchyRootSeparator: rootSeparator, + hierarchySeparator: groupSeparator, + } = (parameters && parameters.options) || { + showRoots: undefined, + hierarchyRootSeparator: '|', + hierarchySeparator: /\/|\./, + }; + + let groups; + if (typeof showRoots !== 'undefined') { + groups = selectedKind.split('/'); + } else { + // This covers off all the remaining cases: + // - If the separators were set above, we should use them + // - If they weren't set, we should only should use the old defaults if the kind contains '.' or '|', + // which for this particular splitting is the only case in which it actually matters. + ({ groups } = parseKind(selectedKind, { rootSeparator, groupSeparator })); + } + + return (groups && groups[groups.length - 1]) || selectedKind; +}; + +export const Title: FunctionComponent<TitleProps> = ({ slot, children }) => { + const context = useContext(DocsContext); + const { selectedKind, parameters } = context; + let text: JSX.Element | string = children; + if (!text) { + if (slot) { + text = slot(context); + } else { + text = defaultTitleSlot({ selectedKind, parameters }); + } + } + return text ? <PureTitle className="sbdocs-title">{text}</PureTitle> : null; +}; diff --git a/addons/docs/src/blocks/index.ts b/addons/docs/src/blocks/index.ts index 4e68cf50276..e4afb011602 100644 --- a/addons/docs/src/blocks/index.ts +++ b/addons/docs/src/blocks/index.ts @@ -5,12 +5,21 @@ export * from './Description'; export * from './DocsContext'; export * from './DocsPage'; export * from './DocsContainer'; +export * from './DocsStory'; +export * from './Heading'; export * from './Meta'; export * from './Preview'; +export * from './Primary'; export * from './Props'; export * from './Source'; +export * from './Stories'; export * from './Story'; +export * from './Subheading'; +export * from './Subtitle'; +export * from './Title'; export * from './Wrapper'; +export * from './shared'; + // helper function for MDX export const makeStoryFn = (val: any) => (typeof val === 'function' ? val : () => val); diff --git a/addons/docs/src/blocks/shared.ts b/addons/docs/src/blocks/shared.ts index 61d2a7f93f5..baab2861c30 100644 --- a/addons/docs/src/blocks/shared.ts +++ b/addons/docs/src/blocks/shared.ts @@ -1,2 +1,41 @@ +import { PropsTableProps } from '@storybook/components'; + export const CURRENT_SELECTION = '.'; + export type Component = any; + +export interface StoryData { + id?: string; + kind?: string; + name?: string; + parameters?: any; +} + +export type DocsStoryProps = StoryData & { + expanded?: boolean; + withToolbar?: boolean; +}; + +export interface SlotContext { + id?: string; + selectedKind?: string; + selectedStory?: string; + parameters?: any; + storyStore?: any; +} + +export type StringSlot = (context: SlotContext) => string; +export type DescriptionSlot = (description: string, context: SlotContext) => string; +export type PropsSlot = (context: SlotContext, component: Component) => PropsTableProps; +export type StorySlot = (stories: StoryData[], context: SlotContext) => DocsStoryProps; + +export type StoriesSlot = (stories: StoryData[], context: SlotContext) => DocsStoryProps[]; + +export interface DocsPageProps { + titleSlot?: StringSlot; + subtitleSlot?: StringSlot; + descriptionSlot?: DescriptionSlot; + primarySlot?: StorySlot; + propsSlot?: PropsSlot; + storiesSlot?: StoriesSlot; +} diff --git a/addons/docs/src/blocks/utils.ts b/addons/docs/src/blocks/utils.ts new file mode 100644 index 00000000000..316c6bae4a9 --- /dev/null +++ b/addons/docs/src/blocks/utils.ts @@ -0,0 +1,34 @@ +/* eslint-disable no-underscore-dangle */ +import { DocsContextProps } from './DocsContext'; +import { StoryData, Component } from './shared'; + +export const getDocsStories = (context: DocsContextProps): StoryData[] => { + const { storyStore, selectedKind } = context; + return storyStore + .getStoriesForKind(selectedKind) + .filter((s: any) => !(s.parameters && s.parameters.docs && s.parameters.docs.disable)); +}; + +const titleCase = (str: string): string => + str + .split('-') + .map(part => part.charAt(0).toUpperCase() + part.slice(1)) + .join(''); + +export const getComponentName = (component: Component): string => { + if (!component) { + return undefined; + } + + if (typeof component === 'string') { + if (component.includes('-')) { + return titleCase(component); + } + return component; + } + if (component.__docgenInfo && component.__docgenInfo.displayName) { + return component.__docgenInfo.displayName; + } + + return component.name; +}; diff --git a/addons/docs/src/frameworks/angular/compodoc.ts b/addons/docs/src/frameworks/angular/compodoc.ts index a8997ff0c11..319e50c781e 100644 --- a/addons/docs/src/frameworks/angular/compodoc.ts +++ b/addons/docs/src/frameworks/angular/compodoc.ts @@ -104,10 +104,10 @@ export const extractProps = (component: Component) => { data.forEach((item: Method | Property) => { const sectionItem: PropDef = { name: item.name, - type: { name: isMethod(item) ? displaySignature(item) : item.type }, + type: { summary: isMethod(item) ? displaySignature(item) : item.type }, required: isMethod(item) ? false : !item.optional, description: item.description, - defaultValue: isMethod(item) ? '' : item.defaultValue, + defaultValue: { summary: isMethod(item) ? '' : item.defaultValue }, }; const section = mapItemToSection(key, item); diff --git a/addons/docs/src/frameworks/common/config.js b/addons/docs/src/frameworks/common/config.ts similarity index 100% rename from addons/docs/src/frameworks/common/config.js rename to addons/docs/src/frameworks/common/config.ts diff --git a/addons/docs/src/frameworks/common/index.ts b/addons/docs/src/frameworks/common/index.ts index 20a01c967ea..3de17860d84 100644 --- a/addons/docs/src/frameworks/common/index.ts +++ b/addons/docs/src/frameworks/common/index.ts @@ -1 +1 @@ -export * from '../../lib/docgenUtils'; +export * from '../../lib/docgen'; diff --git a/addons/docs/src/frameworks/common/makePreset.ts b/addons/docs/src/frameworks/common/makePreset.ts index 420144b5ef4..08654c15063 100644 --- a/addons/docs/src/frameworks/common/makePreset.ts +++ b/addons/docs/src/frameworks/common/makePreset.ts @@ -1,25 +1,17 @@ -import fs from 'fs'; -import * as common from './preset'; +import deprecate from 'util-deprecate'; +import dedent from 'ts-dedent'; +import * as common from '../../preset'; const makePreset = (framework: string) => { - const docsConfig = [`${__dirname}/config.js`]; - const frameworkConfig = `${__dirname}/../../../dist/frameworks/${framework}/config.js`; - if (fs.existsSync(frameworkConfig)) { - docsConfig.push(frameworkConfig); - } - function config(entry: any[] = []) { - return [...docsConfig, ...entry]; - } + deprecate( + () => {}, + dedent` + Framework-specific presets are no longer-needed as of Storybook 5.3 and will be removed in 6.0. - const configureJSX = framework !== 'react'; - const webpack = (webpackConfig: any, options: any) => - common.webpack(webpackConfig, { configureJSX, ...options }); - - return { - ...common, - webpack, - config, - }; + Please use '@storybook/addon-docs/preset' instead of '@storybook/addon-docs/${framework}/preset'. + ` + )(); + return common; }; export default makePreset; diff --git a/addons/docs/src/frameworks/common/preset.ts b/addons/docs/src/frameworks/common/preset.ts index 9566d365f16..002e5555f28 100644 --- a/addons/docs/src/frameworks/common/preset.ts +++ b/addons/docs/src/frameworks/common/preset.ts @@ -20,7 +20,11 @@ export function webpack(webpackConfig: any = {}, options: any = {}) { const { module = {} } = webpackConfig; // it will reuse babel options that are already in use in storybook // also, these babel options are chained with other presets. - const { babelOptions, configureJSX, sourceLoaderOptions = {} } = options; + const { + babelOptions, + configureJSX = options.framework !== 'react', // if not user-specified + sourceLoaderOptions = {}, + } = options; // set `sourceLoaderOptions` to `null` to disable for manual configuration const sourceLoader = sourceLoaderOptions @@ -34,7 +38,7 @@ export function webpack(webpackConfig: any = {}, options: any = {}) { ] : []; - return { + const result = { ...webpackConfig, module: { ...module, @@ -72,8 +76,20 @@ export function webpack(webpackConfig: any = {}, options: any = {}) { ], }, }; + return result; } -export function addons(entry: any[] = []) { +export function addons(entry: any[] = [], options: any) { return [...entry, require.resolve('../../register')]; } + +export function config(entry: any[] = [], options: any = {}) { + const { framework } = options; + const docsConfig = [require.resolve('./config')]; + try { + docsConfig.push(require.resolve(`../${framework}/config`)); + } catch (err) { + // there is no custom config for the user's framework, do nothing + } + return [...docsConfig, ...entry]; +} diff --git a/addons/docs/src/frameworks/react/config.ts b/addons/docs/src/frameworks/react/config.ts index 765e2813e98..11c34986a0a 100644 --- a/addons/docs/src/frameworks/react/config.ts +++ b/addons/docs/src/frameworks/react/config.ts @@ -2,7 +2,7 @@ import { addParameters } from '@storybook/client-api'; import { StoryFn } from '@storybook/addons'; import { extractProps } from './extractProps'; -import { extractComponentDescription } from '../../lib/docgenUtils'; +import { extractComponentDescription } from '../../lib/docgen'; addParameters({ docs: { diff --git a/addons/docs/src/frameworks/react/extractProps.ts b/addons/docs/src/frameworks/react/extractProps.ts index 02da95bfb41..73a2e116ad9 100644 --- a/addons/docs/src/frameworks/react/extractProps.ts +++ b/addons/docs/src/frameworks/react/extractProps.ts @@ -1,12 +1,9 @@ import PropTypes from 'prop-types'; import { isForwardRef, isMemo } from 'react-is'; import { PropDef } from '@storybook/components'; -import { - PropDefGetter, - PropsExtractor, - extractPropsFromDocgen, - hasDocgen, -} from '../../lib/docgenUtils'; +import { hasDocgen, extractPropsFromDocgen, PropsExtractor, TypeSystem } from '../../lib/docgen'; +import { Component } from '../../blocks/shared'; +import { enhancePropTypesProps } from './propTypes/handleProp'; export interface PropDefMap { [p: string]: PropDef; @@ -22,21 +19,30 @@ Object.keys(PropTypes).forEach(typeName => { propTypesMap.set(type.isRequired, typeName); }); -export const getPropDefs: PropDefGetter = (type, section) => { - let processedType = type; +function getPropDefs(component: Component, section: string): PropDef[] { + let processedComponent = component; // eslint-disable-next-line react/forbid-foreign-prop-types - if (!hasDocgen(type) && !type.propTypes) { - if (isForwardRef(type) || type.render) { - processedType = type.render().type; + if (!hasDocgen(component) && !component.propTypes) { + if (isForwardRef(component) || component.render) { + processedComponent = component.render().type; } - if (isMemo(type)) { - processedType = type.type().type; + if (isMemo(component)) { + processedComponent = component.type().type; } } - return extractPropsFromDocgen(processedType, section); -}; + const extractedProps = extractPropsFromDocgen(processedComponent, section); + if (extractedProps.length === 0) { + return []; + } + + if (extractedProps[0].typeSystem === TypeSystem.JAVASCRIPT) { + return enhancePropTypesProps(extractedProps, component); + } + + return extractedProps.map(x => x.propDef); +} export const extractProps: PropsExtractor = component => ({ rows: getPropDefs(component, 'props'), diff --git a/addons/docs/src/frameworks/react/inspection/acornParser.test.ts b/addons/docs/src/frameworks/react/inspection/acornParser.test.ts new file mode 100644 index 00000000000..ad10948e687 --- /dev/null +++ b/addons/docs/src/frameworks/react/inspection/acornParser.test.ts @@ -0,0 +1,199 @@ +import { parse } from './acornParser'; +import { + InspectionType, + InspectionElement, + InspectionObject, + InspectionArray, + InspectionIdentifier, + InspectionLiteral, + InspectionFunction, + InspectionUnknown, +} from './types'; + +describe('parse', () => { + describe('expression', () => { + it('support HTML element', () => { + const result = parse('<div>Hello!</div>'); + const inferedType = result.inferedType as InspectionElement; + + expect(inferedType.type).toBe(InspectionType.ELEMENT); + expect(inferedType.identifier).toBe('div'); + expect(result.ast).toBeDefined(); + }); + + it('support React declaration', () => { + const result = parse('<FunctionalComponent />'); + const inferedType = result.inferedType as InspectionElement; + + expect(inferedType.type).toBe(InspectionType.ELEMENT); + expect(inferedType.identifier).toBe('FunctionalComponent'); + expect(result.ast).toBeDefined(); + }); + + it('support anonymous functional React component', () => { + const result = parse('() => { return <div>Hey!</div>; }'); + const inferedType = result.inferedType as InspectionElement; + + expect(inferedType.type).toBe(InspectionType.ELEMENT); + expect(inferedType.identifier).toBeUndefined(); + expect(result.ast).toBeDefined(); + }); + + it('support named functional React component', () => { + const result = parse('function NamedFunctionalComponent() { return <div>Hey!</div>; }'); + const inferedType = result.inferedType as InspectionElement; + + expect(inferedType.type).toBe(InspectionType.ELEMENT); + expect(inferedType.identifier).toBe('NamedFunctionalComponent'); + expect(result.ast).toBeDefined(); + }); + + it('support class React component', () => { + const result = parse(` + class ClassComponent extends React.PureComponent { + render() { + return <div>Hey!</div>; + } + }`); + const inferedType = result.inferedType as InspectionElement; + + expect(inferedType.type).toBe(InspectionType.ELEMENT); + expect(inferedType.identifier).toBe('ClassComponent'); + expect(result.ast).toBeDefined(); + }); + + it('support PropTypes.shape', () => { + const result = parse('PropTypes.shape({ foo: PropTypes.string })'); + const inferedType = result.inferedType as InspectionObject; + + expect(inferedType.type).toBe(InspectionType.OBJECT); + expect(result.ast).toBeDefined(); + }); + + it('support shape', () => { + const result = parse('shape({ foo: PropTypes.string })'); + const inferedType = result.inferedType as InspectionObject; + + expect(inferedType.type).toBe(InspectionType.OBJECT); + expect(result.ast).toBeDefined(); + }); + + it('support single prop object literal', () => { + const result = parse('{ foo: PropTypes.string }'); + const inferedType = result.inferedType as InspectionObject; + + expect(inferedType.type).toBe(InspectionType.OBJECT); + expect(result.ast).toBeDefined(); + }); + + it('support multi prop object literal', () => { + const result = parse(` + { + foo: PropTypes.string, + bar: PropTypes.string + }`); + const inferedType = result.inferedType as InspectionObject; + + expect(inferedType.type).toBe(InspectionType.OBJECT); + expect(result.ast).toBeDefined(); + }); + + it('support required prop', () => { + const result = parse('{ foo: PropTypes.string.isRequired }'); + const inferedType = result.inferedType as InspectionObject; + + expect(inferedType.type).toBe(InspectionType.OBJECT); + expect(result.ast).toBeDefined(); + }); + + it('support array', () => { + const result = parse("['bottom-left', 'botton-center', 'bottom-right']"); + const inferedType = result.inferedType as InspectionArray; + + expect(inferedType.type).toBe(InspectionType.ARRAY); + expect(result.ast).toBeDefined(); + }); + + it('support object identifier', () => { + const result = parse('NAMED_OBJECT'); + const inferedType = result.inferedType as InspectionIdentifier; + + expect(inferedType.type).toBe(InspectionType.IDENTIFIER); + expect(inferedType.identifier).toBe('NAMED_OBJECT'); + expect(result.ast).toBeDefined(); + }); + + it('support anonymous function', () => { + const result = parse('() => {}'); + const inferedType = result.inferedType as InspectionFunction; + + expect(inferedType.type).toBe(InspectionType.FUNCTION); + expect(inferedType.identifier).toBeUndefined(); + expect(inferedType.hasArguments).toBeFalsy(); + expect(result.ast).toBeDefined(); + }); + + it('support anonymous function with arguments', () => { + const result = parse('(a, b) => {}'); + const inferedType = result.inferedType as InspectionFunction; + + expect(inferedType.type).toBe(InspectionType.FUNCTION); + expect(inferedType.identifier).toBeUndefined(); + expect(inferedType.hasArguments).toBeTruthy(); + expect(result.ast).toBeDefined(); + }); + + it('support named function', () => { + const result = parse('function concat() {}'); + const inferedType = result.inferedType as InspectionFunction; + + expect(inferedType.type).toBe(InspectionType.FUNCTION); + expect(inferedType.identifier).toBe('concat'); + expect(inferedType.hasArguments).toBeFalsy(); + expect(result.ast).toBeDefined(); + }); + + it('support named function with arguments', () => { + const result = parse('function concat(a, b) {}'); + const inferedType = result.inferedType as InspectionFunction; + + expect(inferedType.type).toBe(InspectionType.FUNCTION); + expect(inferedType.identifier).toBe('concat'); + expect(inferedType.hasArguments).toBeTruthy(); + expect(result.ast).toBeDefined(); + }); + + it('support class', () => { + const result = parse('class Foo {}'); + const inferedType = result.inferedType as InspectionFunction; + + expect(inferedType.type).toBe(InspectionType.CLASS); + expect(inferedType.identifier).toBe('Foo'); + expect(result.ast).toBeDefined(); + }); + + [ + { name: 'string', value: "'string value'" }, + { name: 'numeric', value: '1' }, + { name: 'boolean (true)', value: 'true' }, + { name: 'boolean (false)', value: 'false' }, + { name: 'null', value: 'null' }, + ].forEach(x => { + it(`support ${x.name}`, () => { + const result = parse(x.value); + const inferedType = result.inferedType as InspectionLiteral; + + expect(inferedType.type).toBe(InspectionType.LITERAL); + expect(result.ast).toBeDefined(); + }); + }); + + it("returns Unknown when it's not supported", () => { + const result = parse("Symbol('foo')"); + const inferedType = result.inferedType as InspectionUnknown; + + expect(inferedType.type).toBe(InspectionType.UNKNOWN); + expect(result.ast).toBeDefined(); + }); + }); +}); diff --git a/addons/docs/src/frameworks/react/inspection/acornParser.ts b/addons/docs/src/frameworks/react/inspection/acornParser.ts new file mode 100644 index 00000000000..bd845993a88 --- /dev/null +++ b/addons/docs/src/frameworks/react/inspection/acornParser.ts @@ -0,0 +1,211 @@ +import { Parser } from 'acorn'; +// @ts-ignore +import jsx from 'acorn-jsx'; +import { isNil } from 'lodash'; +import estree from 'estree'; +// @ts-ignore +import * as acornWalk from 'acorn-walk'; +import { + InspectionType, + InspectionInferedType, + InspectionLiteral, + InspectionElement, + InspectionFunction, + InspectionClass, + InspectionObject, + InspectionUnknown, + InspectionIdentifier, + InspectionArray, +} from './types'; + +interface ParsingResult<T> { + inferedType: T; + ast: any; +} + +const ACORN_WALK_VISITORS = { + ...acornWalk.base, + JSXElement: () => {}, +}; + +const acornParser = Parser.extend(jsx()); + +// Cannot use "estree.Identifier" type because this function also support "JSXIdentifier". +function extractIdentifierName(identifierNode: any) { + return !isNil(identifierNode) ? identifierNode.name : null; +} + +function parseIdentifier(identifierNode: estree.Identifier): ParsingResult<InspectionIdentifier> { + return { + inferedType: { + type: InspectionType.IDENTIFIER, + identifier: extractIdentifierName(identifierNode), + }, + ast: identifierNode, + }; +} + +function parseLiteral(literalNode: estree.Literal): ParsingResult<InspectionLiteral> { + return { + inferedType: { type: InspectionType.LITERAL }, + ast: literalNode, + }; +} + +function parseFunction( + funcNode: estree.FunctionExpression | estree.ArrowFunctionExpression +): ParsingResult<InspectionFunction | InspectionElement> { + let innerJsxElementNode; + + // If there is at least a JSXElement in the body of the function, then it's a React component. + acornWalk.simple( + funcNode.body, + { + JSXElement(node: any) { + innerJsxElementNode = node; + }, + }, + ACORN_WALK_VISITORS + ); + + const isJsx = !isNil(innerJsxElementNode); + + const inferedType: InspectionFunction | InspectionElement = { + type: isJsx ? InspectionType.ELEMENT : InspectionType.FUNCTION, + hasArguments: funcNode.params.length !== 0, + }; + + const identifierName = extractIdentifierName((funcNode as estree.FunctionExpression).id); + if (!isNil(identifierName)) { + inferedType.identifier = identifierName; + } + + return { + inferedType, + ast: funcNode, + }; +} + +function parseClass( + classNode: estree.ClassExpression +): ParsingResult<InspectionClass | InspectionElement> { + let innerJsxElementNode; + + // If there is at least a JSXElement in the body of the class, then it's a React component. + acornWalk.simple( + classNode.body, + { + JSXElement(node: any) { + innerJsxElementNode = node; + }, + }, + ACORN_WALK_VISITORS + ); + + const inferedType: any = { + type: !isNil(innerJsxElementNode) ? InspectionType.ELEMENT : InspectionType.CLASS, + identifier: extractIdentifierName(classNode.id), + }; + + return { + inferedType, + ast: classNode, + }; +} + +function parseJsxElement(jsxElementNode: any): ParsingResult<InspectionElement> { + const inferedType: InspectionElement = { + type: InspectionType.ELEMENT, + }; + + const identifierName = extractIdentifierName(jsxElementNode.openingElement.name); + if (!isNil(identifierName)) { + inferedType.identifier = identifierName; + } + + return { + inferedType, + ast: jsxElementNode, + }; +} + +function parseCall(callNode: estree.CallExpression): ParsingResult<InspectionObject> { + const identifierNode = + callNode.callee.type === 'MemberExpression' ? callNode.callee.property : callNode.callee; + + const identifierName = extractIdentifierName(identifierNode); + if (identifierName === 'shape') { + return { + inferedType: { type: InspectionType.OBJECT }, + ast: callNode.arguments[0], + }; + } + + return null; +} + +function parseObject(objectNode: estree.ObjectExpression): ParsingResult<InspectionObject> { + return { + inferedType: { type: InspectionType.OBJECT }, + ast: objectNode, + }; +} + +function parseArray(arrayNode: estree.ArrayExpression): ParsingResult<InspectionArray> { + return { + inferedType: { type: InspectionType.ARRAY }, + ast: arrayNode, + }; +} + +// Cannot set "expression" type to "estree.Expression" because the type doesn't include JSX. +function parseExpression(expression: any): ParsingResult<InspectionInferedType> { + switch (expression.type) { + case 'Identifier': + return parseIdentifier(expression); + case 'Literal': + return parseLiteral(expression); + case 'FunctionExpression': + case 'ArrowFunctionExpression': + return parseFunction(expression); + case 'ClassExpression': + return parseClass(expression); + case 'JSXElement': + return parseJsxElement(expression); + case 'CallExpression': + return parseCall(expression); + case 'ObjectExpression': + return parseObject(expression); + case 'ArrayExpression': + return parseArray(expression); + default: + return null; + } +} + +export function parse(value: string): ParsingResult<InspectionInferedType> { + const ast = (acornParser.parse(`(${value})`) as unknown) as estree.Program; + + let parsingResult: ParsingResult<InspectionUnknown> = { + inferedType: { type: InspectionType.UNKNOWN }, + ast, + }; + + if (!isNil(ast.body[0])) { + const rootNode = ast.body[0]; + + switch (rootNode.type) { + case 'ExpressionStatement': { + const expressionResult = parseExpression(rootNode.expression); + if (!isNil(expressionResult)) { + parsingResult = expressionResult as any; + } + break; + } + default: + break; + } + } + + return parsingResult; +} diff --git a/addons/docs/src/frameworks/react/inspection/inspectValue.ts b/addons/docs/src/frameworks/react/inspection/inspectValue.ts new file mode 100644 index 00000000000..b61044f5a8f --- /dev/null +++ b/addons/docs/src/frameworks/react/inspection/inspectValue.ts @@ -0,0 +1,14 @@ +import { parse } from './acornParser'; +import { InspectionResult, InspectionType } from './types'; + +export function inspectValue(value: string): InspectionResult { + try { + const parsingResult = parse(value); + + return { ...parsingResult }; + } catch (e) { + // do nothing. + } + + return { inferedType: { type: InspectionType.UNKNOWN } }; +} diff --git a/addons/docs/src/frameworks/react/inspection/types.ts b/addons/docs/src/frameworks/react/inspection/types.ts new file mode 100644 index 00000000000..e8272f0584d --- /dev/null +++ b/addons/docs/src/frameworks/react/inspection/types.ts @@ -0,0 +1,79 @@ +export enum InspectionType { + IDENTIFIER = 'Identifier', + LITERAL = 'Literal', + OBJECT = 'Object', + ARRAY = 'Array', + FUNCTION = 'Function', + CLASS = 'Class', + ELEMENT = 'Element', + UNKNOWN = 'Unknown', +} + +export interface BaseInspectionInferedType { + type: InspectionType; +} + +// TODO: Fix this. +// export interface OptionalIdentifierInspectionType extends BaseInspectionInferedType { +// identifier?: string; +// } + +// export interface RequiredIdentifierInspectionType extends BaseInspectionInferedType { +// identifier: string; +// } + +// export type IdentifiableInspectionType = +// | OptionalIdentifierInspectionType +// | RequiredIdentifierInspectionType; + +export interface InspectionIdentifier extends BaseInspectionInferedType { + type: InspectionType.IDENTIFIER; + identifier: string; +} + +export interface InspectionLiteral extends BaseInspectionInferedType { + type: InspectionType.LITERAL; +} + +export interface InspectionObject extends BaseInspectionInferedType { + type: InspectionType.OBJECT; +} + +export interface InspectionArray extends BaseInspectionInferedType { + type: InspectionType.ARRAY; +} + +export interface InspectionClass extends BaseInspectionInferedType { + type: InspectionType.CLASS; + identifier: string; +} + +export interface InspectionFunction extends BaseInspectionInferedType { + type: InspectionType.FUNCTION; + identifier?: string; + hasArguments: boolean; +} + +export interface InspectionElement extends BaseInspectionInferedType { + type: InspectionType.ELEMENT; + identifier?: string; +} + +export interface InspectionUnknown extends BaseInspectionInferedType { + type: InspectionType.UNKNOWN; +} + +export type InspectionInferedType = + | InspectionIdentifier + | InspectionLiteral + | InspectionObject + | InspectionArray + | InspectionClass + | InspectionFunction + | InspectionElement + | InspectionUnknown; + +export interface InspectionResult { + inferedType: InspectionInferedType; + ast?: any; +} diff --git a/addons/docs/src/frameworks/react/propTypes/captions.ts b/addons/docs/src/frameworks/react/propTypes/captions.ts new file mode 100644 index 00000000000..83f968d2300 --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/captions.ts @@ -0,0 +1,6 @@ +export const CUSTOM_CAPTION = 'custom'; +export const OBJECT_CAPTION = 'object'; +export const ARRAY_CAPTION = 'array'; +export const CLASS_CAPTION = 'class'; +export const FUNCTION_CAPTION = 'func'; +export const ELEMENT_CAPTION = 'element'; diff --git a/addons/docs/src/frameworks/react/propTypes/createDefaultValue.ts b/addons/docs/src/frameworks/react/propTypes/createDefaultValue.ts new file mode 100644 index 00000000000..35164da7e0e --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/createDefaultValue.ts @@ -0,0 +1,115 @@ +import { isNil } from 'lodash'; +// @ts-ignore +import { PropDefaultValue, PropSummaryValue } from '@storybook/components'; +import { inspectValue } from '../inspection/inspectValue'; +import { OBJECT_CAPTION, FUNCTION_CAPTION, ELEMENT_CAPTION, ARRAY_CAPTION } from './captions'; +import { generateCode } from './generateCode'; +import { + InspectionFunction, + InspectionResult, + InspectionType, + InspectionElement, +} from '../inspection/types'; +import { isHtmlTag } from './isHtmlTag'; + +const MAX_SUMMARY_LENGTH = 50; + +function isTooLongForSummary(value: string): boolean { + return value.length > MAX_SUMMARY_LENGTH; +} + +// TODO: Fix this any type. +function getPrettyIdentifier(inferedType: any): string { + const { type, identifier } = inferedType; + + switch (type) { + case InspectionType.FUNCTION: + return inferedType.hasArguments ? `${identifier}( ... )` : `${identifier}()`; + case InspectionType.ELEMENT: + return `<${identifier} />`; + default: + return identifier; + } +} + +function createSummaryValue(summary: string, detail?: string): PropSummaryValue { + return { summary, detail }; +} + +function generateObject({ ast }: InspectionResult): PropDefaultValue { + let prettyCaption = generateCode(ast, true); + + // Cannot get escodegen to add a space before the last } with the compact mode settings. + // This fix it until a better solution is found. + if (!prettyCaption.endsWith(' }')) { + prettyCaption = `${prettyCaption.slice(0, -1)} }`; + } + + return !isTooLongForSummary(prettyCaption) + ? createSummaryValue(prettyCaption) + : createSummaryValue(OBJECT_CAPTION, generateCode(ast)); +} + +function generateFunc({ inferedType, ast }: InspectionResult): PropDefaultValue { + const { identifier } = inferedType as InspectionFunction; + + if (!isNil(identifier)) { + return createSummaryValue(getPrettyIdentifier(inferedType), generateCode(ast)); + } + + const prettyCaption = generateCode(ast, true); + + return !isTooLongForSummary(prettyCaption) + ? createSummaryValue(prettyCaption) + : createSummaryValue(FUNCTION_CAPTION, generateCode(ast)); +} + +// All elements are JSX elements. +// JSX elements are not supported by escodegen. +function generateElement( + defaultValue: string, + inspectionResult: InspectionResult +): PropDefaultValue { + const { inferedType } = inspectionResult; + const { identifier } = inferedType as InspectionElement; + + if (!isNil(identifier)) { + if (!isHtmlTag(identifier)) { + const prettyIdentifier = getPrettyIdentifier(inferedType); + + return createSummaryValue( + prettyIdentifier, + prettyIdentifier !== defaultValue ? defaultValue : undefined + ); + } + } + + return !isTooLongForSummary(defaultValue) + ? createSummaryValue(defaultValue) + : createSummaryValue(ELEMENT_CAPTION, defaultValue); +} + +function generateArray({ ast }: InspectionResult): PropDefaultValue { + const prettyCaption = generateCode(ast, true); + + return !isTooLongForSummary(prettyCaption) + ? createSummaryValue(prettyCaption) + : createSummaryValue(ARRAY_CAPTION, generateCode(ast)); +} + +export function createDefaultValue(defaultValue: string): PropDefaultValue { + const inspectionResult = inspectValue(defaultValue); + + switch (inspectionResult.inferedType.type) { + case InspectionType.OBJECT: + return generateObject(inspectionResult); + case InspectionType.FUNCTION: + return generateFunc(inspectionResult); + case InspectionType.ELEMENT: + return generateElement(defaultValue, inspectionResult); + case InspectionType.ARRAY: + return generateArray(inspectionResult); + default: + return null; + } +} diff --git a/addons/docs/src/frameworks/react/propTypes/createType.ts b/addons/docs/src/frameworks/react/propTypes/createType.ts new file mode 100644 index 00000000000..cad45030a41 --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/createType.ts @@ -0,0 +1,366 @@ +import { isNil } from 'lodash'; +import { PropSummaryValue, PropType } from '@storybook/components'; +import { ExtractedProp, DocgenPropType } from '../../../lib/docgen'; +import { inspectValue } from '../inspection/inspectValue'; +import { generateCode } from './generateCode'; +import { generateFuncSignature } from './generateFuncSignature'; +import { + OBJECT_CAPTION, + ARRAY_CAPTION, + CLASS_CAPTION, + FUNCTION_CAPTION, + ELEMENT_CAPTION, + CUSTOM_CAPTION, +} from './captions'; +import { InspectionType } from '../inspection/types'; +import { isHtmlTag } from './isHtmlTag'; + +const MAX_SUMMARY_LENGTH = 35; + +enum PropTypesType { + CUSTOM = 'custom', + ANY = 'any', + FUNC = 'func', + SHAPE = 'shape', + OBJECT = 'object', + INSTANCEOF = 'instanceOf', + OBJECTOF = 'objectOf', + UNION = 'union', + ENUM = 'enum', + ARRAYOF = 'arrayOf', + ELEMENT = 'element', + ELEMENTTYPE = 'elementType', + NODE = 'node', +} + +interface EnumValue { + value: string; + computed: boolean; +} + +interface TypeDef { + name: string; + value: PropSummaryValue; + inferedType?: InspectionType; +} + +function createTypeDef({ + name, + summary, + detail, + inferedType, +}: { + name: string; + summary: string; + detail?: string; + inferedType?: InspectionType; +}): TypeDef { + return { + name, + value: { + summary, + detail: !isNil(detail) ? detail : summary, + }, + inferedType, + }; +} + +function cleanPropTypes(value: string): string { + return value.replace(/PropTypes./g, '').replace(/.isRequired/g, ''); +} + +function prettyObject(ast: any, compact = false): string { + return cleanPropTypes(generateCode(ast, compact)); +} + +function getCaptionFromInspectionType(type: InspectionType): string { + switch (type) { + case InspectionType.OBJECT: + return OBJECT_CAPTION; + case InspectionType.ARRAY: + return ARRAY_CAPTION; + case InspectionType.CLASS: + return CLASS_CAPTION; + case InspectionType.FUNCTION: + return FUNCTION_CAPTION; + case InspectionType.ELEMENT: + return ELEMENT_CAPTION; + default: + return CUSTOM_CAPTION; + } +} + +function isTooLongForSummary(value: string): boolean { + return value.length > MAX_SUMMARY_LENGTH; +} + +function generateValuesForObjectAst(ast: any): [string, string] { + let summary = prettyObject(ast, true); + let detail; + + if (!isTooLongForSummary(summary)) { + detail = summary; + } else { + summary = OBJECT_CAPTION; + detail = prettyObject(ast); + } + + return [summary, detail]; +} + +function generateCustom({ raw }: DocgenPropType): TypeDef { + if (!isNil(raw)) { + const { inferedType, ast } = inspectValue(raw); + const { type, identifier } = inferedType as any; + + let summary; + let detail; + + switch (type) { + case InspectionType.IDENTIFIER: + case InspectionType.LITERAL: + summary = raw; + break; + case InspectionType.OBJECT: { + const [objectCaption, objectValue] = generateValuesForObjectAst(ast); + + summary = objectCaption; + detail = objectValue; + break; + } + case InspectionType.ELEMENT: + summary = !isNil(identifier) && !isHtmlTag(identifier) ? identifier : ELEMENT_CAPTION; + detail = raw; + break; + default: + summary = getCaptionFromInspectionType(type); + detail = raw; + break; + } + + return createTypeDef({ + name: PropTypesType.CUSTOM, + summary, + detail, + inferedType: type, + }); + } + + return createTypeDef({ name: PropTypesType.CUSTOM, summary: CUSTOM_CAPTION }); +} + +function generateFunc(extractedProp: ExtractedProp): TypeDef { + const { jsDocTags } = extractedProp; + + if (!isNil(jsDocTags)) { + if (!isNil(jsDocTags.params) || !isNil(jsDocTags.returns)) { + return createTypeDef({ + name: PropTypesType.FUNC, + summary: FUNCTION_CAPTION, + detail: generateFuncSignature(jsDocTags.params, jsDocTags.returns), + }); + } + } + + return createTypeDef({ name: PropTypesType.FUNC, summary: FUNCTION_CAPTION }); +} + +function generateShape(type: DocgenPropType, extractedProp: ExtractedProp): TypeDef { + const fields = Object.keys(type.value) + .map((key: string) => `${key}: ${generateType(type.value[key], extractedProp).value.detail}`) + .join(', '); + + const { ast } = inspectValue(`{ ${fields} }`); + const [summary, detail] = generateValuesForObjectAst(ast); + + return createTypeDef({ + name: PropTypesType.SHAPE, + summary, + detail, + }); +} + +function generateObjectOf(type: DocgenPropType, extractedProp: ExtractedProp): TypeDef { + const format = (of: string) => `objectOf(${of})`; + + const { name, value } = generateType(type.value, extractedProp); + // eslint-disable-next-line prefer-const + let { summary, detail } = value; + + if (name === PropTypesType.SHAPE) { + if (!isTooLongForSummary(detail)) { + summary = detail; + } + } + + return createTypeDef({ + name: PropTypesType.OBJECTOF, + summary: format(summary), + detail: format(detail), + }); +} + +function generateUnion(type: DocgenPropType, extractedProp: ExtractedProp): TypeDef { + if (Array.isArray(type.value)) { + const values = type.value.reduce( + (acc: any, v: any) => { + const { summary, detail } = generateType(v, extractedProp).value; + + acc.summary.push(summary); + acc.detail.push(detail); + + return acc; + }, + { summary: [], detail: [] } + ); + + return createTypeDef({ + name: PropTypesType.UNION, + summary: values.summary.join(' | '), + detail: values.detail.join(' | '), + }); + } + + return createTypeDef({ name: PropTypesType.UNION, summary: type.value }); +} + +function generateEnumValue({ value, computed }: EnumValue): TypeDef { + if (computed) { + const { inferedType, ast } = inspectValue(value) as any; + const { type } = inferedType; + + let caption = getCaptionFromInspectionType(type); + + if ( + type === InspectionType.FUNCTION || + type === InspectionType.CLASS || + type === InspectionType.ELEMENT + ) { + if (!isNil(inferedType.identifier)) { + caption = inferedType.identifier; + } + } + + return createTypeDef({ + name: 'enumvalue', + summary: caption, + detail: type === InspectionType.OBJECT ? prettyObject(ast) : value, + inferedType: type, + }); + } + + return createTypeDef({ name: 'enumvalue', summary: value }); +} + +function generateEnum(type: DocgenPropType): TypeDef { + if (Array.isArray(type.value)) { + const values = type.value.reduce( + (acc: any, v: EnumValue) => { + const { summary, detail } = generateEnumValue(v).value; + + acc.summary.push(summary); + acc.detail.push(detail); + + return acc; + }, + { summary: [], detail: [] } + ); + + return createTypeDef({ + name: PropTypesType.ENUM, + summary: values.summary.join(' | '), + detail: values.detail.join(' | '), + }); + } + + return createTypeDef({ name: PropTypesType.ENUM, summary: type.value }); +} + +function braceAfter(of: string): string { + return `${of}[]`; +} + +function braceAround(of: string): string { + return `[${of}]`; +} + +function createArrayOfObjectTypeDef(summary: string, detail: string): TypeDef { + return createTypeDef({ + name: PropTypesType.ARRAYOF, + summary: summary === OBJECT_CAPTION ? braceAfter(summary) : braceAround(summary), + detail: braceAround(detail), + }); +} + +function generateArray(type: DocgenPropType, extractedProp: ExtractedProp): TypeDef { + const { name, value, inferedType } = generateType(type.value, extractedProp); + const { summary, detail } = value; + + if (name === PropTypesType.CUSTOM) { + if (inferedType === InspectionType.OBJECT) { + return createArrayOfObjectTypeDef(summary, detail); + } + } else if (name === PropTypesType.SHAPE) { + return createArrayOfObjectTypeDef(summary, detail); + } + + return createTypeDef({ name: PropTypesType.ARRAYOF, summary: braceAfter(detail) }); +} + +function generateType(type: DocgenPropType, extractedProp: ExtractedProp): TypeDef { + try { + switch (type.name) { + case PropTypesType.CUSTOM: + return generateCustom(type); + case PropTypesType.FUNC: + return generateFunc(extractedProp); + case PropTypesType.SHAPE: + return generateShape(type, extractedProp); + case PropTypesType.INSTANCEOF: + return createTypeDef({ name: PropTypesType.INSTANCEOF, summary: type.value }); + case PropTypesType.OBJECTOF: + return generateObjectOf(type, extractedProp); + case PropTypesType.UNION: + return generateUnion(type, extractedProp); + case PropTypesType.ENUM: + return generateEnum(type); + case PropTypesType.ARRAYOF: + return generateArray(type, extractedProp); + default: + return createTypeDef({ name: type.name, summary: type.name }); + } + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + } + + return createTypeDef({ name: 'unknown', summary: 'unknown' }); +} + +export function createType(extractedProp: ExtractedProp): PropType { + const { type } = extractedProp.docgenInfo; + + switch (type.name) { + case PropTypesType.CUSTOM: + case PropTypesType.SHAPE: + case PropTypesType.INSTANCEOF: + case PropTypesType.OBJECTOF: + case PropTypesType.UNION: + case PropTypesType.ENUM: + case PropTypesType.ARRAYOF: { + const { summary, detail } = generateType(type, extractedProp).value; + + return { + summary, + detail: summary !== detail ? detail : undefined, + }; + } + case PropTypesType.FUNC: { + const { detail } = generateType(type, extractedProp).value; + + return { summary: detail }; + } + default: + return null; + } +} diff --git a/addons/docs/src/frameworks/react/propTypes/generateCode.ts b/addons/docs/src/frameworks/react/propTypes/generateCode.ts new file mode 100644 index 00000000000..092860023c8 --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/generateCode.ts @@ -0,0 +1,25 @@ +import { generate } from 'escodegen'; + +const BASIC_OPTIONS = { + format: { + indent: { + style: ' ', + }, + semicolons: false, + }, +}; + +const COMPACT_OPTIONS = { + ...BASIC_OPTIONS, + format: { + newline: '', + }, +}; + +const PRETTY_OPTIONS = { + ...BASIC_OPTIONS, +}; + +export function generateCode(ast: any, compact = false): string { + return generate(ast, compact ? COMPACT_OPTIONS : PRETTY_OPTIONS); +} diff --git a/addons/docs/src/frameworks/react/propTypes/generateFuncSignature.test.ts b/addons/docs/src/frameworks/react/propTypes/generateFuncSignature.test.ts new file mode 100644 index 00000000000..d7658879844 --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/generateFuncSignature.test.ts @@ -0,0 +1,156 @@ +import { generateFuncSignature } from './generateFuncSignature'; +import { parseJsDoc } from '../../../lib/jsdocParser'; + +it('should return an empty string with there is no @params and @returns tags', () => { + const result = generateFuncSignature(null, null); + + expect(result).toBe(''); +}); + +it('should return a signature with a single arg when there is a @param tag with a name', () => { + const { params, returns } = parseJsDoc('@param event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event)'); +}); + +it('should return a signature with a single arg when there is a @param tag with a name and a type', () => { + const { params, returns } = parseJsDoc('@param {SyntheticEvent} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: SyntheticEvent)'); +}); + +it('should return a signature with a single arg when there is a @param tag with a name, a type and a desc', () => { + const { params, returns } = parseJsDoc( + '@param {SyntheticEvent} event - React event' + ).extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: SyntheticEvent)'); +}); + +it('should support @param of record type', () => { + const { params, returns } = parseJsDoc('@param {{a: number}} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: ({a: number}))'); +}); + +it('should support @param of union type', () => { + const { params, returns } = parseJsDoc('@param {(number|boolean)} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: (number|boolean))'); +}); + +it('should support @param of array type', () => { + const { params, returns } = parseJsDoc('@param {number[]} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: number[])'); +}); + +it('should support @param with a nullable type', () => { + const { params, returns } = parseJsDoc('@param {?number} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: number)'); +}); + +it('should support @param with a non nullable type', () => { + const { params, returns } = parseJsDoc('@param {!number} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: number)'); +}); + +it('should support optional @param with []', () => { + const { params, returns } = parseJsDoc('@param {number} [event]').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: number)'); +}); + +it('should support optional @param with =', () => { + const { params, returns } = parseJsDoc('@param {number=} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: number)'); +}); + +it('should support @param of type any', () => { + const { params, returns } = parseJsDoc('@param {*} event').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: any)'); +}); + +it('should support multiple @param tags', () => { + const { params, returns } = parseJsDoc( + '@param {SyntheticEvent} event\n@param {string} customData' + ).extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: SyntheticEvent, customData: string)'); +}); + +it('should return a signature with a return type when there is a @returns with a type', () => { + const { params, returns } = parseJsDoc('@returns {string}').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('() => string'); +}); + +it('should support @returns of record type', () => { + const { params, returns } = parseJsDoc('@returns {{a: number, b: string}}').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('() => ({a: number, b: string})'); +}); + +it('should support @returns of array type', () => { + const { params, returns } = parseJsDoc('@returns {integer[]}').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('() => integer[]'); +}); + +it('should support @returns of union type', () => { + const { params, returns } = parseJsDoc('@returns {(number|boolean)}').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('() => (number|boolean)'); +}); + +it('should support @returns type any', () => { + const { params, returns } = parseJsDoc('@returns {*}').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('() => any'); +}); + +it('should support @returns of type void', () => { + const { params, returns } = parseJsDoc('@returns {void}').extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('() => void'); +}); + +it('should return a full signature when there is a single @param tag and a @returns', () => { + const { params, returns } = parseJsDoc( + '@param {SyntheticEvent} event - React event.\n@returns {string}' + ).extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: SyntheticEvent) => string'); +}); + +it('should return a full signature when there is a multiple @param tags and a @returns', () => { + const { params, returns } = parseJsDoc( + '@param {SyntheticEvent} event - React event.\n@param {string} data\n@returns {string}' + ).extractedTags; + const result = generateFuncSignature(params, returns); + + expect(result).toBe('(event: SyntheticEvent, data: string) => string'); +}); diff --git a/addons/docs/src/frameworks/react/propTypes/generateFuncSignature.ts b/addons/docs/src/frameworks/react/propTypes/generateFuncSignature.ts new file mode 100644 index 00000000000..68cc0a5217a --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/generateFuncSignature.ts @@ -0,0 +1,39 @@ +import { isNil } from 'lodash'; +import { ExtractedJsDocParam, ExtractedJsDocReturns } from '../../../lib/jsdocParser'; + +export function generateFuncSignature( + params: ExtractedJsDocParam[], + returns: ExtractedJsDocReturns +): string { + const hasParams = !isNil(params); + const hasReturns = !isNil(returns); + + if (!hasParams && !hasReturns) { + return ''; + } + + const funcParts = []; + + if (hasParams) { + const funcParams = params.map((x: ExtractedJsDocParam) => { + const prettyName = x.getPrettyName(); + const typeName = x.getTypeName(); + + if (!isNil(typeName)) { + return `${prettyName}: ${typeName}`; + } + + return prettyName; + }); + + funcParts.push(`(${funcParams.join(', ')})`); + } else { + funcParts.push('()'); + } + + if (hasReturns) { + funcParts.push(`=> ${returns.getTypeName()}`); + } + + return funcParts.join(' '); +} diff --git a/addons/docs/src/frameworks/react/propTypes/handleProp.test.ts b/addons/docs/src/frameworks/react/propTypes/handleProp.test.ts new file mode 100644 index 00000000000..a77ebf694aa --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/handleProp.test.ts @@ -0,0 +1,955 @@ +/* eslint-disable no-underscore-dangle */ + +import { PropDef } from '@storybook/components'; +import PropTypes from 'prop-types'; +import { Component } from '../../../blocks/shared'; +import { extractPropsFromDocgen, DocgenInfo } from '../../../lib/docgen'; +import { enhancePropTypesProp, enhancePropTypesProps } from './handleProp'; + +const DOCGEN_SECTION = 'props'; + +function createDocgenSection(docgenInfo: DocgenInfo): Record<string, any> { + return { + [DOCGEN_SECTION]: { + ...docgenInfo, + }, + }; +} + +function createDocgenProp({ + name, + type, + ...others +}: Partial<DocgenInfo> & { name: string }): Record<string, any> { + return { + [name]: { + type, + required: false, + ...others, + }, + }; +} + +// eslint-disable-next-line react/forbid-foreign-prop-types +function createComponent({ propTypes = {}, defaultProps = {}, docgenInfo = {} }): Component { + const component = () => {}; + component.propTypes = propTypes; + component.defaultProps = defaultProps; + + // @ts-ignore + component.__docgenInfo = createDocgenSection(docgenInfo); + + return component; +} + +function extractPropDef(component: Component): PropDef { + return enhancePropTypesProp(extractPropsFromDocgen(component, DOCGEN_SECTION)[0]); +} + +describe('enhancePropTypesProp', () => { + describe('type', () => { + function createTestComponent(docgenInfo: Partial<DocgenInfo>): Component { + return createComponent({ + docgenInfo: { + ...createDocgenProp({ name: 'prop', ...docgenInfo }), + }, + }); + } + + describe('custom', () => { + describe('when raw value is available', () => { + it('should support literal', () => { + const component = createTestComponent({ + type: { + name: 'custom', + raw: 'MY_LITERAL', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('MY_LITERAL'); + expect(type.detail).toBeUndefined(); + }); + + it('should support short object', () => { + const component = createTestComponent({ + type: { + name: 'custom', + raw: '{\n text: PropTypes.string.isRequired,\n}', + }, + }); + + const { type } = extractPropDef(component); + + const expectedSummary = '{ text: string }'; + + expect(type.summary.replace(/\s/g, '')).toBe(expectedSummary.replace(/\s/g, '')); + expect(type.detail).toBeUndefined(); + }); + + it('should support long object', () => { + const component = createTestComponent({ + type: { + name: 'custom', + raw: + '{\n text: PropTypes.string.isRequired,\n value: PropTypes.string.isRequired,\n}', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('object'); + + const expectedDetail = `{ + text: string, + value: string + }`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should use identifier of a React element when available', () => { + const component = createTestComponent({ + type: { + name: 'custom', + raw: + 'function InlinedFunctionalComponent() {\n return <div>Inlined FunctionnalComponent!</div>;\n}', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('InlinedFunctionalComponent'); + + const expectedDetail = `function InlinedFunctionalComponent() { + return <div>Inlined FunctionnalComponent!</div>; + }`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should not use identifier of a HTML element', () => { + const component = createTestComponent({ + type: { + name: 'custom', + raw: '<div>Hello world!</div>', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('element'); + + const expectedDetail = '<div>Hello world!</div>'; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should support element without identifier', () => { + const component = createTestComponent({ + type: { + name: 'custom', + raw: '() => {\n return <div>Inlined FunctionnalComponent!</div>;\n}', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('element'); + + const expectedDetail = `() => { + return <div>Inlined FunctionnalComponent!</div>; + }`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should return "custom" when it is not a known type', () => { + const component = createTestComponent({ + type: { + name: 'custom', + raw: 'Symbol("Hey!")', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('custom'); + }); + }); + + it("should return 'custom' when there is no raw value", () => { + const component = createTestComponent({ + type: { + name: 'custom', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('custom'); + }); + }); + + [ + 'any', + 'bool', + 'string', + 'number', + 'symbol', + 'object', + 'element', + 'elementType', + 'node', + ].forEach(x => { + it(`should return '${x}' when type is ${x}`, () => { + const component = createTestComponent({ + type: { + name: x, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe(x); + }); + }); + + it('should support short shape', () => { + const component = createTestComponent({ + type: { + name: 'shape', + value: { + foo: { + name: 'string', + required: false, + }, + }, + }, + }); + + const { type } = extractPropDef(component); + + const expectedSummary = '{ foo: string }'; + + expect(type.summary.replace(/\s/g, '')).toBe(expectedSummary.replace(/\s/g, '')); + expect(type.detail).toBeUndefined(); + }); + + it('should support long shape', () => { + const component = createTestComponent({ + type: { + name: 'shape', + value: { + foo: { + name: 'string', + required: false, + }, + bar: { + name: 'string', + required: false, + }, + another: { + name: 'string', + required: false, + }, + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('object'); + + const expectedDetail = `{ + foo: string, + bar: string, + another: string + }`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should support enum of string', () => { + const component = createTestComponent({ + type: { + name: 'enum', + value: [ + { + value: "'News'", + computed: false, + }, + { + value: "'Photos'", + computed: false, + }, + ], + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe("'News' | 'Photos'"); + }); + + it('should support enum of object', () => { + const component = createTestComponent({ + type: { + name: 'enum', + value: [ + { + value: + '{\n text: PropTypes.string.isRequired,\n value: PropTypes.string.isRequired,\n}', + computed: true, + }, + { + value: '{\n foo: PropTypes.string,\n bar: PropTypes.string,\n}', + computed: true, + }, + ], + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('object | object'); + + const expectedDetail = `{ + text: string, + value: string + } | { + foo: string, + bar: string + }`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should support enum of element', () => { + const component = createTestComponent({ + type: { + name: 'enum', + value: [ + { + value: '() => {\n return <div>FunctionnalComponent!</div>;\n}', + computed: true, + }, + { + value: + 'class ClassComponent extends React.PureComponent {\n render() {\n return <div>ClassComponent!</div>;\n }\n}', + computed: true, + }, + ], + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('element | ClassComponent'); + + const expectedDetail = `() => { + return <div>FunctionnalComponent!</div>; + } | class ClassComponent extends React.PureComponent { + render() { + return <div>ClassComponent!</div>; + } + }`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + describe('func', () => { + it('should return "func" when the prop dont have a description', () => { + const component = createTestComponent({ + type: { + name: 'func', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('func'); + }); + + it('should return "func" when the prop have a description without JSDoc tags', () => { + const component = createTestComponent({ + type: { + name: 'func', + }, + description: 'Hey! Hey!', + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('func'); + }); + + it('should return a func signature when there is JSDoc tags.', () => { + const component = createTestComponent({ + type: { + name: 'func', + }, + description: '@param event\n@param data\n@returns {string}', + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('(event, data) => string'); + }); + }); + + it('should return the instance type when type is instanceOf', () => { + const component = createTestComponent({ + type: { + name: 'instanceOf', + value: 'Set', + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('Set'); + }); + + describe('objectOf', () => { + it('should support objectOf primitive', () => { + const component = createTestComponent({ + type: { + name: 'objectOf', + value: { + name: 'number', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('objectOf(number)'); + expect(type.detail).toBeUndefined(); + }); + + it('should support objectOf of identifier', () => { + const component = createTestComponent({ + type: { + name: 'objectOf', + value: { + name: 'custom', + raw: 'NAMED_OBJECT', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('objectOf(NAMED_OBJECT)'); + expect(type.detail).toBeUndefined(); + }); + + it('should support objectOf short object', () => { + const component = createTestComponent({ + type: { + name: 'objectOf', + value: { + name: 'custom', + raw: '{\n foo: PropTypes.string,\n}', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('objectOf({ foo: string })'); + expect(type.detail).toBeUndefined(); + }); + + it('should support objectOf long object', () => { + const component = createTestComponent({ + type: { + name: 'objectOf', + value: { + name: 'custom', + raw: + '{\n foo: PropTypes.string,\n bar: PropTypes.string,\n another: PropTypes.string,\n}', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('objectOf(object)'); + + const expectedDetail = `objectOf({ + foo: string, + bar: string, + another: string + })`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should support objectOf short shape', () => { + const component = createTestComponent({ + type: { + name: 'objectOf', + value: { + name: 'shape', + value: { + foo: { + name: 'string', + required: false, + }, + }, + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('objectOf({ foo: string })'); + expect(type.detail).toBeUndefined(); + }); + + it('should support objectOf long shape', () => { + const component = createTestComponent({ + type: { + name: 'objectOf', + value: { + name: 'shape', + value: { + foo: { + name: 'string', + required: false, + }, + bar: { + name: 'string', + required: false, + }, + another: { + name: 'string', + required: false, + }, + }, + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('objectOf(object)'); + + const expectedDetail = `objectOf({ + foo: string, + bar: string, + another: string + })`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + }); + + it('should support union', () => { + const component = createTestComponent({ + type: { + name: 'union', + value: [ + { + name: 'string', + }, + { + name: 'instanceOf', + value: 'Set', + }, + ], + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('string | Set'); + expect(type.detail).toBeUndefined(); + }); + + describe('array', () => { + it('should support array of primitive', () => { + const component = createTestComponent({ + type: { + name: 'arrayOf', + value: { + name: 'number', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('number[]'); + expect(type.detail).toBeUndefined(); + }); + + it('should support array of identifier', () => { + const component = createTestComponent({ + type: { + name: 'arrayOf', + value: { + name: 'custom', + raw: 'NAMED_OBJECT', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('NAMED_OBJECT[]'); + expect(type.detail).toBeUndefined(); + }); + + it('should support array of short object', () => { + const component = createTestComponent({ + type: { + name: 'arrayOf', + value: { + name: 'custom', + raw: '{\n foo: PropTypes.string,\n}', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('[{ foo: string }]'); + expect(type.detail).toBeUndefined(); + }); + + it('should support array of long object', () => { + const component = createTestComponent({ + type: { + name: 'arrayOf', + value: { + name: 'custom', + raw: + '{\n text: PropTypes.string.isRequired,\n value: PropTypes.string.isRequired,\n}', + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('object[]'); + + const expectedDetail = `[{ + text: string, + value: string + }]`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should support array of short shape', () => { + const component = createTestComponent({ + type: { + name: 'arrayOf', + value: { + name: 'shape', + value: { + foo: { + name: 'string', + required: false, + }, + }, + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('[{ foo: string }]'); + expect(type.detail).toBeUndefined(); + }); + + it('should support array of long shape', () => { + const component = createTestComponent({ + type: { + name: 'arrayOf', + value: { + name: 'shape', + value: { + foo: { + name: 'string', + required: false, + }, + bar: { + name: 'string', + required: false, + }, + another: { + name: 'string', + required: false, + }, + }, + }, + }, + }); + + const { type } = extractPropDef(component); + + expect(type.summary).toBe('object[]'); + + const expectedDetail = `[{ + foo: string, + bar: string, + another: string + }]`; + + expect(type.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + }); + }); + + describe('defaultValue', () => { + function createTestComponent(defaultValue: string): Component { + return createComponent({ + docgenInfo: { + ...createDocgenProp({ + name: 'prop', + type: { name: 'custom' }, + defaultValue: { value: defaultValue }, + }), + }, + }); + } + + it('should support short object', () => { + const component = createTestComponent("{ foo: 'foo', bar: 'bar' }"); + + const { defaultValue } = extractPropDef(component); + + const expectedSummary = "{ foo: 'foo', bar: 'bar' }"; + + expect(defaultValue.summary.replace(/\s/g, '')).toBe(expectedSummary.replace(/\s/g, '')); + expect(defaultValue.detail).toBeUndefined(); + }); + + it('should support long object', () => { + const component = createTestComponent("{ foo: 'foo', bar: 'bar', another: 'another' }"); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('object'); + + const expectedDetail = `{ + foo: 'foo', + bar: 'bar', + another: 'another' + }`; + + expect(defaultValue.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should support short function', () => { + const component = createTestComponent('() => {}'); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('() => {}'); + expect(defaultValue.detail).toBeUndefined(); + }); + + it('should support long function', () => { + const component = createTestComponent( + '(foo, bar) => {\n const concat = foo + bar;\n const append = concat + " hey!";\n \n return append;\n}' + ); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('func'); + + const expectedDetail = `(foo, bar) => { + const concat = foo + bar; + const append = concat + ' hey!'; + return append + }`; + + expect(defaultValue.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should use the name of function when available and indicate that args are present', () => { + const component = createTestComponent('function concat(a, b) {\n return a + b;\n}'); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('concat( ... )'); + + const expectedDetail = `function concat(a, b) { + return a + b + }`; + + expect(defaultValue.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should use the name of function when available', () => { + const component = createTestComponent('function hello() {\n return "hello";\n}'); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('hello()'); + + const expectedDetail = `function hello() { + return 'hello' + }`; + + expect(defaultValue.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should support short element', () => { + const component = createTestComponent('<div>Hey!</div>'); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('<div>Hey!</div>'); + expect(defaultValue.detail).toBeUndefined(); + }); + + it('should support long element', () => { + const component = createTestComponent( + '() => {\n return <div>Inlined FunctionnalComponent!</div>;\n}' + ); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('element'); + + const expectedDetail = `() => { + return <div>Inlined FunctionnalComponent!</div>; + }`; + + expect(defaultValue.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it("should use the name of the React component when it's available", () => { + const component = createTestComponent( + 'function InlinedFunctionalComponent() {\n return <div>Inlined FunctionnalComponent!</div>;\n}' + ); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('<InlinedFunctionalComponent />'); + + const expectedDetail = `function InlinedFunctionalComponent() { + return <div>Inlined FunctionnalComponent!</div>; + }`; + + expect(defaultValue.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + + it('should not use the name of an HTML element', () => { + const component = createTestComponent('<div>Hey!</div>'); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).not.toBe('<div />'); + }); + + it('should support short array', () => { + const component = createTestComponent('[1]'); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('[1]'); + expect(defaultValue.detail).toBeUndefined(); + }); + + it('should support long array', () => { + const component = createTestComponent( + '[\n {\n thing: {\n id: 2,\n func: () => {},\n arr: [],\n },\n },\n]' + ); + + const { defaultValue } = extractPropDef(component); + + expect(defaultValue.summary).toBe('array'); + + const expectedDetail = `[{ + thing: { + id: 2, + func: () => { + }, + arr: [] + } + }]`; + + expect(defaultValue.detail.replace(/\s/g, '')).toBe(expectedDetail.replace(/\s/g, '')); + }); + }); +}); + +describe('enhancePropTypesProps', () => { + it('should keep the original definition order', () => { + const component = createComponent({ + propTypes: { + foo: PropTypes.string, + middleWithDefaultValue: PropTypes.string, + bar: PropTypes.string, + endWithDefaultValue: PropTypes.string, + }, + docgenInfo: { + ...createDocgenProp({ + name: 'middleWithDefaultValue', + type: { name: 'string' }, + defaultValue: { value: 'Middle!' }, + }), + ...createDocgenProp({ + name: 'endWithDefaultValue', + type: { name: 'string' }, + defaultValue: { value: 'End!' }, + }), + ...createDocgenProp({ + name: 'foo', + type: { name: 'string' }, + }), + ...createDocgenProp({ + name: 'bar', + type: { name: 'string' }, + }), + }, + }); + + const props = enhancePropTypesProps( + extractPropsFromDocgen(component, DOCGEN_SECTION), + component + ); + + expect(props.length).toBe(4); + expect(props[0].name).toBe('foo'); + expect(props[1].name).toBe('middleWithDefaultValue'); + expect(props[2].name).toBe('bar'); + expect(props[3].name).toBe('endWithDefaultValue'); + }); + + it('should not include @ignore props', () => { + const component = createComponent({ + propTypes: { + foo: PropTypes.string, + bar: PropTypes.string, + }, + docgenInfo: { + ...createDocgenProp({ + name: 'foo', + type: { name: 'string' }, + }), + ...createDocgenProp({ + name: 'bar', + type: { name: 'string' }, + description: '@ignore', + }), + }, + }); + + const props = enhancePropTypesProps( + extractPropsFromDocgen(component, DOCGEN_SECTION), + component + ); + + expect(props.length).toBe(1); + expect(props[0].name).toBe('foo'); + }); +}); diff --git a/addons/docs/src/frameworks/react/propTypes/handleProp.ts b/addons/docs/src/frameworks/react/propTypes/handleProp.ts new file mode 100644 index 00000000000..69d7eb6db20 --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/handleProp.ts @@ -0,0 +1,35 @@ +import { isNil } from 'lodash'; +import { PropDef } from '@storybook/components'; +import { ExtractedProp } from '../../../lib/docgen'; +import { createType } from './createType'; +import { createDefaultValue } from './createDefaultValue'; +import { Component } from '../../../blocks/shared'; +import { keepOriginalDefinitionOrder } from './sortProps'; + +export function enhancePropTypesProp(extractedProp: ExtractedProp): PropDef { + const { propDef } = extractedProp; + + const newtype = createType(extractedProp); + if (!isNil(newtype)) { + propDef.type = newtype; + } + + const { defaultValue } = extractedProp.docgenInfo; + if (!isNil(defaultValue)) { + const newDefaultValue = createDefaultValue(defaultValue.value); + if (!isNil(newDefaultValue)) { + propDef.defaultValue = newDefaultValue; + } + } + + return propDef; +} + +export function enhancePropTypesProps( + extractedProps: ExtractedProp[], + component: Component +): PropDef[] { + const enhancedProps = extractedProps.map(enhancePropTypesProp); + + return keepOriginalDefinitionOrder(enhancedProps, component); +} diff --git a/addons/docs/src/frameworks/react/propTypes/isHtmlTag.ts b/addons/docs/src/frameworks/react/propTypes/isHtmlTag.ts new file mode 100644 index 00000000000..eb13de490d0 --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/isHtmlTag.ts @@ -0,0 +1,5 @@ +import htmlTags from 'html-tags'; + +export function isHtmlTag(tagName: string): boolean { + return htmlTags.includes(tagName.toLowerCase()); +} diff --git a/addons/docs/src/frameworks/react/propTypes/sortProps.ts b/addons/docs/src/frameworks/react/propTypes/sortProps.ts new file mode 100644 index 00000000000..9061ee0ded5 --- /dev/null +++ b/addons/docs/src/frameworks/react/propTypes/sortProps.ts @@ -0,0 +1,21 @@ +import { PropDef } from '@storybook/components'; +import { isNil } from 'lodash'; +import { Component } from '../../../blocks/shared'; + +// react-docgen doesn't returned the props in the order they were defined in the "propTypes" object of the component. +// This function re-order them by their original definition order. +export function keepOriginalDefinitionOrder( + extractedProps: PropDef[], + component: Component +): PropDef[] { + // eslint-disable-next-line react/forbid-foreign-prop-types + const { propTypes } = component; + + if (!isNil(propTypes)) { + return Object.keys(propTypes) + .map(x => extractedProps.find(y => y.name === x)) + .filter(x => x); + } + + return extractedProps; +} diff --git a/addons/docs/src/frameworks/vue/config.tsx b/addons/docs/src/frameworks/vue/config.tsx index 0f395e0f47a..e08d3430877 100644 --- a/addons/docs/src/frameworks/vue/config.tsx +++ b/addons/docs/src/frameworks/vue/config.tsx @@ -4,7 +4,7 @@ import toReact from '@egoist/vue-to-react'; import { StoryFn } from '@storybook/addons'; import { addParameters } from '@storybook/client-api'; import { extractProps } from './extractProps'; -import { extractComponentDescription } from '../../lib/docgenUtils'; +import { extractComponentDescription } from '../../lib/docgen/utils'; addParameters({ docs: { diff --git a/addons/docs/src/frameworks/vue/extractProps.ts b/addons/docs/src/frameworks/vue/extractProps.ts index 27397cf3861..495dd8b0c24 100644 --- a/addons/docs/src/frameworks/vue/extractProps.ts +++ b/addons/docs/src/frameworks/vue/extractProps.ts @@ -1,5 +1,5 @@ import { PropDef } from '@storybook/components'; -import { PropsExtractor, extractPropsFromDocgen, hasDocgen } from '../../lib/docgenUtils'; +import { PropsExtractor, hasDocgen, extractPropsFromDocgen } from '../../lib/docgen'; const SECTIONS = ['props', 'events', 'slots']; @@ -9,7 +9,7 @@ export const extractProps: PropsExtractor = component => { } const sections: Record<string, PropDef[]> = {}; SECTIONS.forEach(section => { - sections[section] = extractPropsFromDocgen(component, section); + sections[section] = extractPropsFromDocgen(component, section).map(x => x.propDef); }); return { sections }; }; diff --git a/addons/docs/src/frameworks/vue/preset.ts b/addons/docs/src/frameworks/vue/preset.ts new file mode 100644 index 00000000000..527ce55570c --- /dev/null +++ b/addons/docs/src/frameworks/vue/preset.ts @@ -0,0 +1,8 @@ +export function webpack(webpackConfig: any = {}, options: any = {}) { + webpackConfig.module.rules.push({ + test: /\.vue$/, + loader: 'vue-docgen-loader', + enforce: 'post', + }); + return webpackConfig; +} diff --git a/addons/docs/src/frameworks/web-components/config.js b/addons/docs/src/frameworks/web-components/config.js index a474900c1a0..a26c871ce27 100644 --- a/addons/docs/src/frameworks/web-components/config.js +++ b/addons/docs/src/frameworks/web-components/config.js @@ -8,10 +8,10 @@ import { render } from 'lit-html'; function mapData(data) { return data.map(item => ({ name: item.name, - type: { name: item.type }, + type: { summary: item.type }, required: '', description: item.description, - defaultValue: item.default, + defaultValue: { summary: item.default }, })); } diff --git a/addons/docs/src/lib/DocgenInfo.ts b/addons/docs/src/lib/DocgenInfo.ts deleted file mode 100644 index 9330dc13642..00000000000 --- a/addons/docs/src/lib/DocgenInfo.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface DocgenInfo { - type?: { - name: string; - value?: { - name?: string; - raw?: string; - }; - }; - flowType?: any; - tsType?: any; - required: boolean; - description?: string; - defaultValue?: { - value: string; - }; -} diff --git a/addons/docs/src/lib/docgen/createDefaultValue.ts b/addons/docs/src/lib/docgen/createDefaultValue.ts new file mode 100644 index 00000000000..36fdc32f711 --- /dev/null +++ b/addons/docs/src/lib/docgen/createDefaultValue.ts @@ -0,0 +1,23 @@ +import { isNil } from 'lodash'; +import { PropDefaultValue } from '@storybook/components'; +import { DocgenPropDefaultValue } from './types'; + +const BLACKLIST = ['null', 'undefined']; + +function isDefaultValueBlacklisted(value: string) { + return BLACKLIST.some(x => x === value); +} + +export function createDefaultValue(defaultValue: DocgenPropDefaultValue): PropDefaultValue { + if (!isNil(defaultValue)) { + const { value } = defaultValue; + + if (!isDefaultValueBlacklisted(value)) { + return { + summary: value, + }; + } + } + + return null; +} diff --git a/addons/docs/src/lib/docgen/createPropDef.ts b/addons/docs/src/lib/docgen/createPropDef.ts new file mode 100644 index 00000000000..c314511d86a --- /dev/null +++ b/addons/docs/src/lib/docgen/createPropDef.ts @@ -0,0 +1,99 @@ +import { isNil } from 'lodash'; +import { PropDef } from '@storybook/components'; +import { TypeSystem, DocgenInfo, DocgenType } from './types'; +import { JsDocParsingResult } from '../jsdocParser'; +import { createDefaultValue } from './createDefaultValue'; + +export type PropDefFactory = ( + propName: string, + docgenInfo: DocgenInfo, + jsDocParsingResult?: JsDocParsingResult +) => PropDef; + +function createBasicPropDef(name: string, type: DocgenType, docgenInfo: DocgenInfo): PropDef { + const { description, required, defaultValue } = docgenInfo; + + return { + name, + type: { summary: type.name }, + required, + description, + defaultValue: createDefaultValue(defaultValue), + }; +} + +function createPropDef( + name: string, + type: DocgenType, + docgenInfo: DocgenInfo, + jsDocParsingResult: JsDocParsingResult +): PropDef { + const propDef = createBasicPropDef(name, type, docgenInfo); + + if (jsDocParsingResult.includesJsDoc) { + const { description, extractedTags } = jsDocParsingResult; + + if (!isNil(description)) { + propDef.description = jsDocParsingResult.description; + } + + const hasParams = !isNil(extractedTags.params); + const hasReturns = !isNil(extractedTags.returns) && !isNil(extractedTags.returns.type); + + if (hasParams || hasReturns) { + propDef.jsDocTags = { + params: + hasParams && + extractedTags.params.map(x => ({ name: x.getPrettyName(), description: x.description })), + returns: hasReturns && { description: extractedTags.returns.description }, + }; + } + } + + return propDef; +} + +export const javaScriptFactory: PropDefFactory = ( + propName: string, + docgenInfo: DocgenInfo, + jsDocParsingResult?: JsDocParsingResult +) => { + return createPropDef(propName, docgenInfo.type, docgenInfo, jsDocParsingResult); +}; + +export const tsFactory: PropDefFactory = ( + propName: string, + docgenInfo: DocgenInfo, + jsDocParsingResult?: JsDocParsingResult +) => { + return createPropDef(propName, docgenInfo.tsType, docgenInfo, jsDocParsingResult); +}; + +export const flowFactory: PropDefFactory = ( + propName: string, + docgenInfo: DocgenInfo, + jsDocParsingResult?: JsDocParsingResult +) => { + return createPropDef(propName, docgenInfo.flowType, docgenInfo, jsDocParsingResult); +}; + +export const unknownFactory: PropDefFactory = ( + propName: string, + docgenInfo: DocgenInfo, + jsDocParsingResult?: JsDocParsingResult +) => { + return createPropDef(propName, { name: 'unknown' }, docgenInfo, jsDocParsingResult); +}; + +export const getPropDefFactory = (typeSystem: TypeSystem): PropDefFactory => { + switch (typeSystem) { + case TypeSystem.JAVASCRIPT: + return javaScriptFactory; + case TypeSystem.TYPESCRIPT: + return tsFactory; + case TypeSystem.FLOW: + return flowFactory; + default: + return unknownFactory; + } +}; diff --git a/addons/docs/src/lib/docgen/extractDocgenProps.test.ts b/addons/docs/src/lib/docgen/extractDocgenProps.test.ts new file mode 100644 index 00000000000..64a1a67dd6d --- /dev/null +++ b/addons/docs/src/lib/docgen/extractDocgenProps.test.ts @@ -0,0 +1,155 @@ +/* eslint-disable no-underscore-dangle */ + +import { Component } from '../../blocks/shared'; +import { extractPropsFromDocgen } from './extractDocgenProps'; + +const DOCGEN_SECTION = 'props'; +const PROP_NAME = 'propName'; + +interface TypeSystemDef { + name: string; + typeProperty?: string; +} + +const TypeSystems: TypeSystemDef[] = [ + { name: 'javascript', typeProperty: 'type' }, + { name: 'typescript', typeProperty: 'tsType' }, +]; + +function createType(typeName: string, others: Record<string, any> = {}): Record<string, string> { + return { + name: typeName, + ...others, + }; +} + +function createStringType(typeSystemDef: TypeSystemDef, others: Record<string, any> = {}): any { + return { + [typeSystemDef.typeProperty]: createType('string', others), + }; +} + +function createFuncType(typeSystemDef: TypeSystemDef, others: Record<string, any> = {}): any { + const typeName = typeSystemDef.name === 'javascript' ? 'func' : '() => {}'; + + return { + [typeSystemDef.typeProperty]: createType(typeName, others), + }; +} + +function createComponent(docgenInfo: Record<string, any>): Component { + const component = () => {}; + // @ts-ignore + component.__docgenInfo = { + [DOCGEN_SECTION]: { + [PROP_NAME]: { + required: false, + ...docgenInfo, + }, + }, + }; + + return component; +} + +TypeSystems.forEach(x => { + it('should map defaults docgen info properly', () => { + const component = createComponent({ + ...createStringType(x), + description: 'Hey! Hey!', + defaultValue: { + value: 'Default', + }, + }); + + const { propDef } = extractPropsFromDocgen(component, DOCGEN_SECTION)[0]; + + expect(propDef.name).toBe(PROP_NAME); + expect(propDef.type.summary).toBe('string'); + expect(propDef.description).toBe('Hey! Hey!'); + expect(propDef.required).toBe(false); + expect(propDef.defaultValue.summary).toBe('Default'); + }); + + it('should remove JSDoc tags from the description', () => { + const component = createComponent({ + ...createStringType(x), + description: 'Hey!\n@param event\nreturns {string}', + }); + + const { propDef } = extractPropsFromDocgen(component, DOCGEN_SECTION)[0]; + + expect(propDef.description).toBe('Hey!'); + }); + + it('should not remove newline characters of multilines description without JSDoc tags', () => { + const component = createComponent({ + ...createStringType(x), + description: 'onClick description\nis a\nmulti-lines\ndescription', + }); + + const { propDef } = extractPropsFromDocgen(component, DOCGEN_SECTION)[0]; + + expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription'); + }); + + it('should not remove newline characters of multilines description with JSDoc tags', () => { + const component = createComponent({ + ...createFuncType(x), + description: 'onClick description\nis a\nmulti-lines\ndescription\n@param event', + }); + + const { propDef } = extractPropsFromDocgen(component, DOCGEN_SECTION)[0]; + + expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription'); + }); + + it('should not remove markdown from description without JSDoc tags', () => { + const component = createComponent({ + ...createStringType(x), + description: 'onClick *emphasis*, **strong**, `formatted` description.', + }); + + const { propDef } = extractPropsFromDocgen(component, DOCGEN_SECTION)[0]; + + expect(propDef.description).toBe('onClick *emphasis*, **strong**, `formatted` description.'); + }); + + it('should not remove markdown from description with JSDoc tags', () => { + const component = createComponent({ + ...createFuncType(x), + description: 'onClick *emphasis*, **strong**, `formatted` description.\n@param event', + }); + + const { propDef } = extractPropsFromDocgen(component, DOCGEN_SECTION)[0]; + + expect(propDef.description).toBe('onClick *emphasis*, **strong**, `formatted` description.'); + }); + + it('should return null when the property is marked with @ignore', () => { + const component = createComponent({ + ...createStringType(x), + description: 'onClick description\n@ignore', + }); + + expect(extractPropsFromDocgen(component, DOCGEN_SECTION).length).toBe(0); + }); + + it('should provide raw @param tags', () => { + const component = createComponent({ + ...createFuncType(x), + description: + 'onClick description\n@param {SyntheticEvent} event - Original event.\n@param {string} value', + }); + + const { propDef } = extractPropsFromDocgen(component, DOCGEN_SECTION)[0]; + + expect(propDef.description).toBe('onClick description'); + expect(propDef.jsDocTags).toBeDefined(); + expect(propDef.jsDocTags.params).toBeDefined(); + expect(propDef.jsDocTags.params[0].name).toBe('event'); + expect(propDef.jsDocTags.params[0].description).toBe('Original event.'); + expect(propDef.jsDocTags.params[1].name).toBe('value'); + expect(propDef.jsDocTags.params[1].description).toBeNull(); + }); +}); diff --git a/addons/docs/src/lib/docgen/extractDocgenProps.ts b/addons/docs/src/lib/docgen/extractDocgenProps.ts new file mode 100644 index 00000000000..adcf4d906da --- /dev/null +++ b/addons/docs/src/lib/docgen/extractDocgenProps.ts @@ -0,0 +1,77 @@ +import { isNil } from 'lodash'; +import { PropDef } from '@storybook/components'; +import { Component } from '../../blocks/shared'; +import { ExtractedJsDoc, parseJsDoc } from '../jsdocParser'; +import { DocgenInfo, TypeSystem } from './types'; +import { getDocgenSection, isValidDocgenSection } from './utils'; +import { getPropDefFactory, PropDefFactory } from './createPropDef'; + +export interface ExtractedProp { + propDef: PropDef; + docgenInfo: DocgenInfo; + jsDocTags: ExtractedJsDoc; + typeSystem: TypeSystem; +} + +export type ExtractProps = (component: Component, section: string) => ExtractedProp[]; + +const getTypeSystem = (docgenInfo: DocgenInfo): TypeSystem => { + if (!isNil(docgenInfo.type)) { + return TypeSystem.JAVASCRIPT; + } + + if (!isNil(docgenInfo.flowType)) { + return TypeSystem.FLOW; + } + + if (!isNil(docgenInfo.tsType)) { + return TypeSystem.TYPESCRIPT; + } + + return TypeSystem.UNKNOWN; +}; + +export const extractPropsFromDocgen: ExtractProps = (component, section) => { + const docgenSection = getDocgenSection(component, section); + + if (!isValidDocgenSection(docgenSection)) { + return []; + } + + const docgenPropsKeys = Object.keys(docgenSection); + const typeSystem = getTypeSystem(docgenSection[docgenPropsKeys[0]]); + const createPropDef = getPropDefFactory(typeSystem); + + return docgenPropsKeys + .map(propName => { + const docgenInfo = docgenSection[propName]; + + return !isNil(docgenInfo) + ? extractProp(propName, docgenInfo, typeSystem, createPropDef) + : null; + }) + .filter(x => x); +}; + +function extractProp( + propName: string, + docgenInfo: DocgenInfo, + typeSystem: TypeSystem, + createPropDef: PropDefFactory +): ExtractedProp { + const jsDocParsingResult = parseJsDoc(docgenInfo.description); + const isIgnored = jsDocParsingResult.includesJsDoc && jsDocParsingResult.ignore; + + if (!isIgnored) { + const propDef = createPropDef(propName, docgenInfo, jsDocParsingResult); + + return { + propDef, + jsDocTags: jsDocParsingResult.extractedTags, + docgenInfo, + typeSystem, + }; + } + + return null; +} diff --git a/addons/docs/src/lib/docgen/index.ts b/addons/docs/src/lib/docgen/index.ts new file mode 100644 index 00000000000..4116325caa8 --- /dev/null +++ b/addons/docs/src/lib/docgen/index.ts @@ -0,0 +1,3 @@ +export * from './types'; +export * from './utils'; +export * from './extractDocgenProps'; diff --git a/addons/docs/src/lib/docgen/types.ts b/addons/docs/src/lib/docgen/types.ts new file mode 100644 index 00000000000..fd560c9edc7 --- /dev/null +++ b/addons/docs/src/lib/docgen/types.ts @@ -0,0 +1,44 @@ +import { PropsTableProps } from '@storybook/components'; +import { Component } from '../../blocks/shared'; + +export type PropsExtractor = (component: Component) => PropsTableProps | null; + +export interface DocgenBaseType { + name: string; + description?: string; + require?: boolean; +} + +export interface DocgenPropType extends DocgenBaseType { + value?: any; + raw?: string; + computed?: boolean; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DocgenFlowType extends DocgenBaseType {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DocgenTypeScriptType extends DocgenBaseType {} + +export type DocgenType = DocgenPropType | DocgenFlowType | DocgenTypeScriptType; + +export interface DocgenPropDefaultValue { + value: string; +} + +export interface DocgenInfo { + type?: DocgenPropType; + flowType?: DocgenFlowType; + tsType?: DocgenTypeScriptType; + required: boolean; + description?: string; + defaultValue?: DocgenPropDefaultValue; +} + +export enum TypeSystem { + JAVASCRIPT = 'JavaScript', + FLOW = 'Flow', + TYPESCRIPT = 'TypeScript', + UNKNOWN = 'Unknown', +} diff --git a/addons/docs/src/lib/docgen/utils.ts b/addons/docs/src/lib/docgen/utils.ts new file mode 100644 index 00000000000..4bdc8c7138a --- /dev/null +++ b/addons/docs/src/lib/docgen/utils.ts @@ -0,0 +1,29 @@ +/* eslint-disable no-underscore-dangle */ + +import { isNil } from 'lodash'; +import { Component } from '../../blocks/shared'; + +export const str = (obj: any) => { + if (!obj) { + return ''; + } + if (typeof obj === 'string') { + return obj as string; + } + throw new Error(`Description: expected string, got: ${JSON.stringify(obj)}`); +}; + +export function hasDocgen(component: Component): boolean { + return !!component.__docgenInfo; +} + +export function isValidDocgenSection(docgenSection: any) { + return !isNil(docgenSection) && Object.keys(docgenSection).length > 0; +} + +export function getDocgenSection(component: Component, section: string): any { + return hasDocgen(component) ? component.__docgenInfo[section] : null; +} + +export const extractComponentDescription = (component?: Component) => + component && hasDocgen(component) && str(component.__docgenInfo.description); diff --git a/addons/docs/src/lib/docgenUtils.ts b/addons/docs/src/lib/docgenUtils.ts deleted file mode 100644 index 447ade46e9d..00000000000 --- a/addons/docs/src/lib/docgenUtils.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* eslint-disable no-underscore-dangle */ -import { PropDef, PropsTableProps } from '@storybook/components'; -import { Component } from '../blocks/shared'; -import { getTypeSystemHandler, getPropTypeSystem } from './type-system-handlers'; - -export type PropsExtractor = (component: Component) => PropsTableProps | null; - -export type PropDefGetter = (component: Component, section: string) => PropDef[]; - -export const str = (o: any) => { - if (!o) { - return ''; - } - if (typeof o === 'string') { - return o as string; - } - throw new Error(`Description: expected string, got: ${JSON.stringify(o)}`); -}; - -export const hasDocgen = (component: Component) => !!component.__docgenInfo; - -export const hasDocgenSection = (component: Component, section: string) => - component && - component.__docgenInfo && - component.__docgenInfo[section] && - Object.keys(component.__docgenInfo[section]).length > 0; - -export const extractPropsFromDocgen: PropDefGetter = (component, section) => { - if (!hasDocgenSection(component, section)) { - return []; - } - - const props: Record<string, PropDef> = {}; - const docgenInfoProps = component.__docgenInfo[section]; - const propKeys = Object.keys(docgenInfoProps); - - // Assuming the props for a given component will all have the same type system. - const typeSystem = getPropTypeSystem(docgenInfoProps[propKeys[0]]); - const typeSystemHandler = getTypeSystemHandler(typeSystem); - - propKeys.forEach(propKey => { - const docgenInfoProp = docgenInfoProps[propKey]; - - const result = typeSystemHandler(propKey, docgenInfoProp); - - if (!result.ignore) { - props[propKey] = result.propDef; - } - }); - - return Object.values(props); -}; - -export const extractComponentDescription = (component?: Component) => - component && component.__docgenInfo && str(component.__docgenInfo.description); diff --git a/addons/docs/src/lib/jsdoc-parser.ts b/addons/docs/src/lib/jsdoc-parser.ts deleted file mode 100644 index 577cc763087..00000000000 --- a/addons/docs/src/lib/jsdoc-parser.ts +++ /dev/null @@ -1,187 +0,0 @@ -import doctrine, { Annotation } from 'doctrine'; -import { isNil } from 'lodash'; -import { DocgenInfo } from './DocgenInfo'; - -export type ParseJsDoc = (docgenInfo: DocgenInfo) => JsDocParsingResult; - -export interface JsDocParsingResult { - ignore: boolean; - description?: string; - extractedTags?: ExtractedJsDocTags; -} - -export interface ExtractedJsDocParamTag { - name: string; - type?: doctrine.Type; - description?: string; - raw: doctrine.Tag; - getPrettyName: () => string; - getTypeName: () => string; -} - -export interface ExtractedJsDocReturnsTag { - type?: doctrine.Type; - description?: string; - raw: doctrine.Tag; - getTypeName: () => string; -} - -export interface ExtractedJsDocTags { - params?: ExtractedJsDocParamTag[]; - returns?: ExtractedJsDocReturnsTag; - ignore: boolean; -} - -function parse(content: string): Annotation { - let ast; - - try { - ast = doctrine.parse(content, { - tags: ['param', 'arg', 'argument', 'returns', 'ignore'], - sloppy: true, - }); - } catch (e) { - // eslint-disable-next-line no-console - console.error(e); - - throw new Error('Cannot parse JSDoc tags.'); - } - - return ast; -} - -export const parseJsDoc: ParseJsDoc = (docgenInfo: DocgenInfo) => { - const jsDocAst = parse(docgenInfo.description); - const extractedTags = extractJsDocTags(jsDocAst); - - if (extractedTags.ignore) { - // There is no point in doing other stuff since this prop will not be rendered. - return { - ignore: true, - }; - } - - return { - ignore: false, - // Always use the parsed description to ensure JSDoc is removed from the description. - description: jsDocAst.description, - extractedTags, - }; -}; - -function extractJsDocTags(ast: doctrine.Annotation): ExtractedJsDocTags { - const extractedTags: ExtractedJsDocTags = { - params: null, - returns: null, - ignore: false, - }; - - for (let i = 0; i < ast.tags.length; i += 1) { - const tag = ast.tags[i]; - - // arg & argument are aliases for param. - if (tag.title === 'param' || tag.title === 'arg' || tag.title === 'argument') { - const paramName = tag.name; - - // When the @param doesn't have a name but have a type and a description, "null-null" is returned. - if (!isNil(paramName) && paramName !== 'null-null') { - if (isNil(extractedTags.params)) { - extractedTags.params = []; - } - - extractedTags.params.push({ - name: tag.name, - type: tag.type, - description: tag.description, - raw: tag, - getPrettyName: () => { - if (paramName.includes('null')) { - // There is a few cases in which the returned param name contains "null". - // - @param {SyntheticEvent} event- Original SyntheticEvent - // - @param {SyntheticEvent} event.\n@returns {string} - return paramName.replace('-null', '').replace('.null', ''); - } - - return tag.name; - }, - getTypeName: () => { - return !isNil(tag.type) ? extractJsDocTypeName(tag.type) : null; - }, - }); - } - } else if (tag.title === 'returns') { - if (!isNil(tag.type)) { - extractedTags.returns = { - type: tag.type, - description: tag.description, - raw: tag, - getTypeName: () => { - return extractJsDocTypeName(tag.type); - }, - }; - } - } else if (tag.title === 'ignore') { - extractedTags.ignore = true; - // Once we reach an @ignore tag, there is no point in parsing the other tags since we will not render the prop. - break; - } - } - - return extractedTags; -} - -// FIXME: type argument should be doctrine.Type instead of any. -function extractJsDocTypeName(type: any): string { - if (type.type === 'NameExpression') { - return type.name; - } - - if (type.type === 'RecordType') { - const recordFields = type.fields.map((field: doctrine.type.FieldType) => { - if (!isNil(field.value)) { - const valueTypeName = extractJsDocTypeName(field.value); - - return `${field.key}: ${valueTypeName}`; - } - - return field.key; - }); - - return `({${recordFields.join(', ')}})`; - } - - if (type.type === 'UnionType') { - const unionElements = type.elements.map(extractJsDocTypeName); - - return `(${unionElements.join('|')})`; - } - - // Only support untyped array: []. Might add more support later if required. - if (type.type === 'ArrayType') { - return '[]'; - } - - if (type.type === 'TypeApplication') { - if (!isNil(type.expression)) { - if (type.expression.name === 'Array') { - const arrayType = extractJsDocTypeName(type.applications[0]); - - return `${arrayType}[]`; - } - } - } - - if ( - type.type === 'NullableType' || - type.type === 'NonNullableType' || - type.type === 'OptionalType' - ) { - return extractJsDocTypeName(type.expression); - } - - if (type.type === 'AllLiteral') { - return 'any'; - } - - return null; -} diff --git a/addons/docs/src/lib/jsdocParser.test.ts b/addons/docs/src/lib/jsdocParser.test.ts new file mode 100644 index 00000000000..eb2b539d3bb --- /dev/null +++ b/addons/docs/src/lib/jsdocParser.test.ts @@ -0,0 +1,344 @@ +import { parseJsDoc } from './jsdocParser'; + +describe('parseJsDoc', () => { + it('should set includesJsDoc to false when the value is null', () => { + const { includesJsDoc, description, extractedTags } = parseJsDoc(null); + + expect(includesJsDoc).toBeFalsy(); + expect(description).toBeUndefined(); + expect(extractedTags).toBeUndefined(); + }); + + it('should set includesJsDocto to false when the value dont contains JSDoc', () => { + const { includesJsDoc, description, extractedTags } = parseJsDoc('Hey!'); + + expect(includesJsDoc).toBeFalsy(); + expect(description).toBeUndefined(); + expect(extractedTags).toBeUndefined(); + }); + + it('should set includesJsDoc to true when the value contains JSDoc', () => { + const { includesJsDoc } = parseJsDoc('Hey!\n@version 1.2'); + + expect(includesJsDoc).toBeTruthy(); + }); + + it('should remove all JSDoc tags from the description', () => { + const { description } = parseJsDoc('Hey!\n@version 1.2\n@deprecated'); + + expect(description).toBe('Hey!'); + }); + + describe('@ignore', () => { + it('should set ignore to true when @ignore is present', () => { + const { ignore, description, extractedTags } = parseJsDoc('Hey!\n@ignore'); + + expect(ignore).toBeTruthy(); + expect(description).toBeUndefined(); + expect(extractedTags).toBeUndefined(); + }); + + it('should set ignore to false when @ignore is not present', () => { + const { ignore } = parseJsDoc('Hey!\n@version 1.2'); + + expect(ignore).toBeFalsy(); + }); + }); + + describe('@param', () => { + it('should ignore invalid @param tags', () => { + const { extractedTags } = parseJsDoc('@param'); + + expect(extractedTags.params).toBeNull(); + }); + + it('should return a @param with a name', () => { + const { extractedTags } = parseJsDoc('@param event'); + + expect(extractedTags.params).not.toBeNull(); + expect(extractedTags.params[0].name).toBe('event'); + expect(extractedTags.params[0].type).toBeNull(); + expect(extractedTags.params[0].description).toBeNull(); + }); + + it('should return a @param with a name and a type', () => { + const { extractedTags } = parseJsDoc('@param {SyntheticEvent} event'); + + expect(extractedTags.params).not.toBeNull(); + expect(extractedTags.params[0].name).toBe('event'); + expect(extractedTags.params[0].type).not.toBeNull(); + expect(extractedTags.params[0].type.name).toBe('SyntheticEvent'); + expect(extractedTags.params[0].description).toBeNull(); + }); + + it('should return a @param with a name, a type and a description', () => { + const { extractedTags } = parseJsDoc('@param {SyntheticEvent} event - React event'); + + expect(extractedTags.params).not.toBeNull(); + expect(extractedTags.params[0].name).toBe('event'); + expect(extractedTags.params[0].type).not.toBeNull(); + expect(extractedTags.params[0].type.name).toBe('SyntheticEvent'); + expect(extractedTags.params[0].description).toBe('React event'); + }); + + it('should support multiple @param tags', () => { + const { extractedTags } = parseJsDoc( + '@param {SyntheticEvent} event1 - React event\n@param {SyntheticEvent} event2 - React event\n@param {SyntheticEvent} event3 - React event' + ); + + ['event1', 'event2', 'event3'].forEach((x, i) => { + expect(extractedTags.params[i].name).toBe(x); + expect(extractedTags.params[i].type).not.toBeNull(); + expect(extractedTags.params[i].type.name).toBe('SyntheticEvent'); + expect(extractedTags.params[i].description).toBe('React event'); + }); + }); + + it('should not return extra @param', () => { + const { extractedTags } = parseJsDoc('@param event'); + + expect(Object.keys(extractedTags.params).length).toBe(1); + }); + + it('should support multiline description when there is a @param', () => { + const { description, extractedTags } = parseJsDoc( + 'This is a\nmultiline description\n@param event' + ); + + expect(description).toBe('This is a\nmultiline description'); + expect(extractedTags.params).not.toBeNull(); + expect(extractedTags.params[0].name).toBe('event'); + }); + + it('should support multiline @param description', () => { + const { extractedTags } = parseJsDoc( + '@param event - This is a\nmultiline description\n@param anotherEvent' + ); + + expect(extractedTags.params).not.toBeNull(); + expect(extractedTags.params[0].name).toBe('event'); + expect(extractedTags.params[0].description).toBe('This is a\nmultiline description'); + expect(extractedTags.params[1].name).toBe('anotherEvent'); + }); + + ['@arg', '@argument'].forEach(x => { + it(`should support ${x} alias`, () => { + const { extractedTags } = parseJsDoc(`${x} {SyntheticEvent} event - React event`); + + expect(extractedTags.params).not.toBeNull(); + expect(extractedTags.params[0].name).toBe('event'); + expect(extractedTags.params[0].type).not.toBeNull(); + expect(extractedTags.params[0].type.name).toBe('SyntheticEvent'); + expect(extractedTags.params[0].description).toBe('React event'); + }); + }); + + describe('getTypeName', () => { + it('should support record type with a single field', () => { + const { extractedTags } = parseJsDoc('@param {{a: number}} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('({a: number})'); + }); + + it('should support record type with multiple fields', () => { + const { extractedTags } = parseJsDoc('@param {{a: number, b: string}} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('({a: number, b: string})'); + }); + + it('should support record type with a field having only a name', () => { + const { extractedTags } = parseJsDoc('@param {{a}} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('({a})'); + }); + + it('should support union type', () => { + const { extractedTags } = parseJsDoc('@param {(number|boolean)} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('(number|boolean)'); + }); + + it('should support array type', () => { + const { extractedTags } = parseJsDoc('@param {number[]} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('number[]'); + }); + + it('should support untyped array type', () => { + const { extractedTags } = parseJsDoc('@param {[]} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('[]'); + }); + + it('should support nullable type', () => { + const { extractedTags } = parseJsDoc('@param {?number} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('number'); + }); + + it('should support non nullable type', () => { + const { extractedTags } = parseJsDoc('@param {!number} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('number'); + }); + + it('should support optional param with []', () => { + const { extractedTags } = parseJsDoc('@param {number} [event]'); + + expect(extractedTags.params[0].getTypeName()).toBe('number'); + }); + + it('should support optional param with =', () => { + const { extractedTags } = parseJsDoc('@param {number=} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('number'); + }); + + it('should support any type', () => { + const { extractedTags } = parseJsDoc('@param {*} event'); + + expect(extractedTags.params[0].getTypeName()).toBe('any'); + }); + }); + + describe('getPrettyName', () => { + it('should return @param name', () => { + const { extractedTags } = parseJsDoc('@param {SyntheticEvent} event - React event'); + + expect(extractedTags.params[0].getPrettyName()).toBe('event'); + }); + + it('should fix missing space between the @param name and the description separator', () => { + const { extractedTags } = parseJsDoc('@param {SyntheticEvent} event- React event'); + + expect(extractedTags.params[0].getPrettyName()).toBe('event'); + }); + + it('should fix @param name ending with . followed by a @returns tag', () => { + const { extractedTags } = parseJsDoc('@param {SyntheticEvent} event.\n'); + + expect(extractedTags.params[0].getPrettyName()).toBe('event'); + }); + }); + }); + + describe('@returns', () => { + it('should ignore invalid @returns', () => { + const { extractedTags } = parseJsDoc('@returns'); + + expect(extractedTags.returns).toBeNull(); + }); + + it('should return a @returns with a type', () => { + const { extractedTags } = parseJsDoc('@returns {string}'); + + expect(extractedTags.returns).not.toBeNull(); + expect(extractedTags.returns.type).not.toBeNull(); + expect(extractedTags.returns.type.name).toBe('string'); + }); + + it('should return a @returns with a type and a description', () => { + const { extractedTags } = parseJsDoc('@returns {string} - A bar description'); + + expect(extractedTags.returns).not.toBeNull(); + expect(extractedTags.returns.type).not.toBeNull(); + expect(extractedTags.returns.type.name).toBe('string'); + expect(extractedTags.returns.description).toBe('A bar description'); + }); + + it('should support multiline @returns description', () => { + const { extractedTags } = parseJsDoc( + '@returns {string} - This is\na multiline\ndescription\n' + ); + + expect(extractedTags.returns).not.toBeNull(); + expect(extractedTags.returns.type).not.toBeNull(); + expect(extractedTags.returns.type.name).toBe('string'); + expect(extractedTags.returns.description).toBe('This is\na multiline\ndescription'); + }); + + it('should only consider the last @returns tag when there is multiple', () => { + const { extractedTags } = parseJsDoc('@returns {string}\n@returns {number}'); + + expect(extractedTags.returns).not.toBeNull(); + expect(extractedTags.returns.type).not.toBeNull(); + expect(extractedTags.returns.type.name).toBe('number'); + }); + + describe('getTypeName', () => { + it('should support named type', () => { + const { extractedTags } = parseJsDoc('@returns {string}'); + + expect(extractedTags.returns.getTypeName()).toBe('string'); + }); + + it('should support record type with a single field', () => { + const { extractedTags } = parseJsDoc('@returns {{a: number}}'); + + expect(extractedTags.returns.getTypeName()).toBe('({a: number})'); + }); + + it('should support record type with multiple fields', () => { + const { extractedTags } = parseJsDoc('@returns {{a: number, b: string}}'); + + expect(extractedTags.returns.getTypeName()).toBe('({a: number, b: string})'); + }); + + it('should support record type with a field having only a name', () => { + const { extractedTags } = parseJsDoc('@returns {{a}}'); + + expect(extractedTags.returns.getTypeName()).toBe('({a})'); + }); + + it('should support array type', () => { + const { extractedTags } = parseJsDoc('@returns {integer[]}'); + + expect(extractedTags.returns.getTypeName()).toBe('integer[]'); + }); + + it('should support untyped array type', () => { + const { extractedTags } = parseJsDoc('@returns {[]}'); + + expect(extractedTags.returns.getTypeName()).toBe('[]'); + }); + + it('should support union type', () => { + const { extractedTags } = parseJsDoc('@returns {(number|boolean)}'); + + expect(extractedTags.returns.getTypeName()).toBe('(number|boolean)'); + }); + + it('should support any type', () => { + const { extractedTags } = parseJsDoc('@returns {*}'); + + expect(extractedTags.returns.getTypeName()).toBe('any'); + }); + + it('should support void', () => { + const { extractedTags } = parseJsDoc('@returns {void}'); + + expect(extractedTags.returns.getTypeName()).toBe('void'); + }); + }); + }); + + it('should ignore unsupported JSDoc tags', () => { + const { extractedTags } = parseJsDoc('Hey!\n@param event', { tags: [] }); + + expect(extractedTags.params).toBeNull(); + }); + + it('should remove extra newline characters between tags', () => { + const { extractedTags } = parseJsDoc( + 'Hey!\n@param {SyntheticEvent} event - Original event.\n \n \n \n@returns {string}' + ); + + expect(extractedTags.params).not.toBeNull(); + expect(Object.keys(extractedTags.params).length).toBe(1); + expect(extractedTags.params[0].name).toBe('event'); + expect(extractedTags.params[0].type.name).toBe('SyntheticEvent'); + expect(extractedTags.params[0].description).toBe('Original event.'); + expect(extractedTags.returns).not.toBeNull(); + expect(extractedTags.returns.type.name).toBe('string'); + }); +}); diff --git a/addons/docs/src/lib/jsdocParser.ts b/addons/docs/src/lib/jsdocParser.ts new file mode 100644 index 00000000000..d489baf76d2 --- /dev/null +++ b/addons/docs/src/lib/jsdocParser.ts @@ -0,0 +1,234 @@ +import doctrine, { Annotation } from 'doctrine'; +import { isNil } from 'lodash'; + +export interface ExtractedJsDocParam { + name: string; + type?: any; + description?: string; + getPrettyName: () => string; + getTypeName: () => string; +} + +export interface ExtractedJsDocReturns { + type?: any; + description?: string; + getTypeName: () => string; +} + +export interface ExtractedJsDoc { + params?: ExtractedJsDocParam[]; + returns?: ExtractedJsDocReturns; + ignore: boolean; +} + +export interface JsDocParsingOptions { + tags?: string[]; +} + +export interface JsDocParsingResult { + includesJsDoc: boolean; + ignore: boolean; + description?: string; + extractedTags?: ExtractedJsDoc; +} + +export type ParseJsDoc = (value?: string, options?: JsDocParsingOptions) => JsDocParsingResult; + +function containsJsDoc(value?: string): boolean { + return !isNil(value) && value.includes('@'); +} + +function parse(content: string, tags: string[]): Annotation { + let ast; + + try { + ast = doctrine.parse(content, { + tags, + sloppy: true, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + + throw new Error('Cannot parse JSDoc tags.'); + } + + return ast; +} + +const DEFAULT_OPTIONS = { + tags: ['param', 'arg', 'argument', 'returns', 'ignore'], +}; + +export const parseJsDoc: ParseJsDoc = ( + value?: string, + options: JsDocParsingOptions = DEFAULT_OPTIONS +) => { + if (!containsJsDoc(value)) { + return { + includesJsDoc: false, + ignore: false, + }; + } + + const jsDocAst = parse(value, options.tags); + const extractedTags = extractJsDocTags(jsDocAst); + + if (extractedTags.ignore) { + // There is no point in doing other stuff since this prop will not be rendered. + return { + includesJsDoc: true, + ignore: true, + }; + } + + return { + includesJsDoc: true, + ignore: false, + // Always use the parsed description to ensure JSDoc is removed from the description. + description: jsDocAst.description, + extractedTags, + }; +}; + +function extractJsDocTags(ast: doctrine.Annotation): ExtractedJsDoc { + const extractedTags: ExtractedJsDoc = { + params: null, + returns: null, + ignore: false, + }; + + for (let i = 0; i < ast.tags.length; i += 1) { + const tag = ast.tags[i]; + + if (tag.title === 'ignore') { + extractedTags.ignore = true; + // Once we reach an @ignore tag, there is no point in parsing the other tags since we will not render the prop. + break; + } else { + switch (tag.title) { + // arg & argument are aliases for param. + case 'param': + case 'arg': + case 'argument': { + const paramTag = extractParam(tag); + if (!isNil(paramTag)) { + if (isNil(extractedTags.params)) { + extractedTags.params = []; + } + extractedTags.params.push(paramTag); + } + break; + } + case 'returns': { + const returnsTag = extractReturns(tag); + if (!isNil(returnsTag)) { + extractedTags.returns = returnsTag; + } + break; + } + default: + break; + } + } + } + + return extractedTags; +} + +function extractParam(tag: doctrine.Tag): ExtractedJsDocParam { + const paramName = tag.name; + + // When the @param doesn't have a name but have a type and a description, "null-null" is returned. + if (!isNil(paramName) && paramName !== 'null-null') { + return { + name: tag.name, + type: tag.type, + description: tag.description, + getPrettyName: () => { + if (paramName.includes('null')) { + // There is a few cases in which the returned param name contains "null". + // - @param {SyntheticEvent} event- Original SyntheticEvent + // - @param {SyntheticEvent} event.\n@returns {string} + return paramName.replace('-null', '').replace('.null', ''); + } + + return tag.name; + }, + getTypeName: () => { + return !isNil(tag.type) ? extractTypeName(tag.type) : null; + }, + }; + } + + return null; +} + +function extractReturns(tag: doctrine.Tag): ExtractedJsDocReturns { + if (!isNil(tag.type)) { + return { + type: tag.type, + description: tag.description, + getTypeName: () => { + return extractTypeName(tag.type); + }, + }; + } + + return null; +} + +function extractTypeName(type: doctrine.Type): string { + if (type.type === 'NameExpression') { + return type.name; + } + + if (type.type === 'RecordType') { + const recordFields = type.fields.map((field: doctrine.type.FieldType) => { + if (!isNil(field.value)) { + const valueTypeName = extractTypeName(field.value); + + return `${field.key}: ${valueTypeName}`; + } + + return field.key; + }); + + return `({${recordFields.join(', ')}})`; + } + + if (type.type === 'UnionType') { + const unionElements = type.elements.map(extractTypeName); + + return `(${unionElements.join('|')})`; + } + + // Only support untyped array: []. Might add more support later if required. + if (type.type === 'ArrayType') { + return '[]'; + } + + if (type.type === 'TypeApplication') { + if (!isNil(type.expression)) { + if ((type.expression as doctrine.type.NameExpression).name === 'Array') { + const arrayType = extractTypeName(type.applications[0]); + + return `${arrayType}[]`; + } + } + } + + if ( + type.type === 'NullableType' || + type.type === 'NonNullableType' || + type.type === 'OptionalType' + ) { + return extractTypeName(type.expression); + } + + if (type.type === 'AllLiteral') { + return 'any'; + } + + return null; +} diff --git a/addons/docs/src/lib/type-system-handlers.test.ts b/addons/docs/src/lib/type-system-handlers.test.ts deleted file mode 100644 index 4c02c60d41d..00000000000 --- a/addons/docs/src/lib/type-system-handlers.test.ts +++ /dev/null @@ -1,903 +0,0 @@ -import { propTypesHandler, tsHandler, flowHandler, unknownHandler } from './type-system-handlers'; -import { DocgenInfo } from './DocgenInfo'; - -const DEFAULT_PROP_NAME = 'propName'; - -const PROP_TYPES_STRING_TYPE = { - name: 'string', -}; - -const PROP_TYPES_FUNC_TYPE = { - name: 'func', -}; - -const TS_FUNC_TYPE = { - name: '() => void', -}; - -const TS_STRING_TYPE = { - name: 'string', -}; - -function createDocgenInfo(overrides: Record<string, any> = {}): DocgenInfo { - return { - type: null, - required: true, - description: 'A string prop', - defaultValue: { - value: 'default string', - }, - ...overrides, - }; -} - -describe('prop-types handler', () => { - it('should map defaults docgen info properly', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.name).toBe(DEFAULT_PROP_NAME); - expect(propDef.type.name).toBe(docgenInfo.type.name); - expect(propDef.description).toBe(docgenInfo.description); - expect(propDef.required).toBe(docgenInfo.required); - expect(propDef.defaultValue).toBe(docgenInfo.defaultValue.value); - }); - - describe('for all prop types', () => { - it('should handle prop without a description', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: undefined, - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBeUndefined(); - }); - - it('should clean the description', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick description\n@param {SyntheticEvent} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description'); - }); - - it('should have an empty description when the description only contains JSDoc', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: '@param event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe(''); - }); - - it('should not remove newline characters of multilines description without JSDoc tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick description\nis a\nmulti-lines\ndescription', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription'); - }); - - it('should not remove newline characters of multilines description with JSDoc tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick description\nis a\nmulti-lines\ndescription\n@param event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription'); - }); - - it('should not remove markdown from description without JSDoc tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick *emphasis*, **strong**, `formatted` description.', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick *emphasis*, **strong**, `formatted` description.'); - }); - - it('should not remove markdown from description with JSDoc tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick *emphasis*, **strong**, `formatted` description.\n@param event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick *emphasis*, **strong**, `formatted` description.'); - }); - - it('should not remove @ characters that does not match JSDoc tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick @description@', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick @description@'); - }); - - it('should not set ignore to true when the property is not marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick description', - }); - - const { ignore } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(ignore).toBeFalsy(); - }); - - it('should set ignore to true when the property is marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_STRING_TYPE, - description: 'onClick description\n@ignore', - }); - - const { ignore } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(ignore).toBeTruthy(); - }); - }); - - describe('when the prop is a function', () => { - it("should have func as type when the props doesn't have a description", () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: undefined, - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBeUndefined(); - expect(propDef.type.name).toBe('func'); - }); - - it('should have func as type when the prop have a description without JSDoc', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('func'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have an empty description when the description only contains JSDoc', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: '@param event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe(''); - }); - - describe('when the description contains a @param tag', () => { - it('should have func as type when it is an invalid @param tag', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('func'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have a func signature with a single arg as type when it is a @param tag with a name', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have a func signature with a single arg as type when it is a @param tag with a name and a type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {SyntheticEvent} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have a func signature with a single arg as type when it is a @param tag with a name, a type and a desc', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original SyntheticEvent', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have func as type when it is @param tag without a name 1', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param - Original SyntheticEvent', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('func'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have func as type when it is @param tag without a name 2', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {SyntheticEvent} - Original SyntheticEvent', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('func'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param of record type with a single field', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {{a: number}} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: ({a: number}))'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param of record type with multiple fields', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {{a: number, b: string}} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: ({a: number, b: string}))'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param of record type with a field having only a name', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {{a}} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: ({a}))'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param of union type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {(number|boolean)} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: (number|boolean))'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param of array type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {number[]} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: number[])'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param of untyped array type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {[]} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: [])'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param with a nullable type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {?number} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: number)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param with a non nullable type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {!number} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: number)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support optional param 1', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {number} [event]', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: number)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support optional param 2', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {number=} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: number)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support param of type any', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {*} event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: any)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support multilines description when there is a @param', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\nis a\nmulti-lines\ndescription\n@param event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event)'); - expect(propDef.description).toBe('onClick description\nis a\nmulti-lines\ndescription'); - }); - - it('should support multilines @param description', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param event - This is my param\nmultiline description\n@param customData', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event, customData)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should autofix missing space between the param name and the description separator', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event- Original SyntheticEvent', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should autofix param name ending with . followed by a @returns tag', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param {SyntheticEvent} event.\n', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should provide raw @param tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@param {string} value', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description'); - expect(propDef.jsDocTags).toBeDefined(); - expect(propDef.jsDocTags.params).toBeDefined(); - expect(propDef.jsDocTags.params[0].name).toBe('event'); - expect(propDef.jsDocTags.params[0].description).toBe('Original event.'); - expect(propDef.jsDocTags.params[1].name).toBe('value'); - expect(propDef.jsDocTags.params[1].description).toBeNull(); - }); - }); - - describe('when the description contains multiple @param tags', () => { - it('should have a func signature with multiple args as type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event\n@param {string} customData', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent, customData: string)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should ignore invalid @param tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event\n@param {string} customData\n@param {SyntheticEvent} - Original event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent, customData: string)'); - expect(propDef.description).toBe('onClick description'); - }); - }); - - it('should support @arg alias', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@arg event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support @argument alias', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@argument event', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event)'); - expect(propDef.description).toBe('onClick description'); - }); - - describe('when the description contains a @returns tag', () => { - it('should have func as type when it is an invalid @returns tag', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('func'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have a func signature with a return type as type when it is a @returns tag with a type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {string}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => string'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have a func signature with a return type as type when it is a @returns tag with a type and a description', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {string} - A custom return type', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => string'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have func as type when it is a @returns tag without a type and there is no params.', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns - A custom return type', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('func'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have no return type when it is a @returns tag without a type and there is params.', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@param event\n@returns - A custom return type', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have a full signature as type when there is a @param and a @returns tag 1', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@returns {string}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent) => string'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should have a full signature as type when there is a @param and a @returns tag 2', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@param {string} customData\n@returns {string}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent, customData: string) => string'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should only consider the last @returns tag when there is more than one', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {string}\n@returns {integer}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => integer'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support returns of record type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {{a: number, b: string}}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => ({a: number, b: string})'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support returns of array type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {integer[]}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => integer[]'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support returns of union type', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {(number|boolean)}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => (number|boolean)'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support returns of type any', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {*}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => any'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should support returns of type void', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: 'onClick description\n@returns {void}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('() => void'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should provide raw @returns tags when a description is defined', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@returns {string} - An awesome string.', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description'); - expect(propDef.jsDocTags).toBeDefined(); - expect(propDef.jsDocTags.returns).toBeDefined(); - expect(propDef.jsDocTags.returns.description).toBe('An awesome string.'); - }); - - it('should provide raw @returns tags when there is no description', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@returns {string}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description'); - expect(propDef.jsDocTags).toBeDefined(); - expect(propDef.jsDocTags.returns).toBeDefined(); - expect(propDef.jsDocTags.returns.description).toBeNull(); - }); - }); - - it('should remove extra newline characters between tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n \n \n \n@returns {string}', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent) => string'); - expect(propDef.description).toBe('onClick description'); - }); - - it('should ignore unsupported JSDoc tags', () => { - const docgenInfo = createDocgenInfo({ - type: PROP_TYPES_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event\n@type {number}\n@returns {string}\n@version 2', - }); - - const { propDef } = propTypesHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.type.name).toBe('(event: SyntheticEvent) => string'); - expect(propDef.description).toBe('onClick description'); - }); - }); -}); - -describe('ts handler', () => { - it('should map defaults docgen info properly', () => { - const docgenInfo = createDocgenInfo({ - tsType: PROP_TYPES_STRING_TYPE, - }); - - const { propDef } = tsHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.name).toBe(DEFAULT_PROP_NAME); - expect(propDef.type.name).toBe(docgenInfo.tsType.name); - expect(propDef.description).toBe(docgenInfo.description); - expect(propDef.required).toBe(docgenInfo.required); - expect(propDef.defaultValue).toBe(docgenInfo.defaultValue.value); - }); - - it('should provide raw @param tags', () => { - const docgenInfo = createDocgenInfo({ - tsType: TS_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@param {string} value', - }); - - const { propDef } = tsHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description'); - expect(propDef.jsDocTags).toBeDefined(); - expect(propDef.jsDocTags.params).toBeDefined(); - expect(propDef.jsDocTags.params[0].name).toBe('event'); - expect(propDef.jsDocTags.params[0].description).toBe('Original event.'); - expect(propDef.jsDocTags.params[1].name).toBe('value'); - expect(propDef.jsDocTags.params[1].description).toBeNull(); - }); - - it('should provide raw @returns tags when a description is defined', () => { - const docgenInfo = createDocgenInfo({ - tsType: TS_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@returns {string} - An awesome string.', - }); - - const { propDef } = tsHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description'); - expect(propDef.jsDocTags).toBeDefined(); - expect(propDef.jsDocTags.returns).toBeDefined(); - expect(propDef.jsDocTags.returns.description).toBe('An awesome string.'); - }); - - it('should provide raw @returns tags when there is no description', () => { - const docgenInfo = createDocgenInfo({ - tsType: TS_FUNC_TYPE, - description: - 'onClick description\n@param {SyntheticEvent} event - Original event.\n@returns {string}', - }); - - const { propDef } = tsHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.description).toBe('onClick description'); - expect(propDef.jsDocTags).toBeDefined(); - expect(propDef.jsDocTags.returns).toBeDefined(); - expect(propDef.jsDocTags.returns.description).toBeNull(); - }); - - it('should not set ignore to true when the property is not marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - tsType: TS_STRING_TYPE, - description: 'onClick description', - }); - - const { ignore } = tsHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(ignore).toBeFalsy(); - }); - - it('should set ignore to true when the property is marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - tsType: TS_STRING_TYPE, - description: 'onClick description\n@ignore', - }); - - const { ignore } = tsHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(ignore).toBeTruthy(); - }); -}); - -describe('flow handler', () => { - it('should map defaults docgen info properly', () => { - const docgenInfo = createDocgenInfo({ - flowType: { - name: 'string', - }, - }); - - const { propDef } = flowHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.name).toBe(DEFAULT_PROP_NAME); - expect(propDef.type.name).toBe(docgenInfo.flowType.name); - expect(propDef.description).toBe(docgenInfo.description); - expect(propDef.required).toBe(docgenInfo.required); - expect(propDef.defaultValue).toBe(docgenInfo.defaultValue.value); - }); - - it('should not set ignore to true when the property is not marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - flowType: { - name: 'string', - }, - description: 'onClick description', - }); - - const { ignore } = flowHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(ignore).toBeFalsy(); - }); - - it('should set ignore to true when the property is marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - flowType: { - name: 'string', - }, - description: 'onClick description\n@ignore', - }); - - const { ignore } = flowHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(ignore).toBeTruthy(); - }); -}); - -describe('unknown handler', () => { - it('should map defaults docgen info properly', () => { - const docgenInfo = createDocgenInfo(); - - const { propDef } = unknownHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(propDef.name).toBe(DEFAULT_PROP_NAME); - expect(propDef.type.name).toBe('unknown'); - expect(propDef.description).toBe(docgenInfo.description); - expect(propDef.required).toBe(docgenInfo.required); - expect(propDef.defaultValue).toBe(docgenInfo.defaultValue.value); - }); - - it('should not set ignore to true when the property is not marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - description: 'onClick description', - }); - - const { ignore } = unknownHandler(DEFAULT_PROP_NAME, docgenInfo); - - expect(ignore).toBeFalsy(); - }); - - it('should set ignore to true when the property is marked with @ignore', () => { - const docgenInfo = createDocgenInfo({ - description: 'onClick description\n@ignore', - }); - - const { ignore } = unknownHandler(DEFAULT_PROP_NAME, docgenInfo); - expect(ignore).toBeTruthy(); - }); -}); diff --git a/addons/docs/src/lib/type-system-handlers.ts b/addons/docs/src/lib/type-system-handlers.ts deleted file mode 100644 index 71d8fe95c0d..00000000000 --- a/addons/docs/src/lib/type-system-handlers.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { PropDef } from '@storybook/components'; -import { isNil } from 'lodash'; -import { parseJsDoc, ExtractedJsDocTags, ExtractedJsDocParamTag } from './jsdoc-parser'; -import { DocgenInfo } from './DocgenInfo'; - -export const TypeSystem = { - Flow: 'Flow', - TypeScript: 'TypeScript', - PropTypes: 'PropTypes', - Unknown: 'Unknown', -}; - -export interface TypeSystemHandlerResult { - propDef?: PropDef; - ignore: boolean; -} - -export type TypeSystemHandler = ( - propName: string, - docgenInfo: DocgenInfo -) => TypeSystemHandlerResult; - -interface HandlePropResult extends TypeSystemHandlerResult { - extractedJsDocTags?: ExtractedJsDocTags; -} - -function createDefaultPropDef( - propName: string, - propType: { - name: string; - }, - docgenInfo: DocgenInfo -): PropDef { - const { description, required, defaultValue } = docgenInfo; - - return { - name: propName, - type: propType, - required, - description, - defaultValue: isNil(defaultValue) ? null : defaultValue.value, - }; -} - -function propMightContainsJsDoc(docgenInfo: DocgenInfo): boolean { - return !isNil(docgenInfo.description) && docgenInfo.description.includes('@'); -} - -function handleProp( - propName: string, - propType: { - name: string; - }, - docgenInfo: DocgenInfo -): HandlePropResult { - const propDef = createDefaultPropDef(propName, propType, docgenInfo); - - if (propMightContainsJsDoc(docgenInfo)) { - const { ignore, description, extractedTags } = parseJsDoc(docgenInfo); - - if (ignore) { - return { - ignore: true, - }; - } - - if (!isNil(description)) { - propDef.description = description; - } - - const hasParams = !isNil(extractedTags.params); - const hasReturns = !isNil(extractedTags.returns) && !isNil(extractedTags.returns.type); - - if (hasParams || hasReturns) { - propDef.jsDocTags = { - params: hasParams && extractedTags.params.map(x => x.raw), - returns: hasReturns && extractedTags.returns.raw, - }; - - return { - propDef, - extractedJsDocTags: extractedTags, - ignore: false, - }; - } - } - - return { - propDef, - ignore: false, - }; -} - -export const propTypesHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => { - const result = handleProp(propName, docgenInfo.type, docgenInfo); - - if (!result.ignore) { - const { propDef, extractedJsDocTags } = result; - - // When available use the proper JSDoc tags to describe the function signature instead of displaying "func". - if (propDef.type.name === 'func') { - if (!isNil(extractedJsDocTags)) { - const hasParams = !isNil(extractedJsDocTags.params); - const hasReturns = !isNil(extractedJsDocTags.returns); - - if (hasParams || hasReturns) { - const funcParts = []; - - if (hasParams) { - const funcParams = extractedJsDocTags.params.map((x: ExtractedJsDocParamTag) => { - const prettyName = x.getPrettyName(); - const typeName = x.getTypeName(); - - if (!isNil(typeName)) { - return `${prettyName}: ${typeName}`; - } - - return prettyName; - }); - - funcParts.push(`(${funcParams.join(', ')})`); - } else { - funcParts.push('()'); - } - - if (hasReturns) { - funcParts.push(`=> ${extractedJsDocTags.returns.getTypeName()}`); - } - - propDef.type = { - name: funcParts.join(' '), - }; - } - } - } - } - - return result; -}; - -export const tsHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => { - return handleProp(propName, docgenInfo.tsType, docgenInfo); -}; - -export const flowHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => { - return handleProp(propName, docgenInfo.flowType, docgenInfo); -}; - -export const unknownHandler: TypeSystemHandler = (propName: string, docgenInfo: DocgenInfo) => { - return handleProp(propName, { name: 'unknown' }, docgenInfo); -}; - -export const TypeSystemHandlers: Record<string, TypeSystemHandler> = { - [TypeSystem.Flow]: flowHandler, - [TypeSystem.TypeScript]: tsHandler, - [TypeSystem.PropTypes]: propTypesHandler, - [TypeSystem.Unknown]: unknownHandler, -}; - -export const getPropTypeSystem = (docgenInfo: DocgenInfo): string => { - if (!isNil(docgenInfo.flowType)) { - return TypeSystem.Flow; - } - - if (!isNil(docgenInfo.tsType)) { - return TypeSystem.TypeScript; - } - - if (!isNil(docgenInfo.type)) { - return TypeSystem.PropTypes; - } - - return TypeSystem.Unknown; -}; - -export const getTypeSystemHandler = (typeSystem: string): TypeSystemHandler => { - return TypeSystemHandlers[typeSystem]; -}; diff --git a/addons/docs/src/mdx/__snapshots__/mdx-compiler-plugin.test.js.snap b/addons/docs/src/mdx/__snapshots__/mdx-compiler-plugin.test.js.snap deleted file mode 100644 index 76cfd8a7409..00000000000 --- a/addons/docs/src/mdx/__snapshots__/mdx-compiler-plugin.test.js.snap +++ /dev/null @@ -1,849 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`docs-mdx-compiler-plugin decorators.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Button } from '@storybook/react/demo'; -import { Story, Meta } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta - title=\\"Button\\" - decorators={[ - storyFn => ( - <div - style={{ - backgroundColor: 'yellow', - }} - > - {storyFn()} - </div> - ), - ]} - mdxType=\\"Meta\\" - /> - <h1>{\`Decorated story\`}</h1> - <Story - name=\\"one\\" - decorators={[storyFn => <div className=\\"local\\">{storyFn()}</div>]} - mdxType=\\"Story\\" - > - <Button mdxType=\\"Button\\">One</Button> - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const one = () => <Button>One</Button>; -one.story = {}; -one.story.name = 'one'; -one.story.parameters = { mdxSource: '<Button>One</Button>' }; -one.story.decorators = [storyFn => <div className=\\"local\\">{storyFn()}</div>]; - -const componentMeta = { - title: 'Button', - decorators: [ - storyFn => ( - <div - style={{ - backgroundColor: 'yellow', - }} - > - {storyFn()} - </div> - ), - ], - includeStories: ['one'], -}; - -const mdxStoryNameToId = { one: 'button--one' }; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin docs-only.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Meta } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta title=\\"docs-only\\" mdxType=\\"Meta\\" /> - <h1>{\`Documentation only\`}</h1> - <p> - {\`This is a documentation-only MDX file which generates a dummy \`} - <inlineCode parentName=\\"p\\">{\`docsOnly: true\`}</inlineCode> - {\` story.\`} - </p> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const __page = () => { - throw new Error('Docs-only story'); -}; - -__page.story = { parameters: { docsOnly: true } }; - -const componentMeta = { title: 'docs-only', includeStories: ['__page'] }; - -const mdxStoryNameToId = {}; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin non-story-exports.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Button } from '@storybook/react/demo'; -import { Story, Meta } from '@storybook/addon-docs/blocks'; -export const two = 2; -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = { - two, -}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta title=\\"Button\\" mdxType=\\"Meta\\" /> - <h1>{\`Story definition\`}</h1> - <Story name=\\"one\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">One</Button> - </Story> - - <Story name=\\"hello story\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">Hello button</Button> - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const one = () => <Button>One</Button>; -one.story = {}; -one.story.name = 'one'; -one.story.parameters = { mdxSource: '<Button>One</Button>' }; - -export const helloStory = () => <Button>Hello button</Button>; -helloStory.story = {}; -helloStory.story.name = 'hello story'; -helloStory.story.parameters = { mdxSource: '<Button>Hello button</Button>' }; - -const componentMeta = { title: 'Button', includeStories: ['one', 'helloStory'] }; - -const mdxStoryNameToId = { one: 'button--one', 'hello story': 'button--hello-story' }; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin parameters.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Button } from '@storybook/react/demo'; -import { Story, Meta } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta - title=\\"Button\\" - component={Button} - parameters={{ - notes: 'component notes', - }} - mdxType=\\"Meta\\" - /> - <Story name=\\"component notes\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">Component notes</Button> - </Story> - <Story - name=\\"story notes\\" - parameters={{ - notes: 'story notes', - }} - mdxType=\\"Story\\" - > - <Button mdxType=\\"Button\\">Story notes</Button> - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const componentNotes = () => <Button>Component notes</Button>; -componentNotes.story = {}; -componentNotes.story.name = 'component notes'; -componentNotes.story.parameters = { mdxSource: '<Button>Component notes</Button>' }; - -export const storyNotes = () => <Button>Story notes</Button>; -storyNotes.story = {}; -storyNotes.story.name = 'story notes'; -storyNotes.story.parameters = { - mdxSource: '<Button>Story notes</Button>', - ...{ - notes: 'story notes', - }, -}; - -const componentMeta = { - title: 'Button', - parameters: { - notes: 'component notes', - }, - includeStories: ['componentNotes', 'storyNotes'], -}; - -const mdxStoryNameToId = { - 'component notes': 'button--component-notes', - 'story notes': 'button--story-notes', -}; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin previews.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Button } from '@storybook/react/demo'; -import { Preview, Story, Meta } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta - title=\\"Button\\" - component={Button} - parameters={{ - notes: 'component notes', - }} - mdxType=\\"Meta\\" - /> - <h1>{\`Preview\`}</h1> - <p>{\`Previews can contain normal components, stories, and story references\`}</p> - <Preview mdxType=\\"Preview\\"> - <Button mdxType=\\"Button\\">Just a button</Button> - <Story name=\\"hello button\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">Hello button</Button> - </Story> - <Story name=\\"two\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">Two</Button> - </Story> - <Story id=\\"welcome--welcome\\" mdxType=\\"Story\\" /> - </Preview> - <p>{\`Preview wthout a story\`}</p> - <Preview mdxSource=\\"%0A%3CButton%3EJust%20a%20button%3C/Button%3E%0A\\" mdxType=\\"Preview\\"> - <Button mdxType=\\"Button\\">Just a button</Button> - </Preview> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const helloButton = () => <Button>Hello button</Button>; -helloButton.story = {}; -helloButton.story.name = 'hello button'; -helloButton.story.parameters = { mdxSource: '<Button>Hello button</Button>' }; - -export const two = () => <Button>Two</Button>; -two.story = {}; -two.story.name = 'two'; -two.story.parameters = { mdxSource: '<Button>Two</Button>' }; - -const componentMeta = { - title: 'Button', - parameters: { - notes: 'component notes', - }, - includeStories: ['helloButton', 'two'], -}; - -const mdxStoryNameToId = { 'hello button': 'button--hello-button', two: 'button--two' }; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin story-current.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Story } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <h1>{\`Current story\`}</h1> - <Story id=\\".\\" mdxType=\\"Story\\" /> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -const componentMeta = { includeStories: [] }; - -const mdxStoryNameToId = {}; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin story-def-text-only.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Story, Meta } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta title=\\"Text\\" mdxType=\\"Meta\\" /> - <h1>{\`Story definition\`}</h1> - <Story name=\\"text\\" mdxType=\\"Story\\"> - Plain text - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const text = makeStoryFn('Plain text'); -text.story = {}; -text.story.name = 'text'; -text.story.parameters = { mdxSource: \\"'Plain text'\\" }; - -const componentMeta = { title: 'Text', includeStories: ['text'] }; - -const mdxStoryNameToId = { text: 'text--text' }; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin story-definitions.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Button } from '@storybook/react/demo'; -import { Story, Meta } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta title=\\"Button\\" mdxType=\\"Meta\\" /> - <h1>{\`Story definition\`}</h1> - <Story name=\\"one\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">One</Button> - </Story> - <Story name=\\"hello story\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">Hello button</Button> - </Story> - <Story name=\\"w/punctuation\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">with punctuation</Button> - </Story> - <Story name=\\"1 fine day\\" mdxType=\\"Story\\"> - <Button mdxType=\\"Button\\">starts with number</Button> - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const one = () => <Button>One</Button>; -one.story = {}; -one.story.name = 'one'; -one.story.parameters = { mdxSource: '<Button>One</Button>' }; - -export const helloStory = () => <Button>Hello button</Button>; -helloStory.story = {}; -helloStory.story.name = 'hello story'; -helloStory.story.parameters = { mdxSource: '<Button>Hello button</Button>' }; - -export const wPunctuation = () => <Button>with punctuation</Button>; -wPunctuation.story = {}; -wPunctuation.story.name = 'w/punctuation'; -wPunctuation.story.parameters = { mdxSource: '<Button>with punctuation</Button>' }; - -export const _1FineDay = () => <Button>starts with number</Button>; -_1FineDay.story = {}; -_1FineDay.story.name = '1 fine day'; -_1FineDay.story.parameters = { mdxSource: '<Button>starts with number</Button>' }; - -const componentMeta = { - title: 'Button', - includeStories: ['one', 'helloStory', 'wPunctuation', '_1FineDay'], -}; - -const mdxStoryNameToId = { - one: 'button--one', - 'hello story': 'button--hello-story', - 'w/punctuation': 'button--w-punctuation', - '1 fine day': 'button--1-fine-day', -}; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin story-function.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; -const Story = makeShortcode('Story'); -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Story name=\\"function\\" height=\\"100px\\" mdxType=\\"Story\\"> - {() => { - const btn = document.createElement('button'); - btn.innerHTML = 'Hello Button'; - btn.addEventListener('click', action('Click')); - return btn; - }} - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const functionStory = makeStoryFn(() => { - const btn = document.createElement('button'); - btn.innerHTML = 'Hello Button'; - btn.addEventListener('click', action('Click')); - return btn; -}); -functionStory.story = {}; -functionStory.story.name = 'function'; -functionStory.story.parameters = { - mdxSource: - \\"() => {\\\\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'] }; - -const mdxStoryNameToId = {}; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin story-function-var.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Meta, Story } from '@storybook/addon-docs/blocks'; -export const basicFn = () => <Button mdxType=\\"Button\\" />; -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; -const Button = makeShortcode('Button'); -const layoutProps = { - basicFn, -}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta title=\\"story-function-var\\" mdxType=\\"Meta\\" /> - - <h1>{\`Button\`}</h1> - <p>{\`I can define a story with the function defined in CSF:\`}</p> - <Story name=\\"basic\\" mdxType=\\"Story\\"> - {basicFn} - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const basic = makeStoryFn(basicFn); -basic.story = {}; -basic.story.name = 'basic'; -basic.story.parameters = { mdxSource: 'basicFn' }; - -const componentMeta = { title: 'story-function-var', includeStories: ['basic'] }; - -const mdxStoryNameToId = { basic: 'story-function-var--basic' }; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin story-object.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Story, Meta } from '@storybook/addon-docs/blocks'; -import { Welcome, Button } from '@storybook/angular/demo'; -import { linkTo } from '@storybook/addon-links'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <Meta title=\\"MDX|Welcome\\" mdxType=\\"Meta\\" /> - <h1>{\`Story object\`}</h1> - <Story name=\\"to storybook\\" height=\\"300px\\" mdxType=\\"Story\\"> - {{ - template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`, - props: { - showApp: linkTo('Button'), - }, - moduleMetadata: { - declarations: [Welcome], - }, - }} - </Story> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -export const toStorybook = makeStoryFn({ - template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`, - props: { - showApp: linkTo('Button'), - }, - moduleMetadata: { - declarations: [Welcome], - }, -}); -toStorybook.story = {}; -toStorybook.story.name = 'to storybook'; -toStorybook.story.parameters = { - mdxSource: - '{\\\\n template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`,\\\\n props: {\\\\n showApp: linkTo(\\\\'Button\\\\')\\\\n },\\\\n moduleMetadata: {\\\\n declarations: [Welcome]\\\\n }\\\\n}', -}; - -const componentMeta = { title: 'MDX|Welcome', includeStories: ['toStorybook'] }; - -const mdxStoryNameToId = { 'to storybook': 'mdx-welcome--to-storybook' }; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin story-references.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Story } from '@storybook/addon-docs/blocks'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <h1>{\`Story reference\`}</h1> - <Story id=\\"welcome--welcome\\" mdxType=\\"Story\\" /> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -const componentMeta = { includeStories: [] }; - -const mdxStoryNameToId = {}; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; - -exports[`docs-mdx-compiler-plugin vanilla.mdx 1`] = ` -"/* @jsx mdx */ -import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; - -import { Button } from '@storybook/react/demo'; - -const makeShortcode = name => - function MDXDefaultShortcode(props) { - console.warn( - 'Component ' + - name + - ' was not imported, exported, or provided by MDXProvider as global scope' - ); - return <div {...props} />; - }; - -const layoutProps = {}; -const MDXLayout = 'wrapper'; -function MDXContent({ components, ...props }) { - return ( - <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> - <h1>{\`Hello MDX\`}</h1> - <p>{\`This is some random content.\`}</p> - <Button mdxType=\\"Button\\">Hello button</Button> - </MDXLayout> - ); -} - -MDXContent.isMDXComponent = true; - -const componentMeta = { includeStories: [] }; - -const mdxStoryNameToId = {}; - -componentMeta.parameters = componentMeta.parameters || {}; -componentMeta.parameters.docs = { - container: ({ context, children }) => ( - <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> - ), - page: MDXContent, -}; - -export default componentMeta; -" -`; diff --git a/addons/docs/src/mdx/__testfixtures__/component-id.mdx b/addons/docs/src/mdx/__testfixtures__/component-id.mdx new file mode 100644 index 00000000000..e6ca2de9dad --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/component-id.mdx @@ -0,0 +1,8 @@ +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +<Meta title="Button" component={Button} id="button-id" /> + +<Story name="component notes"> + <Button>Component notes</Button> +</Story> diff --git a/addons/docs/src/mdx/__testfixtures__/component-id.output.snapshot b/addons/docs/src/mdx/__testfixtures__/component-id.output.snapshot new file mode 100644 index 00000000000..55814119d63 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/component-id.output.snapshot @@ -0,0 +1,54 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin component-id.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta title=\\"Button\\" component={Button} id=\\"button-id\\" mdxType=\\"Meta\\" /> + <Story name=\\"component notes\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">Component notes</Button> + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const componentNotes = () => <Button>Component notes</Button>; +componentNotes.story = {}; +componentNotes.story.name = 'component notes'; +componentNotes.story.parameters = { mdxSource: '<Button>Component notes</Button>' }; + +const componentMeta = { title: 'Button', id: 'button-id', includeStories: ['componentNotes'] }; + +const mdxStoryNameToId = { 'component notes': 'button-id--component-notes' }; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/decorators.output.snapshot b/addons/docs/src/mdx/__testfixtures__/decorators.output.snapshot new file mode 100644 index 00000000000..b398e22a6b7 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/decorators.output.snapshot @@ -0,0 +1,88 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin decorators.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta + title=\\"Button\\" + decorators={[ + storyFn => ( + <div + style={{ + backgroundColor: 'yellow', + }} + > + {storyFn()} + </div> + ), + ]} + mdxType=\\"Meta\\" + /> + <h1>{\`Decorated story\`}</h1> + <Story + name=\\"one\\" + decorators={[storyFn => <div className=\\"local\\">{storyFn()}</div>]} + mdxType=\\"Story\\" + > + <Button mdxType=\\"Button\\">One</Button> + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const one = () => <Button>One</Button>; +one.story = {}; +one.story.name = 'one'; +one.story.parameters = { mdxSource: '<Button>One</Button>' }; +one.story.decorators = [storyFn => <div className=\\"local\\">{storyFn()}</div>]; + +const componentMeta = { + title: 'Button', + decorators: [ + storyFn => ( + <div + style={{ + backgroundColor: 'yellow', + }} + > + {storyFn()} + </div> + ), + ], + includeStories: ['one'], +}; + +const mdxStoryNameToId = { one: 'button--one' }; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/docs-only.output.snapshot b/addons/docs/src/mdx/__testfixtures__/docs-only.output.snapshot new file mode 100644 index 00000000000..2b9c0bf30d9 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/docs-only.output.snapshot @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin docs-only.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta title=\\"docs-only\\" mdxType=\\"Meta\\" /> + <h1>{\`Documentation only\`}</h1> + <p> + {\`This is a documentation-only MDX file which generates a dummy \`} + <inlineCode parentName=\\"p\\">{\`docsOnly: true\`}</inlineCode> + {\` story.\`} + </p> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const __page = () => { + throw new Error('Docs-only story'); +}; + +__page.story = { parameters: { docsOnly: true } }; + +const componentMeta = { title: 'docs-only', includeStories: ['__page'] }; + +const mdxStoryNameToId = {}; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/non-story-exports.output.snapshot b/addons/docs/src/mdx/__testfixtures__/non-story-exports.output.snapshot new file mode 100644 index 00000000000..ff3a88ccf2c --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/non-story-exports.output.snapshot @@ -0,0 +1,66 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin non-story-exports.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; +export const two = 2; +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = { + two, +}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta title=\\"Button\\" mdxType=\\"Meta\\" /> + <h1>{\`Story definition\`}</h1> + <Story name=\\"one\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">One</Button> + </Story> + + <Story name=\\"hello story\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">Hello button</Button> + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const one = () => <Button>One</Button>; +one.story = {}; +one.story.name = 'one'; +one.story.parameters = { mdxSource: '<Button>One</Button>' }; + +export const helloStory = () => <Button>Hello button</Button>; +helloStory.story = {}; +helloStory.story.name = 'hello story'; +helloStory.story.parameters = { mdxSource: '<Button>Hello button</Button>' }; + +const componentMeta = { title: 'Button', includeStories: ['one', 'helloStory'] }; + +const mdxStoryNameToId = { one: 'button--one', 'hello story': 'button--hello-story' }; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/parameters.output.snapshot b/addons/docs/src/mdx/__testfixtures__/parameters.output.snapshot new file mode 100644 index 00000000000..d0825f6c34e --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/parameters.output.snapshot @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin parameters.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta + title=\\"Button\\" + component={Button} + parameters={{ + notes: 'component notes', + }} + mdxType=\\"Meta\\" + /> + <Story name=\\"component notes\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">Component notes</Button> + </Story> + <Story + name=\\"story notes\\" + parameters={{ + notes: 'story notes', + }} + mdxType=\\"Story\\" + > + <Button mdxType=\\"Button\\">Story notes</Button> + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const componentNotes = () => <Button>Component notes</Button>; +componentNotes.story = {}; +componentNotes.story.name = 'component notes'; +componentNotes.story.parameters = { mdxSource: '<Button>Component notes</Button>' }; + +export const storyNotes = () => <Button>Story notes</Button>; +storyNotes.story = {}; +storyNotes.story.name = 'story notes'; +storyNotes.story.parameters = { + mdxSource: '<Button>Story notes</Button>', + ...{ + notes: 'story notes', + }, +}; + +const componentMeta = { + title: 'Button', + parameters: { + notes: 'component notes', + }, + includeStories: ['componentNotes', 'storyNotes'], +}; + +const mdxStoryNameToId = { + 'component notes': 'button--component-notes', + 'story notes': 'button--story-notes', +}; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/previews.output.snapshot b/addons/docs/src/mdx/__testfixtures__/previews.output.snapshot new file mode 100644 index 00000000000..2ba1c7bf9af --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/previews.output.snapshot @@ -0,0 +1,85 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin previews.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Preview, Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta + title=\\"Button\\" + component={Button} + parameters={{ + notes: 'component notes', + }} + mdxType=\\"Meta\\" + /> + <h1>{\`Preview\`}</h1> + <p>{\`Previews can contain normal components, stories, and story references\`}</p> + <Preview mdxType=\\"Preview\\"> + <Button mdxType=\\"Button\\">Just a button</Button> + <Story name=\\"hello button\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">Hello button</Button> + </Story> + <Story name=\\"two\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">Two</Button> + </Story> + <Story id=\\"welcome--welcome\\" mdxType=\\"Story\\" /> + </Preview> + <p>{\`Preview wthout a story\`}</p> + <Preview mdxSource=\\"%0A%3CButton%3EJust%20a%20button%3C/Button%3E%0A\\" mdxType=\\"Preview\\"> + <Button mdxType=\\"Button\\">Just a button</Button> + </Preview> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const helloButton = () => <Button>Hello button</Button>; +helloButton.story = {}; +helloButton.story.name = 'hello button'; +helloButton.story.parameters = { mdxSource: '<Button>Hello button</Button>' }; + +export const two = () => <Button>Two</Button>; +two.story = {}; +two.story.name = 'two'; +two.story.parameters = { mdxSource: '<Button>Two</Button>' }; + +const componentMeta = { + title: 'Button', + parameters: { + notes: 'component notes', + }, + includeStories: ['helloButton', 'two'], +}; + +const mdxStoryNameToId = { 'hello button': 'button--hello-button', two: 'button--two' }; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/story-current.output.snapshot b/addons/docs/src/mdx/__testfixtures__/story-current.output.snapshot new file mode 100644 index 00000000000..5b1418ec9af --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/story-current.output.snapshot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin story-current.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Story } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <h1>{\`Current story\`}</h1> + <Story id=\\".\\" mdxType=\\"Story\\" /> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +const componentMeta = { includeStories: [] }; + +const mdxStoryNameToId = {}; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/story-def-text-only.output.snapshot b/addons/docs/src/mdx/__testfixtures__/story-def-text-only.output.snapshot new file mode 100644 index 00000000000..310639df0a5 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/story-def-text-only.output.snapshot @@ -0,0 +1,54 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin story-def-text-only.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta title=\\"Text\\" mdxType=\\"Meta\\" /> + <h1>{\`Story definition\`}</h1> + <Story name=\\"text\\" mdxType=\\"Story\\"> + Plain text + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const text = makeStoryFn('Plain text'); +text.story = {}; +text.story.name = 'text'; +text.story.parameters = { mdxSource: \\"'Plain text'\\" }; + +const componentMeta = { title: 'Text', includeStories: ['text'] }; + +const mdxStoryNameToId = { text: 'text--text' }; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/story-definitions.output.snapshot b/addons/docs/src/mdx/__testfixtures__/story-definitions.output.snapshot new file mode 100644 index 00000000000..3ed503cdc38 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/story-definitions.output.snapshot @@ -0,0 +1,87 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin story-definitions.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta title=\\"Button\\" mdxType=\\"Meta\\" /> + <h1>{\`Story definition\`}</h1> + <Story name=\\"one\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">One</Button> + </Story> + <Story name=\\"hello story\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">Hello button</Button> + </Story> + <Story name=\\"w/punctuation\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">with punctuation</Button> + </Story> + <Story name=\\"1 fine day\\" mdxType=\\"Story\\"> + <Button mdxType=\\"Button\\">starts with number</Button> + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const one = () => <Button>One</Button>; +one.story = {}; +one.story.name = 'one'; +one.story.parameters = { mdxSource: '<Button>One</Button>' }; + +export const helloStory = () => <Button>Hello button</Button>; +helloStory.story = {}; +helloStory.story.name = 'hello story'; +helloStory.story.parameters = { mdxSource: '<Button>Hello button</Button>' }; + +export const wPunctuation = () => <Button>with punctuation</Button>; +wPunctuation.story = {}; +wPunctuation.story.name = 'w/punctuation'; +wPunctuation.story.parameters = { mdxSource: '<Button>with punctuation</Button>' }; + +export const _1FineDay = () => <Button>starts with number</Button>; +_1FineDay.story = {}; +_1FineDay.story.name = '1 fine day'; +_1FineDay.story.parameters = { mdxSource: '<Button>starts with number</Button>' }; + +const componentMeta = { + title: 'Button', + includeStories: ['one', 'helloStory', 'wPunctuation', '_1FineDay'], +}; + +const mdxStoryNameToId = { + one: 'button--one', + 'hello story': 'button--hello-story', + 'w/punctuation': 'button--w-punctuation', + '1 fine day': 'button--1-fine-day', +}; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/story-function-var.output.snapshot b/addons/docs/src/mdx/__testfixtures__/story-function-var.output.snapshot new file mode 100644 index 00000000000..27da826cdc2 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/story-function-var.output.snapshot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin story-function-var.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Meta, Story } from '@storybook/addon-docs/blocks'; +export const basicFn = () => <Button mdxType=\\"Button\\" />; +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; +const Button = makeShortcode('Button'); +const layoutProps = { + basicFn, +}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta title=\\"story-function-var\\" mdxType=\\"Meta\\" /> + + <h1>{\`Button\`}</h1> + <p>{\`I can define a story with the function defined in CSF:\`}</p> + <Story name=\\"basic\\" mdxType=\\"Story\\"> + {basicFn} + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const basic = makeStoryFn(basicFn); +basic.story = {}; +basic.story.name = 'basic'; +basic.story.parameters = { mdxSource: 'basicFn' }; + +const componentMeta = { title: 'story-function-var', includeStories: ['basic'] }; + +const mdxStoryNameToId = { basic: 'story-function-var--basic' }; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/story-function.output.snapshot b/addons/docs/src/mdx/__testfixtures__/story-function.output.snapshot new file mode 100644 index 00000000000..54623560ee5 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/story-function.output.snapshot @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin story-function.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; +const Story = makeShortcode('Story'); +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Story name=\\"function\\" height=\\"100px\\" mdxType=\\"Story\\"> + {() => { + const btn = document.createElement('button'); + btn.innerHTML = 'Hello Button'; + btn.addEventListener('click', action('Click')); + return btn; + }} + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const functionStory = makeStoryFn(() => { + const btn = document.createElement('button'); + btn.innerHTML = 'Hello Button'; + btn.addEventListener('click', action('Click')); + return btn; +}); +functionStory.story = {}; +functionStory.story.name = 'function'; +functionStory.story.parameters = { + mdxSource: + \\"() => {\\\\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'] }; + +const mdxStoryNameToId = {}; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/story-object.output.snapshot b/addons/docs/src/mdx/__testfixtures__/story-object.output.snapshot new file mode 100644 index 00000000000..881825b0598 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/story-object.output.snapshot @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin story-object.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Story, Meta } from '@storybook/addon-docs/blocks'; +import { Welcome, Button } from '@storybook/angular/demo'; +import { linkTo } from '@storybook/addon-links'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <Meta title=\\"MDX|Welcome\\" mdxType=\\"Meta\\" /> + <h1>{\`Story object\`}</h1> + <Story name=\\"to storybook\\" height=\\"300px\\" mdxType=\\"Story\\"> + {{ + template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`, + props: { + showApp: linkTo('Button'), + }, + moduleMetadata: { + declarations: [Welcome], + }, + }} + </Story> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +export const toStorybook = makeStoryFn({ + template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`, + props: { + showApp: linkTo('Button'), + }, + moduleMetadata: { + declarations: [Welcome], + }, +}); +toStorybook.story = {}; +toStorybook.story.name = 'to storybook'; +toStorybook.story.parameters = { + mdxSource: + '{\\\\n template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`,\\\\n props: {\\\\n showApp: linkTo(\\\\'Button\\\\')\\\\n },\\\\n moduleMetadata: {\\\\n declarations: [Welcome]\\\\n }\\\\n}', +}; + +const componentMeta = { title: 'MDX|Welcome', includeStories: ['toStorybook'] }; + +const mdxStoryNameToId = { 'to storybook': 'mdx-welcome--to-storybook' }; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/story-references.output.snapshot b/addons/docs/src/mdx/__testfixtures__/story-references.output.snapshot new file mode 100644 index 00000000000..a96403ad036 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/story-references.output.snapshot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin story-references.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Story } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <h1>{\`Story reference\`}</h1> + <Story id=\\"welcome--welcome\\" mdxType=\\"Story\\" /> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +const componentMeta = { includeStories: [] }; + +const mdxStoryNameToId = {}; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/__testfixtures__/vanilla.output.snapshot b/addons/docs/src/mdx/__testfixtures__/vanilla.output.snapshot new file mode 100644 index 00000000000..e4a19e2ee01 --- /dev/null +++ b/addons/docs/src/mdx/__testfixtures__/vanilla.output.snapshot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin vanilla.mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return <div {...props} />; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + <MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\"> + <h1>{\`Hello MDX\`}</h1> + <p>{\`This is some random content.\`}</p> + <Button mdxType=\\"Button\\">Hello button</Button> + </MDXLayout> + ); +} + +MDXContent.isMDXComponent = true; + +const componentMeta = { includeStories: [] }; + +const mdxStoryNameToId = {}; + +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = { + container: ({ context, children }) => ( + <DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer> + ), + page: MDXContent, +}; + +export default componentMeta; +" +`; diff --git a/addons/docs/src/mdx/mdx-compiler-plugin.js b/addons/docs/src/mdx/mdx-compiler-plugin.js index e72c5c548ad..f5ca25aabfb 100644 --- a/addons/docs/src/mdx/mdx-compiler-plugin.js +++ b/addons/docs/src/mdx/mdx-compiler-plugin.js @@ -130,9 +130,11 @@ function genPreviewExports(ast, context) { function genMeta(ast) { let title = getAttr(ast.openingElement, 'title'); + let id = getAttr(ast.openingElement, 'id'); let parameters = getAttr(ast.openingElement, 'parameters'); let decorators = getAttr(ast.openingElement, 'decorators'); title = title && `'${title.value}'`; + id = id && `'${id.value}'`; if (parameters && parameters.expression) { const { code: params } = generate(parameters.expression, {}); parameters = params; @@ -143,6 +145,7 @@ function genMeta(ast) { } return { title, + id, parameters, decorators, }; @@ -295,11 +298,11 @@ function extractExports(node, options) { } metaExport.includeStories = JSON.stringify(includeStories); - const { title } = metaExport; + const { title, id: componentId } = metaExport; const mdxStoryNameToId = Object.entries(context.storyNameToKey).reduce( (acc, [storyName, storyKey]) => { if (title) { - acc[storyName] = toId(title, storyNameFromExport(storyKey)); + acc[storyName] = toId(componentId || title, storyNameFromExport(storyKey)); } return acc; }, diff --git a/addons/docs/src/mdx/mdx-compiler-plugin.test.js b/addons/docs/src/mdx/mdx-compiler-plugin.test.js index 81d9a4a779b..5945010318b 100644 --- a/addons/docs/src/mdx/mdx-compiler-plugin.test.js +++ b/addons/docs/src/mdx/mdx-compiler-plugin.test.js @@ -1,8 +1,9 @@ -const path = require('path'); -const fs = require('fs-extra'); -const mdx = require('@mdx-js/mdx'); -const prettier = require('prettier'); -const plugin = require('./mdx-compiler-plugin'); +import 'jest-specific-snapshot'; +import path from 'path'; +import fs from 'fs-extra'; +import mdx from '@mdx-js/mdx'; +import prettier from 'prettier'; +import plugin from './mdx-compiler-plugin'; async function generate(filePath) { const content = await fs.readFile(filePath, 'utf8'); @@ -22,28 +23,20 @@ async function generate(filePath) { }); } +const inputRegExp = /\.mdx$/; + describe('docs-mdx-compiler-plugin', () => { - const fixtures = [ - 'vanilla.mdx', - 'story-definitions.mdx', - 'story-def-text-only.mdx', - 'story-object.mdx', - 'story-references.mdx', - 'story-current.mdx', - 'previews.mdx', - 'decorators.mdx', - 'parameters.mdx', - 'non-story-exports.mdx', - 'story-function.mdx', - 'docs-only.mdx', - 'story-function-var.mdx', - ]; - fixtures.forEach(fixtureFile => { - it(fixtureFile, async () => { - const code = await generate(path.resolve(__dirname, `./__testfixtures__/${fixtureFile}`)); - expect(code).toMatchSnapshot(); + const transformFixturesDir = path.join(__dirname, '__testfixtures__'); + fs.readdirSync(transformFixturesDir) + .filter(fileName => inputRegExp.test(fileName)) + .filter(fileName => fileName !== 'story-missing-props.mdx') + .forEach(fixtureFile => { + it(fixtureFile, async () => { + const inputPath = path.join(transformFixturesDir, fixtureFile); + const code = await generate(inputPath); + expect(code).toMatchSpecificSnapshot(inputPath.replace(inputRegExp, '.output.snapshot')); + }); }); - }); it('errors on missing story props', async () => { await expect( generate(path.resolve(__dirname, './__testfixtures__/story-missing-props.mdx')) diff --git a/addons/docs/src/preset.ts b/addons/docs/src/preset.ts new file mode 100644 index 00000000000..ba24891b7bf --- /dev/null +++ b/addons/docs/src/preset.ts @@ -0,0 +1,57 @@ +import * as commonPreset from './frameworks/common/preset'; + +// Map a framework to a preset file that gets executed +type Preset = any; +type FrameworkPresetMapper = (framework: string) => string | void; + +const PRESET_METHODS = [ + 'babel', + 'babelDefault', + 'managerBabel', + 'webpack', + 'webpackFinal', + 'managerWebpack', + 'addons', + 'entries', + 'config', +]; + +function getFrameworkPreset(frameworkPresetFile: string): Preset { + // eslint-disable-next-line import/no-dynamic-require, global-require + return require(frameworkPresetFile); +} + +// Create a composite preset that applies the base preset & +// appends any framework-specific extensions as needed +function withFrameworkExtensions(basePreset: Preset, mapper: FrameworkPresetMapper): Preset { + const extended: Preset = {}; + PRESET_METHODS.forEach(method => { + extended[method] = (existing: any, options: any) => { + let updated = existing; + + const baseMethod = basePreset[method]; + if (baseMethod) { + updated = baseMethod(updated, options); + } + + const frameworkPresetFile = mapper(options.framework); + if (frameworkPresetFile) { + const frameworkPreset = getFrameworkPreset(frameworkPresetFile); + const frameworkMethod = frameworkPreset[method]; + if (frameworkMethod) updated = frameworkMethod(updated, options); + } + + return updated; + }; + }); + return extended; +} + +module.exports = withFrameworkExtensions(commonPreset, framework => { + try { + return require.resolve(`./frameworks/${framework}/preset`); + } catch (err) { + // there is no custom config for the user's framework, do nothing + return null; + } +}); diff --git a/addons/docs/src/typings.d.ts b/addons/docs/src/typings.d.ts index 1843064a188..179e926ed6a 100644 --- a/addons/docs/src/typings.d.ts +++ b/addons/docs/src/typings.d.ts @@ -1,5 +1,6 @@ declare module '@mdx-js/react'; declare module '@storybook/addon-docs/mdx-compiler-plugin'; +declare module '@storybook/addon-docs/blocks'; declare module 'global'; declare module 'react-is'; declare module '@egoist/vue-to-react'; diff --git a/addons/docs/vue/README.md b/addons/docs/vue/README.md index bb2748889b9..8c8348995e4 100644 --- a/addons/docs/vue/README.md +++ b/addons/docs/vue/README.md @@ -25,7 +25,7 @@ yarn add -D @storybook/addon-docs@next Then add the following to your `.storybook/presets.js` exports: ```js -module.exports = ['@storybook/addon-docs/vue/preset']; +module.exports = ['@storybook/addon-docs/preset']; ``` ## DocsPage diff --git a/addons/docs/vue/preset.js b/addons/docs/vue/preset.js index 83a11406ff3..09cb6c49e5e 100644 --- a/addons/docs/vue/preset.js +++ b/addons/docs/vue/preset.js @@ -1,16 +1 @@ -const commonExports = require('../dist/frameworks/common/makePreset').default('vue'); - -const webpack = (webpackConfig, options) => { - const config = commonExports.webpack(webpackConfig, options); - config.module.rules.push({ - test: /\.vue$/, - loader: 'storybook-addon-vue-info/loader', - enforce: 'post', - }); - return config; -}; - -module.exports = { - ...commonExports, - webpack, -}; +module.exports = require('../dist/frameworks/common/makePreset').default('vue'); diff --git a/addons/events/package.json b/addons/events/package.json index b4516196956..278f18c164d 100644 --- a/addons/events/package.json +++ b/addons/events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-events", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Add events to your Storybook stories.", "keywords": [ "addon", @@ -31,11 +31,11 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "format-json": "^1.0.3", "lodash": "^4.17.15", diff --git a/addons/google-analytics/README.md b/addons/google-analytics/README.md index 47ad138dcbd..c4e74fafc6e 100644 --- a/addons/google-analytics/README.md +++ b/addons/google-analytics/README.md @@ -22,4 +22,5 @@ Then, set an environment variable ``` window.STORYBOOK_GA_ID = UA-000000-01 +window.STORYBOOK_REACT_GA_OPTIONS = {} ``` diff --git a/addons/google-analytics/package.json b/addons/google-analytics/package.json index f52c7333787..8f57fc07d61 100644 --- a/addons/google-analytics/package.json +++ b/addons/google-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-google-analytics", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook addon for google analytics", "keywords": [ "addon", @@ -20,8 +20,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "react-ga": "^2.5.7" diff --git a/addons/google-analytics/src/register.ts b/addons/google-analytics/src/register.ts index 3c381e70b7e..1e998ddb877 100644 --- a/addons/google-analytics/src/register.ts +++ b/addons/google-analytics/src/register.ts @@ -5,7 +5,7 @@ import { STORY_CHANGED, STORY_ERRORED, STORY_MISSING } from '@storybook/core-eve import ReactGA from 'react-ga'; addons.register('storybook/google-analytics', api => { - ReactGA.initialize(window.STORYBOOK_GA_ID); + ReactGA.initialize(window.STORYBOOK_GA_ID, window.STORYBOOK_REACT_GA_OPTIONS); api.on(STORY_CHANGED, () => { const { url } = api.getUrlState(); diff --git a/addons/graphql/package.json b/addons/graphql/package.json index f91763dc28d..cc9efe8a8da 100644 --- a/addons/graphql/package.json +++ b/addons/graphql/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-graphql", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook addon to display the GraphiQL IDE", "keywords": [ "addon", @@ -29,8 +29,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "graphiql": "^0.16.0", diff --git a/addons/info/package.json b/addons/info/package.json index 8066a94f181..a4033f9d33f 100644 --- a/addons/info/package.json +++ b/addons/info/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-info", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "A Storybook addon to show additional information for your stories.", "keywords": [ "addon", @@ -28,10 +28,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "marksy": "^7.0.0", diff --git a/addons/info/src/__snapshots__/index.test.js.snap b/addons/info/src/__snapshots__/index.test.js.snap index 8108e71d3a9..faa87784894 100644 --- a/addons/info/src/__snapshots__/index.test.js.snap +++ b/addons/info/src/__snapshots__/index.test.js.snap @@ -1095,6 +1095,7 @@ exports[`addon Info should render component description if story kind matches co "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBd0NxQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", "name": "1o7rzh8-hoverable", "styles": "transition:all 150ms ease-out;transform:translate3d(0,0,0);&:hover{transform:translate3d(0,-2px,0);}&:active{transform:translate3d(0,0,0);};label:hoverable;", + "toString": [Function], }, "inlineGlow": Object { "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUNzQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", @@ -1365,12 +1366,12 @@ exports[`addon Info should render component description if story kind matches co "insert": [Function], "inserted": Object { "11xgcgt": true, + "1fhpnuv": true, "1imo1gr": true, "1maezg8": true, "1si67pu": true, "4zr3vl": true, "esgpkx": true, - "scc5fi": true, }, "key": "css", "nonce": undefined, @@ -2879,6 +2880,7 @@ exports[`addon Info should render component description if story kind matches co "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBd0NxQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", "name": "1o7rzh8-hoverable", "styles": "transition:all 150ms ease-out;transform:translate3d(0,0,0);&:hover{transform:translate3d(0,-2px,0);}&:active{transform:translate3d(0,0,0);};label:hoverable;", + "toString": [Function], }, "inlineGlow": Object { "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUNzQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", @@ -3149,12 +3151,12 @@ exports[`addon Info should render component description if story kind matches co "insert": [Function], "inserted": Object { "11xgcgt": true, + "1fhpnuv": true, "1imo1gr": true, "1maezg8": true, "1si67pu": true, "4zr3vl": true, "esgpkx": true, - "scc5fi": true, }, "key": "css", "nonce": undefined, @@ -5654,6 +5656,7 @@ exports[`addon Info should render component description if story name matches co "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBd0NxQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", "name": "1o7rzh8-hoverable", "styles": "transition:all 150ms ease-out;transform:translate3d(0,0,0);&:hover{transform:translate3d(0,-2px,0);}&:active{transform:translate3d(0,0,0);};label:hoverable;", + "toString": [Function], }, "inlineGlow": Object { "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUNzQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", @@ -5924,12 +5927,12 @@ exports[`addon Info should render component description if story name matches co "insert": [Function], "inserted": Object { "11xgcgt": true, + "1fhpnuv": true, "1imo1gr": true, "1maezg8": true, "1si67pu": true, "4zr3vl": true, "esgpkx": true, - "scc5fi": true, }, "key": "css", "nonce": undefined, @@ -7666,6 +7669,7 @@ exports[`addon Info should render component description if story name matches co "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBd0NxQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", "name": "1o7rzh8-hoverable", "styles": "transition:all 150ms ease-out;transform:translate3d(0,0,0);&:hover{transform:translate3d(0,-2px,0);}&:active{transform:translate3d(0,0,0);};label:hoverable;", + "toString": [Function], }, "inlineGlow": Object { "map": "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9hbmltYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUNzQiIsImZpbGUiOiIuLi9zcmMvYW5pbWF0aW9uLnRzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBrZXlmcmFtZXMgfSBmcm9tICdAZW1vdGlvbi9jb3JlJztcblxuZXhwb3J0IGNvbnN0IGVhc2luZyA9IHtcbiAgcnViYmVyOiAnY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMzUsIDEuMDUpJyxcbn07XG5cbmNvbnN0IHJvdGF0ZTM2MCA9IGtleWZyYW1lc2Bcblx0ZnJvbSB7XG5cdFx0dHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG5cdH1cblx0dG8ge1xuXHRcdHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG5cdH1cbmA7XG5cbmNvbnN0IGdsb3cgPSBrZXlmcmFtZXNgXG4gIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICA1MCUgeyBvcGFjaXR5OiAuNDsgfVxuYDtcblxuY29uc3QgZmxvYXQgPSBrZXlmcmFtZXNgXG4gIDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDFweCk7IH1cbiAgMjUlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7IH1cbiAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC0zcHgpOyB9XG4gIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMXB4KTsgfVxuYDtcblxuY29uc3QgamlnZ2xlID0ga2V5ZnJhbWVzYFxuICAwJSwgMTAwJSB7IHRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLDAsMCk7IH1cbiAgMTIuNSUsIDYyLjUlIHsgdHJhbnNmb3JtOnRyYW5zbGF0ZTNkKC00cHgsMCwwKTsgfVxuICAzNy41JSwgODcuNSUgeyAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg0cHgsMCwwKTsgIH1cbmA7XG5cbmNvbnN0IGlubGluZUdsb3cgPSBjc3NgXG4gIGFuaW1hdGlvbjogJHtnbG93fSAxLjVzIGVhc2UtaW4tb3V0IGluZmluaXRlO1xuICBjb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGN1cnNvcjogcHJvZ3Jlc3M7XG5gO1xuXG4vLyBob3ZlciAmIGFjdGl2ZSBzdGF0ZSBmb3IgbGlua3MgYW5kIGJ1dHRvbnNcbmNvbnN0IGhvdmVyYWJsZSA9IGNzc2BcbiAgdHJhbnNpdGlvbjogYWxsIDE1MG1zIGVhc2Utb3V0O1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuXG4gICY6aG92ZXIge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgLTJweCwgMCk7XG4gIH1cblxuICAmOmFjdGl2ZSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGFuaW1hdGlvbiA9IHtcbiAgcm90YXRlMzYwLFxuICBnbG93LFxuICBmbG9hdCxcbiAgamlnZ2xlLFxuICBpbmxpbmVHbG93LFxuICBob3ZlcmFibGUsXG59O1xuIl19 */", @@ -7936,12 +7940,12 @@ exports[`addon Info should render component description if story name matches co "insert": [Function], "inserted": Object { "11xgcgt": true, + "1fhpnuv": true, "1imo1gr": true, "1maezg8": true, "1si67pu": true, "4zr3vl": true, "esgpkx": true, - "scc5fi": true, }, "key": "css", "nonce": undefined, diff --git a/addons/jest/package.json b/addons/jest/package.json index 41cc9024b5e..7eddaedd9b7 100644 --- a/addons/jest/package.json +++ b/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "React storybook addon that show component jest report", "keywords": [ "addon", @@ -35,11 +35,11 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3", diff --git a/addons/knobs/README.md b/addons/knobs/README.md index 2da7666da27..b00b25b4f36 100644 --- a/addons/knobs/README.md +++ b/addons/knobs/README.md @@ -307,8 +307,37 @@ const groupId = 'GROUP-ID1'; const value = select(label, options, defaultValue, groupId); ``` -> You can also provide options as an array like this: `['red', 'blue', 'yellow']`. +Options can also be an array: +```js +import { select } from '@storybook/addon-knobs'; +const label = 'Cats'; +const options = ['linus', 'eleanor', 'lover'] +const defaultValue = 'eleanor'; +const groupId = 'GROUP-ID2'; +const value = select(label, options, defaultValue, groupId); +``` + +Options can also be an array OF objects: + +```js +const label = 'Dogs'; +const arrayOfObjects = [ + { + label: 'Sparky', + dogParent: 'Matthew', + location: 'Austin', + }, + { + label: 'Juniper', + dogParent: 'Joshua', + location: 'Austin', + }, +]; +const defaultValue = arrayOfObjects[0]; +const groupId = 'GROUP-ID3'; +const value = select(label, options, defaultValue, groupId); +``` ### radio buttons diff --git a/addons/knobs/package.json b/addons/knobs/package.json index 1244eb2b2ed..2ac5d354343 100644 --- a/addons/knobs/package.json +++ b/addons/knobs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-knobs", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook Addon Prop Editor Component", "keywords": [ "addon", @@ -29,12 +29,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "@types/react-color": "^3.0.1", "copy-to-clipboard": "^3.0.8", "core-js": "^3.0.1", diff --git a/addons/knobs/src/components/types/Select.tsx b/addons/knobs/src/components/types/Select.tsx index 8a7f387859f..50a5d52b564 100644 --- a/addons/knobs/src/components/types/Select.tsx +++ b/addons/knobs/src/components/types/Select.tsx @@ -30,15 +30,23 @@ const SelectType: FunctionComponent<SelectTypeProps> & { deserialize: typeof deserialize; } = ({ knob, onChange }) => { const { options } = knob; - const entries = Array.isArray(options) - ? options.reduce<Record<PropertyKey, SelectTypeKnobValue>>((acc, k) => ({ ...acc, [k]: k }), {}) - : (options as Record<PropertyKey, SelectTypeKnobValue>); - const selectedKey = Object.keys(entries).find(k => { - if (Array.isArray(knob.value)) { - return JSON.stringify(entries[k]) === JSON.stringify(knob.value); + const callbackReduceArrayOptions = (acc: any, option: any, i: number) => { + if (typeof option !== 'object') return { ...acc, [option]: option }; + const label = option.label || option.key || i; + return { ...acc, [label]: option }; + }; + + const entries = Array.isArray(options) ? options.reduce(callbackReduceArrayOptions, {}) : options; + + const selectedKey = Object.keys(entries).find(key => { + const { value: knobVal } = knob; + const entryVal = entries[key]; + + if (Array.isArray(knobVal)) { + return JSON.stringify(entryVal) === JSON.stringify(knobVal); } - return entries[k] === knob.value; + return entryVal === knobVal; }); return ( diff --git a/addons/links/package.json b/addons/links/package.json index 7210ec7801e..e0b45ac8e4a 100644 --- a/addons/links/package.json +++ b/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Story Links addon for storybook", "keywords": [ "addon", @@ -29,10 +29,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/router": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/router": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "prop-types": "^15.7.2", diff --git a/addons/links/src/preview.test.js b/addons/links/src/preview.test.js index 49fa1bba24c..46647a36a37 100644 --- a/addons/links/src/preview.test.js +++ b/addons/links/src/preview.test.js @@ -31,14 +31,6 @@ jest.mock('global', () => ({ }, })); -export const mockChannel = () => { - return { - emit: jest.fn(), - on: jest.fn(), - once: jest.fn(), - }; -}; - describe('preview', () => { describe('linkTo()', () => { it('should select the kind and story provided', () => { @@ -116,7 +108,10 @@ describe('preview', () => { addons.getChannel.mockReturnValue(channel); __STORYBOOK_STORY_STORE__.fromId.mockImplementation(input => null); - const handler = linkTo((a, b) => a + b, (a, b) => b + a); + const handler = linkTo( + (a, b) => a + b, + (a, b) => b + a + ); handler('kind', 'name'); expect(channel.emit.mock.calls).toContainEqual([ diff --git a/addons/links/src/react/components/__snapshots__/link.test.js.snap b/addons/links/src/react/components/__snapshots__/link.test.js.snap index a977ec574aa..3ed69931959 100644 --- a/addons/links/src/react/components/__snapshots__/link.test.js.snap +++ b/addons/links/src/react/components/__snapshots__/link.test.js.snap @@ -2,7 +2,7 @@ exports[`LinkTo render should render a link 1`] = ` <a - href="http://localhost/?id=foo--bar" + href="originpathname?search=&id=foo--bar" onClick={[Function]} /> `; diff --git a/addons/links/src/react/components/link.test.js b/addons/links/src/react/components/link.test.js index 804dad07e13..b38b6bf2bc9 100644 --- a/addons/links/src/react/components/link.test.js +++ b/addons/links/src/react/components/link.test.js @@ -3,10 +3,30 @@ import React from 'react'; import addons from '@storybook/addons'; import { SELECT_STORY } from '@storybook/core-events'; -import { mockChannel } from '../../preview.test'; import LinkTo from './link'; jest.mock('@storybook/addons'); +jest.mock('global', () => ({ + document: { + location: { + origin: 'origin', + pathname: 'pathname', + search: 'search', + }, + }, + __STORYBOOK_STORY_STORE__: { + getSelection: jest.fn(() => ({ id: 1 })), + fromId: jest.fn(() => ({})), + }, +})); + +const mockChannel = () => { + return { + emit: jest.fn(), + on: jest.fn(), + once: jest.fn(), + }; +}; describe('LinkTo', () => { describe('render', () => { diff --git a/addons/notes/README.md b/addons/notes/README.md index 3debb6c863a..0211aab0fcb 100644 --- a/addons/notes/README.md +++ b/addons/notes/README.md @@ -79,6 +79,18 @@ storiesOf('Button', module).add( ); ``` +### Upgrading to CSF Format + +Add `notes` to the `parameters` object: + +```js +export default { + parameters: { + notes: 'My notes', + } +} +``` + ## Using Markdown Using Markdown in your notes is supported, Storybook will load Markdown as raw by default. diff --git a/addons/notes/package.json b/addons/notes/package.json index 579484dfb83..218a316df15 100644 --- a/addons/notes/package.json +++ b/addons/notes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-notes", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Write notes for your Storybook stories.", "keywords": [ "addon", @@ -30,13 +30,13 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/router": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/router": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "markdown-to-jsx": "^6.10.3", diff --git a/addons/notes/src/Panel.tsx b/addons/notes/src/Panel.tsx index 02655175fe5..d13879abd9f 100644 --- a/addons/notes/src/Panel.tsx +++ b/addons/notes/src/Panel.tsx @@ -87,7 +87,9 @@ interface NotesLinkProps { export const NotesLink = ({ href, children, ...props }: NotesLinkProps) => { /* https://github.com/sindresorhus/is-absolute-url/blob/master/index.js */ const isAbsoluteUrl = /^[a-z][a-z0-9+.-]*:/.test(href); - if (isAbsoluteUrl) { + const isAnchorUrl = /^#.*/.test(href); + + if (isAbsoluteUrl || isAnchorUrl) { return ( <a href={href} {...props}> {children} diff --git a/addons/ondevice-actions/package.json b/addons/ondevice-actions/package.json index 5e90c0c7a2f..c5b0390fc8d 100644 --- a/addons/ondevice-actions/package.json +++ b/addons/ondevice-actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-actions", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Action Logger addon for react-native storybook", "keywords": [ "storybook" @@ -26,13 +26,13 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", "core-js": "^3.0.1", "fast-deep-equal": "^2.0.1" }, "devDependencies": { - "@storybook/addon-actions": "5.3.0-alpha.41" + "@storybook/addon-actions": "5.3.0-beta.2" }, "peerDependencies": { "@storybook/addon-actions": "*", diff --git a/addons/ondevice-backgrounds/package.json b/addons/ondevice-backgrounds/package.json index b67ac3b235d..342834f0f1d 100644 --- a/addons/ondevice-backgrounds/package.json +++ b/addons/ondevice-backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-backgrounds", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "A react-native storybook addon to show different backgrounds for your preview", "keywords": [ "addon", @@ -31,9 +31,9 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", "core-js": "^3.0.1", "prop-types": "^15.7.2" }, diff --git a/addons/ondevice-knobs/package.json b/addons/ondevice-knobs/package.json index a71209b7789..dffd4f657ea 100644 --- a/addons/ondevice-knobs/package.json +++ b/addons/ondevice-knobs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-knobs", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Display storybook story knobs on your deviced.", "keywords": [ "addon", @@ -27,8 +27,9 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", + "@emotion/native": "^10.0.14", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", "core-js": "^3.0.1", "deep-equal": "^1.0.1", "prop-types": "^15.7.2", @@ -38,7 +39,7 @@ "react-native-switch": "^1.5.0" }, "peerDependencies": { - "@storybook/addon-knobs": "5.2.0-alpha.34", + "@storybook/addon-knobs": "5.2.0-beta.1", "react": "*", "react-native": "*" }, diff --git a/addons/ondevice-knobs/src/GroupTabs.js b/addons/ondevice-knobs/src/GroupTabs.js index b1e38d7ff19..e423304468e 100644 --- a/addons/ondevice-knobs/src/GroupTabs.js +++ b/addons/ondevice-knobs/src/GroupTabs.js @@ -1,6 +1,12 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { ScrollView, Text, TouchableOpacity } from 'react-native'; +import styled from '@emotion/native'; + +const Label = styled.Text(({ theme, active }) => ({ + color: active ? theme.buttonActiveTextColor : theme.buttonTextColor, + fontSize: 17, +})); class GroupTabs extends Component { renderTab(name, group) { @@ -21,14 +27,7 @@ class GroupTabs extends Component { key={name} onPress={() => onGroupSelect(name)} > - <Text - style={{ - color: selectedGroup === name ? 'black' : '#ccc', - fontSize: 17, - }} - > - {title} - </Text> + <Label active={selectedGroup === name}>{title}</Label> </TouchableOpacity> ); } diff --git a/addons/ondevice-knobs/src/PropField.js b/addons/ondevice-knobs/src/PropField.js index 3b053b5a180..dfde3288ceb 100644 --- a/addons/ondevice-knobs/src/PropField.js +++ b/addons/ondevice-knobs/src/PropField.js @@ -1,27 +1,24 @@ import PropTypes from 'prop-types'; import { View, Text } from 'react-native'; import React from 'react'; +import styled from '@emotion/native'; import TypeMap from './types'; const InvalidType = () => <Text style={{ margin: 10 }}>Invalid Type</Text>; +const Label = styled.Text(({ theme }) => ({ + marginLeft: 10, + fontSize: 14, + color: theme.labelColor, + fontWeight: 'bold', +})); + const PropField = ({ onChange, onPress, knob }) => { const InputType = TypeMap[knob.type] || InvalidType; return ( <View> - {!knob.hideLabel ? ( - <Text - style={{ - marginLeft: 10, - fontSize: 14, - color: 'rgb(68, 68, 68)', - fontWeight: 'bold', - }} - > - {`${knob.label || knob.name}`} - </Text> - ) : null} + {!knob.hideLabel ? <Label>{`${knob.label || knob.name}`}</Label> : null} <InputType knob={knob} onChange={onChange} onPress={onPress} /> </View> ); diff --git a/addons/ondevice-knobs/src/panel.js b/addons/ondevice-knobs/src/panel.js index dceafd9e414..489ac5adaa9 100644 --- a/addons/ondevice-knobs/src/panel.js +++ b/addons/ondevice-knobs/src/panel.js @@ -1,8 +1,9 @@ import React from 'react'; -import { View, Text, TouchableOpacity } from 'react-native'; +import { View, Text } from 'react-native'; import PropTypes from 'prop-types'; import { SELECT_STORY, FORCE_RE_RENDER } from '@storybook/core-events'; import { SET, SET_OPTIONS, RESET, CHANGE, CLICK } from '@storybook/addon-knobs'; +import styled from '@emotion/native'; import GroupTabs from './GroupTabs'; import PropForm from './PropForm'; @@ -10,6 +11,20 @@ const getTimestamp = () => +new Date(); const DEFAULT_GROUP_ID = 'Other'; +const Touchable = styled.TouchableOpacity(({ theme }) => ({ + borderRadius: 2, + borderWidth: 1, + borderColor: theme.borderColor, + padding: 4, + margin: 10, + justifyContent: 'center', + alignItems: 'center', +})); + +const ResetButton = styled.Text(({ theme }) => ({ + color: theme.buttonTextColor, +})); + export default class Panel extends React.Component { constructor(props) { super(props); @@ -152,7 +167,7 @@ export default class Panel extends React.Component { } return ( - <View style={{ flex: 1 }}> + <View style={{ flex: 1, paddingTop: 10 }}> {groupIds.length > 0 && ( <GroupTabs groups={groups} onGroupSelect={this.onGroupSelect} selectedGroup={groupId} /> )} @@ -163,20 +178,9 @@ export default class Panel extends React.Component { onFieldClick={this.handleClick} /> </View> - <TouchableOpacity - style={{ - borderRadius: 2, - borderWidth: 1, - borderColor: '#f7f4f4', - padding: 4, - margin: 10, - justifyContent: 'center', - alignItems: 'center', - }} - onPress={this.reset} - > - <Text>RESET</Text> - </TouchableOpacity> + <Touchable onPress={this.reset}> + <ResetButton>RESET</ResetButton> + </Touchable> </View> ); } diff --git a/addons/ondevice-knobs/src/types/Array.js b/addons/ondevice-knobs/src/types/Array.js index 8234353f642..88b781ea14e 100644 --- a/addons/ondevice-knobs/src/types/Array.js +++ b/addons/ondevice-knobs/src/types/Array.js @@ -1,7 +1,16 @@ import PropTypes from 'prop-types'; import React from 'react'; +import styled from '@emotion/native'; -import { TextInput } from 'react-native'; +const Input = styled.TextInput(({ theme }) => ({ + borderWidth: 1, + borderColor: theme.borderColor, + borderRadius: 2, + fontSize: 13, + padding: 5, + margin: 10, + color: theme.labelColor, +})); function formatArray(value, separator) { if (value === '') { @@ -11,19 +20,10 @@ function formatArray(value, separator) { } const ArrayType = ({ knob, onChange }) => ( - <TextInput + <Input id={knob.name} underlineColorAndroid="transparent" autoCapitalize="none" - style={{ - borderWidth: 1, - borderColor: '#f7f4f4', - borderRadius: 2, - fontSize: 13, - padding: 5, - margin: 10, - color: '#555', - }} value={knob.value.join(knob.separator)} onChangeText={e => onChange(formatArray(e, knob.separator))} /> diff --git a/addons/ondevice-knobs/src/types/Button.js b/addons/ondevice-knobs/src/types/Button.js index f6f05d05109..5b5a4238a67 100644 --- a/addons/ondevice-knobs/src/types/Button.js +++ b/addons/ondevice-knobs/src/types/Button.js @@ -1,10 +1,16 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { TouchableOpacity, Text } from 'react-native'; +import { TouchableOpacity } from 'react-native'; +import styled from '@emotion/native'; + +const Label = styled.Text(({ theme }) => ({ + fontSize: 17, + color: theme.labelColor, +})); const ButtonType = ({ knob, onPress }) => ( <TouchableOpacity style={{ margin: 10 }} onPress={() => onPress(knob)}> - <Text style={{ fontSize: 17, color: '#007aff' }}>{knob.name}</Text> + <Label>{knob.name}</Label> </TouchableOpacity> ); diff --git a/addons/ondevice-knobs/src/types/Color.js b/addons/ondevice-knobs/src/types/Color.js index ebee0bbbe27..102cae7ad1c 100644 --- a/addons/ondevice-knobs/src/types/Color.js +++ b/addons/ondevice-knobs/src/types/Color.js @@ -2,6 +2,17 @@ import PropTypes from 'prop-types'; import React from 'react'; import { Text, Modal, View, TouchableOpacity, TouchableWithoutFeedback } from 'react-native'; import { ColorPicker, fromHsv } from 'react-native-color-picker'; +import styled from '@emotion/native'; + +const Touchable = styled.TouchableOpacity(({ theme, color }) => ({ + borderColor: theme.borderColor, + width: 30, + height: 20, + borderRadius: 2, + borderWidth: 1, + margin: 10, + backgroundColor: color, +})); class ColorType extends React.Component { constructor(props) { @@ -32,17 +43,9 @@ class ColorType extends React.Component { render() { const { knob } = this.props; const { displayColorPicker } = this.state; - const colorStyle = { - borderColor: 'rgb(247, 244, 244)', - width: 30, - height: 20, - borderRadius: 2, - margin: 10, - backgroundColor: knob.value, - }; return ( <View> - <TouchableOpacity style={colorStyle} onPress={this.openColorPicker} /> + <Touchable color={knob.value} onPress={this.openColorPicker} /> <Modal supportedOrientations={['portrait', 'landscape']} transparent diff --git a/addons/ondevice-knobs/src/types/Date.js b/addons/ondevice-knobs/src/types/Date.js index d0eec146625..7776ba2959f 100644 --- a/addons/ondevice-knobs/src/types/Date.js +++ b/addons/ondevice-knobs/src/types/Date.js @@ -1,7 +1,20 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; -import { TouchableOpacity, Text, View } from 'react-native'; +import { View } from 'react-native'; import DateTimePicker from 'react-native-modal-datetime-picker'; +import styled from '@emotion/native'; + +const Touchable = styled.TouchableOpacity(({ theme }) => ({ + borderColor: theme.borderColor, + borderWidth: 1, + borderRadius: 2, + padding: 5, +})); + +const Label = styled.Text(({ theme }) => ({ + fontSize: 13, + color: theme.labelColor, +})); // TODO seconds support class DateType extends PureComponent { @@ -49,29 +62,17 @@ class DateType extends PureComponent { return ( <View style={{ margin: 10 }}> <View style={{ flexDirection: 'row' }}> - <TouchableOpacity + <Touchable onPress={this.showDatePicker}> + <Label>{dateString}</Label> + </Touchable> + <Touchable style={{ - borderWidth: 1, - borderColor: '#f7f4f4', - borderRadius: 2, - padding: 5, - }} - onPress={this.showDatePicker} - > - <Text style={{ fontSize: 13, color: '#555' }}>{dateString}</Text> - </TouchableOpacity> - <TouchableOpacity - style={{ - borderWidth: 1, - borderColor: '#f7f4f4', - borderRadius: 2, - padding: 5, marginLeft: 5, }} onPress={this.showTimePicker} > - <Text style={{ fontSize: 13, color: '#555' }}>{timeString}</Text> - </TouchableOpacity> + <Label>{timeString}</Label> + </Touchable> </View> <DateTimePicker date={d} diff --git a/addons/ondevice-knobs/src/types/Number.js b/addons/ondevice-knobs/src/types/Number.js index 00adaf2ad37..dbd4946ce4f 100644 --- a/addons/ondevice-knobs/src/types/Number.js +++ b/addons/ondevice-knobs/src/types/Number.js @@ -1,6 +1,16 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { TextInput, View, Slider } from 'react-native'; +import { View, Slider } from 'react-native'; +import styled from '@emotion/native'; + +const Input = styled.TextInput(({ theme }) => ({ + borderWidth: 1, + borderColor: theme.borderColor, + borderRadius: 2, + fontSize: 13, + padding: 5, + color: theme.labelColor, +})); class NumberType extends React.Component { constructor(props) { @@ -29,15 +39,7 @@ class NumberType extends React.Component { const { knob } = this.props; return ( - <TextInput - style={{ - borderWidth: 1, - borderColor: '#f7f4f4', - borderRadius: 2, - fontSize: 13, - padding: 5, - color: '#555', - }} + <Input autoCapitalize="none" underlineColorAndroid="transparent" value={(knob.value || '').toString()} diff --git a/addons/ondevice-knobs/src/types/Object.js b/addons/ondevice-knobs/src/types/Object.js index 2fef52a20e5..87d8725baaf 100644 --- a/addons/ondevice-knobs/src/types/Object.js +++ b/addons/ondevice-knobs/src/types/Object.js @@ -1,17 +1,17 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { TextInput } from 'react-native'; import deepEqual from 'deep-equal'; +import styled from '@emotion/native'; -const styles = { +const Input = styled.TextInput(({ theme }) => ({ borderWidth: 1, - borderColor: '#f7f4f4', borderRadius: 2, fontSize: 13, padding: 5, margin: 10, - color: '#555', -}; + borderColor: theme.borderColor, + color: theme.labelColor, +})); class ObjectType extends React.Component { constructor(...args) { @@ -70,9 +70,9 @@ class ObjectType extends React.Component { } return ( - <TextInput + <Input id={knob.name} - style={{ ...styles, ...extraStyle }} + style={extraStyle} value={jsonString} onChangeText={this.handleChange} multiline diff --git a/addons/ondevice-knobs/src/types/Select.js b/addons/ondevice-knobs/src/types/Select.js index 512ee186398..530131bc4d5 100644 --- a/addons/ondevice-knobs/src/types/Select.js +++ b/addons/ondevice-knobs/src/types/Select.js @@ -1,9 +1,19 @@ /* eslint no-underscore-dangle: 0 */ import PropTypes from 'prop-types'; -import { View, TextInput } from 'react-native'; +import { View } from 'react-native'; import React from 'react'; import ModalPicker from 'react-native-modal-selector'; +import styled from '@emotion/native'; + +const Input = styled.TextInput(({ theme }) => ({ + borderWidth: 1, + borderRadius: 2, + padding: 5, + margin: 10, + borderColor: theme.borderColor, + color: theme.labelColor, +})); class SelectType extends React.Component { getOptions = ({ options }) => { @@ -30,15 +40,7 @@ class SelectType extends React.Component { onChange={option => onChange(option.key)} animationType="none" > - <TextInput - style={{ - borderWidth: 1, - borderColor: '#f7f4f4', - borderRadius: 2, - padding: 5, - color: '#555', - margin: 10, - }} + <Input editable={false} value={selected} autoCapitalize="none" diff --git a/addons/ondevice-knobs/src/types/Text.js b/addons/ondevice-knobs/src/types/Text.js index 5c96f27310e..e806e73f810 100644 --- a/addons/ondevice-knobs/src/types/Text.js +++ b/addons/ondevice-knobs/src/types/Text.js @@ -1,18 +1,19 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { TextInput } from 'react-native'; +import styled from '@emotion/native'; + +const Input = styled.TextInput(({ theme }) => ({ + borderWidth: 1, + borderColor: theme.borderColor, + borderRadius: 2, + fontSize: 13, + padding: 5, + margin: 10, + color: theme.labelColor, +})); const TextType = ({ knob, onChange }) => ( - <TextInput - style={{ - borderWidth: 1, - borderColor: '#f7f4f4', - borderRadius: 2, - fontSize: 13, - padding: 5, - margin: 10, - color: '#555', - }} + <Input id={knob.name} value={knob.value} onChangeText={onChange} diff --git a/addons/ondevice-notes/package.json b/addons/ondevice-notes/package.json index 23b4c0b2657..a54c2d81341 100644 --- a/addons/ondevice-notes/package.json +++ b/addons/ondevice-notes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-notes", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Write notes for your react-native Storybook stories.", "keywords": [ "addon", @@ -27,11 +27,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", + "@emotion/core": "^10.0.20", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", "core-js": "^3.0.1", "prop-types": "^15.7.2", "react-native-simple-markdown": "^1.1.0" diff --git a/addons/ondevice-notes/src/components/Notes.tsx b/addons/ondevice-notes/src/components/Notes.tsx index 4878a7c0286..b27360ad81d 100644 --- a/addons/ondevice-notes/src/components/Notes.tsx +++ b/addons/ondevice-notes/src/components/Notes.tsx @@ -3,6 +3,7 @@ import { View } from 'react-native'; import Markdown from 'react-native-simple-markdown'; import { AddonStore } from '@storybook/addons'; import { API } from '@storybook/api'; +import { ThemeContext } from '@emotion/core'; export const PARAM_KEY = `notes`; @@ -30,7 +31,13 @@ export const Notes = ({ active, api }: NotesProps) => { return ( <View style={{ padding: 10, flex: 1 }}> - <Markdown>{textAfterFormatted}</Markdown> + <ThemeContext.Consumer> + {theme => ( + <Markdown styles={{ text: { color: (theme as any).labelColor } }}> + {textAfterFormatted} + </Markdown> + )} + </ThemeContext.Consumer> </View> ); }; diff --git a/addons/options/README.md b/addons/options/README.md index ef028e9f18d..628ad9ee9c5 100644 --- a/addons/options/README.md +++ b/addons/options/README.md @@ -75,23 +75,10 @@ addParameters({ */ addonPanelInRight: false, /** - * regex for finding the hierarchy separator - * @example: - * null - turn off hierarchy - * /\// - split by `/` - * /\./ - split by `.` - * /\/|\./ - split by `/` or `.` - * @type {Regex} + * display the top-level grouping as a "root" in the sidebar + * @type {Boolean} */ - hierarchySeparator: null, - /** - * regex for finding the hierarchy root separator - * @example: - * null - turn off multiple hierarchy roots - * /\|/ - split by `|` - * @type {Regex} - */ - hierarchyRootSeparator: null, + showRoots: null, /** * sidebar tree animations * @type {Boolean} diff --git a/addons/options/package.json b/addons/options/package.json index b5ce4fa3f09..9be92f95fc1 100644 --- a/addons/options/package.json +++ b/addons/options/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-options", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Options addon for storybook", "keywords": [ "addon", @@ -29,7 +29,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", "core-js": "^3.0.1", "util-deprecate": "^1.0.2" }, diff --git a/addons/queryparams/package.json b/addons/queryparams/package.json index e4733a010c0..5377e8d1027 100644 --- a/addons/queryparams/package.json +++ b/addons/queryparams/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-queryparams", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "parameter addon for storybook", "keywords": [ "addon", @@ -30,12 +30,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "qs": "^6.6.0", diff --git a/addons/storyshots/storyshots-core/package.json b/addons/storyshots/storyshots-core/package.json index 274a9876d8d..6790d1c6d1e 100644 --- a/addons/storyshots/storyshots-core/package.json +++ b/addons/storyshots/storyshots-core/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storyshots", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.", "keywords": [ "addon", @@ -33,8 +33,8 @@ }, "dependencies": { "@jest/transform": "^24.9.0", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", "@types/glob": "^7.1.1", "@types/jest": "^24.0.16", "@types/jest-specific-snapshot": "^0.5.3", @@ -47,8 +47,8 @@ "ts-dedent": "^1.1.0" }, "devDependencies": { - "@storybook/addon-docs": "5.3.0-alpha.41", - "@storybook/react": "5.3.0-alpha.41", + "@storybook/addon-docs": "5.3.0-beta.2", + "@storybook/react": "5.3.0-beta.2", "babel-loader": "^8.0.6", "enzyme-to-json": "^3.4.1", "jest-emotion": "^10.0.17", diff --git a/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.ts b/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.ts index 6a3a9afcfb5..4dd4eeba8a4 100644 --- a/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.ts +++ b/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-export */ import fs from 'fs'; import glob from 'glob'; import { describe, it } from 'global'; diff --git a/addons/storyshots/storyshots-core/src/api/snapshotsTestsTemplate.ts b/addons/storyshots/storyshots-core/src/api/snapshotsTestsTemplate.ts index 2dbdf03861b..84185930f76 100644 --- a/addons/storyshots/storyshots-core/src/api/snapshotsTestsTemplate.ts +++ b/addons/storyshots/storyshots-core/src/api/snapshotsTestsTemplate.ts @@ -1,3 +1,5 @@ +/* eslint-disable jest/no-export */ +/* eslint-disable jest/expect-expect */ import { describe, it } from 'global'; import { addSerializer } from 'jest-specific-snapshot'; @@ -6,13 +8,17 @@ function snapshotTest({ item, asyncJest, framework, testMethod, testMethodParams const context = { ...item, framework }; if (asyncJest === true) { - it(name, (done: jest.DoneCallback) => - testMethod({ - done, - story: item, - context, - ...testMethodParams, - }) + it( + name, + () => + new Promise(done => + testMethod({ + done, + story: item, + context, + ...testMethodParams, + }) + ) ); } else { it(name, () => @@ -27,9 +33,7 @@ function snapshotTest({ item, asyncJest, framework, testMethod, testMethodParams function snapshotTestSuite({ item, suite, ...restParams }: any) { const { kind, children } = item; - // eslint-disable-next-line jest/valid-describe describe(suite, () => { - // eslint-disable-next-line jest/valid-describe describe(kind, () => { children.forEach((c: any) => { snapshotTest({ item: c, ...restParams }); diff --git a/addons/storyshots/storyshots-core/src/frameworks/Loader.ts b/addons/storyshots/storyshots-core/src/frameworks/Loader.ts index cade940022e..501f0fbac20 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/Loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/Loader.ts @@ -1,9 +1,19 @@ -import { ClientApi } from '@storybook/client-api'; +import { ClientStoryApi, Loadable } from '@storybook/addons'; +import { ClientApi as ClientApiThing } from '@storybook/client-api'; import { StoryshotsOptions } from '../api/StoryshotsOptions'; import { SupportedFramework } from './SupportedFramework'; export type RenderTree = (story: any, context?: any, options?: any) => any; +export interface ClientApi extends ClientStoryApi<unknown> { + configure(loader: Loadable, module: NodeModule | false): void; + forceReRender(): void; + clearDecorators: ClientApiThing['clearDecorators']; + getStorybook: ClientApiThing['getStorybook']; + setAddon: ClientApiThing['setAddon']; + raw: ClientApiThing['raw']; +} + export interface Loader { load: ( options: StoryshotsOptions diff --git a/addons/storyshots/storyshots-core/src/frameworks/angular/loader.ts b/addons/storyshots/storyshots-core/src/frameworks/angular/loader.ts index 3a0c78bf643..ea3a5fbfbaa 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/angular/loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/angular/loader.ts @@ -29,10 +29,9 @@ function test(options: StoryshotsOptions): boolean { function load(options: StoryshotsOptions) { setupAngularJestPreset(); - const { configPath, config } = options; const storybook = require.requireActual('@storybook/angular'); - configure({ configPath, config, storybook }); + configure({ ...options, storybook }); return { framework: 'angular' as const, diff --git a/addons/storyshots/storyshots-core/src/frameworks/configure.ts b/addons/storyshots/storyshots-core/src/frameworks/configure.ts index 9151a46562a..7bdd0a5b207 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/configure.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/configure.ts @@ -1,17 +1,85 @@ import fs from 'fs'; import path from 'path'; +import glob from 'glob'; +import { ClientApi } from './Loader'; +import { StoryshotsOptions } from '../api/StoryshotsOptions'; -function getConfigPathParts(configPath: string): string { - const resolvedConfigPath = path.resolve(configPath); - - if (fs.lstatSync(resolvedConfigPath).isDirectory()) { - return path.join(resolvedConfigPath, 'config'); +const isFile = (file: string): boolean => { + try { + return fs.lstatSync(file).isFile(); + } catch (e) { + return false; } +}; - return resolvedConfigPath; +interface Output { + stories: string[]; + files: string[]; } -function configure(options: { configPath?: string; config: any; storybook: any }): void { +const getPreviewFile = (configDir: string): string | false => { + const preview = path.join(configDir, 'preview.js'); + const previewTS = path.join(configDir, 'preview.ts'); + const config = path.join(configDir, 'config.js'); + const configTS = path.join(configDir, 'config.ts'); + + if (isFile(previewTS)) { + return previewTS; + } + if (isFile(preview)) { + return preview; + } + if (isFile(configTS)) { + return configTS; + } + if (isFile(config)) { + return config; + } + + return false; +}; + +const getMainFile = (configDir: string): string | false => { + const main = path.join(configDir, 'main.js'); + + if (isFile(main)) { + return main; + } + + return false; +}; + +function getConfigPathParts(input: string): Output { + const configDir = path.resolve(input); + + if (fs.lstatSync(configDir).isDirectory()) { + const output: Output = { files: [], stories: [] }; + + const preview = getPreviewFile(configDir); + const main = getMainFile(configDir); + + if (preview) { + output.files.push(preview); + } + if (main) { + const { stories = [] } = require.requireActual(main); + + const result = stories.reduce((acc: string[], i: string) => [...acc, ...glob.sync(i)], []); + + output.stories = result; + } + + return output; + } + + return { files: [configDir], stories: [] }; +} + +function configure( + options: { + storybook: ClientApi; + } & StoryshotsOptions +): void { const { configPath = '.storybook', config, storybook } = options; if (config && typeof config === 'function') { @@ -19,9 +87,16 @@ function configure(options: { configPath?: string; config: any; storybook: any } return; } - const resolvedConfigPath = getConfigPathParts(configPath); + const { files, stories } = getConfigPathParts(configPath); - require.requireActual(resolvedConfigPath); + files.forEach(f => { + require.requireActual(f); + }); + + if (stories && stories.length) { + // eslint-disable-next-line global-require, import/no-dynamic-require + storybook.configure(() => stories.map(f => require(f)), false); + } } export default configure; diff --git a/addons/storyshots/storyshots-core/src/frameworks/frameworkLoader.ts b/addons/storyshots/storyshots-core/src/frameworks/frameworkLoader.ts index 10ea02cf33b..8bfca595b7a 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/frameworkLoader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/frameworkLoader.ts @@ -13,16 +13,13 @@ function getLoaders(): Loader[] { .readdirSync(__dirname) .map(name => path.join(__dirname, name)) .filter(isDirectory) - .reduce( - (acc, framework) => { - const filename = path.join(framework, loaderScriptName); - const jsFile = `${filename}.js`; - const tsFile = `${filename}.ts`; + .reduce((acc, framework) => { + const filename = path.join(framework, loaderScriptName); + const jsFile = `${filename}.js`; + const tsFile = `${filename}.ts`; - return acc.concat([jsFile, tsFile]); - }, - [] as string[] - ) + return acc.concat([jsFile, tsFile]); + }, [] as string[]) .filter(fs.existsSync) .map(loader => require(loader).default); } diff --git a/addons/storyshots/storyshots-core/src/frameworks/html/loader.ts b/addons/storyshots/storyshots-core/src/frameworks/html/loader.ts index 08108195547..5a720e978d3 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/html/loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/html/loader.ts @@ -10,10 +10,9 @@ function test(options: StoryshotsOptions): boolean { function load(options: StoryshotsOptions) { global.STORYBOOK_ENV = 'html'; - const { configPath, config } = options; const storybook = require.requireActual('@storybook/html'); - configure({ configPath, config, storybook }); + configure({ ...options, storybook }); return { framework: 'html' as const, diff --git a/addons/storyshots/storyshots-core/src/frameworks/preact/loader.ts b/addons/storyshots/storyshots-core/src/frameworks/preact/loader.ts index 7b579fc26c2..09eaa79a069 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/preact/loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/preact/loader.ts @@ -15,10 +15,9 @@ function test(options: StoryshotsOptions): boolean { function load(options: StoryshotsOptions) { global.STORYBOOK_ENV = 'preact'; - const { configPath, config } = options; const storybook = require.requireActual('@storybook/preact'); - configure({ configPath, config, storybook }); + configure({ ...options, storybook }); return { framework: 'preact' as const, diff --git a/addons/storyshots/storyshots-core/src/frameworks/react/loader.ts b/addons/storyshots/storyshots-core/src/frameworks/react/loader.ts index 0d6cf164f64..54383dce00f 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/react/loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/react/loader.ts @@ -8,10 +8,9 @@ function test(options: StoryshotsOptions): boolean { } function load(options: StoryshotsOptions) { - const { configPath, config } = options; const storybook = require.requireActual('@storybook/react'); - configure({ configPath, config, storybook }); + configure({ ...options, storybook }); return { framework: 'react' as const, diff --git a/addons/storyshots/storyshots-core/src/frameworks/riot/loader.ts b/addons/storyshots/storyshots-core/src/frameworks/riot/loader.ts index abbf19a54de..3223c5cf389 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/riot/loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/riot/loader.ts @@ -16,10 +16,9 @@ function load(options: StoryshotsOptions) { global.STORYBOOK_ENV = 'riot'; mockRiotToIncludeCompiler(); - const { configPath, config } = options; const storybook = require.requireActual('@storybook/riot'); - configure({ configPath, config, storybook }); + configure({ ...options, storybook }); return { framework: 'riot' as const, diff --git a/addons/storyshots/storyshots-core/src/frameworks/svelte/loader.ts b/addons/storyshots/storyshots-core/src/frameworks/svelte/loader.ts index a1b9203e7b5..4ae5b02acfd 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/svelte/loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/svelte/loader.ts @@ -13,10 +13,9 @@ function test(options: StoryshotsOptions): boolean { function load(options: StoryshotsOptions) { global.STORYBOOK_ENV = 'svelte'; - const { configPath, config } = options; const storybook = require.requireActual('@storybook/svelte'); - configure({ configPath, config, storybook }); + configure({ ...options, storybook }); return { framework: 'svelte' as const, diff --git a/addons/storyshots/storyshots-core/src/frameworks/vue/loader.ts b/addons/storyshots/storyshots-core/src/frameworks/vue/loader.ts index abba41352e9..2433026458a 100644 --- a/addons/storyshots/storyshots-core/src/frameworks/vue/loader.ts +++ b/addons/storyshots/storyshots-core/src/frameworks/vue/loader.ts @@ -16,10 +16,9 @@ function load(options: StoryshotsOptions) { global.STORYBOOK_ENV = 'vue'; mockVueToIncludeCompiler(); - const { configPath, config } = options; const storybook = require.requireActual('@storybook/vue'); - configure({ configPath, config, storybook }); + configure({ ...options, storybook }); return { framework: 'vue' as const, diff --git a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.enzyme.test.js.snap b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.enzyme.test.js.snap index 4bd1f88f130..75ec281cdcd 100644 --- a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.enzyme.test.js.snap +++ b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.enzyme.test.js.snap @@ -53,13 +53,37 @@ exports[`Storyshots Another Button with text 1`] = ` </Button> `; -exports[`Storyshots Async With Timeout 1`] = ` +exports[`Storyshots Async with 5ms timeout simulating async operation 1`] = ` <AsyncTestComponent> <h1 /> </AsyncTestComponent> `; -exports[`Storyshots Button With Some Emoji 1`] = ` +exports[`Storyshots Button With Text 1`] = ` +<Button + onClick={[Function]} +> + <button + onClick={[Function]} + style={ + Object { + "backgroundColor": "#FFFFFF", + "border": "1px solid #eee", + "borderRadius": 3, + "cursor": "pointer", + "fontSize": 15, + "margin": 10, + "padding": "3px 10px", + } + } + type="button" + > + Hello Button + </button> +</Button> +`; + +exports[`Storyshots Button with some emoji 1`] = ` <Button onClick={[Function]} > @@ -88,31 +112,7 @@ exports[`Storyshots Button With Some Emoji 1`] = ` </Button> `; -exports[`Storyshots Button With Text 1`] = ` -<Button - onClick={[Function]} -> - <button - onClick={[Function]} - style={ - Object { - "backgroundColor": "#FFFFFF", - "border": "1px solid #eee", - "borderRadius": 3, - "cursor": "pointer", - "fontSize": 15, - "margin": 10, - "padding": "3px 10px", - } - } - type="button" - > - Hello Button - </button> -</Button> -`; - -exports[`Storyshots Welcome MDX To Storybook 1`] = ` +exports[`Storyshots Welcome MDX to Storybook 1`] = ` <Welcome showApp={[Function]} > @@ -316,7 +316,7 @@ exports[`Storyshots Welcome MDX To Storybook 1`] = ` </Welcome> `; -exports[`Storyshots Welcome To Storybook 1`] = ` +exports[`Storyshots Welcome to Storybook 1`] = ` <Welcome showApp={[Function]} > diff --git a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallow.test.js.snap b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallow.test.js.snap index a0c27ed2b41..445c7ba9a4f 100644 --- a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallow.test.js.snap +++ b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallow.test.js.snap @@ -45,13 +45,33 @@ exports[`Storyshots Another Button with text 1`] = ` </button> `; -exports[`Storyshots Async With Timeout 1`] = ` +exports[`Storyshots Async with 5ms timeout simulating async operation 1`] = ` <h1> </h1> `; -exports[`Storyshots Button With Some Emoji 1`] = ` +exports[`Storyshots Button With Text 1`] = ` +<button + onClick={[Function]} + style={ + Object { + "backgroundColor": "#FFFFFF", + "border": "1px solid #eee", + "borderRadius": 3, + "cursor": "pointer", + "fontSize": 15, + "margin": 10, + "padding": "3px 10px", + } + } + type="button" +> + Hello Button +</button> +`; + +exports[`Storyshots Button with some emoji 1`] = ` <button onClick={[Function]} style={ @@ -76,27 +96,7 @@ exports[`Storyshots Button With Some Emoji 1`] = ` </button> `; -exports[`Storyshots Button With Text 1`] = ` -<button - onClick={[Function]} - style={ - Object { - "backgroundColor": "#FFFFFF", - "border": "1px solid #eee", - "borderRadius": 3, - "cursor": "pointer", - "fontSize": 15, - "margin": 10, - "padding": "3px 10px", - } - } - type="button" -> - Hello Button -</button> -`; - -exports[`Storyshots Welcome MDX To Storybook 1`] = ` +exports[`Storyshots Welcome MDX to Storybook 1`] = ` <Main> <Title> Welcome to storybook @@ -170,7 +170,7 @@ exports[`Storyshots Welcome MDX To Storybook 1`] = ` </Main> `; -exports[`Storyshots Welcome To Storybook 1`] = ` +exports[`Storyshots Welcome to Storybook 1`] = ` <Main> <Title> Welcome to storybook diff --git a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallowWithOptions.test.js.snap b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallowWithOptions.test.js.snap index a0c27ed2b41..445c7ba9a4f 100644 --- a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallowWithOptions.test.js.snap +++ b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.shallowWithOptions.test.js.snap @@ -45,13 +45,33 @@ exports[`Storyshots Another Button with text 1`] = ` </button> `; -exports[`Storyshots Async With Timeout 1`] = ` +exports[`Storyshots Async with 5ms timeout simulating async operation 1`] = ` <h1> </h1> `; -exports[`Storyshots Button With Some Emoji 1`] = ` +exports[`Storyshots Button With Text 1`] = ` +<button + onClick={[Function]} + style={ + Object { + "backgroundColor": "#FFFFFF", + "border": "1px solid #eee", + "borderRadius": 3, + "cursor": "pointer", + "fontSize": 15, + "margin": 10, + "padding": "3px 10px", + } + } + type="button" +> + Hello Button +</button> +`; + +exports[`Storyshots Button with some emoji 1`] = ` <button onClick={[Function]} style={ @@ -76,27 +96,7 @@ exports[`Storyshots Button With Some Emoji 1`] = ` </button> `; -exports[`Storyshots Button With Text 1`] = ` -<button - onClick={[Function]} - style={ - Object { - "backgroundColor": "#FFFFFF", - "border": "1px solid #eee", - "borderRadius": 3, - "cursor": "pointer", - "fontSize": 15, - "margin": 10, - "padding": "3px 10px", - } - } - type="button" -> - Hello Button -</button> -`; - -exports[`Storyshots Welcome MDX To Storybook 1`] = ` +exports[`Storyshots Welcome MDX to Storybook 1`] = ` <Main> <Title> Welcome to storybook @@ -170,7 +170,7 @@ exports[`Storyshots Welcome MDX To Storybook 1`] = ` </Main> `; -exports[`Storyshots Welcome To Storybook 1`] = ` +exports[`Storyshots Welcome to Storybook 1`] = ` <Main> <Title> Welcome to storybook diff --git a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.snapshotWithOptionsFunction.test.js.snap b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.snapshotWithOptionsFunction.test.js.snap index 15dea97c439..30257648479 100644 --- a/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.snapshotWithOptionsFunction.test.js.snap +++ b/addons/storyshots/storyshots-core/stories/__snapshots__/storyshot.snapshotWithOptionsFunction.test.js.snap @@ -45,13 +45,33 @@ exports[`Storyshots Another Button with text 1`] = ` </button> `; -exports[`Storyshots Async With Timeout 1`] = ` +exports[`Storyshots Async with 5ms timeout simulating async operation 1`] = ` <h1> </h1> `; -exports[`Storyshots Button With Some Emoji 1`] = ` +exports[`Storyshots Button With Text 1`] = ` +<button + onClick={[Function]} + style={ + Object { + "backgroundColor": "#FFFFFF", + "border": "1px solid #eee", + "borderRadius": 3, + "cursor": "pointer", + "fontSize": 15, + "margin": 10, + "padding": "3px 10px", + } + } + type="button" +> + Hello Button +</button> +`; + +exports[`Storyshots Button with some emoji 1`] = ` <button onClick={[Function]} style={ @@ -76,27 +96,7 @@ exports[`Storyshots Button With Some Emoji 1`] = ` </button> `; -exports[`Storyshots Button With Text 1`] = ` -<button - onClick={[Function]} - style={ - Object { - "backgroundColor": "#FFFFFF", - "border": "1px solid #eee", - "borderRadius": 3, - "cursor": "pointer", - "fontSize": 15, - "margin": 10, - "padding": "3px 10px", - } - } - type="button" -> - Hello Button -</button> -`; - -exports[`Storyshots Welcome MDX To Storybook 1`] = ` +exports[`Storyshots Welcome MDX to Storybook 1`] = ` <article style={ Object { @@ -270,7 +270,7 @@ exports[`Storyshots Welcome MDX To Storybook 1`] = ` </article> `; -exports[`Storyshots Welcome To Storybook 1`] = ` +exports[`Storyshots Welcome to Storybook 1`] = ` <article style={ Object { diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.async.storyshot b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.async.storyshot index 2b0ad426c6c..bb2f1c61126 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.async.storyshot +++ b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.async.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Async With Timeout 1`] = ` +exports[`Storyshots Async with 5ms timeout simulating async operation 1`] = ` <AsyncTestComponent> <h1> THIS IS SO DONE diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.foo b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.foo index 63102b6aa4f..d4459afef80 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.foo +++ b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.foo @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Async With Timeout 1`] = ` +exports[`Storyshots Async with 5ms timeout simulating async operation 1`] = ` <h1> </h1> diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.storyshot b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.storyshot index 63102b6aa4f..d4459afef80 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.storyshot +++ b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Async.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Async With Timeout 1`] = ` +exports[`Storyshots Async with 5ms timeout simulating async operation 1`] = ` <h1> </h1> diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.foo b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.foo index 0c782e5eb37..47dabe9763f 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.foo +++ b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.foo @@ -1,6 +1,26 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Button With Some Emoji 1`] = ` +exports[`Storyshots Button With Text 1`] = ` +<button + onClick={[Function]} + style={ + Object { + "backgroundColor": "#FFFFFF", + "border": "1px solid #eee", + "borderRadius": 3, + "cursor": "pointer", + "fontSize": 15, + "margin": 10, + "padding": "3px 10px", + } + } + type="button" +> + Hello Button +</button> +`; + +exports[`Storyshots Button with some emoji 1`] = ` <button onClick={[Function]} style={ @@ -24,23 +44,3 @@ exports[`Storyshots Button With Some Emoji 1`] = ` </span> </button> `; - -exports[`Storyshots Button With Text 1`] = ` -<button - onClick={[Function]} - style={ - Object { - "backgroundColor": "#FFFFFF", - "border": "1px solid #eee", - "borderRadius": 3, - "cursor": "pointer", - "fontSize": 15, - "margin": 10, - "padding": "3px 10px", - } - } - type="button" -> - Hello Button -</button> -`; diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.storyshot b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.storyshot index 0c782e5eb37..47dabe9763f 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.storyshot +++ b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Button.stories.storyshot @@ -1,6 +1,26 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Button With Some Emoji 1`] = ` +exports[`Storyshots Button With Text 1`] = ` +<button + onClick={[Function]} + style={ + Object { + "backgroundColor": "#FFFFFF", + "border": "1px solid #eee", + "borderRadius": 3, + "cursor": "pointer", + "fontSize": 15, + "margin": 10, + "padding": "3px 10px", + } + } + type="button" +> + Hello Button +</button> +`; + +exports[`Storyshots Button with some emoji 1`] = ` <button onClick={[Function]} style={ @@ -24,23 +44,3 @@ exports[`Storyshots Button With Some Emoji 1`] = ` </span> </button> `; - -exports[`Storyshots Button With Text 1`] = ` -<button - onClick={[Function]} - style={ - Object { - "backgroundColor": "#FFFFFF", - "border": "1px solid #eee", - "borderRadius": 3, - "cursor": "pointer", - "fontSize": 15, - "margin": 10, - "padding": "3px 10px", - } - } - type="button" -> - Hello Button -</button> -`; diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.foo b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.foo index 7cb2b61c5ae..4662f49c876 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.foo +++ b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.foo @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Welcome To Storybook 1`] = ` +exports[`Storyshots Welcome to Storybook 1`] = ` <article style={ Object { diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.storyshot b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.storyshot index 9084215a29c..97712dfd14e 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.storyshot +++ b/addons/storyshots/storyshots-core/stories/required_with_context/__snapshots__/Welcome.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Welcome MDX To Storybook 1`] = ` +exports[`Storyshots Welcome MDX to Storybook 1`] = ` <article style={ Object { @@ -174,7 +174,7 @@ exports[`Storyshots Welcome MDX To Storybook 1`] = ` </article> `; -exports[`Storyshots Welcome To Storybook 1`] = ` +exports[`Storyshots Welcome to Storybook 1`] = ` <article style={ Object { diff --git a/addons/storyshots/storyshots-puppeteer/package.json b/addons/storyshots/storyshots-puppeteer/package.json index 7903744d1fa..5ffc83f3aeb 100644 --- a/addons/storyshots/storyshots-puppeteer/package.json +++ b/addons/storyshots/storyshots-puppeteer/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storyshots-puppeteer", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Image snapshots addition to StoryShots based on puppeteer", "keywords": [ "addon", @@ -29,8 +29,8 @@ "prepare": "node ../../../scripts/prepare.js" }, "dependencies": { - "@storybook/node-logger": "5.3.0-alpha.41", - "@storybook/router": "5.3.0-alpha.41", + "@storybook/node-logger": "5.3.0-beta.2", + "@storybook/router": "5.3.0-beta.2", "@types/jest-image-snapshot": "^2.8.0", "@types/puppeteer-core": "^1.9.0", "core-js": "^3.0.1", @@ -39,7 +39,7 @@ "regenerator-runtime": "^0.13.3" }, "peerDependencies": { - "@storybook/addon-storyshots": "5.3.0-alpha.13" + "@storybook/addon-storyshots": "5.3.0-beta.1" }, "publishConfig": { "access": "public" diff --git a/addons/storysource/package.json b/addons/storysource/package.json index ebc6be7ce0c..1021f552353 100644 --- a/addons/storysource/package.json +++ b/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Stories addon for storybook", "keywords": [ "addon", @@ -28,11 +28,11 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/router": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/router": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "estraverse": "^4.2.0", "loader-utils": "^1.2.3", diff --git a/addons/viewport/package.json b/addons/viewport/package.json index 621cef2ce18..ba59263ca44 100644 --- a/addons/viewport/package.json +++ b/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook addon to change the viewport size to mobile", "keywords": [ "addon", @@ -23,17 +23,18 @@ "*.js", "*.d.ts" ], - "main": "preview.js", + "main": "dist/preview.js", + "types": "dist/preview.d.ts", "scripts": { "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "memoizerific": "^1.11.3", diff --git a/addons/viewport/preview.js b/addons/viewport/preview.js deleted file mode 100644 index dc47e9c63cb..00000000000 --- a/addons/viewport/preview.js +++ /dev/null @@ -1,5 +0,0 @@ -const preview = require('./dist/legacy_preview/index'); - -exports.configureViewport = preview.configureViewport; -exports.DEFAULT_VIEWPORT = preview.DEFAULT_VIEWPORT; -exports.INITIAL_VIEWPORTS = preview.INITIAL_VIEWPORTS; diff --git a/addons/viewport/src/preview.ts b/addons/viewport/src/preview.ts new file mode 100644 index 00000000000..be2dc03d34c --- /dev/null +++ b/addons/viewport/src/preview.ts @@ -0,0 +1 @@ +export { configureViewport, DEFAULT_VIEWPORT, INITIAL_VIEWPORTS } from './legacy_preview'; diff --git a/app/angular/package.json b/app/angular/package.json index 5156ee85193..1dfc41ec1cf 100644 --- a/app/angular/package.json +++ b/app/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Angular: Develop Angular Components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -33,9 +33,9 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", - "@storybook/node-logger": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", + "@storybook/node-logger": "5.3.0-beta.2", "core-js": "^3.0.1", "fork-ts-checker-webpack-plugin": "^3.0.1", "global": "^4.3.2", diff --git a/app/angular/src/client/preview/angular/components/app.component.ts b/app/angular/src/client/preview/angular/components/app.component.ts index 60b2d89139c..7856bf8f894 100644 --- a/app/angular/src/client/preview/angular/components/app.component.ts +++ b/app/angular/src/client/preview/angular/components/app.component.ts @@ -77,7 +77,7 @@ export class AppComponent implements OnInit, OnDestroy { const value = props[key]; const instanceProperty = instance[key]; - if (!(instanceProperty instanceof EventEmitter) && (value !== undefined && value !== null)) { + if (!(instanceProperty instanceof EventEmitter) && value !== undefined && value !== null) { // eslint-disable-next-line no-param-reassign instance[key] = value; if (hasNgOnChangesHook) { diff --git a/app/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts b/app/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts index 2b60aa49a4b..02d82e734f2 100644 --- a/app/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts +++ b/app/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts @@ -2,7 +2,7 @@ import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import getTsLoaderOptions from '../ts_config'; import createForkTsCheckerInstance from '../create-fork-ts-checker-plugin'; -// eslint-disable-next-line global-require +// eslint-disable-next-line global-require, jest/no-mocks-import jest.mock('fs', () => require('../../../../../__mocks__/fs')); jest.mock('path', () => ({ resolve: () => 'tsconfig.json', diff --git a/app/angular/src/server/__tests__/ts_config.test.ts b/app/angular/src/server/__tests__/ts_config.test.ts index 383eb7ccc18..046001787ad 100644 --- a/app/angular/src/server/__tests__/ts_config.test.ts +++ b/app/angular/src/server/__tests__/ts_config.test.ts @@ -1,6 +1,6 @@ import getTsLoaderOptions from '../ts_config'; -// eslint-disable-next-line global-require +// eslint-disable-next-line global-require, jest/no-mocks-import jest.mock('fs', () => require('../../../../../__mocks__/fs')); jest.mock('path', () => ({ resolve: () => 'tsconfig.json', diff --git a/app/angular/src/server/options.ts b/app/angular/src/server/options.ts index 75a84f17d3f..4d703cf796d 100644 --- a/app/angular/src/server/options.ts +++ b/app/angular/src/server/options.ts @@ -3,6 +3,7 @@ const packageJson = require('../../package.json'); export default { packageJson, + framework: 'angular', frameworkPresets: [ require.resolve('./framework-preset-angular.js'), require.resolve('./framework-preset-angular-cli.js'), diff --git a/app/ember/package.json b/app/ember/package.json index 7d50ad987fd..27e3e318369 100644 --- a/app/ember/package.json +++ b/app/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/master/app/ember", "bugs": { @@ -31,7 +31,7 @@ }, "dependencies": { "@ember/test-helpers": "^1.5.0", - "@storybook/core": "5.3.0-alpha.41", + "@storybook/core": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "regenerator-runtime": "^0.13.3", diff --git a/app/ember/src/server/options.js b/app/ember/src/server/options.js index 919e0202bca..b5b03fad7e6 100644 --- a/app/ember/src/server/options.js +++ b/app/ember/src/server/options.js @@ -2,5 +2,6 @@ import packageJson from '../../package.json'; export default { packageJson, + framework: 'ember', frameworkPresets: [require.resolve('./framework-preset-babel-ember.js')], }; diff --git a/app/html/package.json b/app/html/package.json index c05cfd381e5..f562f3886d3 100644 --- a/app/html/package.json +++ b/app/html/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -33,8 +33,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", "@types/webpack-env": "^1.13.9", "core-js": "^3.0.1", "global": "^4.3.2", diff --git a/app/html/src/server/options.ts b/app/html/src/server/options.ts index 27701b0063c..1d349ea837d 100644 --- a/app/html/src/server/options.ts +++ b/app/html/src/server/options.ts @@ -3,5 +3,6 @@ const packageJson = require('../../package.json'); export default { packageJson, + framework: 'html', frameworkPresets: [require.resolve('./framework-preset-html.js')], }; diff --git a/app/marko/package.json b/app/marko/package.json index 1b7163e4014..cf32da4d8b3 100644 --- a/app/marko/package.json +++ b/app/marko/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/marko", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Marko: Develop Marko Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -33,8 +33,8 @@ }, "dependencies": { "@marko/webpack": "^2.0.0", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "regenerator-runtime": "^0.13.3", diff --git a/app/marko/src/server/options.js b/app/marko/src/server/options.js index 00159044ab4..75f0bacac6f 100644 --- a/app/marko/src/server/options.js +++ b/app/marko/src/server/options.js @@ -2,5 +2,6 @@ import packageJson from '../../package.json'; export default { packageJson, + framework: 'marko', frameworkPresets: [require.resolve('./framework-preset-marko.js')], }; diff --git a/app/mithril/package.json b/app/mithril/package.json index 48373a36184..b18d4a4e672 100644 --- a/app/mithril/package.json +++ b/app/mithril/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/mithril", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Mithril: Develop Mithril Component in isolation.", "keywords": [ "storybook" @@ -35,8 +35,8 @@ "dependencies": { "@babel/core": "^7.6.2", "@babel/plugin-transform-react-jsx": "^7.3.0", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", "@types/mithril": "^2.0.0", "core-js": "^3.0.1", "global": "^4.3.2", diff --git a/app/mithril/src/server/options.ts b/app/mithril/src/server/options.ts index 1f6aa7326e1..2ffb2b00f60 100644 --- a/app/mithril/src/server/options.ts +++ b/app/mithril/src/server/options.ts @@ -2,5 +2,6 @@ import packageJson from '../../package.json'; export default { packageJson, + framework: 'mithril', frameworkPresets: [require.resolve('./framework-preset-mithril.js')], }; diff --git a/app/polymer/package.json b/app/polymer/package.json index 19b9a8f2498..f451eb4034e 100644 --- a/app/polymer/package.json +++ b/app/polymer/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/polymer", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Polymer: Develop Polymer components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -32,7 +32,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/core": "5.3.0-alpha.41", + "@storybook/core": "5.3.0-beta.2", "@webcomponents/webcomponentsjs": "^1.2.0", "core-js": "^3.0.1", "global": "^4.3.2", diff --git a/app/polymer/src/server/options.js b/app/polymer/src/server/options.js index 81879f131cd..7d832b7cebc 100644 --- a/app/polymer/src/server/options.js +++ b/app/polymer/src/server/options.js @@ -2,5 +2,6 @@ import packageJson from '../../package.json'; export default { packageJson, + framework: 'polymer', frameworkPresets: [require.resolve('./framework-preset-polymer.js')], }; diff --git a/app/preact/package.json b/app/preact/package.json index e8e5dc6956f..709d7d38ab8 100644 --- a/app/preact/package.json +++ b/app/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" @@ -34,8 +34,8 @@ }, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.3.0", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", "@types/webpack-env": "^1.13.9", "core-js": "^3.0.1", "global": "^4.3.2", diff --git a/app/preact/src/server/options.ts b/app/preact/src/server/options.ts index 20900ed077f..73981f5d909 100644 --- a/app/preact/src/server/options.ts +++ b/app/preact/src/server/options.ts @@ -2,5 +2,6 @@ const packageJson = require('../../package.json'); export default { packageJson, + framework: 'preact', frameworkPresets: [require.resolve('./framework-preset-preact.js')], }; diff --git a/app/rax/package.json b/app/rax/package.json index 765ac5ab0ea..50701eed073 100644 --- a/app/rax/package.json +++ b/app/rax/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/rax", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Rax: Develop Rax Component in isolation.", "keywords": [ "rax", @@ -33,7 +33,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/core": "5.3.0-alpha.41", + "@storybook/core": "5.3.0-beta.2", "babel-preset-rax": "^1.0.0-beta.0", "core-js": "^3.0.1", "driver-dom": "^2.0.0", diff --git a/app/rax/src/server/options.js b/app/rax/src/server/options.js index 1c06efc33f4..42127e24799 100644 --- a/app/rax/src/server/options.js +++ b/app/rax/src/server/options.js @@ -2,5 +2,6 @@ import packageJson from '../../package.json'; export default { packageJson, + framework: 'rax', frameworkPresets: [require.resolve('./framework-preset-rax.js')], }; diff --git a/app/react-native-server/package.json b/app/react-native-server/package.json index 5b39be49aea..87245e03fe2 100644 --- a/app/react-native-server/package.json +++ b/app/react-native-server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-native-server", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "A better way to develop React Native Components for your app", "keywords": [ "react", @@ -31,13 +31,13 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/channel-websocket": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/ui": "5.3.0-alpha.41", - "commander": "^3.0.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/channel-websocket": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/ui": "5.3.0-beta.2", + "commander": "^4.0.1", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.6.0", diff --git a/app/react-native-server/src/server/options.js b/app/react-native-server/src/server/options.js index 4e3f610f6b3..873b3caab16 100644 --- a/app/react-native-server/src/server/options.js +++ b/app/react-native-server/src/server/options.js @@ -7,6 +7,7 @@ function extendOptions(options, extendServer) { return { ...options, + framework: 'react-native', extendServer, packageJson, mode: 'dev', diff --git a/app/react-native/package.json b/app/react-native/package.json index 6fe883fef92..284df1cdfa1 100644 --- a/app/react-native/package.json +++ b/app/react-native/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-native", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "A better way to develop React Native Components for your app", "keywords": [ "react", @@ -31,11 +31,11 @@ "dependencies": { "@emotion/core": "^10.0.20", "@emotion/native": "^10.0.14", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/channel-websocket": "5.3.0-alpha.41", - "@storybook/channels": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/channel-websocket": "5.3.0-beta.2", + "@storybook/channels": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", "core-js": "^3.0.1", "emotion-theming": "^10.0.19", "react-native-swipe-gestures": "^1.0.4" diff --git a/app/react/package.json b/app/react/package.json index d0b41455894..085a37da699 100644 --- a/app/react/package.json +++ b/app/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -36,9 +36,9 @@ "@babel/plugin-transform-react-constant-elements": "^7.2.0", "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", - "@storybook/node-logger": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", + "@storybook/node-logger": "5.3.0-beta.2", "@svgr/webpack": "^4.0.3", "@types/webpack-env": "^1.13.7", "babel-plugin-add-react-displayname": "^0.0.5", diff --git a/app/react/src/server/cra-config.test.ts b/app/react/src/server/cra-config.test.ts index 20feeab6603..4c4425dd848 100644 --- a/app/react/src/server/cra-config.test.ts +++ b/app/react/src/server/cra-config.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import */ import fs from 'fs'; import path from 'path'; import { diff --git a/app/react/src/server/cra-config.ts b/app/react/src/server/cra-config.ts index b38418da6bc..6514e74b956 100644 --- a/app/react/src/server/cra-config.ts +++ b/app/react/src/server/cra-config.ts @@ -71,29 +71,26 @@ export function isReactScriptsInstalled(requiredVersion = '2.0.0') { } export const getRules = (extensions: string[]) => (rules: RuleSetRule[]) => - rules.reduce( - (craRules, rule) => { - // If at least one extension satisfies the rule test, the rule is one - // we want to extract - if (rule.test && extensions.some(normalizeCondition(rule.test))) { - // If the base test is for extensions, return early - return craRules.concat(rule); - } + rules.reduce((craRules, rule) => { + // If at least one extension satisfies the rule test, the rule is one + // we want to extract + if (rule.test && extensions.some(normalizeCondition(rule.test))) { + // If the base test is for extensions, return early + return craRules.concat(rule); + } - // Get any rules contained in rule.oneOf - if (!rule.test && rule.oneOf) { - craRules.push(...getRules(extensions)(rule.oneOf)); - } + // Get any rules contained in rule.oneOf + if (!rule.test && rule.oneOf) { + craRules.push(...getRules(extensions)(rule.oneOf)); + } - // Get any rules contained in rule.rules - if (!rule.test && rule.rules) { - craRules.push(...getRules(extensions)(rule.rules)); - } + // Get any rules contained in rule.rules + if (!rule.test && rule.rules) { + craRules.push(...getRules(extensions)(rule.rules)); + } - return craRules; - }, - [] as RuleSetRule[] - ); + return craRules; + }, [] as RuleSetRule[]); const getStyleRules = getRules(cssExtensions.concat(cssModuleExtensions)); @@ -101,23 +98,20 @@ export const getTypeScriptRules = (webpackConfigRules: RuleSetRule[], configDir: const rules = getRules(typeScriptExtensions)(webpackConfigRules); // Adds support for using TypeScript in the `.storybook` (or config) folder. - return rules.reduce( - (accRules, rule) => { - // Resolves an issue where this config is parsed twice (#4903). - if (typeof rule.include !== 'string') { - return [...accRules, rule]; - } + return rules.reduce((accRules, rule) => { + // Resolves an issue where this config is parsed twice (#4903). + if (typeof rule.include !== 'string') { + return [...accRules, rule]; + } - return [ - ...accRules, - { - ...rule, - include: [rule.include, path.resolve(configDir)], - }, - ]; - }, - [] as RuleSetRule[] - ); + return [ + ...accRules, + { + ...rule, + include: [rule.include, path.resolve(configDir)], + }, + ]; + }, [] as RuleSetRule[]); }; export const getModulePath = () => { diff --git a/app/react/src/server/options.ts b/app/react/src/server/options.ts index 04dc76219b3..5e16a0eaee5 100644 --- a/app/react/src/server/options.ts +++ b/app/react/src/server/options.ts @@ -2,6 +2,7 @@ const packageJson = require('../../package.json'); export default { packageJson, + framework: 'react', frameworkPresets: [ require.resolve('./framework-preset-react.js'), require.resolve('./framework-preset-cra.js'), diff --git a/app/riot/package.json b/app/riot/package.json index 43f79a26642..b31793e6dd7 100644 --- a/app/riot/package.json +++ b/app/riot/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/riot", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for riot.js: View riot snippets in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -33,7 +33,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/core": "5.3.0-alpha.41", + "@storybook/core": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "raw-loader": "^3.1.0", diff --git a/app/riot/src/server/options.js b/app/riot/src/server/options.js index a70e6667624..fbaea49b857 100644 --- a/app/riot/src/server/options.js +++ b/app/riot/src/server/options.js @@ -2,5 +2,6 @@ import packageJson from '../../package.json'; export default { packageJson, + framework: 'riot', frameworkPresets: [require.resolve('./framework-preset-riot.js')], }; diff --git a/app/svelte/package.json b/app/svelte/package.json index e0ee7e0221b..db761a11102 100644 --- a/app/svelte/package.json +++ b/app/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -23,6 +23,7 @@ "*.d.ts" ], "main": "dist/client/index.js", + "types": "dist/client/index.d.ts", "bin": { "build-storybook": "./bin/build.js", "start-storybook": "./bin/index.js", @@ -32,7 +33,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/core": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "regenerator-runtime": "^0.13.3", diff --git a/app/svelte/src/client/index.js b/app/svelte/src/client/index.ts similarity index 100% rename from app/svelte/src/client/index.js rename to app/svelte/src/client/index.ts diff --git a/app/svelte/src/client/preview/globals.js b/app/svelte/src/client/preview/globals.ts similarity index 100% rename from app/svelte/src/client/preview/globals.js rename to app/svelte/src/client/preview/globals.ts diff --git a/app/svelte/src/client/preview/index.js b/app/svelte/src/client/preview/index.ts similarity index 65% rename from app/svelte/src/client/preview/index.js rename to app/svelte/src/client/preview/index.ts index baf0133c723..177d45653da 100644 --- a/app/svelte/src/client/preview/index.js +++ b/app/svelte/src/client/preview/index.ts @@ -15,7 +15,8 @@ export const { } = clientApi; const framework = 'svelte'; -export const storiesOf = (...args) => clientApi.storiesOf(...args).addParameters({ framework }); -export const configure = (...args) => coreConfigure(...args, framework); +export const storiesOf = (...args: any) => + clientApi.storiesOf(...args).addParameters({ framework }); +export const configure = (...args: any) => coreConfigure(...args, framework); export { forceReRender }; diff --git a/app/svelte/src/client/preview/render.js b/app/svelte/src/client/preview/render.ts similarity index 91% rename from app/svelte/src/client/preview/render.js rename to app/svelte/src/client/preview/render.ts index c69b7634b63..76f8b005258 100644 --- a/app/svelte/src/client/preview/render.js +++ b/app/svelte/src/client/preview/render.ts @@ -1,19 +1,21 @@ import { document } from 'global'; import dedent from 'ts-dedent'; +import { MountViewArgs, RenderMainArgs } from './types'; -let previousComponent = null; +type Component = any; + +let previousComponent: Component = null; function cleanUpPreviousStory() { if (!previousComponent) { return; } - previousComponent.$destroy(); previousComponent = null; } -function mountView({ Component, target, props, on, Wrapper, WrapperData }) { - let component; +function mountView({ Component, target, props, on, Wrapper, WrapperData }: MountViewArgs) { + let component: Component; if (Wrapper) { const fragment = document.createDocumentFragment(); @@ -47,8 +49,7 @@ export default function render({ selectedStory, showMain, showError, - // showException, -}) { +}: RenderMainArgs) { const { /** @type {SvelteComponent} */ Component, diff --git a/app/svelte/src/client/preview/types.ts b/app/svelte/src/client/preview/types.ts new file mode 100644 index 00000000000..31bf80ea626 --- /dev/null +++ b/app/svelte/src/client/preview/types.ts @@ -0,0 +1,33 @@ +import { StoryFn } from '@storybook/addons'; + +export interface ShowErrorArgs { + title: string; + description: string; +} + +export interface RenderMainArgs { + storyFn: StoryFn<any>; + selectedKind: string; + selectedStory: string; + showMain: () => void; + showError: (args: ShowErrorArgs) => void; +} + +export interface MountViewArgs { + Component: any; + target: any; + props: MountProps; + on: any; + Wrapper: any; + WrapperData: any; +} + +interface MountProps { + rounded: boolean; + text: string; +} + +interface WrapperData { + innerStyle: string; + style: string; +} diff --git a/app/svelte/src/server/build.js b/app/svelte/src/server/build.ts similarity index 100% rename from app/svelte/src/server/build.js rename to app/svelte/src/server/build.ts diff --git a/app/svelte/src/server/framework-preset-svelte.js b/app/svelte/src/server/framework-preset-svelte.ts similarity index 78% rename from app/svelte/src/server/framework-preset-svelte.js rename to app/svelte/src/server/framework-preset-svelte.ts index 6fcbfb1f79c..d29eaf8ec51 100644 --- a/app/svelte/src/server/framework-preset-svelte.js +++ b/app/svelte/src/server/framework-preset-svelte.ts @@ -1,4 +1,6 @@ -export function webpack(config) { +import { Configuration } from 'webpack'; // eslint-disable-line + +export function webpack(config: Configuration) { return { ...config, module: { diff --git a/app/svelte/src/server/index.js b/app/svelte/src/server/index.ts similarity index 100% rename from app/svelte/src/server/index.js rename to app/svelte/src/server/index.ts diff --git a/app/svelte/src/server/options.js b/app/svelte/src/server/options.ts similarity index 59% rename from app/svelte/src/server/options.js rename to app/svelte/src/server/options.ts index 3e4a77d7640..64c8aa3cd58 100644 --- a/app/svelte/src/server/options.js +++ b/app/svelte/src/server/options.ts @@ -1,6 +1,7 @@ -import packageJson from '../../package.json'; +const packageJson = require('../../package.json'); export default { packageJson, + framework: 'svelte', frameworkPresets: [require.resolve('./framework-preset-svelte.js')], }; diff --git a/app/svelte/src/typings.d.ts b/app/svelte/src/typings.d.ts new file mode 100644 index 00000000000..6288cba4b09 --- /dev/null +++ b/app/svelte/src/typings.d.ts @@ -0,0 +1,2 @@ +declare module '@storybook/core/*'; +declare module 'global'; diff --git a/app/svelte/tsconfig.json b/app/svelte/tsconfig.json new file mode 100644 index 00000000000..9fc120ad083 --- /dev/null +++ b/app/svelte/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "types": ["webpack-env"], + "resolveJsonModule": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "src/**/*.test.*" + ] +} \ No newline at end of file diff --git a/app/vue/package.json b/app/vue/package.json index cd3c783fa39..f236c0cce67 100644 --- a/app/vue/package.json +++ b/app/vue/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for Vue: Develop Vue Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -33,8 +33,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", "@types/webpack-env": "^1.13.9", "core-js": "^3.0.1", "global": "^4.3.2", diff --git a/app/vue/src/server/options.ts b/app/vue/src/server/options.ts index 1351e17477d..46df1823ce8 100644 --- a/app/vue/src/server/options.ts +++ b/app/vue/src/server/options.ts @@ -2,5 +2,6 @@ const packageJson = require('../../package.json'); export default { packageJson, + framework: 'vue', frameworkPresets: [require.resolve('./framework-preset-vue.js')], }; diff --git a/app/web-components/package.json b/app/web-components/package.json index 723b0ea5479..1059055ad2b 100644 --- a/app/web-components/package.json +++ b/app/web-components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit-html", @@ -37,8 +37,8 @@ "dependencies": { "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-import-meta": "^7.2.0", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", "@types/webpack-env": "^1.13.9", "babel-plugin-bundled-import-meta": "^0.3.1", "core-js": "^3.0.1", diff --git a/app/web-components/src/server/options.ts b/app/web-components/src/server/options.ts index 5217ce3a23b..6dff94b2b6d 100644 --- a/app/web-components/src/server/options.ts +++ b/app/web-components/src/server/options.ts @@ -3,5 +3,6 @@ const packageJson = require('../../package.json'); export default { packageJson, + framework: 'web-components', frameworkPresets: [require.resolve('./framework-preset-web-components.js')], }; diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index fcfde0bd528..00000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Node.js -# Build a general Node.js project with npm. -# Add steps that analyze code, save build artifacts, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript - -trigger: -- master - -pool: - vmImage: 'ubuntu-latest' - -steps: -- task: NodeTool@0 - inputs: - versionSpec: '10.x' - displayName: 'Install Node.js' - -- script: | - yarn install - yarn bootstrap --core - yarn build-storybooks - displayName: 'examples' diff --git a/cypress/support/commands.js b/cypress/support/commands.js index d7377c5df89..ecad1e42571 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -1,5 +1,4 @@ -/* eslint-disable no-unused-expressions */ -/* eslint-disable jest/valid-expect */ +/* eslint-disable jest/no-standalone-expect, no-unused-expressions, jest/valid-expect */ // *********************************************** // This example commands.js shows you how to // create various custom commands and overwrite diff --git a/dev-kits/addon-decorator/package.json b/dev-kits/addon-decorator/package.json index a2af1940b17..5b38c4f0ee9 100644 --- a/dev-kits/addon-decorator/package.json +++ b/dev-kits/addon-decorator/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-decorator", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "decorator addon for storybook", "keywords": [ "addon", @@ -24,8 +24,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.4.0" }, diff --git a/dev-kits/addon-parameter/package.json b/dev-kits/addon-parameter/package.json index 0e58408efae..16cd71d62ed 100644 --- a/dev-kits/addon-parameter/package.json +++ b/dev-kits/addon-parameter/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-parameter", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "parameter addon for storybook", "keywords": [ "addon", @@ -24,12 +24,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3", diff --git a/dev-kits/addon-preview-wrapper/package.json b/dev-kits/addon-preview-wrapper/package.json index 9176713035e..35e8e65e04b 100644 --- a/dev-kits/addon-preview-wrapper/package.json +++ b/dev-kits/addon-preview-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-preview-wrapper", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "preview wrapper addon for storybook", "keywords": [ "addon", @@ -24,7 +24,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", "react": "^16.8.3" }, "publishConfig": { diff --git a/dev-kits/addon-roundtrip/package.json b/dev-kits/addon-roundtrip/package.json index 1c114a98c3a..e341c82d079 100644 --- a/dev-kits/addon-roundtrip/package.json +++ b/dev-kits/addon-roundtrip/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-roundtrip", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "description": "roundtrip addon for storybook", "keywords": [ "addon", @@ -24,13 +24,13 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/api": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/api": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3", diff --git a/docs/package.json b/docs/package.json index 7bbb8ab614e..5cc87a73a6d 100644 --- a/docs/package.json +++ b/docs/package.json @@ -32,22 +32,22 @@ "gatsby-source-filesystem": "^1.5.39", "gatsby-transformer-remark": "^1.7.44", "global": "^4.4.0", - "html-react-parser": "^0.9.1", + "html-react-parser": "^0.10.0", "is-builtin-module": "^3.0.0", "lodash": "^4.17.15", "marked": "^0.7.0", "polished": "^3.4.2", "prop-types": "^15.7.2", - "react": "^16.11.0", + "react": "^16.12.0", "react-document-title": "^2.0.3", - "react-dom": "^16.11.0", + "react-dom": "^16.12.0", "react-helmet": "^5.2.0", "react-popper-tooltip": "^2.10.0", "react-router": "^4.3.1", "react-stack-grid": "^0.7.1", "recompose": "^0.30.0", "sitemap": "^4.1.1", - "styled-components": "^4.4.0", + "styled-components": "^4.4.1", "ts-dedent": "^1.1.0", "validatorjs": "^3.17.1" } diff --git a/docs/src/new-components/basics/shared/site.js b/docs/src/new-components/basics/shared/site.js index 3ab939a7cc3..3901a245b63 100644 --- a/docs/src/new-components/basics/shared/site.js +++ b/docs/src/new-components/basics/shared/site.js @@ -10,7 +10,7 @@ export const metadata = { description: `Storybook is an open source tool for developing UI components in isolation for React, Vue, and Angular`, ogImage: '/images/social/open-graph.png', googleSiteVerification: '', - latestVersion: 'v5.1', + latestVersion: 'v5.3', }; export const url = { diff --git a/docs/src/new-components/basics/tooltip/TooltipLinkList.js b/docs/src/new-components/basics/tooltip/TooltipLinkList.js index 9c9a8d68b85..7fd87163f0f 100644 --- a/docs/src/new-components/basics/tooltip/TooltipLinkList.js +++ b/docs/src/new-components/basics/tooltip/TooltipLinkList.js @@ -7,7 +7,7 @@ const List = styled.div` min-width: 180px; overflow: hidden; overflow-y: auto; - maxheight: ${10.5 * 32 /* 10.5 items */}; + maxheight: ${11.5 * 32 /* 11.5 items */}; `; function TooltipLinkList({ links, LinkWrapper }) { diff --git a/docs/src/new-components/basics/tooltip/TooltipMessage.stories.js b/docs/src/new-components/basics/tooltip/TooltipMessage.stories.js index ae615685aef..52c5c7e3ff2 100644 --- a/docs/src/new-components/basics/tooltip/TooltipMessage.stories.js +++ b/docs/src/new-components/basics/tooltip/TooltipMessage.stories.js @@ -32,7 +32,10 @@ storiesOf('basics/tooltip/TooltipMessage', module) <TooltipMessage title="Lorem ipsum dolor sit" desc="Amet consectatur vestibulum concet durum politu coret weirom" - links={[{ title: 'Get more tips', href: 'test' }, { title: 'Done', href: 'test' }]} + links={[ + { title: 'Get more tips', href: 'test' }, + { title: 'Done', href: 'test' }, + ]} /> )) .add('minimal message', () => ( diff --git a/docs/src/pages/basics/writing-stories/index.md b/docs/src/pages/basics/writing-stories/index.md index 1764fb9cb92..8f14ae9bc01 100644 --- a/docs/src/pages/basics/writing-stories/index.md +++ b/docs/src/pages/basics/writing-stories/index.md @@ -116,10 +116,13 @@ If you want to load from multiple locations, you can use an array: ```js import { configure } from '@storybook/react'; -configure([ - require.context('../src/components', true, /\.stories\.js$/), - require.context('../lib', true, /\.stories\.js$/) -], module); +configure( + [ + require.context('../src/components', true, /\.stories\.js$/), + require.context('../lib', true, /\.stories\.js$/), + ], + module +); ``` Or if you want to do some custom loading logic, you can use a loader function. Just remember to return an array of module exports if you want to use Component Story Format. Here's an example that forces files to load in a specific order. @@ -127,12 +130,12 @@ Or if you want to do some custom loading logic, you can use a loader function. J ```js import { configure } from '@storybook/react'; -const loaderFn = () => ([ +const loaderFn = () => [ require('./welcome.stories.js'), require('./prelude.stories.js'), require('./button.stories.js'), require('./input.stories.js'), -]); +]; configure(loaderFn, module); ``` @@ -163,7 +166,7 @@ const loaderFn = () => { // manual loading require('./welcome.stories.js'); require('./button.stories.js'); - + // dynamic loading, unavailable in react-native const req = require.context('../src/components', true, /\.stories\.js$/); req.keys().forEach(fname => req(fname)); @@ -267,7 +270,7 @@ callout.story = { ## Story hierarchy -Stories can be organized in a nested structure using "/" as a separator, and can be given a top-level heading using a "|" root separator. +Stories can be organized in a nested structure using "/" as a separator. For example the following snippets nest the `Button` and `Checkbox` components within the `Atoms` group, under a top-level heading called `Design System`. @@ -277,7 +280,7 @@ import React from 'react'; import Button from './Button'; export default { - title: 'Design System|Atoms/Button', + title: 'Design System/Atoms/Button', }; export const normal = () => <Button onClick={action('clicked')}>Hello Button</Button>; ``` @@ -288,13 +291,13 @@ import React from 'react'; import Checkbox from './Checkbox'; export default { - title: 'Design System|Atoms/Checkbox', + title: 'Design System/Atoms/Checkbox', }; export const empty = () => <Checkbox label="empty" />; export const checked = () => <Checkbox label="checked" checked />; ``` -If you prefer other characters as separators, you can configure this using the `hierarchySeparator` and `hierarchyRootSeparator` config options. See the +By default the top-level heading will be treated as any other group, but if you'd like it to be given special emphasis as a "root", use the `showRoots` config option. See the [configuration options parameter](/configurations/options-parameter) page to learn more. ## Generating nesting path based on \_\_dirname @@ -309,7 +312,7 @@ import base from 'paths.macro'; import BaseButton from '../components/BaseButton'; export default { - title: `Other|${base}/Dirname Example`, + title: `Other/${base}/Dirname Example`, }; export const story1 = () => <BaseButton label="Story 1" />; export const story2 = () => <BaseButton label="Story 2" />; diff --git a/docs/src/pages/configurations/options-parameter/index.md b/docs/src/pages/configurations/options-parameter/index.md index 3b0a2654533..2905291e894 100644 --- a/docs/src/pages/configurations/options-parameter/index.md +++ b/docs/src/pages/configurations/options-parameter/index.md @@ -38,23 +38,10 @@ addParameters({ */ panelPosition: 'bottom', /** - * regex for finding the hierarchy separator - * @example: - * null - turn off hierarchy - * /\// - split by `/` - * /\./ - split by `.` - * /\/|\./ - split by `/` or `.` - * @type {Regex} + * display the top-level grouping as a "root" in the sidebar + * @type {Boolean} */ - hierarchySeparator: /\/|\./, - /** - * regex for finding the hierarchy root separator - * @example: - * null - turn off multiple hierarchy roots - * /\|/ - split by `|` - * @type {Regex} - */ - hierarchyRootSeparator: /\|/, + showRoots: null, /** * sidebar tree animations * @type {Boolean} diff --git a/docs/src/pages/configurations/typescript-config/index.md b/docs/src/pages/configurations/typescript-config/index.md index cb16b460ac8..e07b75b041a 100644 --- a/docs/src/pages/configurations/typescript-config/index.md +++ b/docs/src/pages/configurations/typescript-config/index.md @@ -7,7 +7,7 @@ This is a central reference for using Storybook with TypeScript. ## Typescript configuration presets -The easiest way to write and configure your stories in TypeScript is by using [Storybook presets](../../presets/introduction/index.md). +The easiest way to write and configure your stories in TypeScript is by using [Storybook presets](../../presets/introduction). If you're using Create React App (CRA) and have configured it to work with TS, you should use the [CRA preset](https://github.com/storybookjs/presets/tree/master/packages/preset-create-react-app), which configures Storybook to reuse CRA's TS handling. diff --git a/docs/src/pages/formats/component-story-format/index.md b/docs/src/pages/formats/component-story-format/index.md index 855fa2d5307..479ef1c7cbd 100644 --- a/docs/src/pages/formats/component-story-format/index.md +++ b/docs/src/pages/formats/component-story-format/index.md @@ -17,7 +17,7 @@ The default export defines metadata about your component, including the `compone import MyComponent from './MyComponent'; export default { - title: 'Path|To/MyComponent', + title: 'Path/To/MyComponent', component: MyComponent, decorators: [ ... ], parameters: { ... } @@ -47,7 +47,11 @@ simple.story = { Storybook handles named exports and `story.name` slightly differently. When should you use one vs. the other? -In general, you should use named exports. Storybook passes them through a `storyNameFromExport` function ([#7901](https://github.com/storybookjs/storybook/pull/7901)), which is implemented with `lodash.startCase`: +The named export is always used to determine the story ID / URL. + +If you specify `story.name`, it will be used as the story display name in the UI. + +If you don't specify `story.name`, the named export will be used to generate the display name. Storybook passes the named export through a `storyNameFromExport` function ([#7901](https://github.com/storybookjs/storybook/pull/7901)), which is implemented with `lodash.startCase`: ```js it('should format CSF exports with sensible defaults', () => { @@ -65,16 +69,14 @@ it('should format CSF exports with sensible defaults', () => { }); ``` -When you want to change the name of your story, rename the CSF export. This will change the name of the story and also change the Story's ID / URL. - -You should use the `story.name` option in the following cases: +Therefore, you should specify `story.name` in the following cases: 1. Want the name to show up in the Storybook UI in a way that's not possible with a named export, e.g. reserved keywords like "default", special characters like emoji, spacing/capitalization other than what's provided by `storyNameFromExport` -2. Want to preserve the Story ID independently from changing how it's displayed. Having stable Story ID's is useful for integration with third party tools. +2. Want to preserve the Story ID independently from changing how it's displayed. Having stable Story ID's can be useful for integration with third party tools. ## Non-story exports -In some cases, you may want to export a mixture of story and non-stories. For example., it can be useful to export data that's used in your stories. +In some cases, you may want to export a mixture of story and non-stories. For example, it can be useful to export data that's used in your stories. To make this possible, you can use optional `includeStories` and `excludeStories` configuration fields in the default export, which can be set to either an array of strings, or a regular expression. diff --git a/docs/src/pages/formats/storiesof-api/index.md b/docs/src/pages/formats/storiesof-api/index.md index f67826dad83..1aad7d55e6a 100644 --- a/docs/src/pages/formats/storiesof-api/index.md +++ b/docs/src/pages/formats/storiesof-api/index.md @@ -80,7 +80,7 @@ storiesOf('Button', module).add( To make it easier to adopt the new [Component Story Format (CSF)](../component-story-format/), we've created an automatic migration tool to transform `storiesOf` API to Module format. ```sh -sb migrate storiesof-to-csf --glob src/**/*.stories.js +sb migrate storiesof-to-csf --glob=src/**/*.stories.js ``` For more information, see the CLI's [Codemod README](https://github.com/storybookjs/storybook/tree/next/lib/codemod). diff --git a/docs/src/pages/guides/guide-ember/index.md b/docs/src/pages/guides/guide-ember/index.md index 30beda3c26f..0f3b8f946e2 100644 --- a/docs/src/pages/guides/guide-ember/index.md +++ b/docs/src/pages/guides/guide-ember/index.md @@ -35,7 +35,7 @@ If you don't have `package.json` in your project, you'll need to init it first: npm init ``` -Then add the following NPM script to your package json in order to start the storybook later in this guide: +Then add the following NPM script to your `package.json` in order to start the storybook later in this guide: > In order for your storybook to run properly be sure to be either run `ember serve` or `ember build` before running any storybook commands. Running `ember serve` before storybook will enable live reloading. @@ -105,7 +105,7 @@ export const component = () => { }; ``` -> If you are using an older version of ember <= 3.1 please use this story style +> If you are using an older version of Ember <= 3.1 please use this story style ```js import { compile } from 'ember-source/dist/ember-template-compiler'; diff --git a/docs/src/versions/next.json b/docs/src/versions/next.json index 7a2559f2767..10aa535142d 100644 --- a/docs/src/versions/next.json +++ b/docs/src/versions/next.json @@ -1 +1 @@ -{"version":"5.3.0-alpha.41","info":{"plain":"### Features\n\n* Addon-docs: Render array of shape properly in props table ([#8707](https://github.com/storybookjs/storybook/pull/8707))\n* Addon-docs: Render params description in props table, support @ignore ([#8702](https://github.com/storybookjs/storybook/pull/8702))\n\n### Bug Fixes\n\n* Addon-docs: Fix \"Cannot read property 'props'\" ([#8731](https://github.com/storybookjs/storybook/pull/8731))\n* UI: Fix unmount components on Canvas/Docs tab switch ([#8625](https://github.com/storybookjs/storybook/pull/8625))\n* Angular: Fix loading baseConfig if no angular.json found ([#8727](https://github.com/storybookjs/storybook/pull/8727))"}} \ No newline at end of file +{"version":"5.3.0-beta.2","info":{"plain":"### Features\n\n* Addon-docs: Customizable DocPage doc blocks ([#8855](https://github.com/storybookjs/storybook/pull/8855))\n\n### Bug Fixes\n\n* Addon-docs: Add back Props \"exclude\" support ([#8868](https://github.com/storybookjs/storybook/pull/8868))\n* Addon-docs: Fix MDX component permalinking ([#8872](https://github.com/storybookjs/storybook/pull/8872))\n* Addon-docs: Fix regression to @ignore in Props ([#8867](https://github.com/storybookjs/storybook/pull/8867))\n\n### Maintenance\n\n* Addon-docs: Add tests for prop types default value ([#8869](https://github.com/storybookjs/storybook/pull/8869))"}} \ No newline at end of file diff --git a/docs/yarn.lock b/docs/yarn.lock index 903df224c82..8d52d1858b7 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -163,25 +163,13 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.2.tgz#53211e564604beb9befa7a4400ebf8147473eeef" integrity sha512-RMtr1i6E8MXaBWwhXL3yeOU8JXRnz8GNxHvaUfVvwxokvayUY0zoBeWbKw1S9XkufmGEEdQd228pSZXFkAln8Q== -"@emotion/is-prop-valid@0.8.2": +"@emotion/is-prop-valid@0.8.2", "@emotion/is-prop-valid@^0.8.1": version "0.8.2" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.2.tgz#b9692080da79041683021fcc32f96b40c54c59dc" integrity sha512-ZQIMAA2kLUWiUeMZNJDTeCwYRx1l8SQL0kHktze4COT22occKpDML1GDUXP5/sxhOMrZO8vZw773ni4H5Snrsg== dependencies: "@emotion/memoize" "0.7.2" -"@emotion/is-prop-valid@^0.8.1": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.1.tgz#6fb3ae2d24f07c8cd090f233e45771d9cd826d48" - integrity sha512-Wtaek/KGUP+HusWIa8DqtOR6U/Tl+QIdVkfJQHV3IT6ZImnJwklP5UVVPKZvkfljeFk3Q45CAPJ5N10gJ5XoLA== - dependencies: - "@emotion/memoize" "0.7.1" - -"@emotion/memoize@0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f" - integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg== - "@emotion/memoize@0.7.2": version "0.7.2" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30" @@ -226,16 +214,11 @@ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c" integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ== -"@emotion/unitless@0.7.4": +"@emotion/unitless@0.7.4", "@emotion/unitless@^0.7.0": version "0.7.4" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677" integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ== -"@emotion/unitless@^0.7.0": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f" - integrity sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg== - "@emotion/utils@0.11.2": version "0.11.2" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183" @@ -3653,14 +3636,7 @@ domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domhandler@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" - integrity sha1-LeWaCCLVAn+r/28DLCsloqir5zg= - dependencies: - domelementtype "1" - -domhandler@^2.3.0: +domhandler@2.4.2, domhandler@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== @@ -5811,48 +5787,36 @@ html-comment-regex@^1.1.0: resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== -html-dom-parser@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-0.2.2.tgz#960bdbf82632f11dfa7550c1b6f2aabcd6307243" - integrity sha512-8qWXUf0JY8k21oPZIWN9VddADoac+TeNTvFyF/ZJ5JgtzDIt2Fk9uwUHYKkGHnZb2LPj3SeB2V4WK0Hn/MEH/Q== +html-dom-parser@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-0.2.3.tgz#bfee592fc01c12bac08dcfa5da2611f9559a1812" + integrity sha512-GdzE63/U0IQEvcpAz0cUdYx2zQx0Ai+HWvE9TXEgwP27+SymUzKa7iB4DhjYpf2IdNLfTTOBuMS5nxeWOosSMQ== dependencies: "@types/domhandler" "2.4.1" - domhandler "2.3.0" - htmlparser2 "3.9.1" + domhandler "2.4.2" + htmlparser2 "3.10.1" html-entities@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= -html-react-parser@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-0.9.1.tgz#1fc1434c201c18930a20b271f862b1967f0497e2" - integrity sha512-hr5s4FvVeocxt9bZILNi/2571/JrxlLvyDzQr6WxOc2PeZXXF6s3r4UkXOHFHgFH3WV9DV7S75zNZfE78momsw== +html-react-parser@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-0.10.0.tgz#b0f3700831ce52e04013158982167c65292a418d" + integrity sha512-IDSoBgA8ZCiSoJSiumFMEUY1gsqEUeDDj8zUBGjET39RAC0aZpICp2F/doQFRqdLV0dCLLYHI7NabUara2nH1w== dependencies: "@types/domhandler" "2.4.1" - html-dom-parser "0.2.2" + html-dom-parser "0.2.3" react-property "1.0.1" - style-to-object "0.2.3" + style-to-object "0.3.0" html-void-elements@^1.0.0, html-void-elements@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.4.tgz#95e8bb5ecd6b88766569c2645f2b5f1591db9ba5" integrity sha512-yMk3naGPLrfvUV9TdDbuYXngh/TpHbA6TrOw3HL9kS8yhwx7i309BReNg7CbAJXGE+UMJ6je5OqJ7lC63o6YuQ== -htmlparser2@3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.1.tgz#621b7a58bc9acd003f7af0a2c9a00aa67c8505d2" - integrity sha1-Yht6WLyazQA/evCiyaAKpnyFBdI= - dependencies: - domelementtype "^1.3.0" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^2.0.2" - -htmlparser2@^3.10.0, htmlparser2@^3.3.0, htmlparser2@^3.9.1: +htmlparser2@3.10.1, htmlparser2@^3.10.0, htmlparser2@^3.3.0, htmlparser2@^3.9.1: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== @@ -9843,25 +9807,15 @@ react-dom@^15.6.0: object-assign "^4.1.0" prop-types "^15.5.10" -react-dom@^16.11.0: - version "16.11.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.11.0.tgz#7e7c4a5a85a569d565c2462f5d345da2dd849af5" - integrity sha512-nrRyIUE1e7j8PaXSPtyRKtz+2y9ubW/ghNgqKFHHAHaeP0fpF5uXR+sq8IMRHC+ZUxw7W9NyCDTBtwWxvkb0iA== +react-dom@^16.12.0, react-dom@^16.8.3: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" + integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.17.0" - -react-dom@^16.8.3: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962" - integrity sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.15.0" + scheduler "^0.18.0" react-error-overlay@^3.0.0: version "3.0.0" @@ -10076,19 +10030,10 @@ react@^15.6.0: object-assign "^4.1.0" prop-types "^15.5.10" -react@^16.11.0: - version "16.11.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" - integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - -react@^16.8.3: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa" - integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w== +react@^16.12.0, react@^16.8.3: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83" + integrity sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -10918,18 +10863,10 @@ sc-formatter@^3.0.1: resolved "https://registry.yarnpkg.com/sc-formatter/-/sc-formatter-3.0.2.tgz#9abdb14e71873ce7157714d3002477bbdb33c4e6" integrity sha512-9PbqYBpCq+OoEeRQ3QfFIGE6qwjjBcd2j7UjgDlhnZbtSnuGgHdcRklPKYGuYFH82V/dwd+AIpu8XvA1zqTd+A== -scheduler@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e" - integrity sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -scheduler@^0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" - integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== +scheduler@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" + integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -11828,17 +11765,17 @@ style-loader@^0.13.0: dependencies: loader-utils "^1.0.2" -style-to-object@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.2.3.tgz#afcf42bc03846b1e311880c55632a26ad2780bcb" - integrity sha512-1d/k4EY2N7jVLOqf2j04dTc37TPOv/hHxZmvpg8Pdh8UYydxeu/C1W1U4vD8alzf5V2Gt7rLsmkr4dxAlDm9ng== +style-to-object@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== dependencies: inline-style-parser "0.1.1" -styled-components@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.4.0.tgz#4e381e2dab831d0e6ea431c2840a96323e84e21b" - integrity sha512-xQ6vTI/0zNjZ1BBDRxyjvBddrxhQ3DxjeCdaLM1lSn5FDnkTOQgRkmWvcUiTajqc5nJqKVl+7sUioMqktD0+Zw== +styled-components@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.4.1.tgz#e0631e889f01db67df4de576fedaca463f05c2f2" + integrity sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/traverse" "^7.0.0" diff --git a/examples-native/crna-kitchen-sink/package.json b/examples-native/crna-kitchen-sink/package.json index 0d3fbc49504..7b10fad4865 100644 --- a/examples-native/crna-kitchen-sink/package.json +++ b/examples-native/crna-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "crna-kitchen-sink", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "main": "node_modules/expo/AppEntry.js", "workspaces": { @@ -31,20 +31,20 @@ "devDependencies": { "@babel/core": "^7.2.2", "@babel/plugin-transform-react-jsx-source": "^7.2.0", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-ondevice-actions": "5.3.0-alpha.41", - "@storybook/addon-ondevice-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-ondevice-knobs": "5.3.0-alpha.41", - "@storybook/addon-ondevice-notes": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/react-native": "5.3.0-alpha.41", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-ondevice-actions": "5.3.0-beta.2", + "@storybook/addon-ondevice-backgrounds": "5.3.0-beta.2", + "@storybook/addon-ondevice-knobs": "5.3.0-beta.2", + "@storybook/addon-ondevice-notes": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/react-native": "5.3.0-beta.2", "babel-loader": "^8.0.4", "babel-plugin-module-resolver": "^3.2.0", "babel-preset-expo": "^7.0.0", "core-js": "^3.0.1", - "expo-cli": "^2.17.1", + "expo-cli": "^3.7.1", "jest-expo": "^33.0.2", "react-test-renderer": "16.10.2", "schedule": "^0.5.0" diff --git a/examples/angular-cli/.storybook/config.ts b/examples/angular-cli/.storybook/config.ts index 344389e4ddd..0316837b5eb 100644 --- a/examples/angular-cli/.storybook/config.ts +++ b/examples/angular-cli/.storybook/config.ts @@ -14,7 +14,7 @@ addCssWarning(); addParameters({ options: { - hierarchyRootSeparator: /\|/, + showRoots: true, }, docs: { // inlineStories: true, diff --git a/examples/angular-cli/.storybook/presets.js b/examples/angular-cli/.storybook/presets.js index da117ff9853..a04174c7a33 100644 --- a/examples/angular-cli/.storybook/presets.js +++ b/examples/angular-cli/.storybook/presets.js @@ -1 +1 @@ -module.exports = ['@storybook/addon-docs/angular/preset']; +module.exports = ['@storybook/addon-docs/preset']; diff --git a/examples/angular-cli/package.json b/examples/angular-cli/package.json index 720c8b1c69b..5c52f977f16 100644 --- a/examples/angular-cli/package.json +++ b/examples/angular-cli/package.json @@ -1,6 +1,6 @@ { "name": "angular-cli", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "license": "MIT", "scripts": { @@ -37,21 +37,21 @@ "@angular/cli": "^8.3.6", "@angular/compiler-cli": "^8.2.8", "@compodoc/compodoc": "^1.1.11", - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-docs": "5.3.0-alpha.41", - "@storybook/addon-jest": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/angular": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-docs": "5.3.0-beta.2", + "@storybook/addon-jest": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/angular": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "@types/core-js": "^2.5.0", "@types/jest": "^24.0.11", "@types/node": "^12.7.9", @@ -63,7 +63,7 @@ "jest": "^24.7.1", "jest-preset-angular": "^7.1.0", "protractor": "~5.4.2", - "ts-node": "~8.4.1", + "ts-node": "~8.5.2", "typescript": "^3.4.0" } } diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-actions.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-actions.stories.storyshot index 15bf0a82283..1ed30bcfe76 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-actions.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-actions.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Actions Action And Method 1`] = ` +exports[`Storyshots Addon/Actions Action and method 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -18,7 +18,7 @@ exports[`Storyshots Addon|Actions Action And Method 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Addon|Actions Action Only 1`] = ` +exports[`Storyshots Addon/Actions Action only 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-background.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-background.stories.storyshot index f9548c66262..14c4f68af5d 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-background.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-background.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Background background component 1`] = ` +exports[`Storyshots Addon/Background background component 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -64,7 +64,7 @@ exports[`Storyshots Addon|Background background component 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Addon|Background background template 1`] = ` +exports[`Storyshots Addon/Background background template 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-centered.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-centered.stories.storyshot index a567e050180..ddb525e3dd5 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-centered.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-centered.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Centered centered component 1`] = ` +exports[`Storyshots Addon/Centered centered component 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -76,7 +76,7 @@ exports[`Storyshots Addon|Centered centered component 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Addon|Centered centered template 1`] = ` +exports[`Storyshots Addon/Centered centered template 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-docs.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-docs.stories.storyshot index 5f393342ed7..3f6bbf0f2ae 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-docs.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-docs.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Docs With Some Emoji 1`] = ` +exports[`Storyshots Addon/Docs with some emoji 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -21,7 +21,7 @@ exports[`Storyshots Addon|Docs With Some Emoji 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Addon|Docs With Text 1`] = ` +exports[`Storyshots Addon/Docs with text 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-jest.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-jest.stories.storyshot index 1c3a8b3f475..f790202b114 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-jest.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-jest.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Jest App Component With Jest Tests 1`] = ` +exports[`Storyshots Addon/Jest app.component with jest tests 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-knobs.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-knobs.stories.storyshot index b165c070723..648edb60aca 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-knobs.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-knobs.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Knobs All Knobs 1`] = ` +exports[`Storyshots Addon/Knobs All knobs 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -51,7 +51,7 @@ exports[`Storyshots Addon|Knobs All Knobs 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Addon|Knobs Simple 1`] = ` +exports[`Storyshots Addon/Knobs Simple 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -76,7 +76,7 @@ exports[`Storyshots Addon|Knobs Simple 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Addon|Knobs Xss Safety 1`] = ` +exports[`Storyshots Addon/Knobs XSS safety 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-links.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-links.stories.storyshot index aca946a25e0..7c9183ea217 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-links.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-links.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Links Button With Link To Another Story 1`] = ` +exports[`Storyshots Addon/Links button with link to another story 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/addon-notes.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/addon-notes.stories.storyshot index ee78510f1a6..35fb1e998f6 100644 --- a/examples/angular-cli/src/stories/__snapshots__/addon-notes.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/addon-notes.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Notes Note With Html 1`] = ` +exports[`Storyshots Addon/Notes Note with HTML 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -18,7 +18,7 @@ exports[`Storyshots Addon|Notes Note With Html 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Addon|Notes Simple Note 1`] = ` +exports[`Storyshots Addon/Notes Simple note 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/app.component.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/app.component.stories.storyshot index 812919e5188..3425505a243 100644 --- a/examples/angular-cli/src/stories/__snapshots__/app.component.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/app.component.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots App Component Component With Separate Template 1`] = ` +exports[`Storyshots App Component Component with separate template 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/core.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/core.stories.storyshot index 405f4504501..7bde756e9ed 100644 --- a/examples/angular-cli/src/stories/__snapshots__/core.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/core.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Core|Parameters Passed To Story 1`] = ` +exports[`Storyshots Core/Parameters passed to story 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -12,7 +12,7 @@ exports[`Storyshots Core|Parameters Passed To Story 1`] = ` <button _ngcontent-a-c20="" > - Parameters are {"options":{"hierarchyRootSeparator":{},"hierarchySeparator":{}},"docs":{"iframeHeight":"60px"},"globalParameter":"globalParameter","framework":"angular","chapterParameter":"chapterParameter","storyParameter":"storyParameter","displayName":"passed to story"} + Parameters are {"options":{"showRoots":true},"docs":{"iframeHeight":"60px"},"globalParameter":"globalParameter","framework":"angular","chapterParameter":"chapterParameter","storyParameter":"storyParameter","__id":"core-parameters--passed-to-story"} </button> </storybook-button-component> </storybook-dynamic-app-root> diff --git a/examples/angular-cli/src/stories/__snapshots__/custom-ng-content.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/custom-ng-content.stories.storyshot index 3616eacf80c..abe75474540 100644 --- a/examples/angular-cli/src/stories/__snapshots__/custom-ng-content.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/custom-ng-content.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|ng-content Default 1`] = ` +exports[`Storyshots Custom/ng-content Default 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/custom-pipes.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/custom-pipes.stories.storyshot index ac80b8afb21..d7b43692652 100644 --- a/examples/angular-cli/src/stories/__snapshots__/custom-pipes.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/custom-pipes.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|Pipes Simple 1`] = ` +exports[`Storyshots Custom/Pipes Simple 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -14,7 +14,7 @@ exports[`Storyshots Custom|Pipes Simple 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Pipes With Knobs Story 1`] = ` +exports[`Storyshots Custom/Pipes With Knobs 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/custom-providers.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/custom-providers.stories.storyshot index e16b95cda99..2f9b464a2d1 100644 --- a/examples/angular-cli/src/stories/__snapshots__/custom-providers.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/custom-providers.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|Providers Simple 1`] = ` +exports[`Storyshots Custom/Providers Simple 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -17,7 +17,7 @@ exports[`Storyshots Custom|Providers Simple 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Providers With Knobs Story 1`] = ` +exports[`Storyshots Custom/Providers With knobs 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/custom-styles.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/custom-styles.stories.storyshot index df81df2c440..f9628db33bf 100644 --- a/examples/angular-cli/src/stories/__snapshots__/custom-styles.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/custom-styles.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|Style Default Story 1`] = ` +exports[`Storyshots Custom/Style Default 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -21,7 +21,7 @@ exports[`Storyshots Custom|Style Default Story 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Style With Knobs Story 1`] = ` +exports[`Storyshots Custom/Style With Knobs 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/metadata-combined.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/metadata-combined.stories.storyshot index f4a53212f89..30ef8eefcaa 100644 --- a/examples/angular-cli/src/stories/__snapshots__/metadata-combined.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/metadata-combined.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Metadata|Combined Combined 1 1`] = ` +exports[`Storyshots Metadata/Combined Combined 1 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -30,7 +30,7 @@ exports[`Storyshots Metadata|Combined Combined 1 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Metadata|Combined Combined 2 1`] = ` +exports[`Storyshots Metadata/Combined Combined 2 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/metadata-individual.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/metadata-individual.stories.storyshot index 25b3e0f4814..5e437c1bdd1 100644 --- a/examples/angular-cli/src/stories/__snapshots__/metadata-individual.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/metadata-individual.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Metadata|Individual Individual 1 1`] = ` +exports[`Storyshots Metadata/Individual Individual 1 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -30,7 +30,7 @@ exports[`Storyshots Metadata|Individual Individual 1 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Metadata|Individual Individual 2 1`] = ` +exports[`Storyshots Metadata/Individual Individual 2 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/metadata-shared.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/metadata-shared.stories.storyshot index 42116cfe07a..0f8de42d1b3 100644 --- a/examples/angular-cli/src/stories/__snapshots__/metadata-shared.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/metadata-shared.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Metadata|Shared Shared 1 1`] = ` +exports[`Storyshots Metadata/Shared Shared 1 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -30,7 +30,7 @@ exports[`Storyshots Metadata|Shared Shared 1 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Metadata|Shared Shared 2 1`] = ` +exports[`Storyshots Metadata/Shared Shared 2 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/__snapshots__/ngrx-store.stories.storyshot b/examples/angular-cli/src/stories/__snapshots__/ngrx-store.stories.storyshot index 7891f51327e..82c58dc1f6c 100644 --- a/examples/angular-cli/src/stories/__snapshots__/ngrx-store.stories.storyshot +++ b/examples/angular-cli/src/stories/__snapshots__/ngrx-store.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots ngrx|Store With component 1`] = ` +exports[`Storyshots ngrx/Store With component 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -14,7 +14,7 @@ exports[`Storyshots ngrx|Store With component 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots ngrx|Store With template 1`] = ` +exports[`Storyshots ngrx/Store With template 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/addon-actions.stories.ts b/examples/angular-cli/src/stories/addon-actions.stories.ts index dc7d8a047f3..40d245c49a2 100644 --- a/examples/angular-cli/src/stories/addon-actions.stories.ts +++ b/examples/angular-cli/src/stories/addon-actions.stories.ts @@ -2,7 +2,7 @@ import { action } from '@storybook/addon-actions'; import { Button } from '@storybook/angular/demo'; export default { - title: 'Addon|Actions', + title: 'Addon/Actions', }; export const actionOnly = () => ({ diff --git a/examples/angular-cli/src/stories/addon-background.stories.ts b/examples/angular-cli/src/stories/addon-background.stories.ts index aa1f808d6ea..3d1ed5d3e48 100644 --- a/examples/angular-cli/src/stories/addon-background.stories.ts +++ b/examples/angular-cli/src/stories/addon-background.stories.ts @@ -2,7 +2,7 @@ import { moduleMetadata, storiesOf } from '@storybook/angular'; import { Button } from '@storybook/angular/demo'; import { AppComponent } from '../app/app.component'; -storiesOf('Addon|Background', module) +storiesOf('Addon/Background', module) .addParameters({ backgrounds: [ { name: 'twitter', value: '#00aced', default: true }, @@ -14,7 +14,7 @@ storiesOf('Addon|Background', module) props: {}, })); -storiesOf('Addon|Background', module) +storiesOf('Addon/Background', module) .addDecorator( moduleMetadata({ declarations: [Button], diff --git a/examples/angular-cli/src/stories/addon-centered.stories.ts b/examples/angular-cli/src/stories/addon-centered.stories.ts index 9748d17255f..1f2834a541a 100644 --- a/examples/angular-cli/src/stories/addon-centered.stories.ts +++ b/examples/angular-cli/src/stories/addon-centered.stories.ts @@ -3,14 +3,14 @@ import { moduleMetadata, storiesOf } from '@storybook/angular'; import { Button } from '@storybook/angular/demo'; import { AppComponent } from '../app/app.component'; -storiesOf('Addon|Centered', module) +storiesOf('Addon/Centered', module) .addDecorator(centered) .add('centered component', () => ({ component: AppComponent, props: {}, })); -storiesOf('Addon|Centered', module) +storiesOf('Addon/Centered', module) .addDecorator( moduleMetadata({ declarations: [Button], diff --git a/examples/angular-cli/src/stories/addon-docs.stories.mdx b/examples/angular-cli/src/stories/addon-docs.stories.mdx index 318db4f3080..d6e01af6864 100644 --- a/examples/angular-cli/src/stories/addon-docs.stories.mdx +++ b/examples/angular-cli/src/stories/addon-docs.stories.mdx @@ -19,7 +19,7 @@ How you like them apples?! Just like in React, we first declare our component. -<Meta title="Addon|Docs" decorators={[moduleMetadata({ declarations: [Button] })]} /> +<Meta title="Addon/Docs" decorators={[moduleMetadata({ declarations: [Button] })]} /> This declaration doesn't show up in the MDX output. diff --git a/examples/angular-cli/src/stories/addon-jest.stories.ts b/examples/angular-cli/src/stories/addon-jest.stories.ts index f7c2ac7b4c3..c0f821ddc4c 100644 --- a/examples/angular-cli/src/stories/addon-jest.stories.ts +++ b/examples/angular-cli/src/stories/addon-jest.stories.ts @@ -4,7 +4,7 @@ import { AppComponent } from '../app/app.component'; import * as results from '../../addon-jest.testresults.json'; export default { - title: 'Addon|Jest', + title: 'Addon/Jest', decorators: [ withTests({ results, diff --git a/examples/angular-cli/src/stories/addon-knobs.stories.ts b/examples/angular-cli/src/stories/addon-knobs.stories.ts index 61b79ee5214..fc4436e6eb8 100644 --- a/examples/angular-cli/src/stories/addon-knobs.stories.ts +++ b/examples/angular-cli/src/stories/addon-knobs.stories.ts @@ -17,7 +17,7 @@ import { SimpleKnobsComponent } from './knobs.component'; import { AllKnobsComponent } from './all-knobs.component'; export default { - title: 'Addon|Knobs', + title: 'Addon/Knobs', decorators: [withKnobs], parameters: { knobs: { diff --git a/examples/angular-cli/src/stories/addon-links.stories.ts b/examples/angular-cli/src/stories/addon-links.stories.ts index ec41687fbfc..785828427eb 100644 --- a/examples/angular-cli/src/stories/addon-links.stories.ts +++ b/examples/angular-cli/src/stories/addon-links.stories.ts @@ -2,7 +2,7 @@ import { linkTo } from '@storybook/addon-links'; import { Button } from '@storybook/angular/demo'; export default { - title: 'Addon|Links', + title: 'Addon/Links', }; export const buttonWithLinkToAnotherStory = () => ({ diff --git a/examples/angular-cli/src/stories/addon-notes.stories.ts b/examples/angular-cli/src/stories/addon-notes.stories.ts index 59d68ab17e7..e4a3b3b5923 100644 --- a/examples/angular-cli/src/stories/addon-notes.stories.ts +++ b/examples/angular-cli/src/stories/addon-notes.stories.ts @@ -1,7 +1,7 @@ import { Button } from '@storybook/angular/demo'; export default { - title: 'Addon|Notes', + title: 'Addon/Notes', }; export const simpleNote = () => ({ diff --git a/examples/angular-cli/src/stories/component-with-di/__snapshots__/di.component.stories.storyshot b/examples/angular-cli/src/stories/component-with-di/__snapshots__/di.component.stories.storyshot index e5a7203f3a7..e7a5a337303 100644 --- a/examples/angular-cli/src/stories/component-with-di/__snapshots__/di.component.stories.storyshot +++ b/examples/angular-cli/src/stories/component-with-di/__snapshots__/di.component.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|Dependencies Inputs And Inject Dependencies 1`] = ` +exports[`Storyshots Custom/Dependencies inputs and inject dependencies 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -31,7 +31,7 @@ exports[`Storyshots Custom|Dependencies Inputs And Inject Dependencies 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Dependencies Inputs And Inject Dependencies With Knobs 1`] = ` +exports[`Storyshots Custom/Dependencies inputs and inject dependencies with knobs 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/component-with-di/di.component.stories.ts b/examples/angular-cli/src/stories/component-with-di/di.component.stories.ts index bbfc736dd1f..92033eada97 100644 --- a/examples/angular-cli/src/stories/component-with-di/di.component.stories.ts +++ b/examples/angular-cli/src/stories/component-with-di/di.component.stories.ts @@ -2,7 +2,7 @@ import { withKnobs, text } from '@storybook/addon-knobs'; import { DiComponent } from './di.component'; export default { - title: 'Custom|Dependencies', + title: 'Custom/Dependencies', }; export const inputsAndInjectDependencies = () => ({ diff --git a/examples/angular-cli/src/stories/component-with-style/__snapshots__/styled.component.stories.storyshot b/examples/angular-cli/src/stories/component-with-style/__snapshots__/styled.component.stories.storyshot index d26ec96e609..fde2c3b965a 100644 --- a/examples/angular-cli/src/stories/component-with-style/__snapshots__/styled.component.stories.storyshot +++ b/examples/angular-cli/src/stories/component-with-style/__snapshots__/styled.component.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|styleUrls Component With Styles 1`] = ` +exports[`Storyshots Custom/styleUrls Component with styles 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/component-with-style/styled.component.stories.ts b/examples/angular-cli/src/stories/component-with-style/styled.component.stories.ts index 3934fb7a5d2..e94b3b4f21d 100644 --- a/examples/angular-cli/src/stories/component-with-style/styled.component.stories.ts +++ b/examples/angular-cli/src/stories/component-with-style/styled.component.stories.ts @@ -1,7 +1,7 @@ import { StyledComponent } from './styled.component'; export default { - title: 'Custom|styleUrls', + title: 'Custom/styleUrls', }; export const componentWithStyles = () => ({ diff --git a/examples/angular-cli/src/stories/core.stories.ts b/examples/angular-cli/src/stories/core.stories.ts index 10c2a42233e..0e8908b13ba 100644 --- a/examples/angular-cli/src/stories/core.stories.ts +++ b/examples/angular-cli/src/stories/core.stories.ts @@ -8,7 +8,7 @@ const storyParameter = 'storyParameter'; addParameters({ globalParameter }); export default { - title: 'Core|Parameters', + title: 'Core/Parameters', parameters: { chapterParameter, }, diff --git a/examples/angular-cli/src/stories/custom-ng-content.stories.ts b/examples/angular-cli/src/stories/custom-ng-content.stories.ts index 4ccc2c3e46b..495047971ea 100644 --- a/examples/angular-cli/src/stories/custom-ng-content.stories.ts +++ b/examples/angular-cli/src/stories/custom-ng-content.stories.ts @@ -9,7 +9,7 @@ import { storiesOf } from '@storybook/angular'; }) class WithNgContentComponent {} -storiesOf('Custom|ng-content', module).add('Default', () => ({ +storiesOf('Custom/ng-content', module).add('Default', () => ({ template: `<storybook-with-ng-content><h1>This is rendered in ng-content</h1></storybook-with-ng-content>`, moduleMetadata: { declarations: [WithNgContentComponent], diff --git a/examples/angular-cli/src/stories/custom-pipes.stories.ts b/examples/angular-cli/src/stories/custom-pipes.stories.ts index 217ebe5ee36..48edeb238d0 100644 --- a/examples/angular-cli/src/stories/custom-pipes.stories.ts +++ b/examples/angular-cli/src/stories/custom-pipes.stories.ts @@ -5,7 +5,7 @@ import { NameComponent } from './moduleMetadata/name.component'; import { CustomPipePipe } from './moduleMetadata/custom.pipe'; export default { - title: 'Custom|Pipes', + title: 'Custom/Pipes', decorators: [ moduleMetadata({ imports: [], diff --git a/examples/angular-cli/src/stories/custom-providers.stories.ts b/examples/angular-cli/src/stories/custom-providers.stories.ts index ad8b66a9048..fd5a3acf12b 100644 --- a/examples/angular-cli/src/stories/custom-providers.stories.ts +++ b/examples/angular-cli/src/stories/custom-providers.stories.ts @@ -5,7 +5,7 @@ import { DummyService } from './moduleMetadata/dummy.service'; import { ServiceComponent } from './moduleMetadata/service.component'; export default { - title: 'Custom|Providers', + title: 'Custom/Providers', decorators: [ moduleMetadata({ imports: [], diff --git a/examples/angular-cli/src/stories/custom-styles.stories.ts b/examples/angular-cli/src/stories/custom-styles.stories.ts index 1d1bcd1f69b..c54b858ad67 100644 --- a/examples/angular-cli/src/stories/custom-styles.stories.ts +++ b/examples/angular-cli/src/stories/custom-styles.stories.ts @@ -4,7 +4,7 @@ import { withKnobs, text } from '@storybook/addon-knobs'; import { Button } from '@storybook/angular/demo'; export default { - title: 'Custom|Style', + title: 'Custom/Style', decorators: [ moduleMetadata({ declarations: [Button], diff --git a/examples/angular-cli/src/stories/customControlValueAccessor/__snapshots__/custom-cva-component.stories.storyshot b/examples/angular-cli/src/stories/customControlValueAccessor/__snapshots__/custom-cva-component.stories.storyshot index 414a6740959..36c082cd97f 100644 --- a/examples/angular-cli/src/stories/customControlValueAccessor/__snapshots__/custom-cva-component.stories.storyshot +++ b/examples/angular-cli/src/stories/customControlValueAccessor/__snapshots__/custom-cva-component.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|ngModel Custom Control Value Accessor 1`] = ` +exports[`Storyshots Custom/ngModel custom ControlValueAccessor 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/customControlValueAccessor/custom-cva-component.stories.ts b/examples/angular-cli/src/stories/customControlValueAccessor/custom-cva-component.stories.ts index 1abfbbfb60f..a620d636cea 100644 --- a/examples/angular-cli/src/stories/customControlValueAccessor/custom-cva-component.stories.ts +++ b/examples/angular-cli/src/stories/customControlValueAccessor/custom-cva-component.stories.ts @@ -6,7 +6,7 @@ const description = ` `; export default { - title: 'Custom|ngModel', + title: 'Custom/ngModel', }; export const customControlValueAccessor = () => ({ diff --git a/examples/angular-cli/src/stories/inheritance/__snapshots__/inheritance.stories.storyshot b/examples/angular-cli/src/stories/inheritance/__snapshots__/inheritance.stories.storyshot index 4d680501adf..a273a408a4e 100644 --- a/examples/angular-cli/src/stories/inheritance/__snapshots__/inheritance.stories.storyshot +++ b/examples/angular-cli/src/stories/inheritance/__snapshots__/inheritance.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|Inheritance Base Button 1`] = ` +exports[`Storyshots Custom/Inheritance base button 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -14,7 +14,7 @@ exports[`Storyshots Custom|Inheritance Base Button 1`] = ` </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Inheritance Icon Button 1`] = ` +exports[`Storyshots Custom/Inheritance icon button 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/inheritance/inheritance.stories.ts b/examples/angular-cli/src/stories/inheritance/inheritance.stories.ts index 6d5dbc9030d..0ca1dfcd367 100644 --- a/examples/angular-cli/src/stories/inheritance/inheritance.stories.ts +++ b/examples/angular-cli/src/stories/inheritance/inheritance.stories.ts @@ -2,7 +2,7 @@ import { IconButtonComponent } from './icon-button.component'; import { BaseButtonComponent } from './base-button.component'; export default { - title: 'Custom|Inheritance', + title: 'Custom/Inheritance', }; export const iconButton = () => ({ diff --git a/examples/angular-cli/src/stories/metadata-combined.stories.ts b/examples/angular-cli/src/stories/metadata-combined.stories.ts index 9aeceb8b8d2..4233e46a133 100644 --- a/examples/angular-cli/src/stories/metadata-combined.stories.ts +++ b/examples/angular-cli/src/stories/metadata-combined.stories.ts @@ -3,7 +3,7 @@ import { TokenComponent, ITEMS, DEFAULT_NAME } from './moduleMetadata/token.comp import { CustomPipePipe } from './moduleMetadata/custom.pipe'; export default { - title: 'Metadata|Combined', + title: 'Metadata/Combined', decorators: [ moduleMetadata({ imports: [], diff --git a/examples/angular-cli/src/stories/metadata-individual.stories.ts b/examples/angular-cli/src/stories/metadata-individual.stories.ts index 39887d5a822..35392945881 100644 --- a/examples/angular-cli/src/stories/metadata-individual.stories.ts +++ b/examples/angular-cli/src/stories/metadata-individual.stories.ts @@ -1,7 +1,7 @@ import { TokenComponent, ITEMS, DEFAULT_NAME } from './moduleMetadata/token.component'; export default { - title: 'Metadata|Individual', + title: 'Metadata/Individual', }; export const individual1 = () => ({ diff --git a/examples/angular-cli/src/stories/metadata-shared.stories.ts b/examples/angular-cli/src/stories/metadata-shared.stories.ts index 0189ffb13f1..c09bfabb53e 100644 --- a/examples/angular-cli/src/stories/metadata-shared.stories.ts +++ b/examples/angular-cli/src/stories/metadata-shared.stories.ts @@ -2,7 +2,7 @@ import { moduleMetadata } from '@storybook/angular'; import { TokenComponent, ITEMS, DEFAULT_NAME } from './moduleMetadata/token.component'; export default { - title: 'Metadata|Shared', + title: 'Metadata/Shared', decorators: [ moduleMetadata({ imports: [], diff --git a/examples/angular-cli/src/stories/module-context/__snapshots__/module-context-forRoot.stories.storyshot b/examples/angular-cli/src/stories/module-context/__snapshots__/module-context-forRoot.stories.storyshot index fa0397a37c2..8272f966287 100644 --- a/examples/angular-cli/src/stories/module-context/__snapshots__/module-context-forRoot.stories.storyshot +++ b/examples/angular-cli/src/stories/module-context/__snapshots__/module-context-forRoot.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|Feature Module as Context with forRoot Component with default providers 1`] = ` +exports[`Storyshots Custom/Feature Module as Context with forRoot Component with default providers 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -31,7 +31,7 @@ exports[`Storyshots Custom|Feature Module as Context with forRoot Component with </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Feature Module as Context with forRoot Component with overridden provider 1`] = ` +exports[`Storyshots Custom/Feature Module as Context with forRoot Component with overridden provider 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -62,7 +62,7 @@ exports[`Storyshots Custom|Feature Module as Context with forRoot Component with </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Feature Module as Context with forRoot Component with self and dependencies declared in its feature module 1`] = ` +exports[`Storyshots Custom/Feature Module as Context with forRoot Component with self and dependencies declared in its feature module 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/module-context/__snapshots__/module-context.stories.storyshot b/examples/angular-cli/src/stories/module-context/__snapshots__/module-context.stories.storyshot index 838d283d5c2..2e34fd8ed68 100644 --- a/examples/angular-cli/src/stories/module-context/__snapshots__/module-context.stories.storyshot +++ b/examples/angular-cli/src/stories/module-context/__snapshots__/module-context.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Custom|Feature Module as Context Component with default providers 1`] = ` +exports[`Storyshots Custom/Feature Module as Context Component with default providers 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -31,7 +31,7 @@ exports[`Storyshots Custom|Feature Module as Context Component with default prov </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Feature Module as Context Component with overridden provider 1`] = ` +exports[`Storyshots Custom/Feature Module as Context Component with overridden provider 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} @@ -62,7 +62,7 @@ exports[`Storyshots Custom|Feature Module as Context Component with overridden p </storybook-dynamic-app-root> `; -exports[`Storyshots Custom|Feature Module as Context Component with self and dependencies declared in its feature module 1`] = ` +exports[`Storyshots Custom/Feature Module as Context Component with self and dependencies declared in its feature module 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/module-context/module-context-forRoot.stories.ts b/examples/angular-cli/src/stories/module-context/module-context-forRoot.stories.ts index 7f9e1f56a41..91039deff0f 100644 --- a/examples/angular-cli/src/stories/module-context/module-context-forRoot.stories.ts +++ b/examples/angular-cli/src/stories/module-context/module-context-forRoot.stories.ts @@ -6,7 +6,7 @@ import { ChipsModule } from './chips.module'; import { ChipsGroupComponent } from './chips-group.component'; import { ChipComponent } from './chip.component'; -storiesOf('Custom|Feature Module as Context with forRoot', module) +storiesOf('Custom/Feature Module as Context with forRoot', module) .addDecorator(withKnobs) .addDecorator( moduleMetadata({ diff --git a/examples/angular-cli/src/stories/module-context/module-context.stories.ts b/examples/angular-cli/src/stories/module-context/module-context.stories.ts index c3ffbe7c147..0c3ad488bfb 100644 --- a/examples/angular-cli/src/stories/module-context/module-context.stories.ts +++ b/examples/angular-cli/src/stories/module-context/module-context.stories.ts @@ -7,7 +7,7 @@ import { ChipsGroupComponent } from './chips-group.component'; import { ChipComponent } from './chip.component'; import { CHIP_COLOR } from './chip-color.token'; -storiesOf('Custom|Feature Module as Context', module) +storiesOf('Custom/Feature Module as Context', module) .addDecorator(withKnobs) .addDecorator( moduleMetadata({ diff --git a/examples/angular-cli/src/stories/ngrx-store.stories.ts b/examples/angular-cli/src/stories/ngrx-store.stories.ts index cb20255a105..8312f8b372c 100644 --- a/examples/angular-cli/src/stories/ngrx-store.stories.ts +++ b/examples/angular-cli/src/stories/ngrx-store.stories.ts @@ -18,7 +18,7 @@ class WithStoreComponent { } } -storiesOf('ngrx|Store', module) +storiesOf('ngrx/Store', module) .addDecorator( moduleMetadata({ imports: [ diff --git a/examples/angular-cli/src/stories/on-push/__snapshots__/on-push.stories.storyshot b/examples/angular-cli/src/stories/on-push/__snapshots__/on-push.stories.storyshot index 15ea94c5945..bc7d043ffef 100644 --- a/examples/angular-cli/src/stories/on-push/__snapshots__/on-push.stories.storyshot +++ b/examples/angular-cli/src/stories/on-push/__snapshots__/on-push.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Core|OnPush Class Specified Component With On Push And Knobs 1`] = ` +exports[`Storyshots Core/OnPush Class-specified component with OnPush and Knobs 1`] = ` <storybook-dynamic-app-root cfr={[Function CodegenComponentFactoryResolver]} data={[Function Object]} diff --git a/examples/angular-cli/src/stories/on-push/on-push.stories.ts b/examples/angular-cli/src/stories/on-push/on-push.stories.ts index d050b138787..5077336acf9 100644 --- a/examples/angular-cli/src/stories/on-push/on-push.stories.ts +++ b/examples/angular-cli/src/stories/on-push/on-push.stories.ts @@ -2,7 +2,7 @@ import { withKnobs, text, color } from '@storybook/addon-knobs'; import { OnPushBoxComponent } from './on-push-box.component'; export default { - title: 'Core|OnPush', + title: 'Core/OnPush', decorators: [withKnobs], }; diff --git a/examples/cra-kitchen-sink/package.json b/examples/cra-kitchen-sink/package.json index 0595029941d..339a53c0237 100644 --- a/examples/cra-kitchen-sink/package.json +++ b/examples/cra-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "cra-kitchen-sink", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build": "react-scripts build", @@ -18,23 +18,23 @@ "react-lifecycles-compat": "^3.0.4" }, "devDependencies": { - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-docs": "5.3.0-alpha.41", - "@storybook/addon-events": "5.3.0-alpha.41", - "@storybook/addon-info": "5.3.0-alpha.41", - "@storybook/addon-jest": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/client-logger": "5.3.0-alpha.41", - "@storybook/react": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-docs": "5.3.0-beta.2", + "@storybook/addon-events": "5.3.0-beta.2", + "@storybook/addon-info": "5.3.0-beta.2", + "@storybook/addon-jest": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/client-logger": "5.3.0-beta.2", + "@storybook/react": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "react-scripts": "^3.0.1" } } diff --git a/examples/cra-kitchen-sink/src/stories/test.stories.mdx b/examples/cra-kitchen-sink/src/stories/test.stories.mdx index 1e6df8d1d17..6d296277b34 100644 --- a/examples/cra-kitchen-sink/src/stories/test.stories.mdx +++ b/examples/cra-kitchen-sink/src/stories/test.stories.mdx @@ -1,6 +1,6 @@ import { Story, Meta } from '@storybook/addon-docs/blocks'; -<Meta title="Docs|Test" /> +<Meta title="Docs/Test" /> <Story name="NewStory123"> <h2> Hello </h2> diff --git a/examples/cra-react15/.storybook/config.js b/examples/cra-react15/.storybook/config.js index 4e08d6629c4..e3988b952e5 100644 --- a/examples/cra-react15/.storybook/config.js +++ b/examples/cra-react15/.storybook/config.js @@ -13,7 +13,7 @@ const loadFn = () => { require('../src/stories/welcome.stories'); // test mixtures of storiesof & module files - const req = require.context('../src/stories', true, /\.stories\.js$/); + const req = require.context('../src/stories', true, /button\.stories\.js$/); return req.keys().map(fname => req(fname)); }; diff --git a/examples/cra-react15/package.json b/examples/cra-react15/package.json index 7b3bd601348..b81ea111504 100644 --- a/examples/cra-react15/package.json +++ b/examples/cra-react15/package.json @@ -1,6 +1,6 @@ { "name": "cra-react15", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build": "react-scripts build", @@ -18,10 +18,10 @@ "react-scripts": "3.0.1" }, "devDependencies": { - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/react": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/react": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "babel-core": "6", "babel-runtime": "6" } diff --git a/examples/cra-ts-kitchen-sink/.storybook/config.ts b/examples/cra-ts-kitchen-sink/.storybook/config.ts index db54c9b99c8..86334f4d6d6 100644 --- a/examples/cra-ts-kitchen-sink/.storybook/config.ts +++ b/examples/cra-ts-kitchen-sink/.storybook/config.ts @@ -8,6 +8,7 @@ addParameters({ options: { brandTitle: 'CRA TypeScript Kitchen Sink', brandUrl: 'https://github.com/storybookjs/storybook/tree/master/examples/cra-ts-kitchen-sink', + showRoots: true, }, }); diff --git a/examples/cra-ts-kitchen-sink/.storybook/presets.js b/examples/cra-ts-kitchen-sink/.storybook/presets.js index d8b8fdeeb45..0fa1bcda804 100644 --- a/examples/cra-ts-kitchen-sink/.storybook/presets.js +++ b/examples/cra-ts-kitchen-sink/.storybook/presets.js @@ -6,6 +6,14 @@ module.exports = [ options: { tsDocgenLoaderOptions: { tsconfigPath: path.resolve(__dirname, '../tsconfig.json'), + shouldExtractLiteralValuesFromEnum: true, + propFilter: prop => { + if (prop.parent) { + return !prop.parent.fileName.includes('node_modules/@types/react/'); + } + + return true; + }, }, }, }, diff --git a/examples/cra-ts-kitchen-sink/package.json b/examples/cra-ts-kitchen-sink/package.json index 8dbef179d50..2e51e82d6e6 100644 --- a/examples/cra-ts-kitchen-sink/package.json +++ b/examples/cra-ts-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "cra-ts-kitchen-sink", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build": "react-scripts build", @@ -34,15 +34,15 @@ "typescript": "3.6.4" }, "devDependencies": { - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-info": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/preset-create-react-app": "^1.2.0", - "@storybook/react": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-info": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/preset-create-react-app": "^1.3.1", + "@storybook/react": "5.3.0-beta.2", "@types/enzyme": "^3.9.0", "@types/react": "^16.8.14", "@types/react-dom": "^16.8.2", @@ -50,7 +50,7 @@ "enzyme-adapter-react-16": "^1.9.1", "enzyme-to-json": "^3.4.1", "fork-ts-checker-webpack-plugin": "^3.0.1", - "react-docgen-typescript-loader": "^3.0.1", + "react-docgen-typescript-loader": "^3.3.0", "react-scripts": "^3.0.1", "tslint": "^5.14.0", "tslint-config-airbnb": "^5.11.1", diff --git a/examples/cra-ts-kitchen-sink/src/components/Button.stories.tsx b/examples/cra-ts-kitchen-sink/src/components/Button.stories.tsx index 46209d5111e..f7da6411c63 100644 --- a/examples/cra-ts-kitchen-sink/src/components/Button.stories.tsx +++ b/examples/cra-ts-kitchen-sink/src/components/Button.stories.tsx @@ -4,7 +4,7 @@ import { radios } from '@storybook/addon-knobs'; import Button, { Type } from './Button'; export default { - title: 'Docgen|Button', + title: 'Docgen/Button', component: Button, }; diff --git a/examples/cra-ts-kitchen-sink/src/stories/PropsSort.js b/examples/cra-ts-kitchen-sink/src/stories/PropsSort.js new file mode 100644 index 00000000000..2e4a6b383e1 --- /dev/null +++ b/examples/cra-ts-kitchen-sink/src/stories/PropsSort.js @@ -0,0 +1,16 @@ +/* eslint-disable react/no-unused-prop-types */ +/* eslint-disable react/require-default-props */ +import React from 'react'; +import PropTypes from 'prop-types'; + +export const PropsSort = () => <div>PropsSort!</div>; +PropsSort.propTypes = { + foo: PropTypes.string, + middleWithDefaultValue: PropTypes.string, + bar: PropTypes.string, + endWithDefaultValue: PropTypes.string, +}; +PropsSort.defaultProps = { + middleWithDefaultValue: 'Middle!', + endWithDefaultValue: 'End!', +}; diff --git a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/docgen.stories.mdx b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/docgen.stories.mdx index 61f7e9022f3..3bc0a9ceea0 100644 --- a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/docgen.stories.mdx +++ b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/docgen.stories.mdx @@ -2,7 +2,7 @@ import { Meta, Props, Description } from '@storybook/addon-docs/blocks'; import * as DocgenJS from './DocgenJS'; import * as DocgenTS from './DocgenTS'; -<Meta title="Docgen|Props" /> +<Meta title="Docgen/Props" /> export const DescriptionProps = ({ of }) => ( <> diff --git a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc-perfo.stories.mdx b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc-perfo.stories.mdx index 960fb64c368..b419ff21e35 100644 --- a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc-perfo.stories.mdx +++ b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc-perfo.stories.mdx @@ -1,10 +1,10 @@ import { Meta, Props } from '@storybook/addon-docs/blocks'; -import { ButtonTooManyProps } from "./jsdoc-perfo"; +import { ButtonTooManyProps } from './jsdoc-perfo'; -<Meta title="Docgen|jsdoc-perfo" /> +<Meta title="Docgen/jsdoc-perfo" /> ## Render 150 props with JSDoc tags <Props of={ButtonTooManyProps} /> <Props of={ButtonTooManyProps} /> -<Props of={ButtonTooManyProps} /> \ No newline at end of file +<Props of={ButtonTooManyProps} /> diff --git a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc.stories.mdx b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc.stories.mdx index 00a62562eb2..ea2d2ff7da8 100644 --- a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc.stories.mdx +++ b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/jsdoc/jsdoc.stories.mdx @@ -1,9 +1,9 @@ import { Meta, Props } from '@storybook/addon-docs/blocks'; -import { JsDocProps, FailingJsDocProps } from "./jsdoc"; -import { TypeScriptProps } from "./jsdoc-ts"; +import { JsDocProps, FailingJsDocProps } from './jsdoc'; +import { TypeScriptProps } from './jsdoc-ts'; -<Meta title="Docgen|jsdoc" /> +<Meta title="Docgen/jsdoc" /> <Props of={JsDocProps} /> <Props of={TypeScriptProps} /> -<Props of={FailingJsDocProps} /> \ No newline at end of file +<Props of={FailingJsDocProps} /> diff --git a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/prop-types.js b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/prop-types.js index 79876bf5da7..bcd6246ad96 100644 --- a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/prop-types.js +++ b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/prop-types.js @@ -1,24 +1,359 @@ /* eslint-disable react/no-unused-prop-types */ import React from 'react'; -import PropTypes, { string } from 'prop-types'; +import PropTypes, { string, shape } from 'prop-types'; -const ITEM_SHAPE = { +const NAMED_OBJECT = { text: PropTypes.string.isRequired, value: PropTypes.string.isRequired, }; +const ANOTHER_OBJECT = { + foo: PropTypes.string, + bar: PropTypes.string, +}; + +const NAMED_SHAPE = PropTypes.shape({ + foo: PropTypes.string, +}); + +export const POSITIONS = ['top-left', 'top-right', 'top-center']; + +const FunctionalComponent = () => { + return <div>FunctionnalComponent!</div>; +}; + +class ClassComponent extends React.PureComponent { + render() { + return <div>ClassComponent!</div>; + } +} + +function concat(a, b) { + return a + b; +} + export const PropTypesProps = () => <div>PropTypes!</div>; PropTypesProps.propTypes = { - arrayOfPrimitive: PropTypes.arrayOf(PropTypes.string), - arrayOfShape: PropTypes.arrayOf(ITEM_SHAPE), - arrayOfInlineShape: PropTypes.arrayOf({ - text: string.isRequired, - value: string.isRequired, - }).isRequired, + // eslint-disable-next-line react/forbid-prop-types + any: PropTypes.any, + bool: PropTypes.bool, + string: PropTypes.string, + func: PropTypes.func, + /** + * A function with JSDoc tags. + * + * @param {string} foo - A foo value. + * @param {number} bar - A bar value. + * @returns {ComplexObject} - Returns a complex object. + */ + funcWithJsDoc: PropTypes.func, + namedDefaultFunc: PropTypes.func, + number: PropTypes.number, + /** + * Plain object propType (use shape!!) + */ + obj: PropTypes.object, // eslint-disable-line react/forbid-prop-types + symbol: PropTypes.symbol, + node: PropTypes.node, + functionalElement: PropTypes.element, + functionalElementInline: PropTypes.element, + functionalElementNamedInline: PropTypes.element, + classElement: PropTypes.element, + classElementInline: PropTypes.element, + functionalElementType: PropTypes.elementType, + classElementType: PropTypes.elementType, + /** + * `instanceOf` is also supported and the custom type will be shown instead of `instanceOf` + */ + instanceOf: PropTypes.instanceOf(Set), + /** + * `oneOf` is basically an Enum which is also supported but can be pretty big. + */ + oneOfString: PropTypes.oneOf(['News', 'Photos']), + oneOfNumeric: PropTypes.oneOf([0, 1, 2, 3]), + oneOfShapes: PropTypes.oneOf([ + PropTypes.shape({ foo: PropTypes.string }), + PropTypes.shape({ bar: PropTypes.number }), + ]), + oneOfComplexShapes: PropTypes.oneOf([ + PropTypes.shape({ + /** + * Just an internal propType for a shape. + * It's also required, and as you can see it supports multi-line comments! + */ + id: PropTypes.number.isRequired, + /** + * A simple non-required function + */ + func: PropTypes.func, + /** + * An `arrayOf` shape + */ + arr: PropTypes.arrayOf( + PropTypes.shape({ + /** + * 5-level deep propType definition and still works. + */ + index: PropTypes.number.isRequired, + }) + ), + }), + shape({ bar: PropTypes.number }), + ]), + oneOfComplexType: PropTypes.oneOf([NAMED_OBJECT, ANOTHER_OBJECT]), + oneOfComponents: PropTypes.oneOf([FunctionalComponent, ClassComponent]), + oneOfEval: PropTypes.oneOf((() => ['News', 'Photos'])()), + oneOfVar: PropTypes.oneOf(POSITIONS), + oneOfNested: PropTypes.oneOf(['News', ['bottom-left', 'botton-center', 'bottom-right']]), + /** + * A multi-type prop is also valid and is displayed as `Union<String|Message>` + */ + oneOfType: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Set)]), + /** + * array of a primitive type + */ + arrayOfPrimitive: PropTypes.arrayOf(PropTypes.number), + arrayOfNamedObject: PropTypes.arrayOf(NAMED_OBJECT), + arrayOfShortInlineObject: PropTypes.arrayOf({ + foo: PropTypes.string, + }), + arrayOfInlineObject: PropTypes.arrayOf({ + text: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + }), + arrayOfComplexInlineObject: PropTypes.arrayOf({ + text: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + shape: { + id: PropTypes.string.isRequired, + age: PropTypes.number.isRequired, + }, + }), + arrayOfShortShape: PropTypes.arrayOf( + PropTypes.shape({ + bar: PropTypes.string, + }) + ), + arrayOfComplexShape: PropTypes.arrayOf( + PropTypes.shape({ + /** + * Just an internal propType for a shape. + * It's also required, and as you can see it supports multi-line comments! + */ + id: PropTypes.number.isRequired, + /** + * A simple non-required function + */ + func: PropTypes.func, + /** + * An `arrayOf` shape + */ + arr: PropTypes.arrayOf( + PropTypes.shape({ + /** + * 5-level deep propType definition and still works. + */ + index: PropTypes.number.isRequired, + }) + ), + }) + ), + /** + * A simple `objectOf` propType. + */ + simpleObjectOf: PropTypes.objectOf(PropTypes.number), + objectOfShortInlineObject: PropTypes.objectOf({ + foo: PropTypes.string, + }), + objectOfInlineObject: PropTypes.objectOf({ + foo: PropTypes.string, + bar: PropTypes.string, + barry: PropTypes.string, + }), + objectOfShortShape: PropTypes.objectOf( + PropTypes.shape({ + foo: string, + }) + ), + /** + * A very complex `objectOf` propType. + */ + objectOfComplexShape: PropTypes.objectOf( + PropTypes.shape({ + /** + * Just an internal propType for a shape. + * It's also required, and as you can see it supports multi-line comments! + */ + id: PropTypes.number.isRequired, + /** + * A simple non-required function + */ + func: PropTypes.func, + /** + * An `arrayOf` shape + */ + arr: PropTypes.arrayOf( + PropTypes.shape({ + /** + * 5-level deep propType definition and still works. + */ + index: PropTypes.number.isRequired, + }) + ), + }) + ), + namedObjectOf: PropTypes.objectOf(NAMED_OBJECT), + shapeShort: PropTypes.shape({ + foo: string, + }), + /** + * propType for shape with nested arrayOf + * + * Also, multi-line description + */ + shapeComplex: PropTypes.shape({ + /** + * Just an internal propType for a shape. + * It's also required, and as you can see it supports multi-line comments! + */ + id: PropTypes.number.isRequired, + /** + * A simple non-required function + */ + func: PropTypes.func, + /** + * An `arrayOf` shape + */ + arr: PropTypes.arrayOf( + PropTypes.shape({ + /** + * 5-level deep propType definition and still works. + */ + index: PropTypes.number.isRequired, + }) + ), + shape: PropTypes.shape({ + shape: PropTypes.shape({ + foo: PropTypes.string, + oneOf: PropTypes.oneOf(['one', 'two']), + }), + }), + oneOf: PropTypes.oneOf(['one', 'two']), + }), + namedShape: NAMED_SHAPE, + namedObjectInShape: PropTypes.shape(NAMED_OBJECT), + exact: PropTypes.exact({ + name: PropTypes.string, + quantity: PropTypes.number, + }), + namedExact: PropTypes.exact(NAMED_OBJECT), + /** + * test string with a comment that has + * two identical lines + * two identical lines + */ + optionalString: PropTypes.string, + requiredString: PropTypes.string.isRequired, + nullDefaultValue: PropTypes.string, + undefinedDefaultValue: PropTypes.string, }; PropTypesProps.defaultProps = { - arrayOfPrimitive: ['foo', 'bar'], - arrayOfShape: [{ text: 'foo', value: 'bar' }], + any: 'Default any', + bool: false, + string: 'Default string', + func: () => {}, + funcWithJsDoc: (foo, bar) => { + // eslint-disable-next-line + const yo = window.document; + // eslint-disable-next-line + const pouf = souffle; + + return { foo, bar }; + }, + namedDefaultFunc: concat, + number: 5, + obj: { + key: 'value', + }, + symbol: Symbol('Default symbol'), + node: <div>Hello!</div>, + functionalElement: <FunctionalComponent />, + functionalElementInline: () => { + return <div>Inlined FunctionnalComponent!</div>; + }, + functionalElementNamedInline: function InlinedFunctionalComponent() { + return <div>Inlined FunctionnalComponent!</div>; + }, + classElement: <ClassComponent />, + classElementInline: class InlinedClassComponent extends React.PureComponent { + render() { + return <div>Inlined ClassComponent!</div>; + } + }, + functionalElementType: FunctionalComponent, + classElementType: ClassComponent, + instanceOf: new Set(), + oneOfString: 'News', + oneOfNumeric: 1, + oneOfShapes: { foo: 'bar' }, + oneOfComplexShapes: { + thing: { + id: 2, + func: () => {}, + arr: [], + }, + }, + oneOfComplexType: { text: 'foo', value: 'bar' }, + oneOfComponents: <FunctionalComponent />, + oneOfEval: 'Photos', + oneOfVar: 'top-right', + oneOfNested: 'top-right', + oneOfType: 'hello', + arrayOfPrimitive: [1, 2, 3], + arrayOfNamedObject: [{ text: 'foo', value: 'bar' }], + arrayOfShortInlineObject: [{ foo: 'bar' }], + arrayOfInlineObject: [{ text: 'foo', value: 'bar' }], + arrayOfComplexInlineObject: [{ text: 'foo', value: 'bar' }], + arrayOfShortShape: [{ bar: 'foo' }], + arrayOfComplexShape: [ + { + thing: { + id: 2, + func: () => {}, + arr: [], + }, + }, + ], + simpleObjectOf: { key: 1 }, + objectOfShortInlineObject: { foo: 'bar' }, + objectOfInlineObject: { foo: 'bar', bar: 'foo' }, + objectOfShortShape: { foo: 'bar' }, + objectOfComplexShape: { + thing: { + id: 2, + func: () => {}, + arr: [], + }, + }, + namedObjectOf: { text: 'foo', value: 'bar' }, + shapeShort: { foo: 'bar' }, + shapeComplex: { + id: 3, + func: () => {}, + arr: [], + shape: { + shape: { + foo: 'bar', + }, + }, + }, + namedShape: { foo: 'bar' }, + namedObjectInShape: { text: 'foo', value: 'bar' }, + exact: { name: 'foo', quantity: 2 }, + namedExact: { text: 'foo', value: 'bar' }, + optionalString: 'Default String', + nullDefaultValue: null, + undefinedDefaultValue: undefined, }; diff --git a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/ts-types.tsx b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/ts-types.tsx index 75b6df11da0..ca1193f1704 100644 --- a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/ts-types.tsx +++ b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/ts-types.tsx @@ -1,17 +1,132 @@ import React, { FC } from 'react'; -interface ItemShape { +function concat(a: string, b: string): string { + return a + b; +} + +interface ItemInterface { text: string; value: string; } +interface PersonInterface { + name: string; +} + +type InterfaceIntersection = ItemInterface & PersonInterface; + +interface GenericInterface<T> { + value: T; +} + +enum DefaultEnum { + TopLeft, + TopRight, + TopCenter, +} + +enum NumericEnum { + TopLeft = 0, + TopRight, + TopCenter, +} + +enum StringEnum { + TopLeft = 'top-left', + TopRight = 'top-right', + TopCenter = 'top-center', +} + +type EnumUnion = DefaultEnum | NumericEnum; + +type StringLiteralUnion = 'top-left' | 'top-right' | 'top-center'; +type NumericLiteralUnion = 0 | 1 | 2; + +type StringAlias = string; +type NumberAlias = number; +type AliasesIntersection = StringAlias & NumberAlias; +type AliasesUnion = StringAlias | NumberAlias; +type GenericAlias<T> = { value: T }; + interface TypeScriptPropsProps { + any: any; + string: string; + bool: boolean; + number: number; + voidFunc: () => void; + funcWithArgsAndReturns: (a: string, b: string) => string; + funcWithunionArg: (a: string | number) => string; + funcWithMultipleUnionReturns: () => string | ItemInterface; + funcWithIndexTypes: <T, K extends keyof T>(o: T, propertyNames: K[]) => T[K][]; + symbol: symbol; + interface: ItemInterface; + genericInterface: GenericInterface<string>; arrayOfPrimitive: string[]; - arrayOfShape: ItemShape[]; + arrayOfComplexObject: ItemInterface[]; + tupleOfPrimitive: [string, number]; + tupleWithComplexType: [string, ItemInterface]; + defaultEnum: DefaultEnum; + numericEnum: NumericEnum; + stringEnum: StringEnum; + enumUnion: EnumUnion; + recordOfPrimitive: Record<string, number>; + recordOfComplexObject: Record<string, ItemInterface>; + intersectionType: InterfaceIntersection; + intersectionWithInlineType: ItemInterface & { inlineValue: string }; + unionOfPrimitive: string | number; + unionOfComplexType: ItemInterface | InterfaceIntersection; + nullablePrimitve?: string; + nullableComplexType?: ItemInterface; + nullableComplexTypeUndefinedDefaultValue?: ItemInterface; + readonly readonlyPrimitive: string; + typeAlias: StringAlias; + aliasesIntersection: AliasesIntersection; + aliasesUnion: AliasesUnion; + genericAlias: GenericAlias<string>; + namedStringLiteralUnion: StringLiteralUnion; + inlinedStringLiteralUnion: 'bottom-left' | 'bottom-right' | 'bottom-center'; + namedNumericLiteralUnion: NumericLiteralUnion; + inlinedNumericLiteralUnion: 0 | 1 | 2; } export const TypeScriptProps: FC<TypeScriptPropsProps> = () => <div>TypeScript!</div>; TypeScriptProps.defaultProps = { + any: 'Any value', + string: 'A string value', + bool: true, + number: 5, + voidFunc: () => {}, + funcWithArgsAndReturns: concat, + symbol: Symbol('Default symbol'), + interface: { text: 'foo', value: 'bar' }, + genericInterface: { value: 'A string value' }, arrayOfPrimitive: ['foo', 'bar'], - arrayOfShape: [{ text: 'foo', value: 'bar' }], + arrayOfComplexObject: [{ text: 'foo', value: 'bar' }], + tupleOfPrimitive: ['string value', 5], + tupleWithComplexType: ['string value', { text: 'foo', value: 'bar' }], + defaultEnum: DefaultEnum.TopRight, + numericEnum: NumericEnum.TopRight, + stringEnum: StringEnum.TopRight, + enumUnion: DefaultEnum.TopLeft, + recordOfPrimitive: { foo: 1, bar: 2 }, + recordOfComplexObject: { foo: { text: 'bar', value: 'bar2' } }, + intersectionType: { text: 'foo', value: 'bar', name: 'foo-bar' }, + intersectionWithInlineType: { text: 'foo', value: 'bar', inlineValue: 'this is inlined' }, + unionOfPrimitive: 'A string value', + unionOfComplexType: { text: 'foo', value: 'bar' }, + nullableComplexTypeUndefinedDefaultValue: undefined, + typeAlias: 'foo', + aliasesUnion: 'foo', + genericAlias: { value: 'foo' }, + namedStringLiteralUnion: 'top-right', + inlinedStringLiteralUnion: 'bottom-right', + namedNumericLiteralUnion: 0, + inlinedNumericLiteralUnion: 1, }; + +interface TypeScriptHtmlComponentProps { + text: string; +} + +export const TypeScriptHtmlComponent: FC<React.HTMLAttributes<HTMLDivElement> & + TypeScriptHtmlComponentProps> = () => <div>My HTML component</div>; diff --git a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/types.stories.mdx b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/types.stories.mdx index 50540fdc529..69cf76448f7 100644 --- a/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/types.stories.mdx +++ b/examples/cra-ts-kitchen-sink/src/stories/docgen-tests/types/types.stories.mdx @@ -1,8 +1,8 @@ import { Meta, Props } from '@storybook/addon-docs/blocks'; -import { PropTypesProps } from "./prop-types"; -import { TypeScriptProps } from "./ts-types"; +import { PropTypesProps } from './prop-types'; +import { TypeScriptProps, TypeScriptHtmlComponent } from './ts-types'; -<Meta title="Docgen|types" /> +<Meta title="Docgen/types" /> ## Prop Types @@ -10,4 +10,6 @@ import { TypeScriptProps } from "./ts-types"; ## TypeScript -<Props of={TypeScriptProps} /> \ No newline at end of file +<Props of={TypeScriptProps} /> + +<Props of={TypeScriptHtmlComponent} /> diff --git a/examples/cra-ts-kitchen-sink/src/stories/props-sort.stories.mdx b/examples/cra-ts-kitchen-sink/src/stories/props-sort.stories.mdx new file mode 100644 index 00000000000..9e234655586 --- /dev/null +++ b/examples/cra-ts-kitchen-sink/src/stories/props-sort.stories.mdx @@ -0,0 +1,7 @@ +import { PropsSort } from "./PropsSort"; +import { Props } from '@storybook/addon-docs/blocks'; + +<Meta title="PropsSort" /> + +<Props of={PropsSort} /> +<Props of={PropsSort} exclude={["foo"]} /> \ No newline at end of file diff --git a/examples/dev-kits/package.json b/examples/dev-kits/package.json index a83195f3162..3d569ddf50f 100644 --- a/examples/dev-kits/package.json +++ b/examples/dev-kits/package.json @@ -1,22 +1,22 @@ { "name": "@storybook/example-devkits", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build-storybook": "build-storybook -c ./", "storybook": "start-storybook -p 9011 -c ./" }, "devDependencies": { - "@storybook/addon-decorator": "5.3.0-alpha.41", - "@storybook/addon-parameter": "5.3.0-alpha.41", - "@storybook/addon-preview-wrapper": "5.3.0-alpha.41", - "@storybook/addon-roundtrip": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/node-logger": "5.3.0-alpha.41", - "@storybook/react": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addon-decorator": "5.3.0-beta.2", + "@storybook/addon-parameter": "5.3.0-beta.2", + "@storybook/addon-preview-wrapper": "5.3.0-beta.2", + "@storybook/addon-roundtrip": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/node-logger": "5.3.0-beta.2", + "@storybook/react": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "cors": "^2.8.5", "cross-env": "^6.0.3", "enzyme-to-json": "^3.4.1", diff --git a/examples/ember-cli/.storybook/config.js b/examples/ember-cli/.storybook/config.js index f3f05b316dc..2e126f9c84f 100644 --- a/examples/ember-cli/.storybook/config.js +++ b/examples/ember-cli/.storybook/config.js @@ -4,8 +4,7 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); addParameters({ options: { - hierarchySeparator: /\/|\./, - hierarchyRootSeparator: /\|/, + showRoots: true, }, }); diff --git a/examples/ember-cli/package.json b/examples/ember-cli/package.json index 81eff3eca77..ddc1c86dc94 100644 --- a/examples/ember-cli/package.json +++ b/examples/ember-cli/package.json @@ -1,6 +1,6 @@ { "name": "ember-example", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build": "ember build", @@ -15,19 +15,19 @@ }, "devDependencies": { "@babel/core": "^7.3.4", - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/ember": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/ember": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "babel-loader": "^8", "broccoli-asset-rev": "^3.0.0", "cross-env": "^6.0.3", diff --git a/examples/ember-cli/stories/addon-a11y.stories.js b/examples/ember-cli/stories/addon-a11y.stories.js index 66ca80ec35a..a8bcb652920 100644 --- a/examples/ember-cli/stories/addon-a11y.stories.js +++ b/examples/ember-cli/stories/addon-a11y.stories.js @@ -2,7 +2,7 @@ import hbs from 'htmlbars-inline-precompile'; import { checkA11y } from '@storybook/addon-a11y'; export default { - title: 'Addon|a11y', + title: 'Addon/a11y', decorators: [checkA11y], parameters: { diff --git a/examples/ember-cli/stories/addon-actions.stories.js b/examples/ember-cli/stories/addon-actions.stories.js index e11f8c8201b..aab9fd86f06 100644 --- a/examples/ember-cli/stories/addon-actions.stories.js +++ b/examples/ember-cli/stories/addon-actions.stories.js @@ -2,7 +2,7 @@ import hbs from 'htmlbars-inline-precompile'; import { action } from '@storybook/addon-actions'; export default { - title: 'Addon|Actions', + title: 'Addon/Actions', parameters: { options: { diff --git a/examples/ember-cli/stories/addon-backgrounds.stories.js b/examples/ember-cli/stories/addon-backgrounds.stories.js index ea282fa81c5..0f8ab7df34b 100644 --- a/examples/ember-cli/stories/addon-backgrounds.stories.js +++ b/examples/ember-cli/stories/addon-backgrounds.stories.js @@ -1,7 +1,7 @@ import hbs from 'htmlbars-inline-precompile'; export default { - title: 'Addon|Backgrounds', + title: 'Addon/Backgrounds', parameters: { backgrounds: [ diff --git a/examples/ember-cli/stories/addon-centered.stories.js b/examples/ember-cli/stories/addon-centered.stories.js index 3cdd11dee89..797e882feda 100644 --- a/examples/ember-cli/stories/addon-centered.stories.js +++ b/examples/ember-cli/stories/addon-centered.stories.js @@ -2,7 +2,7 @@ import hbs from 'htmlbars-inline-precompile'; import Centered from '@storybook/addon-centered/ember'; export default { - title: 'Addon|Centered', + title: 'Addon/Centered', decorators: [Centered], parameters: { diff --git a/examples/ember-cli/stories/addon-knobs.stories.js b/examples/ember-cli/stories/addon-knobs.stories.js index f0fcbb19c4d..7cc3806665d 100644 --- a/examples/ember-cli/stories/addon-knobs.stories.js +++ b/examples/ember-cli/stories/addon-knobs.stories.js @@ -3,7 +3,7 @@ import { withKnobs, text, color, boolean } from '@storybook/addon-knobs'; import { action } from '@storybook/addon-actions'; export default { - title: 'Addon|Knobs', + title: 'Addon/Knobs', decorators: [withKnobs], parameters: { diff --git a/examples/ember-cli/stories/addon-links.stories.js b/examples/ember-cli/stories/addon-links.stories.js index 6e1e16610e2..8aba44e7002 100644 --- a/examples/ember-cli/stories/addon-links.stories.js +++ b/examples/ember-cli/stories/addon-links.stories.js @@ -2,7 +2,7 @@ import hbs from 'htmlbars-inline-precompile'; import { linkTo } from '@storybook/addon-links'; export default { - title: 'Addon|Links', + title: 'Addon/Links', }; export const goToWelcome = () => ({ diff --git a/examples/ember-cli/stories/addon-notes.stories.js b/examples/ember-cli/stories/addon-notes.stories.js index ac437cc6213..25ebe7cf591 100644 --- a/examples/ember-cli/stories/addon-notes.stories.js +++ b/examples/ember-cli/stories/addon-notes.stories.js @@ -1,7 +1,7 @@ import hbs from 'htmlbars-inline-precompile'; export default { - title: 'Addon|Notes', + title: 'Addon/Notes', }; export const simpleNote = () => ({ diff --git a/examples/html-kitchen-sink/.storybook/addons.js b/examples/html-kitchen-sink/.storybook/addons.js deleted file mode 100644 index c38a31c6ea8..00000000000 --- a/examples/html-kitchen-sink/.storybook/addons.js +++ /dev/null @@ -1,11 +0,0 @@ -import '@storybook/addon-a11y/register'; -import '@storybook/addon-actions/register'; -import '@storybook/addon-backgrounds/register'; -import '@storybook/addon-events/register'; -import '@storybook/addon-jest/register'; -import '@storybook/addon-knobs/register'; -import '@storybook/addon-links/register'; -import '@storybook/addon-notes/register'; -import '@storybook/addon-options/register'; -import '@storybook/addon-storysource/register'; -import '@storybook/addon-viewport/register'; diff --git a/examples/html-kitchen-sink/.storybook/main.js b/examples/html-kitchen-sink/.storybook/main.js new file mode 100644 index 00000000000..4982b94cf40 --- /dev/null +++ b/examples/html-kitchen-sink/.storybook/main.js @@ -0,0 +1,18 @@ +module.exports = { + // this dirname is because we run tests from project root + stories: [`${__dirname}/../stories/*.stories.*`], + presets: ['@storybook/addon-docs/preset'], + addons: [ + '@storybook/addon-a11y/register', + '@storybook/addon-actions/register', + '@storybook/addon-backgrounds/register', + '@storybook/addon-events/register', + '@storybook/addon-jest/register', + '@storybook/addon-knobs/register', + '@storybook/addon-links/register', + '@storybook/addon-notes/register', + '@storybook/addon-options/register', + '@storybook/addon-storysource/register', + '@storybook/addon-viewport/register', + ], +}; diff --git a/examples/html-kitchen-sink/.storybook/presets.js b/examples/html-kitchen-sink/.storybook/presets.js deleted file mode 100644 index 7c4d1835bcf..00000000000 --- a/examples/html-kitchen-sink/.storybook/presets.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = ['@storybook/addon-docs/html/preset']; diff --git a/examples/html-kitchen-sink/.storybook/config.js b/examples/html-kitchen-sink/.storybook/preview.js similarity index 61% rename from examples/html-kitchen-sink/.storybook/config.js rename to examples/html-kitchen-sink/.storybook/preview.js index 2dfefa732c7..60851dbe04b 100644 --- a/examples/html-kitchen-sink/.storybook/config.js +++ b/examples/html-kitchen-sink/.storybook/preview.js @@ -1,4 +1,4 @@ -import { configure, addParameters, addDecorator } from '@storybook/html'; +import { addParameters, addDecorator } from '@storybook/html'; import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); @@ -12,11 +12,9 @@ addParameters({ }, }, options: { - hierarchyRootSeparator: /\|/, + showRoots: true, }, docs: { iframeHeight: '200px', }, }); - -configure(require.context('../stories', true, /\.stories\.(js|mdx)$/), module); diff --git a/examples/html-kitchen-sink/package.json b/examples/html-kitchen-sink/package.json index 951b3f2584e..bd7390c7851 100644 --- a/examples/html-kitchen-sink/package.json +++ b/examples/html-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "html-kitchen-sink", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "description": "", "keywords": [], @@ -13,26 +13,26 @@ "storybook": "start-storybook -p 9006" }, "devDependencies": { - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-docs": "5.3.0-alpha.41", - "@storybook/addon-events": "5.3.0-alpha.41", - "@storybook/addon-jest": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/client-api": "5.3.0-alpha.41", - "@storybook/core": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/html": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-docs": "5.3.0-beta.2", + "@storybook/addon-events": "5.3.0-beta.2", + "@storybook/addon-jest": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/client-api": "5.3.0-beta.2", + "@storybook/core": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/html": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "eventemitter3": "^4.0.0", "format-json": "^1.0.3", "global": "^4.3.2", diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-a11y.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-a11y.stories.storyshot index 29179f8340f..d2f9a117a08 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-a11y.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-a11y.stories.storyshot @@ -1,8 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|a11y Default 1`] = `<button />`; +exports[`Storyshots Addons/a11y Default 1`] = `<button />`; -exports[`Storyshots Addons|a11y Disabled 1`] = ` +exports[`Storyshots Addons/a11y Delayed render 1`] = `<div />`; + +exports[`Storyshots Addons/a11y Disabled 1`] = ` <button disabled="" > @@ -10,13 +12,7 @@ exports[`Storyshots Addons|a11y Disabled 1`] = ` </button> `; -exports[`Storyshots Addons|a11y Label 1`] = ` -<button> - Testing the a11y addon -</button> -`; - -exports[`Storyshots Addons|a11y Story 4 1`] = ` +exports[`Storyshots Addons/a11y Invalid contrast 1`] = ` <button style="color: black; background-color: brown;" > @@ -24,4 +20,8 @@ exports[`Storyshots Addons|a11y Story 4 1`] = ` </button> `; -exports[`Storyshots Addons|a11y Story 5 1`] = `<div />`; +exports[`Storyshots Addons/a11y Label 1`] = ` +<button> + Testing the a11y addon +</button> +`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-actions.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-actions.stories.storyshot index e60f715f988..262e351ec8f 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-actions.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-actions.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Actions Story 1 1`] = ` +exports[`Storyshots Addons/Actions Decorated actions + config 1`] = ` <button type="button" > @@ -8,7 +8,7 @@ exports[`Storyshots Addons|Actions Story 1 1`] = ` </button> `; -exports[`Storyshots Addons|Actions Story 2 1`] = ` +exports[`Storyshots Addons/Actions Decorated actions 1`] = ` <button type="button" > @@ -16,7 +16,7 @@ exports[`Storyshots Addons|Actions Story 2 1`] = ` </button> `; -exports[`Storyshots Addons|Actions Story 3 1`] = ` +exports[`Storyshots Addons/Actions Hello World 1`] = ` <button type="button" > @@ -24,7 +24,7 @@ exports[`Storyshots Addons|Actions Story 3 1`] = ` </button> `; -exports[`Storyshots Addons|Actions Story 4 1`] = ` +exports[`Storyshots Addons/Actions Multiple actions + config 1`] = ` <button type="button" > @@ -32,31 +32,31 @@ exports[`Storyshots Addons|Actions Story 4 1`] = ` </button> `; -exports[`Storyshots Addons|Actions Story 5 1`] = ` +exports[`Storyshots Addons/Actions Multiple actions 1`] = ` +<button + type="button" +> + Hello World +</button> +`; + +exports[`Storyshots Addons/Actions Multiple actions, object + config 1`] = ` +<button + type="button" +> + Hello World +</button> +`; + +exports[`Storyshots Addons/Actions Multiple actions, object 1`] = ` +<button + type="button" +> + Hello World +</button> +`; + +exports[`Storyshots Addons/Actions Multiple actions, selector 1`] = ` `; - -exports[`Storyshots Addons|Actions Story 6 1`] = ` -<button - type="button" -> - Hello World -</button> -`; - -exports[`Storyshots Addons|Actions Story 7 1`] = ` -<button - type="button" -> - Hello World -</button> -`; - -exports[`Storyshots Addons|Actions Story 8 1`] = ` -<button - type="button" -> - Hello World -</button> -`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-backgrounds.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-backgrounds.stories.storyshot index c6683463f0e..7a5e0008d7b 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-backgrounds.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-backgrounds.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Backgrounds Story 1 1`] = ` +exports[`Storyshots Addons/Backgrounds story 1 1`] = ` <span style="color: white" > @@ -8,7 +8,7 @@ exports[`Storyshots Addons|Backgrounds Story 1 1`] = ` </span> `; -exports[`Storyshots Addons|Backgrounds Story 2 1`] = ` +exports[`Storyshots Addons/Backgrounds story 2 1`] = ` <span style="color: white" > diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-centered.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-centered.stories.storyshot index 1d660b4925c..78639e13b3c 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-centered.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-centered.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Centered Story 1 1`] = ` +exports[`Storyshots Addons/Centered button in center 1`] = ` <div id="sb-addon-centered-wrapper" style="position: fixed; top: 0px; left: 0px; bottom: 0px; right: 0px; display: flex; align-items: center; overflow: auto;" diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-docs.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-docs.stories.storyshot index 8e9de5ca98c..ce994d4ab4d 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-docs.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-docs.stories.storyshot @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Docs Function Story 1`] = ` +exports[`Storyshots Addons/Docs function 1`] = ` <button> Hello Button </button> `; -exports[`Storyshots Addons|Docs Heading 1`] = ` +exports[`Storyshots Addons/Docs heading 1`] = ` <h1> Hello World </h1> diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-events.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-events.stories.storyshot index 6887b83c61b..e87017fba57 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-events.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-events.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Events Logger 1`] = ` +exports[`Storyshots Addons/Events Logger 1`] = ` `; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-jest.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-jest.stories.storyshot index 346b24a2633..437fd6b56c7 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-jest.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-jest.stories.storyshot @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Jest With Tests 1`] = `This story shows test results`; +exports[`Storyshots Addons/Jest With Tests 1`] = `This story shows test results`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-knobs.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-knobs.stories.storyshot index b0680c2196b..3366b7f3e0b 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-knobs.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-knobs.stories.storyshot @@ -1,26 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Knobs DOM 1`] = ` -<p> - John Doe -</p> -`; - -exports[`Storyshots Addons|Knobs Simple 1`] = ` -<div> - I am John Doe and I'm 44 years old. -</div> -`; - -exports[`Storyshots Addons|Knobs Story 3 1`] = ` -<p - style="transition: color 0.5s ease-out; color: orangered;" -> - John Doe -</p> -`; - -exports[`Storyshots Addons|Knobs Story 4 1`] = ` +exports[`Storyshots Addons/Knobs All knobs 1`] = ` <div style="border: 2px dotted deeppink; padding: 8px 22px; border-radius: 8px" > @@ -67,4 +47,24 @@ exports[`Storyshots Addons|Knobs Story 4 1`] = ` </div> `; -exports[`Storyshots Addons|Knobs Story 5 1`] = `<img src=x onerror="alert('XSS Attack')" >`; +exports[`Storyshots Addons/Knobs CSS transitions 1`] = ` +<p + style="transition: color 0.5s ease-out; color: orangered;" +> + John Doe +</p> +`; + +exports[`Storyshots Addons/Knobs DOM 1`] = ` +<p> + John Doe +</p> +`; + +exports[`Storyshots Addons/Knobs Simple 1`] = ` +<div> + I am John Doe and I'm 44 years old. +</div> +`; + +exports[`Storyshots Addons/Knobs XSS safety 1`] = `<img src=x onerror="alert('XSS Attack')" >`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-notes.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-notes.stories.storyshot index 7267fb23a7f..229ca7197d4 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-notes.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/addon-notes.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Notes Story 1 1`] = ` +exports[`Storyshots Addons/Notes Simple note 1`] = ` <p> diff --git a/examples/html-kitchen-sink/stories/addon-a11y.stories.js b/examples/html-kitchen-sink/stories/addon-a11y.stories.js index d34e5fa623c..89942adb7cf 100644 --- a/examples/html-kitchen-sink/stories/addon-a11y.stories.js +++ b/examples/html-kitchen-sink/stories/addon-a11y.stories.js @@ -4,7 +4,7 @@ import { withA11y } from '@storybook/addon-a11y'; const text = 'Testing the a11y addon'; export default { - title: 'Addons|a11y', + title: 'Addons/a11y', decorators: [withA11y], parameters: { options: { selectedPanel: 'storybook/a11y/panel' }, diff --git a/examples/html-kitchen-sink/stories/addon-actions.stories.js b/examples/html-kitchen-sink/stories/addon-actions.stories.js index 82008bb1115..4b7f110b639 100644 --- a/examples/html-kitchen-sink/stories/addon-actions.stories.js +++ b/examples/html-kitchen-sink/stories/addon-actions.stories.js @@ -5,7 +5,7 @@ const pickTarget = decorate([args => [args[0].target]]); const button = () => `<button type="button">Hello World</button>`; export default { - title: 'Addons|Actions', + title: 'Addons/Actions', }; export const story1 = () => withActions('click')(button); @@ -31,9 +31,10 @@ export const story5 = () => story5.story = { name: 'Multiple actions, selector' }; export const story6 = () => - withActions({ click: 'clicked', contextmenu: 'right clicked' }, { clearOnStoryChange: false })( - button - ); + withActions( + { click: 'clicked', contextmenu: 'right clicked' }, + { clearOnStoryChange: false } + )(button); story6.story = { name: 'Multiple actions, object + config' }; export const story7 = () => pickTarget.withActions('click', 'contextmenu')(button); diff --git a/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js b/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js index 4a63ab1fce6..6a2d799ac4c 100644 --- a/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js +++ b/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js @@ -1,5 +1,5 @@ export default { - title: 'Addons|Backgrounds', + title: 'Addons/Backgrounds', parameters: { backgrounds: [ { name: 'light', value: '#eeeeee' }, diff --git a/examples/html-kitchen-sink/stories/addon-centered.stories.js b/examples/html-kitchen-sink/stories/addon-centered.stories.js index 8242764f7fe..858709b9a32 100644 --- a/examples/html-kitchen-sink/stories/addon-centered.stories.js +++ b/examples/html-kitchen-sink/stories/addon-centered.stories.js @@ -1,7 +1,7 @@ import centered from '@storybook/addon-centered/html'; export default { - title: 'Addons|Centered', + title: 'Addons/Centered', decorators: [centered], }; diff --git a/examples/html-kitchen-sink/stories/addon-docs.stories.mdx b/examples/html-kitchen-sink/stories/addon-docs.stories.mdx index c7fa6458e67..adcf8cdbbda 100644 --- a/examples/html-kitchen-sink/stories/addon-docs.stories.mdx +++ b/examples/html-kitchen-sink/stories/addon-docs.stories.mdx @@ -3,7 +3,7 @@ import { action } from '@storybook/addon-actions'; # Storybook Docs for HTML -<Meta title="Addons|Docs" /> +<Meta title="Addons/Docs" /> ## Story definition diff --git a/examples/html-kitchen-sink/stories/addon-events.stories.js b/examples/html-kitchen-sink/stories/addon-events.stories.js index 32c2bf2796c..120e24fbf89 100644 --- a/examples/html-kitchen-sink/stories/addon-events.stories.js +++ b/examples/html-kitchen-sink/stories/addon-events.stories.js @@ -17,7 +17,7 @@ const emitter = new EventEmitter(); const emit = emitter.emit.bind(emitter); export default { - title: 'Addons|Events', + title: 'Addons/Events', decorators: [ withEvents({ emit, diff --git a/examples/html-kitchen-sink/stories/addon-jest.stories.js b/examples/html-kitchen-sink/stories/addon-jest.stories.js index d39a86527ed..f2dee19b523 100644 --- a/examples/html-kitchen-sink/stories/addon-jest.stories.js +++ b/examples/html-kitchen-sink/stories/addon-jest.stories.js @@ -2,7 +2,7 @@ import { withTests as wt } from '@storybook/addon-jest'; import results from './addon-jest.testresults.json'; export default { - title: 'Addons|Jest', + title: 'Addons/Jest', decorators: [wt({ results })], }; diff --git a/examples/html-kitchen-sink/stories/addon-knobs.stories.js b/examples/html-kitchen-sink/stories/addon-knobs.stories.js index edae4ae8933..e97a4608cdc 100644 --- a/examples/html-kitchen-sink/stories/addon-knobs.stories.js +++ b/examples/html-kitchen-sink/stories/addon-knobs.stories.js @@ -16,7 +16,7 @@ import { const cachedContainer = document.createElement('p'); export default { - title: 'Addons|Knobs', + title: 'Addons/Knobs', decorators: [withKnobs], }; diff --git a/examples/html-kitchen-sink/stories/addon-notes.stories.js b/examples/html-kitchen-sink/stories/addon-notes.stories.js index 8fd33be9c37..795a21fe7a9 100644 --- a/examples/html-kitchen-sink/stories/addon-notes.stories.js +++ b/examples/html-kitchen-sink/stories/addon-notes.stories.js @@ -1,5 +1,5 @@ export default { - title: 'Addons|Notes', + title: 'Addons/Notes', }; export const story1 = () => diff --git a/examples/marko-cli/.storybook/config.js b/examples/marko-cli/.storybook/config.js index 2485daee8bb..7957ba4f980 100644 --- a/examples/marko-cli/.storybook/config.js +++ b/examples/marko-cli/.storybook/config.js @@ -4,7 +4,7 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); addParameters({ options: { - hierarchyRootSeparator: /\|/, + showRoots: true, }, }); diff --git a/examples/marko-cli/package.json b/examples/marko-cli/package.json index 8eb7a7a50b4..596e2dcced1 100644 --- a/examples/marko-cli/package.json +++ b/examples/marko-cli/package.json @@ -1,6 +1,6 @@ { "name": "marko-cli", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "description": "Demo of how to build an app using marko-starter", "repository": { @@ -23,14 +23,14 @@ "marko-starter": "^2.0.4" }, "devDependencies": { - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/marko": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/marko": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "prettier": "^1.16.4", "webpack": "^4.33.0" } diff --git a/examples/marko-cli/src/stories/addon-actions.stories.js b/examples/marko-cli/src/stories/addon-actions.stories.js index 9f943b71a9e..9a76a79fd11 100644 --- a/examples/marko-cli/src/stories/addon-actions.stories.js +++ b/examples/marko-cli/src/stories/addon-actions.stories.js @@ -2,7 +2,7 @@ import { action } from '@storybook/addon-actions'; import Button from '../components/action-button/index.marko'; export default { - title: 'Addons|Actions/Button', + title: 'Addons/Actions/Button', parameters: { component: Button, options: { diff --git a/examples/marko-cli/src/stories/addon-knobs.stories.js b/examples/marko-cli/src/stories/addon-knobs.stories.js index e1849a60aaa..c55067257f2 100644 --- a/examples/marko-cli/src/stories/addon-knobs.stories.js +++ b/examples/marko-cli/src/stories/addon-knobs.stories.js @@ -2,7 +2,7 @@ import { withKnobs, text, number } from '@storybook/addon-knobs'; import Hello from '../components/hello/index.marko'; export default { - title: 'Addons|Knobs/Hello', + title: 'Addons/Knobs/Hello', decorators: [withKnobs], parameters: { component: Hello, diff --git a/examples/marko-cli/src/stories/clickcount.stories.js b/examples/marko-cli/src/stories/clickcount.stories.js index d02fe83b40c..c6557e9772c 100644 --- a/examples/marko-cli/src/stories/clickcount.stories.js +++ b/examples/marko-cli/src/stories/clickcount.stories.js @@ -1,7 +1,7 @@ import ClickCount from '../components/click-count/index.marko'; export default { - title: 'Main|ClickCount', + title: 'Main/ClickCount', parameters: { component: ClickCount, }, diff --git a/examples/marko-cli/src/stories/hello.stories.js b/examples/marko-cli/src/stories/hello.stories.js index f4114a7901e..4c9e74866c6 100644 --- a/examples/marko-cli/src/stories/hello.stories.js +++ b/examples/marko-cli/src/stories/hello.stories.js @@ -1,7 +1,7 @@ import Hello from '../components/hello/index.marko'; export default { - title: 'Main|Hello', + title: 'Main/Hello', parameters: { component: Hello, }, diff --git a/examples/marko-cli/src/stories/stopwatch.stories.js b/examples/marko-cli/src/stories/stopwatch.stories.js index 1f62d6c736d..5310d01270e 100644 --- a/examples/marko-cli/src/stories/stopwatch.stories.js +++ b/examples/marko-cli/src/stories/stopwatch.stories.js @@ -1,7 +1,7 @@ import StopWatch from '../components/stop-watch/index.marko'; export default { - title: 'Main|StopWatch', + title: 'Main/StopWatch', parameters: { component: StopWatch, }, diff --git a/examples/marko-cli/src/stories/welcome.stories.js b/examples/marko-cli/src/stories/welcome.stories.js index 62bef2b231b..4ffce8d5dda 100644 --- a/examples/marko-cli/src/stories/welcome.stories.js +++ b/examples/marko-cli/src/stories/welcome.stories.js @@ -1,7 +1,7 @@ import Welcome from '../components/welcome/index.marko'; export default { - title: 'Main|Welcome', + title: 'Main/Welcome', parameters: { component: Welcome, }, diff --git a/examples/mithril-kitchen-sink/.storybook/config.js b/examples/mithril-kitchen-sink/.storybook/config.js index 5e73476ab14..3db6d5be468 100644 --- a/examples/mithril-kitchen-sink/.storybook/config.js +++ b/examples/mithril-kitchen-sink/.storybook/config.js @@ -4,7 +4,7 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); addParameters({ options: { - hierarchyRootSeparator: /\|/, + showRoots: true, }, }); diff --git a/examples/mithril-kitchen-sink/package.json b/examples/mithril-kitchen-sink/package.json index 0d1501e36e9..f82f099a98f 100644 --- a/examples/mithril-kitchen-sink/package.json +++ b/examples/mithril-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "mithril-example", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build-storybook": "build-storybook", @@ -10,20 +10,20 @@ "mithril": "^1.1.6" }, "devDependencies": { - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/mithril": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/mithril": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "webpack": "^4.33.0" } } diff --git a/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js index 58e06373596..193629f7ef8 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js @@ -5,7 +5,7 @@ import { action, actions } from '@storybook/addon-actions'; import Button from '../Button'; export default { - title: 'Addons|Actions', + title: 'Addons/Actions', }; export const story1 = () => ({ diff --git a/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js index 2a6e62c39d3..7423669b09a 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js @@ -4,7 +4,7 @@ import m from 'mithril'; import BaseButton from '../BaseButton'; export default { - title: 'Addons|Backgrounds', + title: 'Addons/Backgrounds', parameters: { backgrounds: [ { name: 'light', value: '#eeeeee' }, diff --git a/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js index f646d74b4a2..3fc3e4514e3 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js @@ -5,7 +5,7 @@ import Centered from '@storybook/addon-centered/mithril'; import Button from '../Button'; export default { - title: 'Addons|Centered', + title: 'Addons/Centered', decorators: [Centered], parameters: { component: Centered, diff --git a/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js index 6d08bc923f1..6d8b76d6ace 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js @@ -15,7 +15,7 @@ import { } from '@storybook/addon-knobs'; export default { - title: 'Addons|Knobs', + title: 'Addons/Knobs', decorators: [withKnobs], }; diff --git a/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js index 63ea9c04ab5..72589574ae1 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js @@ -6,7 +6,7 @@ import { linkTo } from '@storybook/addon-links'; import Button from '../Button'; export default { - title: 'Addons|Links', + title: 'Addons/Links', }; export const story1 = () => ({ diff --git a/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js index 6af53269ecd..6801d66fcec 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js @@ -3,7 +3,7 @@ import m from 'mithril'; export default { - title: 'Addons|Notes', + title: 'Addons/Notes', }; export const story1 = () => ({ diff --git a/examples/official-storybook/components/ButtonGroup.js b/examples/official-storybook/components/ButtonGroup.js new file mode 100644 index 00000000000..01953ea10d9 --- /dev/null +++ b/examples/official-storybook/components/ButtonGroup.js @@ -0,0 +1,17 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +/** ButtonGroup component description from docgen */ +export const ButtonGroup = ({ background, children }) => ( + <div style={{ background }}>{children}</div> +); + +ButtonGroup.defaultProps = { + background: '#ff0', + children: null, +}; + +ButtonGroup.propTypes = { + background: PropTypes.string, + children: PropTypes.arrayOf(PropTypes.element), +}; diff --git a/examples/official-storybook/main.js b/examples/official-storybook/main.js index 29b9882f448..ebd5bdbf7d7 100644 --- a/examples/official-storybook/main.js +++ b/examples/official-storybook/main.js @@ -1,10 +1,13 @@ module.exports = { - presets: ['@storybook/addon-docs/react/preset'], - addons: existing => [ - ...existing, + presets: ['@storybook/addon-docs/preset'], + stories: [ + '../../lib/ui/src/**/*.stories./(js|tsx|mdx)', + '../../lib/components/src/**/*.stories.(js|tsx|mdx)', + './stories/*.stories.(js|tsx|mdx)', + ], + addons: [ '@storybook/addon-storysource/register', '@storybook/addon-design-assets/register', - '@storybook/addon-docs/register', '@storybook/addon-actions/register', '@storybook/addon-links/register', '@storybook/addon-events/register', diff --git a/examples/official-storybook/package.json b/examples/official-storybook/package.json index 9cab6feb874..bc0215f6cb2 100644 --- a/examples/official-storybook/package.json +++ b/examples/official-storybook/package.json @@ -1,6 +1,6 @@ { "name": "official-storybook", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build-storybook": "cross-env STORYBOOK_DISPLAY_WARNING=true DISPLAY_WARNING=true build-storybook -c ./", @@ -13,34 +13,34 @@ }, "devDependencies": { "@packtracker/webpack-plugin": "^2.0.1", - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-contexts": "5.3.0-alpha.41", - "@storybook/addon-cssresources": "5.3.0-alpha.41", - "@storybook/addon-design-assets": "5.3.0-alpha.41", - "@storybook/addon-docs": "5.3.0-alpha.41", - "@storybook/addon-events": "5.3.0-alpha.41", - "@storybook/addon-graphql": "5.3.0-alpha.41", - "@storybook/addon-info": "5.3.0-alpha.41", - "@storybook/addon-jest": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-queryparams": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storyshots-puppeteer": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/components": "5.3.0-alpha.41", - "@storybook/core-events": "5.3.0-alpha.41", - "@storybook/node-logger": "5.3.0-alpha.41", - "@storybook/react": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", - "@storybook/theming": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-contexts": "5.3.0-beta.2", + "@storybook/addon-cssresources": "5.3.0-beta.2", + "@storybook/addon-design-assets": "5.3.0-beta.2", + "@storybook/addon-docs": "5.3.0-beta.2", + "@storybook/addon-events": "5.3.0-beta.2", + "@storybook/addon-graphql": "5.3.0-beta.2", + "@storybook/addon-info": "5.3.0-beta.2", + "@storybook/addon-jest": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-queryparams": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storyshots-puppeteer": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/components": "5.3.0-beta.2", + "@storybook/core-events": "5.3.0-beta.2", + "@storybook/node-logger": "5.3.0-beta.2", + "@storybook/react": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", + "@storybook/theming": "5.3.0-beta.2", "cors": "^2.8.5", "cross-env": "^6.0.3", "enzyme-to-json": "^3.4.1", diff --git a/examples/official-storybook/preview.js b/examples/official-storybook/preview.js index 32628d68c6f..f536535ede7 100644 --- a/examples/official-storybook/preview.js +++ b/examples/official-storybook/preview.js @@ -1,5 +1,5 @@ import React from 'react'; -import { configure, addDecorator, addParameters } from '@storybook/react'; +import { addDecorator, addParameters } from '@storybook/react'; import { Global, ThemeProvider, themes, createReset, convert } from '@storybook/theming'; import { withCssResources } from '@storybook/addon-cssresources'; import { withA11y } from '@storybook/addon-a11y'; @@ -45,8 +45,7 @@ addParameters({ }, }, options: { - hierarchySeparator: /\/|\./, - hierarchyRootSeparator: '|', + showRoots: true, theme: themes.light, // { base: 'dark', brandTitle: 'Storybook!' }, storySort: (a, b) => a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id, { numeric: true }), @@ -57,21 +56,6 @@ addParameters({ { name: 'dark', value: '#222222' }, ], docs: { - // eslint-disable-next-line react/prop-types - page: ({ context }) => ( - <DocsPage - context={context} - subtitleSlot={({ selectedKind }) => `Subtitle: ${selectedKind}`} - /> - ), + page: () => <DocsPage subtitleSlot={({ selectedKind }) => `Subtitle: ${selectedKind}`} />, }, }); - -configure( - [ - require.context('../../lib/ui/src', true, /\.stories\.(js|tsx?|mdx)$/), - require.context('../../lib/components/src', true, /\.stories\.(js|tsx?|mdx)$/), - require.context('./stories', true, /\.stories\.(js|tsx?|mdx)$/), - ], - module -); diff --git a/examples/official-storybook/stories/addon-a11y/base-button.stories.js b/examples/official-storybook/stories/addon-a11y/base-button.stories.js index a882bf92a4e..cfdac38ea8b 100644 --- a/examples/official-storybook/stories/addon-a11y/base-button.stories.js +++ b/examples/official-storybook/stories/addon-a11y/base-button.stories.js @@ -5,7 +5,7 @@ import DelayedRender from '../../components/DelayedRender'; const text = 'Testing the a11y addon'; export default { - title: 'Addons|A11y/BaseButton', + title: 'Addons/A11y/BaseButton', component: BaseButton, parameters: { options: { selectedPanel: 'storybook/a11y/panel' }, diff --git a/examples/official-storybook/stories/addon-a11y/button.stories.js b/examples/official-storybook/stories/addon-a11y/button.stories.js index dc7863262db..6f030c88bec 100644 --- a/examples/official-storybook/stories/addon-a11y/button.stories.js +++ b/examples/official-storybook/stories/addon-a11y/button.stories.js @@ -4,7 +4,7 @@ import Button from '../../components/addon-a11y/Button'; const text = 'Testing the a11y addon'; export default { - title: 'Addons|A11y/Button', + title: 'Addons/A11y/Button', component: Button, parameters: { options: { selectedPanel: 'storybook/a11y/panel' }, diff --git a/examples/official-storybook/stories/addon-a11y/form.stories.js b/examples/official-storybook/stories/addon-a11y/form.stories.js index 9aa54fc6b0d..d0df82b3b09 100644 --- a/examples/official-storybook/stories/addon-a11y/form.stories.js +++ b/examples/official-storybook/stories/addon-a11y/form.stories.js @@ -5,7 +5,7 @@ import { Form } from '@storybook/components'; const text = 'Testing the a11y addon'; export default { - title: 'Addons|A11y/Form', + title: 'Addons/A11y/Form', component: Form, parameters: { options: { selectedPanel: 'storybook/a11y/panel' }, diff --git a/examples/official-storybook/stories/addon-a11y/image.stories.js b/examples/official-storybook/stories/addon-a11y/image.stories.js index 49961fd9330..7b516b0c7cd 100644 --- a/examples/official-storybook/stories/addon-a11y/image.stories.js +++ b/examples/official-storybook/stories/addon-a11y/image.stories.js @@ -5,7 +5,7 @@ const text = 'Testing the a11y addon'; const image = 'http://placehold.it/350x150'; export default { - title: 'Addons|A11y/Image', + title: 'Addons/A11y/Image', parameters: { options: { selectedPanel: 'storybook/a11y/panel' }, }, diff --git a/examples/official-storybook/stories/addon-a11y/typography.stories.js b/examples/official-storybook/stories/addon-a11y/typography.stories.js index a147933e190..1c51cef77ac 100644 --- a/examples/official-storybook/stories/addon-a11y/typography.stories.js +++ b/examples/official-storybook/stories/addon-a11y/typography.stories.js @@ -5,7 +5,7 @@ const text = 'Testing the a11y addon'; const href = 'javascript:void 0'; export default { - title: 'Addons|A11y/Typography', + title: 'Addons/A11y/Typography', parameters: { options: { selectedPanel: 'storybook/a11y/panel' }, }, diff --git a/examples/official-storybook/stories/addon-actions.stories.js b/examples/official-storybook/stories/addon-actions.stories.js index 8e3afb2858f..66ae37eadea 100644 --- a/examples/official-storybook/stories/addon-actions.stories.js +++ b/examples/official-storybook/stories/addon-actions.stories.js @@ -15,7 +15,7 @@ const pickNative = decorate([args => [args[0].nativeEvent]]); const pickNativeAction = decorateAction([args => [args[0].nativeEvent]]); export default { - title: 'Addons|Actions', + title: 'Addons/Actions', parameters: { options: { selectedPanel: 'storybook/actions/panel', diff --git a/examples/official-storybook/stories/addon-backgrounds.stories.js b/examples/official-storybook/stories/addon-backgrounds.stories.js index b9eb8b54be7..17ef4de2626 100644 --- a/examples/official-storybook/stories/addon-backgrounds.stories.js +++ b/examples/official-storybook/stories/addon-backgrounds.stories.js @@ -3,7 +3,7 @@ import React from 'react'; import BaseButton from '../components/BaseButton'; export default { - title: 'Addons|Backgrounds', + title: 'Addons/Backgrounds', parameters: { backgrounds: [ diff --git a/examples/official-storybook/stories/addon-centered.stories.js b/examples/official-storybook/stories/addon-centered.stories.js index 7635212ded5..44cc6d60502 100644 --- a/examples/official-storybook/stories/addon-centered.stories.js +++ b/examples/official-storybook/stories/addon-centered.stories.js @@ -4,7 +4,7 @@ import centered from '@storybook/addon-centered/react'; import BaseButton from '../components/BaseButton'; export default { - title: 'Addons|Centered', + title: 'Addons/Centered', decorators: [centered], }; diff --git a/examples/official-storybook/stories/addon-contexts.stories.js b/examples/official-storybook/stories/addon-contexts.stories.js index 9edc06cbf67..0e76638a612 100644 --- a/examples/official-storybook/stories/addon-contexts.stories.js +++ b/examples/official-storybook/stories/addon-contexts.stories.js @@ -39,7 +39,7 @@ const storyLevelContexts = [ ]; export default { - title: 'Addons|Contexts', + title: 'Addons/Contexts', decorators: [withContexts(topLevelContexts)], }; diff --git a/examples/official-storybook/stories/addon-cssresources.stories.js b/examples/official-storybook/stories/addon-cssresources.stories.js index 70a29ac628e..18537dbe8c9 100644 --- a/examples/official-storybook/stories/addon-cssresources.stories.js +++ b/examples/official-storybook/stories/addon-cssresources.stories.js @@ -1,7 +1,7 @@ import React from 'react'; export default { - title: 'Addons|Cssresources', + title: 'Addons/Cssresources', }; export const primaryLargeButton = () => ( diff --git a/examples/official-storybook/stories/addon-design-assets.stories.js b/examples/official-storybook/stories/addon-design-assets.stories.js index 9b5185fcea5..b0f928195c9 100644 --- a/examples/official-storybook/stories/addon-design-assets.stories.js +++ b/examples/official-storybook/stories/addon-design-assets.stories.js @@ -1,7 +1,7 @@ import React from 'react'; export default { - title: 'Addons|Design assets', + title: 'Addons/Design assets', parameters: { options: { diff --git a/examples/official-storybook/stories/addon-docs/addon-docs-blocks.stories.js b/examples/official-storybook/stories/addon-docs/addon-docs-blocks.stories.js new file mode 100644 index 00000000000..1f614050bb0 --- /dev/null +++ b/examples/official-storybook/stories/addon-docs/addon-docs-blocks.stories.js @@ -0,0 +1,176 @@ +import React from 'react'; +import { + Title, + Subtitle, + Description, + Primary, + Props, + Stories, +} from '@storybook/addon-docs/blocks'; +import { DocgenButton } from '../../components/DocgenButton'; +import BaseButton from '../../components/BaseButton'; +import { ButtonGroup } from '../../components/ButtonGroup'; + +export default { + title: 'Addons/Docs/stories docs bocks', + component: DocgenButton, + parameters: { + docs: { + page: () => ( + <> + <Title /> + <Subtitle /> + <Description /> + <Primary /> + <Props /> + <Stories /> + </> + ), + }, + }, +}; + +export const defDocsPage = () => <div>Default docs page</div>; + +export const smallDocsPage = () => <div>Just primary story, </div>; +smallDocsPage.story = { + parameters: { + docs: { + page: () => ( + <> + <Title /> + <Primary /> + </> + ), + }, + }, +}; + +export const checkBoxProps = () => <div>Primary props displayed with a check box </div>; +checkBoxProps.story = { + parameters: { + docs: { + page: () => { + const [showProps, setShowProps] = React.useState(false); + return ( + <> + <Title /> + <Subtitle /> + <Description /> + <Primary /> + <label> + <input + type="checkbox" + checked={showProps} + onChange={() => setShowProps(!showProps)} + /> + <span>display props</span> + </label> + {showProps && <Props />} + </> + ); + }, + }, + }, +}; + +export const customLabels = () => <div>Display custom title, Subtitle, Description</div>; +customLabels.story = { + parameters: { + docs: { + page: () => ( + <> + <Title>Custom title + Custom sub title + Custom description + + + + + ), + }, + }, +}; + +export const customStoriesFilter = () =>
Displays ALL stories (not excluding first one)
; +customStoriesFilter.story = { + parameters: { + docs: { + page: () => ( + <> + stories} /> + + ), + }, + }, +}; + +export const descriptionSlot = () =>
Adds markdown to the description
; +descriptionSlot.story = { + parameters: { + docs: { + page: () => ( + <> + `${description}`} /> + + ), + }, + }, +}; + +export const multipleComponents = () => ( + + + + + +); + +multipleComponents.story = { + name: 'Many Components', + parameters: { + component: ButtonGroup, + subcomponents: { + 'Docgen Button': DocgenButton, + 'Base Button': BaseButton, + }, + docs: { + page: () => ( + <> + + <Subtitle /> + <Description /> + <Primary slot={stories => stories.find(story => story.story === 'Many Components')} /> + <Props /> + </> + ), + }, + }, +}; + +export const componentsProps = () => <div>Display multiple prop tables in tabs</div>; +componentsProps.story = { + subcomponents: { + 'Docgen Button': DocgenButton, + 'Base Button': BaseButton, + }, + parameters: { + docs: { + page: () => ( + <> + <Title>Multiple prop tables + + Here's what happens when your component has some related components + + + + ), + }, + }, +}; diff --git a/examples/official-storybook/stories/addon-docs/addon-docs.stories.js b/examples/official-storybook/stories/addon-docs/addon-docs.stories.js index 6a2f2ae2e0f..1b06f9bfc19 100644 --- a/examples/official-storybook/stories/addon-docs/addon-docs.stories.js +++ b/examples/official-storybook/stories/addon-docs/addon-docs.stories.js @@ -4,7 +4,7 @@ import mdxNotes from '../notes/notes.mdx'; import { DocgenButton } from '../../components/DocgenButton'; export default { - title: 'Addons|Docs/stories', + title: 'Addons/Docs/stories', component: DocgenButton, }; @@ -52,3 +52,5 @@ docsDisable.story = { docs: { disable: true }, }, }; + +export const largerThanPreview = () =>
HUGE
; diff --git a/examples/official-storybook/stories/addon-docs/addon-docs.stories.mdx b/examples/official-storybook/stories/addon-docs/addon-docs.stories.mdx index b9a11b4a483..fa187420739 100644 --- a/examples/official-storybook/stories/addon-docs/addon-docs.stories.mdx +++ b/examples/official-storybook/stories/addon-docs/addon-docs.stories.mdx @@ -8,15 +8,17 @@ import { ColorItem, Meta, } from '@storybook/addon-docs/blocks'; +import { withKnobs, text } from '@storybook/addon-knobs'; import { action } from '@storybook/addon-actions'; import { Button } from '@storybook/react/demo'; import FlowTypeButton from '../../components/FlowTypeButton'; import { DocgenButton } from '../../components/DocgenButton';
{storyFn()}
]} + id="addons-docs-mdx-id" + decorators={[storyFn =>
{storyFn()}
, withKnobs]} parameters={{ notes: 'component notes' }} /> @@ -64,7 +66,7 @@ export const nonStory2 = () => ; // another one - + diff --git a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js index c699766b551..d9f894195c0 100644 --- a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js +++ b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import { Button } from '@storybook/react/demo'; export default { - title: 'Addons|Docs/csf-with-mdx-docs', + title: 'Addons/Docs/csf-with-mdx-docs', component: Button, includeStories: [], // or don't load this file at all }; diff --git a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.mdx b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.mdx index 485a6dbd6b4..f6418af2eb0 100644 --- a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.mdx +++ b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.mdx @@ -1,7 +1,7 @@ import { Meta, Story } from '@storybook/addon-docs/blocks'; import * as stories from './csf-with-mdx-docs.stories'; - + # Button diff --git a/examples/official-storybook/stories/addon-docs/docs-only.stories.mdx b/examples/official-storybook/stories/addon-docs/docs-only.stories.mdx index 606558f5fa6..d748141b63f 100644 --- a/examples/official-storybook/stories/addon-docs/docs-only.stories.mdx +++ b/examples/official-storybook/stories/addon-docs/docs-only.stories.mdx @@ -1,6 +1,6 @@ import { Meta } from '@storybook/addon-docs/blocks'; - + # Documentation-only MDX diff --git a/examples/official-storybook/stories/addon-docs/markdown.stories.mdx b/examples/official-storybook/stories/addon-docs/markdown.stories.mdx index 3431243f0cc..a711700e13c 100644 --- a/examples/official-storybook/stories/addon-docs/markdown.stories.mdx +++ b/examples/official-storybook/stories/addon-docs/markdown.stories.mdx @@ -1,6 +1,6 @@ import { Meta } from '@storybook/addon-docs/blocks'; - + # h1 Heading diff --git a/examples/official-storybook/stories/addon-docs/mdx.stories.js b/examples/official-storybook/stories/addon-docs/mdx.stories.js index 8d558fb190b..c4cab584e45 100644 --- a/examples/official-storybook/stories/addon-docs/mdx.stories.js +++ b/examples/official-storybook/stories/addon-docs/mdx.stories.js @@ -3,7 +3,7 @@ import { DocsContainer } from '@storybook/addon-docs/blocks'; import markdown from './markdown.stories.mdx'; export default { - title: 'Addons|Docs/mdx-in-story', + title: 'Addons/Docs/mdx-in-story', decorators: [storyFn => {storyFn()}], }; diff --git a/examples/official-storybook/stories/addon-docs/props.stories.mdx b/examples/official-storybook/stories/addon-docs/props.stories.mdx index d6a03b4ee0a..ba40711117a 100644 --- a/examples/official-storybook/stories/addon-docs/props.stories.mdx +++ b/examples/official-storybook/stories/addon-docs/props.stories.mdx @@ -3,7 +3,7 @@ import { DocgenButton } from '../../components/DocgenButton'; import { ForwardRefButton } from '../../components/ForwardRefButton'; import { MemoButton } from '../../components/MemoButton'; - + ## Docgen diff --git a/examples/official-storybook/stories/addon-events.stories.js b/examples/official-storybook/stories/addon-events.stories.js index 7f280c366b0..6a358119afc 100644 --- a/examples/official-storybook/stories/addon-events.stories.js +++ b/examples/official-storybook/stories/addon-events.stories.js @@ -67,7 +67,7 @@ const events = [ ]; export default { - title: 'Addons|Events', + title: 'Addons/Events', decorators: [withEvents({ emit, events })], parameters: { options: { diff --git a/examples/official-storybook/stories/addon-graphql.stories.js b/examples/official-storybook/stories/addon-graphql.stories.js index 6a175d206e5..f1e8044e0d9 100644 --- a/examples/official-storybook/stories/addon-graphql.stories.js +++ b/examples/official-storybook/stories/addon-graphql.stories.js @@ -1,7 +1,7 @@ import React from 'react'; export default { - title: 'Addons|GraphQL', + title: 'Addons/GraphQL', }; export const getPikachu = () =>
hello
; diff --git a/examples/official-storybook/stories/addon-info/decorators.stories.js b/examples/official-storybook/stories/addon-info/decorators.stories.js index fc0d763ee9f..0d3774ffdcc 100644 --- a/examples/official-storybook/stories/addon-info/decorators.stories.js +++ b/examples/official-storybook/stories/addon-info/decorators.stories.js @@ -3,7 +3,7 @@ import { withInfo } from '@storybook/addon-info'; import BaseButton from '../../components/BaseButton'; export default { - title: 'Addons|Info/Decorator', + title: 'Addons/Info/Decorator', decorators: [withInfo('Info can take options via the global or local decorator as well.')], }; diff --git a/examples/official-storybook/stories/addon-info/forward-ref.stories.js b/examples/official-storybook/stories/addon-info/forward-ref.stories.js index c4e674be179..21fdcd5ac6d 100644 --- a/examples/official-storybook/stories/addon-info/forward-ref.stories.js +++ b/examples/official-storybook/stories/addon-info/forward-ref.stories.js @@ -4,7 +4,7 @@ import ForwardedRefButton from '../../components/ForwardedRefButton'; import ForwardedRefButtonWDisplayName from '../../components/ForwardedRefButtonWDisplayName'; export default { - title: 'Addons|Info/ForwardRef', + title: 'Addons/Info/ForwardRef', decorators: [withInfo], }; diff --git a/examples/official-storybook/stories/addon-info/github-issues.js b/examples/official-storybook/stories/addon-info/github-issues.js index c3832af3fb0..3b96ca11ede 100644 --- a/examples/official-storybook/stories/addon-info/github-issues.js +++ b/examples/official-storybook/stories/addon-info/github-issues.js @@ -8,7 +8,7 @@ const Input = hoc(() => ); const TextArea = hoc(({ children }) => ); export default { - title: 'Addons|Info/GitHub issues', + title: 'Addons/Info/GitHub issues', decorators: [withInfo], }; diff --git a/examples/official-storybook/stories/addon-info/jsx.stories.js b/examples/official-storybook/stories/addon-info/jsx.stories.js index dcdd37d6d48..5052bf5f241 100644 --- a/examples/official-storybook/stories/addon-info/jsx.stories.js +++ b/examples/official-storybook/stories/addon-info/jsx.stories.js @@ -21,7 +21,7 @@ const JSXDescription = ( ); export default { - title: 'Addons|Info/JSX', + title: 'Addons/Info/JSX', decorators: [withInfo], }; diff --git a/examples/official-storybook/stories/addon-info/markdown.stories.js b/examples/official-storybook/stories/addon-info/markdown.stories.js index 5f9048be9bc..208b5c84ffe 100644 --- a/examples/official-storybook/stories/addon-info/markdown.stories.js +++ b/examples/official-storybook/stories/addon-info/markdown.stories.js @@ -6,7 +6,7 @@ import BaseButton from '../../components/BaseButton'; import externalMdDocs from './EXAMPLE.md'; export default { - title: 'Addons|Info/Markdown', + title: 'Addons/Info/Markdown', decorators: [withInfo], excludeStories: ['markdownDescription'], }; diff --git a/examples/official-storybook/stories/addon-info/options.stories.js b/examples/official-storybook/stories/addon-info/options.stories.js index 12bb82cb98c..632518c932f 100644 --- a/examples/official-storybook/stories/addon-info/options.stories.js +++ b/examples/official-storybook/stories/addon-info/options.stories.js @@ -8,7 +8,7 @@ import TableComponent from '../../components/TableComponent'; import { markdownDescription } from './markdown.stories'; export default { - title: 'Addons|Info/Options', + title: 'Addons/Info/Options', decorators: [withInfo], }; diff --git a/examples/official-storybook/stories/addon-info/parameters.stories.js b/examples/official-storybook/stories/addon-info/parameters.stories.js index 1a7eee9c6d2..257c165f993 100644 --- a/examples/official-storybook/stories/addon-info/parameters.stories.js +++ b/examples/official-storybook/stories/addon-info/parameters.stories.js @@ -6,7 +6,7 @@ import BaseButton from '../../components/BaseButton'; import { markdownDescription } from './markdown.stories'; export default { - title: 'Addons|Info/Parameters', + title: 'Addons/Info/Parameters', decorators: [ withInfo({ styles: { diff --git a/examples/official-storybook/stories/addon-info/react-docgen.stories.js b/examples/official-storybook/stories/addon-info/react-docgen.stories.js index 1b8ba8dbf11..bbb6412abeb 100644 --- a/examples/official-storybook/stories/addon-info/react-docgen.stories.js +++ b/examples/official-storybook/stories/addon-info/react-docgen.stories.js @@ -8,7 +8,7 @@ import BaseButton from '../../components/BaseButton'; import { NamedExportButton } from '../../components/NamedExportButton'; export default { - title: 'Addons|Info/React Docgen', + title: 'Addons/Info/React Docgen', component: DocgenButton, decorators: [withInfo], }; diff --git a/examples/official-storybook/stories/addon-info/story-source.stories.js b/examples/official-storybook/stories/addon-info/story-source.stories.js index 51659a3ce20..fb2a42ece90 100644 --- a/examples/official-storybook/stories/addon-info/story-source.stories.js +++ b/examples/official-storybook/stories/addon-info/story-source.stories.js @@ -6,7 +6,7 @@ import BaseButton from '../../components/BaseButton'; import TableComponent from '../../components/TableComponent'; export default { - title: 'Addons|Info/Story Source', + title: 'Addons/Info/Story Source', decorators: [withInfo], }; diff --git a/examples/official-storybook/stories/addon-jest.stories.js b/examples/official-storybook/stories/addon-jest.stories.js index b86d7f17b85..b0226b4cd8f 100644 --- a/examples/official-storybook/stories/addon-jest.stories.js +++ b/examples/official-storybook/stories/addon-jest.stories.js @@ -4,7 +4,7 @@ import { withTests as withTestsHOC } from '@storybook/addon-jest'; import results from './addon-jest.testresults.json'; export default { - title: 'Addons|Jest', + title: 'Addons/Jest', decorators: [withTestsHOC({ results })], }; diff --git a/examples/official-storybook/stories/addon-knobs/with-knobs-decorators.stories.js b/examples/official-storybook/stories/addon-knobs/with-knobs-decorators.stories.js index af31294f7de..1a9a5a6d7ba 100644 --- a/examples/official-storybook/stories/addon-knobs/with-knobs-decorators.stories.js +++ b/examples/official-storybook/stories/addon-knobs/with-knobs-decorators.stories.js @@ -1,7 +1,7 @@ import { withKnobs, text } from '@storybook/addon-knobs'; export default { - title: 'Addons|Knobs.with decorators', + title: 'Addons/Knobs/with decorators', }; export const withDecoratorCallingStoryFunctionMoreThanOnce = () => { diff --git a/examples/official-storybook/stories/addon-knobs/with-knobs-options.stories.js b/examples/official-storybook/stories/addon-knobs/with-knobs-options.stories.js index 77f24abc232..d4ee216a4fd 100644 --- a/examples/official-storybook/stories/addon-knobs/with-knobs-options.stories.js +++ b/examples/official-storybook/stories/addon-knobs/with-knobs-options.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import { withKnobs, text } from '@storybook/addon-knobs'; export default { - title: 'Addons|Knobs.withKnobs using options', + title: 'Addons/Knobs/withKnobs using options', decorators: [ withKnobs({ escapeHTML: false, diff --git a/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js b/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js index ee7330922dd..c6209f09a21 100644 --- a/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js +++ b/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js @@ -41,7 +41,7 @@ let injectedItems = []; let injectedIsLoading = false; export default { - title: 'Addons|Knobs.withKnobs', + title: 'Addons/Knobs/withKnobs', decorators: [withKnobs], }; @@ -75,12 +75,27 @@ export const tweaksStaticValues = () => { const images = files('Happy Picture', 'image/*', [ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfiARwMCyEWcOFPAAAAP0lEQVQoz8WQMQoAIAwDL/7/z3GwghSp4KDZyiUpBMCYUgd8rehtH16/l3XewgU2KAzapjXBbNFaPS6lDMlKB6OiDv3iAH1OAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE4LTAxLTI4VDEyOjExOjMzLTA3OjAwlAHQBgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOC0wMS0yOFQxMjoxMTozMy0wNzowMOVcaLoAAAAASUVORK5CYII=', ]); + // array of objects + const arrayOfObjects = [ + { + label: 'Sparky', + dogParent: 'Matthew', + location: 'Austin', + }, + { + label: 'Juniper', + dogParent: 'Joshua', + location: 'Austin', + }, + ]; + + const dog = select('Dogs', arrayOfObjects, arrayOfObjects[0]); // NOTE: the default value must not change - e.g., do not do date('Label', new Date()) or date('Label') const defaultBirthday = new Date('Jan 20 2017 GMT+0'); const birthday = date('Birthday', defaultBirthday); - const intro = `My name is ${name}, I'm ${age} years old, and my favorite fruit is ${fruit}. I also enjoy ${otherFruit}.`; + const intro = `My name is ${name}, I'm ${age} years old, and my favorite fruit is ${fruit}. I also enjoy ${otherFruit}, and hanging out with my dog ${dog.label}`; const style = { backgroundColor, ...otherStyles }; const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!'; const dateOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }; diff --git a/examples/official-storybook/stories/addon-links/button.stories.js b/examples/official-storybook/stories/addon-links/button.stories.js index 6f63a99ed18..16ef54740b8 100644 --- a/examples/official-storybook/stories/addon-links/button.stories.js +++ b/examples/official-storybook/stories/addon-links/button.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import { linkTo } from '@storybook/addon-links'; export default { - title: 'Addons|Links.Button', + title: 'Addons/Links/Button', }; export const First = () => ( diff --git a/examples/official-storybook/stories/addon-links/href.stories.js b/examples/official-storybook/stories/addon-links/href.stories.js index d2b82ad448e..98dc6fb4a89 100644 --- a/examples/official-storybook/stories/addon-links/href.stories.js +++ b/examples/official-storybook/stories/addon-links/href.stories.js @@ -3,7 +3,7 @@ import { hrefTo } from '@storybook/addon-links'; import { action } from '@storybook/addon-actions'; export default { - title: 'Addons|Links.Href', + title: 'Addons/Links/Href', }; export const log = () => { diff --git a/examples/official-storybook/stories/addon-links/link.stories.js b/examples/official-storybook/stories/addon-links/link.stories.js index 84d2c457960..110ea0cb8d3 100644 --- a/examples/official-storybook/stories/addon-links/link.stories.js +++ b/examples/official-storybook/stories/addon-links/link.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import LinkTo from '@storybook/addon-links/react'; export default { - title: 'Addons|Links.Link', + title: 'Addons/Links/Link', }; export const First = () => Go to Second; diff --git a/examples/official-storybook/stories/addon-links/scroll.stories.js b/examples/official-storybook/stories/addon-links/scroll.stories.js index 3b72fac54e1..e41c7c48265 100644 --- a/examples/official-storybook/stories/addon-links/scroll.stories.js +++ b/examples/official-storybook/stories/addon-links/scroll.stories.js @@ -2,7 +2,7 @@ import React, { Fragment } from 'react'; import LinkTo from '@storybook/addon-links/react'; export default { - title: 'Addons|Links.Scroll position', + title: 'Addons/Links/Scroll position', decorators: [ storyFn => ( diff --git a/examples/official-storybook/stories/addon-links/select.stories.js b/examples/official-storybook/stories/addon-links/select.stories.js index 5e751f53944..0ba2d66e89a 100644 --- a/examples/official-storybook/stories/addon-links/select.stories.js +++ b/examples/official-storybook/stories/addon-links/select.stories.js @@ -3,7 +3,7 @@ import { linkTo } from '@storybook/addon-links'; import LinkTo from '@storybook/addon-links/react'; export default { - title: 'Addons|Links.Select', + title: 'Addons/Links/Select', }; export const Index = () => ( diff --git a/examples/official-storybook/stories/addon-notes.stories.js b/examples/official-storybook/stories/addon-notes.stories.js index 0cc89c42eab..f6053091f72 100644 --- a/examples/official-storybook/stories/addon-notes.stories.js +++ b/examples/official-storybook/stories/addon-notes.stories.js @@ -8,6 +8,10 @@ const markdownString = ` This is inline github-flavored markdown! +[Link to a bottom ID](#anchor--addons-notes--with-a-markdown-table) +[Link to an external website](http://example.com) +[Link to a other storybook page](/story/addons-notes--addon-notes) + ## Example Usage ~~~js import React from 'react'; @@ -70,7 +74,7 @@ const giphyMarkdown = ` `; export default { - title: 'Addons|Notes', + title: 'Addons/Notes', }; export const addonNotes = () => ( diff --git a/examples/official-storybook/stories/addon-options.stories.js b/examples/official-storybook/stories/addon-options.stories.js index 6fc0d029643..358abb41b2f 100644 --- a/examples/official-storybook/stories/addon-options.stories.js +++ b/examples/official-storybook/stories/addon-options.stories.js @@ -1,7 +1,7 @@ import React from 'react'; export default { - title: 'Addons|Options', + title: 'Addons/Options', }; export const settingName = () => ( diff --git a/examples/official-storybook/stories/addon-queryparams.stories.js b/examples/official-storybook/stories/addon-queryparams.stories.js index 72bf9b7c2c9..8fe633c230f 100644 --- a/examples/official-storybook/stories/addon-queryparams.stories.js +++ b/examples/official-storybook/stories/addon-queryparams.stories.js @@ -3,7 +3,7 @@ import React from 'react'; import { withQuery } from '@storybook/addon-queryparams'; export default { - title: 'Addons|QueryParams', + title: 'Addons/QueryParams', decorators: [withQuery], parameters: { diff --git a/examples/official-storybook/stories/addon-storyshots.stories.js b/examples/official-storybook/stories/addon-storyshots.stories.js index 9e9c27a1099..18eeb9eda95 100644 --- a/examples/official-storybook/stories/addon-storyshots.stories.js +++ b/examples/official-storybook/stories/addon-storyshots.stories.js @@ -9,7 +9,7 @@ const Block = styled.div({ }); export default { - title: 'Addons|Storyshots', + title: 'Addons/Storyshots', }; export const block = () => ; diff --git a/examples/official-storybook/stories/addon-viewport/custom-default.stories.js b/examples/official-storybook/stories/addon-viewport/custom-default.stories.js index 83c8ab021dd..aa98e44191f 100644 --- a/examples/official-storybook/stories/addon-viewport/custom-default.stories.js +++ b/examples/official-storybook/stories/addon-viewport/custom-default.stories.js @@ -5,7 +5,7 @@ import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport'; const Panel = styled.div(); export default { - title: 'Addons|Viewport.Custom Default (Kindle Fire 2)', + title: 'Addons/Viewport/Custom Default (Kindle Fire 2)', parameters: { viewport: { viewports: { diff --git a/examples/official-storybook/stories/addon-viewport/default.stories.js b/examples/official-storybook/stories/addon-viewport/default.stories.js index 430a7fb88aa..945473987ad 100644 --- a/examples/official-storybook/stories/addon-viewport/default.stories.js +++ b/examples/official-storybook/stories/addon-viewport/default.stories.js @@ -5,7 +5,7 @@ import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport'; const Panel = styled.div(); export default { - title: 'Addons|Viewport', + title: 'Addons/Viewport', parameters: { viewport: { viewports: INITIAL_VIEWPORTS, diff --git a/examples/official-storybook/stories/core/decorators.stories.js b/examples/official-storybook/stories/core/decorators.stories.js index 6d301a93db5..be0c8c2071e 100644 --- a/examples/official-storybook/stories/core/decorators.stories.js +++ b/examples/official-storybook/stories/core/decorators.stories.js @@ -15,7 +15,7 @@ addDecorator((s, { kind }) => ); export default { - title: 'Core|Decorators', + title: 'Core/Decorators', decorators: [ s => ( <> diff --git a/examples/official-storybook/stories/core/errors.stories.js b/examples/official-storybook/stories/core/errors.stories.js index 4c1db62270a..54950d17808 100644 --- a/examples/official-storybook/stories/core/errors.stories.js +++ b/examples/official-storybook/stories/core/errors.stories.js @@ -4,7 +4,7 @@ const badOutput = { renderable: 'no, react can not render objects' }; const BadComponent = () => badOutput; export default { - title: 'Core|Errors', + title: 'Core/Errors', }; export const exception = () => { diff --git a/examples/official-storybook/stories/core/events.stories.js b/examples/official-storybook/stories/core/events.stories.js index 0b6949d139d..4da37afffc0 100644 --- a/examples/official-storybook/stories/core/events.stories.js +++ b/examples/official-storybook/stories/core/events.stories.js @@ -10,7 +10,7 @@ const increment = () => { }; export default { - title: 'Core|Events', + title: 'Core/Events', }; export const force = () => ; diff --git a/examples/official-storybook/stories/core/parameters.stories.js b/examples/official-storybook/stories/core/parameters.stories.js index c1ac1a0a35e..25c93dadf61 100644 --- a/examples/official-storybook/stories/core/parameters.stories.js +++ b/examples/official-storybook/stories/core/parameters.stories.js @@ -10,7 +10,7 @@ addDecorator(fn => fn({ customStoryContext: 52, parameters: { customParameter: 4 addParameters({ globalParameter: 'globalParameter' }); export default { - title: 'Core|Parameters', + title: 'Core/Parameters', decorators: [fn => fn({ parameters: { decoratorParameter: 'decoratorParameter' } })], parameters: { chapterParameter: 'chapterParameter', diff --git a/examples/official-storybook/stories/core/scroll.stories.js b/examples/official-storybook/stories/core/scroll.stories.js index e77afec9ae7..4b619f0af7c 100644 --- a/examples/official-storybook/stories/core/scroll.stories.js +++ b/examples/official-storybook/stories/core/scroll.stories.js @@ -1,29 +1,56 @@ import React from 'react'; +import { styled } from '@storybook/theming'; + +import { Spaced } from '@storybook/components'; export default { - title: 'Core|Scroll', + title: 'Core/Scroll', }; +const Horizontal = styled(props => )({ + display: 'grid', + gridTemplateColumns: '100px calc(100vw + 100px) 100px', +}); +const Vertical = styled(props => )({}); + export const story1 = () => ( -
+
START, when switching stories, you should be able to read this at the top of the page
-
+
middle
       END, this text should be below the scroll "fold" and therefore only be readable after
       scrolling
     
-
+
); story1.story = { name: 'story with 100vh padding 1' }; export const story2 = () => ( -
+
START, when switching stories, you should be able to read this at the top of the page
-
+
middle
       END, this text should be below the scroll "fold" and therefore only be readable after
       scrolling
     
-
+
); story2.story = { name: 'story with 100vh padding 2' }; + +export const story3 = () => ( + +
START
+
middle
+
END
+
+); +story3.story = { name: 'story with 100vw+' }; + +export const story4 = () => ( + +
START
+
middle
+
END
+
+); +story4.story = { name: 'story with 100vw+ 2' }; diff --git a/examples/official-storybook/stories/core/unicode.stories.js b/examples/official-storybook/stories/core/unicode.stories.js index dada3c9f833..5da6025bd80 100644 --- a/examples/official-storybook/stories/core/unicode.stories.js +++ b/examples/official-storybook/stories/core/unicode.stories.js @@ -1,7 +1,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; -storiesOf('Core|Unicode', module) +storiesOf('Core/Unicode', module) .add('😀', () =>

❤️

) .add('Кнопки', () =>

нормальный

) .add('바보', () =>

🤷🏻‍♂️

); diff --git a/examples/official-storybook/stories/demo/button.stories.js b/examples/official-storybook/stories/demo/button.stories.js index e0958d19ef4..ed9e74c27d4 100644 --- a/examples/official-storybook/stories/demo/button.stories.js +++ b/examples/official-storybook/stories/demo/button.stories.js @@ -3,8 +3,9 @@ import { action } from '@storybook/addon-actions'; import { Button } from '@storybook/react/demo'; export default { - title: 'Other|Demo/Button', + title: 'Other/Demo/Button', component: Button, + id: 'demo-button-id', parameters: { docs: { inlineStories: false, diff --git a/examples/official-storybook/stories/demo/button.stories.mdx b/examples/official-storybook/stories/demo/button.stories.mdx index a20e5690550..bfb6ae95f89 100644 --- a/examples/official-storybook/stories/demo/button.stories.mdx +++ b/examples/official-storybook/stories/demo/button.stories.mdx @@ -3,7 +3,7 @@ import { action } from '@storybook/addon-actions'; import { Button } from '@storybook/react/demo'; import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks'; - + # Simple Button diff --git a/examples/official-storybook/stories/demo/welcome.stories.js b/examples/official-storybook/stories/demo/welcome.stories.js index cca11f79f2c..b0b56a55bc0 100644 --- a/examples/official-storybook/stories/demo/welcome.stories.js +++ b/examples/official-storybook/stories/demo/welcome.stories.js @@ -3,7 +3,7 @@ import { linkTo } from '@storybook/addon-links'; import { Welcome } from '@storybook/react/demo'; export default { - title: 'Other|Demo/Welcome', + title: 'Other/Demo/Welcome', component: Welcome, }; diff --git a/examples/official-storybook/stories/deprecated/addon-actions.stories.js b/examples/official-storybook/stories/deprecated/addon-actions.stories.js index a907ba9dfb3..0da9183e3d7 100644 --- a/examples/official-storybook/stories/deprecated/addon-actions.stories.js +++ b/examples/official-storybook/stories/deprecated/addon-actions.stories.js @@ -15,7 +15,7 @@ const pickNative = decorate([args => [args[0].nativeEvent]]); const pickNativeAction = decorateAction([args => [args[0].nativeEvent]]); export default { - title: 'Addons|Actions.deprecated', + title: 'Addons/Actions/deprecated', }; export const decoratedAction = () => ( diff --git a/examples/official-storybook/stories/deprecated/addon-events.stories.js b/examples/official-storybook/stories/deprecated/addon-events.stories.js index cb832b0c73b..73146d7e075 100644 --- a/examples/official-storybook/stories/deprecated/addon-events.stories.js +++ b/examples/official-storybook/stories/deprecated/addon-events.stories.js @@ -66,7 +66,7 @@ const events = [ ]; export default { - title: 'Addons|Events.deprecated', + title: 'Addons/Events/deprecated', decorators: [ storyFn => ( diff --git a/examples/official-storybook/stories/deprecated/addon-info.stories.js b/examples/official-storybook/stories/deprecated/addon-info.stories.js index 6de7dd79182..4180d2ed88d 100644 --- a/examples/official-storybook/stories/deprecated/addon-info.stories.js +++ b/examples/official-storybook/stories/deprecated/addon-info.stories.js @@ -6,7 +6,7 @@ import BaseButton from '../../components/BaseButton'; import { markdownDescription } from '../addon-info/markdown.stories'; export default { - title: 'Addons|Info/deprecated', + title: 'Addons/Info/deprecated', }; export const displaysMarkdown = withInfo(markdownDescription)(() => ( diff --git a/examples/polymer-cli/.storybook/config.js b/examples/polymer-cli/.storybook/config.js index 6eab4026bae..ce0fb744466 100644 --- a/examples/polymer-cli/.storybook/config.js +++ b/examples/polymer-cli/.storybook/config.js @@ -4,7 +4,7 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); addParameters({ options: { - hierarchyRootSeparator: /\|/, + showRoots: true, }, }); diff --git a/examples/polymer-cli/package.json b/examples/polymer-cli/package.json index 4b8f18edb0c..5871287c5cf 100644 --- a/examples/polymer-cli/package.json +++ b/examples/polymer-cli/package.json @@ -1,6 +1,6 @@ { "name": "polymer-cli", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build-storybook": "build-storybook", @@ -9,17 +9,17 @@ }, "dependencies": { "@polymer/polymer": "^2.6.0", - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/polymer": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/polymer": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "@webcomponents/webcomponentsjs": "^1.2.0", "global": "^4.3.2", "lit-html": "^1.0.0", diff --git a/examples/polymer-cli/src/stories/addon-actions.stories.js b/examples/polymer-cli/src/stories/addon-actions.stories.js index 9e0ee92c547..f8bb6b11948 100644 --- a/examples/polymer-cli/src/stories/addon-actions.stories.js +++ b/examples/polymer-cli/src/stories/addon-actions.stories.js @@ -4,7 +4,7 @@ import { document } from 'global'; import '../simple-button.html'; export default { - title: 'Addon|Actions', + title: 'Addon/Actions', }; export const actionOnly = () => { diff --git a/examples/polymer-cli/src/stories/addon-backgrounds.stories.js b/examples/polymer-cli/src/stories/addon-backgrounds.stories.js index bf7f776d961..9610bc16587 100644 --- a/examples/polymer-cli/src/stories/addon-backgrounds.stories.js +++ b/examples/polymer-cli/src/stories/addon-backgrounds.stories.js @@ -1,5 +1,5 @@ export default { - title: 'Addon|Backgrounds', + title: 'Addon/Backgrounds', parameters: { backgrounds: [ diff --git a/examples/polymer-cli/src/stories/addon-knobs.stories.js b/examples/polymer-cli/src/stories/addon-knobs.stories.js index 0cfffdd2577..ed5a1ee19ce 100644 --- a/examples/polymer-cli/src/stories/addon-knobs.stories.js +++ b/examples/polymer-cli/src/stories/addon-knobs.stories.js @@ -15,7 +15,7 @@ import { boolean, } from '@storybook/addon-knobs'; -storiesOf('Addon|Knobs', module) +storiesOf('Addon/Knobs', module) .addDecorator(withKnobs) .add('simple', () => { const title = text('Button title', 'Hello'); diff --git a/examples/polymer-cli/src/stories/addon-links.stories.js b/examples/polymer-cli/src/stories/addon-links.stories.js index e3bb16249e5..4af90cc1030 100644 --- a/examples/polymer-cli/src/stories/addon-links.stories.js +++ b/examples/polymer-cli/src/stories/addon-links.stories.js @@ -4,7 +4,7 @@ import { document } from 'global'; import '../simple-button.html'; export default { - title: 'Addon|Links', + title: 'Addon/Links', }; export const withCreateElement = () => { diff --git a/examples/polymer-cli/src/stories/addon-notes.stories.js b/examples/polymer-cli/src/stories/addon-notes.stories.js index 8c9dcd9a174..ea11b37cfc4 100644 --- a/examples/polymer-cli/src/stories/addon-notes.stories.js +++ b/examples/polymer-cli/src/stories/addon-notes.stories.js @@ -1,5 +1,5 @@ export default { - title: 'Addon|Notes', + title: 'Addon/Notes', }; export const simpleNote = () => diff --git a/examples/polymer-cli/src/stories/core.stories.js b/examples/polymer-cli/src/stories/core.stories.js index 96633026df6..5a84645bb6d 100644 --- a/examples/polymer-cli/src/stories/core.stories.js +++ b/examples/polymer-cli/src/stories/core.stories.js @@ -7,7 +7,7 @@ const storyParameter = 'storyParameter'; addParameters({ globalParameter }); export default { - title: 'Core|Parameters', + title: 'Core/Parameters', parameters: { chapterParameter, diff --git a/examples/polymer-cli/src/stories/custom-decorators.stories.js b/examples/polymer-cli/src/stories/custom-decorators.stories.js index f83b5575062..fadc6c47cae 100644 --- a/examples/polymer-cli/src/stories/custom-decorators.stories.js +++ b/examples/polymer-cli/src/stories/custom-decorators.stories.js @@ -1,7 +1,7 @@ import { document } from 'global'; export default { - title: 'Custom|Decorator', + title: 'Custom/Decorator', decorators: [ storyFn => { diff --git a/examples/polymer-cli/src/stories/custom-rendering.stories.js b/examples/polymer-cli/src/stories/custom-rendering.stories.js index 08cc3e5eee6..32ff209cb21 100644 --- a/examples/polymer-cli/src/stories/custom-rendering.stories.js +++ b/examples/polymer-cli/src/stories/custom-rendering.stories.js @@ -5,7 +5,7 @@ import { StringTemplateButton } from '../string-template-button'; import '../separated-button/separated-button.html'; -storiesOf('Custom|Methods for rendering', module) +storiesOf('Custom/Methods for rendering', module) .add('html string', () => '
Rendered with string
') .add('html with custom elements', () => '') .add('document.createElement', () => { diff --git a/examples/preact-kitchen-sink/.storybook/config.js b/examples/preact-kitchen-sink/.storybook/config.js index 2bc7cbb87d5..b97b8482d52 100644 --- a/examples/preact-kitchen-sink/.storybook/config.js +++ b/examples/preact-kitchen-sink/.storybook/config.js @@ -5,8 +5,7 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); addParameters({ options: { - hierarchySeparator: /\/|\./, - hierarchyRootSeparator: /\|/, + showRoots: true, }, }); diff --git a/examples/preact-kitchen-sink/package.json b/examples/preact-kitchen-sink/package.json index 49f94e5f09f..b5a80b35d38 100644 --- a/examples/preact-kitchen-sink/package.json +++ b/examples/preact-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "preact-example", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", @@ -15,21 +15,21 @@ "devDependencies": { "@babel/core": "^7.3.4", "@babel/plugin-transform-runtime": "^7.2.0", - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-contexts": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/preact": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-contexts": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/preact": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "babel-loader": "^8.0.4", "cross-env": "^6.0.3", "file-loader": "^4.2.0", diff --git a/examples/preact-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot b/examples/preact-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot index 21711980741..c15dfb282f7 100644 --- a/examples/preact-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot +++ b/examples/preact-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Actions Action And Method 1`] = ` +exports[`Storyshots Addons/Actions Action and method 1`] = ` `; -exports[`Storyshots Addons|Backgrounds Example 2 1`] = ` +exports[`Storyshots Addons/Backgrounds Example 2 1`] = ` ; diff --git a/examples/preact-kitchen-sink/src/stories/addon-backgrounds.stories.js b/examples/preact-kitchen-sink/src/stories/addon-backgrounds.stories.js index 844af43ad48..960ee54461f 100644 --- a/examples/preact-kitchen-sink/src/stories/addon-backgrounds.stories.js +++ b/examples/preact-kitchen-sink/src/stories/addon-backgrounds.stories.js @@ -5,7 +5,7 @@ import { h } from 'preact'; import Button from '../Button'; export default { - title: 'Addons|Backgrounds', + title: 'Addons/Backgrounds', parameters: { backgrounds: [ diff --git a/examples/preact-kitchen-sink/src/stories/addon-centered.stories.js b/examples/preact-kitchen-sink/src/stories/addon-centered.stories.js index 09ffee19464..3faae466226 100644 --- a/examples/preact-kitchen-sink/src/stories/addon-centered.stories.js +++ b/examples/preact-kitchen-sink/src/stories/addon-centered.stories.js @@ -6,7 +6,7 @@ import Centered from '@storybook/addon-centered/preact'; import Button from '../Button'; export default { - title: 'Addons|Centered', + title: 'Addons/Centered', component: Button, decorators: [Centered], }; diff --git a/examples/preact-kitchen-sink/src/stories/addon-contexts.stories.js b/examples/preact-kitchen-sink/src/stories/addon-contexts.stories.js index 2fad6842ffc..445148b61c5 100644 --- a/examples/preact-kitchen-sink/src/stories/addon-contexts.stories.js +++ b/examples/preact-kitchen-sink/src/stories/addon-contexts.stories.js @@ -41,7 +41,7 @@ const storyLevelContexts = [ ]; export default { - title: 'Addons|Contexts', + title: 'Addons/Contexts', decorators: [withContexts(topLevelContexts)], }; diff --git a/examples/preact-kitchen-sink/src/stories/addon-knobs.stories.js b/examples/preact-kitchen-sink/src/stories/addon-knobs.stories.js index b06af614d22..330c3a8f56b 100644 --- a/examples/preact-kitchen-sink/src/stories/addon-knobs.stories.js +++ b/examples/preact-kitchen-sink/src/stories/addon-knobs.stories.js @@ -16,7 +16,7 @@ import { } from '@storybook/addon-knobs'; export default { - title: 'Addons|Knobs', + title: 'Addons/Knobs', decorators: [withKnobs], }; diff --git a/examples/preact-kitchen-sink/src/stories/addon-links.stories.js b/examples/preact-kitchen-sink/src/stories/addon-links.stories.js index c1ab6fd5524..b138b207a60 100644 --- a/examples/preact-kitchen-sink/src/stories/addon-links.stories.js +++ b/examples/preact-kitchen-sink/src/stories/addon-links.stories.js @@ -7,7 +7,7 @@ import { linkTo } from '@storybook/addon-links'; import Button from '../Button'; export default { - title: 'Addons|Links', + title: 'Addons/Links', }; export const goToWelcome = () => ( diff --git a/examples/preact-kitchen-sink/src/stories/addon-notes.stories.js b/examples/preact-kitchen-sink/src/stories/addon-notes.stories.js index bec41784912..14d3bf9feea 100644 --- a/examples/preact-kitchen-sink/src/stories/addon-notes.stories.js +++ b/examples/preact-kitchen-sink/src/stories/addon-notes.stories.js @@ -5,7 +5,7 @@ import { h } from 'preact'; import { withNotes } from '@storybook/addon-notes'; export default { - title: 'Addons|Notes', + title: 'Addons/Notes', decorators: [withNotes], }; diff --git a/examples/rax-kitchen-sink/.storybook/config.js b/examples/rax-kitchen-sink/.storybook/config.js index 211422ec39a..a461578d87e 100644 --- a/examples/rax-kitchen-sink/.storybook/config.js +++ b/examples/rax-kitchen-sink/.storybook/config.js @@ -7,8 +7,7 @@ addParameters({ goFullScreen: false, showAddonsPanel: true, showSearchBox: false, - hierarchySeparator: /\./, - hierarchyRootSeparator: /\|/, + showRoots: true, enableShortcuts: true, panelPosition: 'bottom', }, diff --git a/examples/rax-kitchen-sink/package.json b/examples/rax-kitchen-sink/package.json index e3bd349280e..a68dd302ad9 100644 --- a/examples/rax-kitchen-sink/package.json +++ b/examples/rax-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "rax-kitchen-sink", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build": "rax-scripts build", @@ -21,23 +21,23 @@ "rax-view": "^1.0.0" }, "devDependencies": { - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-events": "5.3.0-alpha.41", - "@storybook/addon-info": "5.3.0-alpha.41", - "@storybook/addon-jest": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/rax": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-events": "5.3.0-beta.2", + "@storybook/addon-info": "5.3.0-beta.2", + "@storybook/addon-jest": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/rax": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "babel-eslint": "^10.0.3", "babel-preset-rax": "^1.0.0-beta.0", "rax-scripts": "^2.0.0", diff --git a/examples/rax-kitchen-sink/src/components/App/__snapshots__/App.test.js.snap b/examples/rax-kitchen-sink/src/components/App/__snapshots__/App.test.js.snap index 052ed9614b7..30207536666 100644 --- a/examples/rax-kitchen-sink/src/components/App/__snapshots__/App.test.js.snap +++ b/examples/rax-kitchen-sink/src/components/App/__snapshots__/App.test.js.snap @@ -2,61 +2,43 @@ exports[`App render correctly 1`] = ` Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "Welcome to Rax", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, - "fontSize": 32, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], - "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, - }, "tagName": "DIV", }, Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "To get started, edit src/components/App.js and save to reload.", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, - "fontSize": 32, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], - "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, - }, "tagName": "DIV", } `; diff --git a/examples/rax-kitchen-sink/src/components/Welcome/__snapshots__/Welcome.test.js.snap b/examples/rax-kitchen-sink/src/components/Welcome/__snapshots__/Welcome.test.js.snap index 9b8f4ed5508..293214cab81 100644 --- a/examples/rax-kitchen-sink/src/components/Welcome/__snapshots__/Welcome.test.js.snap +++ b/examples/rax-kitchen-sink/src/components/Welcome/__snapshots__/Welcome.test.js.snap @@ -2,22 +2,22 @@ exports[`Welcome render correctly 1`] = ` Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "Welcome to storybook for Rax", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, "fontSize": 40, "fontWeight": "bold", "lineHeight": 50, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, @@ -43,91 +43,73 @@ Object { "tagName": "IMG", }, Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "This is a UI component dev environment for your Rax app.", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, "fontSize": 12, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, "marginBottom": 10, }, "tagName": "DIV", }, Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "We've added some basic stories inside the 'src/stories' directory. A story is a single state of one or more UI components. You can have as many stories as you want. (Basically a story is like a visual test case.)", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, "fontSize": 12, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, "marginBottom": 10, }, "tagName": "DIV", }, Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "See these sample", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, "fontSize": 12, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, "marginBottom": 10, }, "tagName": "DIV", @@ -138,31 +120,25 @@ Object { }, "children": Array [ Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "button", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, "fontSize": 12, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, "marginBottom": 10, }, "tagName": "DIV", @@ -171,73 +147,55 @@ Object { "tagName": "BUTTON", }, Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "for a component called 'Button'.", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, "fontSize": 12, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, "marginBottom": 10, }, "tagName": "DIV", }, Object { + "attributes": Object { + "class": "rax-view", + }, "children": Array [ Object { + "attributes": Object { + "class": "rax-text", + }, "children": Array [ "Just like that, you can add your own components as stories. You can also edit those components and see changes right away. (Try editing the 'Button' stories located at 'src/stories/index.js' .)", ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "block", - "flexDirection": "column", - "flexShrink": 0, "fontSize": 12, - "whiteSpace": "pre-wrap", + "webkitLineClamp": undefined, }, "tagName": "SPAN", }, ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, "marginBottom": 10, }, "tagName": "DIV", }, ], "style": Object { - "alignContent": "flex-start", - "border": "0 solid black", - "boxSizing": "border-box", - "display": "flex", - "flexDirection": "column", - "flexShrink": 0, "fontFamily": "\\"Helvetica Neue\\", Helvetica, \\"Segoe UI\\", Arial, freesans, sans-serif", "margin": 15, }, diff --git a/examples/rax-kitchen-sink/src/stories/addon-a11y.stories.js b/examples/rax-kitchen-sink/src/stories/addon-a11y.stories.js index f07cb65b366..43e25ed67ed 100644 --- a/examples/rax-kitchen-sink/src/stories/addon-a11y.stories.js +++ b/examples/rax-kitchen-sink/src/stories/addon-a11y.stories.js @@ -5,7 +5,7 @@ import View from 'rax-view'; import markdown from './note.md'; export default { - title: 'Addon|addon-a11y', + title: 'Addon/addon-a11y', decorators: [withA11Y], }; diff --git a/examples/rax-kitchen-sink/src/stories/addon-actions.stories.js b/examples/rax-kitchen-sink/src/stories/addon-actions.stories.js index 8d7cabd2c34..00496f4718e 100644 --- a/examples/rax-kitchen-sink/src/stories/addon-actions.stories.js +++ b/examples/rax-kitchen-sink/src/stories/addon-actions.stories.js @@ -4,7 +4,7 @@ import { action } from '@storybook/addon-actions'; import Text from 'rax-text'; export default { - title: 'Addon|addon-actions', + title: 'Addon/addon-actions', }; export const withText = () => ( diff --git a/examples/rax-kitchen-sink/src/stories/addon-centered.stories.js b/examples/rax-kitchen-sink/src/stories/addon-centered.stories.js index e28ff40f04b..2e0eebf1305 100644 --- a/examples/rax-kitchen-sink/src/stories/addon-centered.stories.js +++ b/examples/rax-kitchen-sink/src/stories/addon-centered.stories.js @@ -4,7 +4,7 @@ import Text from 'rax-text'; import App from '../components/App'; export default { - title: 'Addon|addon-centered', + title: 'Addon/addon-centered', decorators: [Centered], }; diff --git a/examples/rax-kitchen-sink/src/stories/addon-jest.stories.js b/examples/rax-kitchen-sink/src/stories/addon-jest.stories.js index a12843c6ea2..3d350d1cde5 100644 --- a/examples/rax-kitchen-sink/src/stories/addon-jest.stories.js +++ b/examples/rax-kitchen-sink/src/stories/addon-jest.stories.js @@ -6,7 +6,7 @@ import Welcome from '../components/Welcome'; import results from '../../jest-test-results.json'; export default { - title: 'Addon|addon-jest', + title: 'Addon/addon-jest', decorators: [withTests({ results })], }; diff --git a/examples/rax-kitchen-sink/src/stories/addon-knobs.stories.js b/examples/rax-kitchen-sink/src/stories/addon-knobs.stories.js index af84931e473..2775c44adf5 100644 --- a/examples/rax-kitchen-sink/src/stories/addon-knobs.stories.js +++ b/examples/rax-kitchen-sink/src/stories/addon-knobs.stories.js @@ -4,7 +4,7 @@ import { withKnobs, text, boolean, number } from '@storybook/addon-knobs'; import Text from 'rax-text'; export default { - title: 'Addon|addon-knobs', + title: 'Addon/addon-knobs', decorators: [withKnobs], }; diff --git a/examples/rax-kitchen-sink/src/stories/addon-notes.stories.js b/examples/rax-kitchen-sink/src/stories/addon-notes.stories.js index fd70ef90343..b4b4c85dca1 100644 --- a/examples/rax-kitchen-sink/src/stories/addon-notes.stories.js +++ b/examples/rax-kitchen-sink/src/stories/addon-notes.stories.js @@ -4,7 +4,7 @@ import Text from 'rax-text'; import markdown from './note.md'; export default { - title: 'Addon|addon-notes', + title: 'Addon/addon-notes', decorators: [withNotes], }; diff --git a/examples/riot-kitchen-sink/.storybook/config.js b/examples/riot-kitchen-sink/.storybook/config.js index 1cafda7d7d6..ed71c4a8b74 100644 --- a/examples/riot-kitchen-sink/.storybook/config.js +++ b/examples/riot-kitchen-sink/.storybook/config.js @@ -4,7 +4,7 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); addParameters({ options: { - hierarchyRootSeparator: /\|/, + showRoots: true, }, }); diff --git a/examples/riot-kitchen-sink/package.json b/examples/riot-kitchen-sink/package.json index 3f7dfb07743..75f9c0a66b2 100644 --- a/examples/riot-kitchen-sink/package.json +++ b/examples/riot-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "riot-example", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", @@ -15,20 +15,20 @@ }, "devDependencies": { "@babel/core": "^7.3.4", - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/riot": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/riot": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", "babel-loader": "^8.0.4", "cross-env": "^6.0.3", "file-loader": "^4.2.0", diff --git a/examples/riot-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot b/examples/riot-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot index dfdfc9a794f..d45cb2881b2 100644 --- a/examples/riot-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot +++ b/examples/riot-kitchen-sink/src/stories/__snapshots__/addon-actions.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Actions Action Only 1`] = ` +exports[`Storyshots Addon/Actions Action only 1`] = `
`; -exports[`Storyshots Addon|Actions Multiple Actions 1`] = ` +exports[`Storyshots Addon/Actions Multiple actions 1`] = `
`; -exports[`Storyshots Addon|Backgrounds Story 2 1`] = ` +exports[`Storyshots Addon/Backgrounds story 2 1`] = `
`; -exports[`Storyshots Addon|Knobs Simple 1`] = ` +exports[`Storyshots Addon/Knobs Simple 1`] = `
`; -exports[`Storyshots Addon|Knobs Xss Safety 1`] = ` +exports[`Storyshots Addon/Knobs XSS safety 1`] = `
`; -exports[`Storyshots Addon|Notes Simple Note 1`] = ` +exports[`Storyshots Addon/Notes Simple note 1`] = `
- Parameters are {"options":{"hierarchyRootSeparator":{},"hierarchySeparator":{}},"docs":{},"globalParameter":"globalParameter","framework":"riot","chapterParameter":"chapterParameter","displayName":"passed to story","storyParameter":"storyParameter","id":"root","dataIs":"parameters"} + Parameters are {"options":{"showRoots":true},"docs":{},"globalParameter":"globalParameter","framework":"riot","chapterParameter":"chapterParameter","__id":"core-parameters--passed-to-story","storyParameter":"storyParameter","id":"root","dataIs":"parameters"}
`; diff --git a/examples/riot-kitchen-sink/src/stories/__snapshots__/nested-tags.stories.storyshot b/examples/riot-kitchen-sink/src/stories/__snapshots__/nested-tags.stories.storyshot index 5840eda50c9..c571daeaacd 100644 --- a/examples/riot-kitchen-sink/src/stories/__snapshots__/nested-tags.stories.storyshot +++ b/examples/riot-kitchen-sink/src/stories/__snapshots__/nested-tags.stories.storyshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Story|Nest tags Matriochka 1`] = ` +exports[`Storyshots Story/Nest tags Matriochka 1`] = `
`; -exports[`Storyshots Story|Nest tags Three Tags 1`] = ` +exports[`Storyshots Story/Nest tags Three tags 1`] = `
`; -exports[`Storyshots Story|How to create a story Built From Raw Import 1`] = ` +exports[`Storyshots Story/How to create a story built from raw import 1`] = `
`; -exports[`Storyshots Story|How to create a story Built From Tags And Template 1`] = ` +exports[`Storyshots Story/How to create a story built from tags and template 1`] = `
`; -exports[`Storyshots Story|How to create a story Built From The Precompilation 1`] = ` +exports[`Storyshots Story/How to create a story built from the precompilation 1`] = `
`; -exports[`Storyshots Story|How to create a story Built With Tag 1`] = ` +exports[`Storyshots Story/How to create a story built with tag 1`] = `
`; -exports[`Storyshots Story|How to create a story Tags Template And Tag Constructor At Once 1`] = ` +exports[`Storyshots Story/How to create a story tags, template and tagConstructor at once 1`] = `
`; -exports[`Storyshots Story|How to create a story The Mount Instruction Is Not Necessary 1`] = ` +exports[`Storyshots Story/How to create a story the mount instruction is not necessary 1`] = `
`; -exports[`Storyshots Story|How to create a story The Opts Value Is Not Necessary 1`] = ` +exports[`Storyshots Story/How to create a story the opts value is not necessary 1`] = `
diff --git a/examples/riot-kitchen-sink/src/stories/addon-backgrounds.stories.js b/examples/riot-kitchen-sink/src/stories/addon-backgrounds.stories.js index eac0791294f..9c5ba032ab4 100644 --- a/examples/riot-kitchen-sink/src/stories/addon-backgrounds.stories.js +++ b/examples/riot-kitchen-sink/src/stories/addon-backgrounds.stories.js @@ -1,7 +1,7 @@ import ButtonRaw from './Button.txt'; export default { - title: 'Addon|Backgrounds', + title: 'Addon/Backgrounds', parameters: { backgrounds: [ { name: 'light', value: '#eeeeee' }, diff --git a/examples/riot-kitchen-sink/src/stories/addon-knobs.stories.js b/examples/riot-kitchen-sink/src/stories/addon-knobs.stories.js index 9b44ceb8bdf..de49663bb51 100644 --- a/examples/riot-kitchen-sink/src/stories/addon-knobs.stories.js +++ b/examples/riot-kitchen-sink/src/stories/addon-knobs.stories.js @@ -12,7 +12,7 @@ import { } from '@storybook/addon-knobs'; export default { - title: 'Addon|Knobs', + title: 'Addon/Knobs', decorators: [withKnobs], }; diff --git a/examples/riot-kitchen-sink/src/stories/addon-links.stories.js b/examples/riot-kitchen-sink/src/stories/addon-links.stories.js index 56af1084748..a372d6a5b46 100644 --- a/examples/riot-kitchen-sink/src/stories/addon-links.stories.js +++ b/examples/riot-kitchen-sink/src/stories/addon-links.stories.js @@ -5,7 +5,7 @@ import ButtonRaw from './Button.txt'; compileNow(ButtonRaw); export default { - title: 'Addon|Links', + title: 'Addon/Links', }; export const goToWelcome = () => diff --git a/examples/riot-kitchen-sink/src/stories/addon-notes.stories.js b/examples/riot-kitchen-sink/src/stories/addon-notes.stories.js index c0fb1912040..1b20fdc4830 100644 --- a/examples/riot-kitchen-sink/src/stories/addon-notes.stories.js +++ b/examples/riot-kitchen-sink/src/stories/addon-notes.stories.js @@ -1,5 +1,5 @@ export default { - title: 'Addon|Notes', + title: 'Addon/Notes', }; export const simpleNote = () => ({ diff --git a/examples/riot-kitchen-sink/src/stories/core.stories.js b/examples/riot-kitchen-sink/src/stories/core.stories.js index 9ffa8d32b53..f34fbb36779 100644 --- a/examples/riot-kitchen-sink/src/stories/core.stories.js +++ b/examples/riot-kitchen-sink/src/stories/core.stories.js @@ -9,7 +9,7 @@ tag('parameters', '
Parameters are {JSON.stringify (this.opts)}
', '', addParameters({ globalParameter }); export default { - title: 'Core|Parameters', + title: 'Core/Parameters', parameters: { chapterParameter, }, diff --git a/examples/riot-kitchen-sink/src/stories/nested-tags.stories.js b/examples/riot-kitchen-sink/src/stories/nested-tags.stories.js index 3664f40bb5c..f6180cb8689 100644 --- a/examples/riot-kitchen-sink/src/stories/nested-tags.stories.js +++ b/examples/riot-kitchen-sink/src/stories/nested-tags.stories.js @@ -5,7 +5,7 @@ import './AnotherTest.tag'; const simpleTestCompiled = asCompiledCode(SimpleTestRaw); export default { - title: 'Story|Nest tags', + title: 'Story/Nest tags', }; export const threeTags = () => ({ diff --git a/examples/riot-kitchen-sink/src/stories/story-code.stories.js b/examples/riot-kitchen-sink/src/stories/story-code.stories.js index da34681f8b0..49a3ab6e535 100644 --- a/examples/riot-kitchen-sink/src/stories/story-code.stories.js +++ b/examples/riot-kitchen-sink/src/stories/story-code.stories.js @@ -5,7 +5,7 @@ import './AnotherTest.tag'; const simpleTestCompiled = asCompiledCode(SimpleTestRaw); export default { - title: 'Story|How to create a story', + title: 'Story/How to create a story', }; export const builtWithTag = () => diff --git a/examples/standalone-preview/package.json b/examples/standalone-preview/package.json index 3a328d9f962..e647a3a3dd6 100644 --- a/examples/standalone-preview/package.json +++ b/examples/standalone-preview/package.json @@ -1,12 +1,12 @@ { "name": "standalone-preview", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "storybook": "parcel ./storybook.html --port 1337" }, "devDependencies": { - "@storybook/react": "5.3.0-alpha.41", + "@storybook/react": "5.3.0-beta.2", "parcel": "^1.12.3", "react": "^16.8.4", "react-dom": "^16.8.4" diff --git a/examples/svelte-kitchen-sink/.storybook/config.js b/examples/svelte-kitchen-sink/.storybook/config.js index bd76665f9cb..fa4f691f63b 100644 --- a/examples/svelte-kitchen-sink/.storybook/config.js +++ b/examples/svelte-kitchen-sink/.storybook/config.js @@ -4,7 +4,7 @@ import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); addParameters({ options: { - hierarchyRootSeparator: /\|/, + showRoots: true, }, }); diff --git a/examples/svelte-kitchen-sink/package.json b/examples/svelte-kitchen-sink/package.json index 75559be0491..4901df9c340 100644 --- a/examples/svelte-kitchen-sink/package.json +++ b/examples/svelte-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "svelte-example", - "version": "5.3.0-alpha.41", + "version": "5.3.0-beta.2", "private": true, "scripts": { "build-storybook": "build-storybook -s public", @@ -10,19 +10,19 @@ "global": "^4.3.2" }, "devDependencies": { - "@storybook/addon-a11y": "5.3.0-alpha.41", - "@storybook/addon-actions": "5.3.0-alpha.41", - "@storybook/addon-backgrounds": "5.3.0-alpha.41", - "@storybook/addon-centered": "5.3.0-alpha.41", - "@storybook/addon-knobs": "5.3.0-alpha.41", - "@storybook/addon-links": "5.3.0-alpha.41", - "@storybook/addon-notes": "5.3.0-alpha.41", - "@storybook/addon-options": "5.3.0-alpha.41", - "@storybook/addon-storyshots": "5.3.0-alpha.41", - "@storybook/addon-storysource": "5.3.0-alpha.41", - "@storybook/addon-viewport": "5.3.0-alpha.41", - "@storybook/addons": "5.3.0-alpha.41", - "@storybook/source-loader": "5.3.0-alpha.41", - "@storybook/svelte": "5.3.0-alpha.41" + "@storybook/addon-a11y": "5.3.0-beta.2", + "@storybook/addon-actions": "5.3.0-beta.2", + "@storybook/addon-backgrounds": "5.3.0-beta.2", + "@storybook/addon-centered": "5.3.0-beta.2", + "@storybook/addon-knobs": "5.3.0-beta.2", + "@storybook/addon-links": "5.3.0-beta.2", + "@storybook/addon-notes": "5.3.0-beta.2", + "@storybook/addon-options": "5.3.0-beta.2", + "@storybook/addon-storyshots": "5.3.0-beta.2", + "@storybook/addon-storysource": "5.3.0-beta.2", + "@storybook/addon-viewport": "5.3.0-beta.2", + "@storybook/addons": "5.3.0-beta.2", + "@storybook/source-loader": "5.3.0-beta.2", + "@storybook/svelte": "5.3.0-beta.2" } } diff --git a/examples/svelte-kitchen-sink/src/components/Button.svelte b/examples/svelte-kitchen-sink/src/components/Button.svelte index 43a8cf854d1..6e69c974368 100644 --- a/examples/svelte-kitchen-sink/src/components/Button.svelte +++ b/examples/svelte-kitchen-sink/src/components/Button.svelte @@ -22,7 +22,6 @@