From ade44956e8773485cec2e32efdf8ef027eb23634 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Tue, 24 Apr 2018 18:58:51 -0700 Subject: [PATCH 1/9] initial --- addons/background/src/vue.js | 1 + examples/vue-kitchen-sink/package.json | 1 + 2 files changed, 2 insertions(+) create mode 100644 addons/background/src/vue.js diff --git a/addons/background/src/vue.js b/addons/background/src/vue.js new file mode 100644 index 000000000000..8fea6fbb10c5 --- /dev/null +++ b/addons/background/src/vue.js @@ -0,0 +1 @@ +import Vue from 'vue'; diff --git a/examples/vue-kitchen-sink/package.json b/examples/vue-kitchen-sink/package.json index 39cf8102cfcb..c81f18653bdf 100644 --- a/examples/vue-kitchen-sink/package.json +++ b/examples/vue-kitchen-sink/package.json @@ -14,6 +14,7 @@ }, "devDependencies": { "@storybook/addon-actions": "4.0.0-alpha.3", + "@storybook/addon-backgrounds": "4.0.0-alpha.3", "@storybook/addon-centered": "4.0.0-alpha.3", "@storybook/addon-knobs": "4.0.0-alpha.3", "@storybook/addon-links": "4.0.0-alpha.3", From f27e8b44e47e55f11665b547428aa8d3aa5d4292 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Tue, 24 Apr 2018 18:59:24 -0700 Subject: [PATCH 2/9] eslint --- addons/background/src/vue.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/background/src/vue.js b/addons/background/src/vue.js index 8fea6fbb10c5..8b4aa26e9f12 100644 --- a/addons/background/src/vue.js +++ b/addons/background/src/vue.js @@ -1 +1,2 @@ +// eslint-disable-next-line import/no-extraneous-dependencies import Vue from 'vue'; From b3a703c527823e321260e68d81aa816f0f6ed8a4 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Wed, 25 Apr 2018 00:19:16 -0700 Subject: [PATCH 3/9] vue background --- addons/background/src/vue.js | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/addons/background/src/vue.js b/addons/background/src/vue.js index 8b4aa26e9f12..a91e7c28604e 100644 --- a/addons/background/src/vue.js +++ b/addons/background/src/vue.js @@ -1,2 +1,28 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import Vue from 'vue'; +import addons from '@storybook/addons'; + +const vueHandler = (channel, backgrounds) => (getStory, context) => ({ + data() { + return { + context, + getStory, + story: getStory(context), + }; + }, + + render(h) { + return h(this.story); + }, + + created() { + channel.emit('background-set', backgrounds); + }, + + beforeDestroy() { + channel.emit('background-unset'); + }, +}); + +export default function makeDecorator(backgrounds) { + const channel = addons.getChannel(); + return vueHandler(channel, backgrounds); +} From 1997ec599e7115cdc3b89425152c8b517c90e534 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Wed, 25 Apr 2018 00:19:38 -0700 Subject: [PATCH 4/9] refactor exports --- addons/background/src/index.js | 69 +++------------------------------- addons/background/src/react.js | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 64 deletions(-) create mode 100644 addons/background/src/react.js diff --git a/addons/background/src/index.js b/addons/background/src/index.js index 3fdf626475b4..cc18cbf1aa8e 100644 --- a/addons/background/src/index.js +++ b/addons/background/src/index.js @@ -1,66 +1,7 @@ -import React from 'react'; -import { polyfill } from 'react-lifecycles-compat'; -import PropTypes from 'prop-types'; +import { window } from 'global'; +import ReactBackground from './react'; +import VueBackground from './vue'; -import addons from '@storybook/addons'; +const Background = window.STORYBOOK_ENV === 'vue' ? VueBackground : ReactBackground; -export class BackgroundDecorator extends React.Component { - constructor(props) { - super(props); - - const { channel } = props; - - // A channel is explicitly passed in for testing - if (channel) { - this.channel = channel; - } else { - this.channel = addons.getChannel(); - } - - this.state = {}; - } - - componentDidMount() { - this.channel.emit('background-set', this.props.backgrounds); - } - - componentWillUnmount() { - this.channel.emit('background-unset'); - } - - render() { - return this.state.story; - } -} - -BackgroundDecorator.getDerivedStateFromProps = ({ story }, { prevStory }) => { - if (story !== prevStory) { - return { - story: story(), - prevStory: story, - }; - } - return null; -}; - -BackgroundDecorator.propTypes = { - backgrounds: PropTypes.arrayOf(PropTypes.object), - channel: PropTypes.shape({ - emit: PropTypes.func, - on: PropTypes.func, - removeListener: PropTypes.func, - }), - // eslint-disable-next-line react/no-unused-prop-types - story: PropTypes.func.isRequired, -}; - -BackgroundDecorator.defaultProps = { - backgrounds: [], - channel: undefined, -}; - -polyfill(BackgroundDecorator); - -export default backgrounds => story => ( - -); +export default Background; diff --git a/addons/background/src/react.js b/addons/background/src/react.js new file mode 100644 index 000000000000..3fdf626475b4 --- /dev/null +++ b/addons/background/src/react.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { polyfill } from 'react-lifecycles-compat'; +import PropTypes from 'prop-types'; + +import addons from '@storybook/addons'; + +export class BackgroundDecorator extends React.Component { + constructor(props) { + super(props); + + const { channel } = props; + + // A channel is explicitly passed in for testing + if (channel) { + this.channel = channel; + } else { + this.channel = addons.getChannel(); + } + + this.state = {}; + } + + componentDidMount() { + this.channel.emit('background-set', this.props.backgrounds); + } + + componentWillUnmount() { + this.channel.emit('background-unset'); + } + + render() { + return this.state.story; + } +} + +BackgroundDecorator.getDerivedStateFromProps = ({ story }, { prevStory }) => { + if (story !== prevStory) { + return { + story: story(), + prevStory: story, + }; + } + return null; +}; + +BackgroundDecorator.propTypes = { + backgrounds: PropTypes.arrayOf(PropTypes.object), + channel: PropTypes.shape({ + emit: PropTypes.func, + on: PropTypes.func, + removeListener: PropTypes.func, + }), + // eslint-disable-next-line react/no-unused-prop-types + story: PropTypes.func.isRequired, +}; + +BackgroundDecorator.defaultProps = { + backgrounds: [], + channel: undefined, +}; + +polyfill(BackgroundDecorator); + +export default backgrounds => story => ( + +); From 86ca14adf754040acf82acea58eb37be3dafeebc Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Wed, 25 Apr 2018 00:19:55 -0700 Subject: [PATCH 5/9] update README and updated examples --- addons/background/README.md | 22 +++++++++++++++++ .../vue-kitchen-sink/.storybook/addons.js | 1 + .../src/stories/addon-backgrounds.stories.js | 24 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js diff --git a/addons/background/README.md b/addons/background/README.md index 55f0146e95b4..a0ae78a76bdb 100644 --- a/addons/background/README.md +++ b/addons/background/README.md @@ -70,6 +70,28 @@ storiesOf("Button", module) .add("with text", () => ); ``` +In the case of Vue, use it similarly to React! + +```js +import { storiesOf } from '@storybook/vue'; +import backgrounds from '@storybook/addon-backgrounds'; + +storiesOf('Addon|Backgrounds', module) + .addDecorator( + backgrounds([ + { name: 'twitter', value: '#00aced' }, + { name: 'facebook', value: '#3b5998', default: true }, + ]) + ) + .add('story 1', () => { + const content = 'You should be able to switch backgrounds for this story'; + + return { + template: ``, + }; + }) +``` + > In the case of Mithril, use these imports: > > ```js diff --git a/examples/vue-kitchen-sink/.storybook/addons.js b/examples/vue-kitchen-sink/.storybook/addons.js index d6145bf315b8..ff96ea46a3bd 100644 --- a/examples/vue-kitchen-sink/.storybook/addons.js +++ b/examples/vue-kitchen-sink/.storybook/addons.js @@ -5,3 +5,4 @@ import '@storybook/addon-notes/register'; import '@storybook/addon-knobs/register'; import '@storybook/addon-viewport/register'; import '@storybook/addon-options/register'; +import '@storybook/addon-backgrounds/register'; diff --git a/examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js b/examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js new file mode 100644 index 000000000000..3621cf9d65d7 --- /dev/null +++ b/examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js @@ -0,0 +1,24 @@ +import { storiesOf } from '@storybook/vue'; +import backgrounds from '@storybook/addon-backgrounds'; + +storiesOf('Addon|Backgrounds', module) + .addDecorator( + backgrounds([ + { name: 'twitter', value: '#00aced' }, + { name: 'facebook', value: '#3b5998', default: true }, + ]) + ) + .add('story 1', () => { + const content = 'You should be able to switch backgrounds for this story'; + + return { + template: ``, + }; + }) + .add('story 2', () => { + const content = 'This one too!'; + + return { + template: ``, + }; + }); From 48b27e7fa9cc67a2883e43c43a8fbba0fbba0428 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Wed, 25 Apr 2018 00:36:54 -0700 Subject: [PATCH 6/9] update + add tests --- addons/background/package.json | 3 ++ .../src/__tests__/{index.js => react.js} | 2 +- addons/background/src/__tests__/vue.js | 42 +++++++++++++++++++ addons/background/src/vue.js | 2 +- 4 files changed, 47 insertions(+), 2 deletions(-) rename addons/background/src/__tests__/{index.js => react.js} (97%) create mode 100644 addons/background/src/__tests__/vue.js diff --git a/addons/background/package.json b/addons/background/package.json index 78d7dd0a795f..7f15251b7133 100644 --- a/addons/background/package.json +++ b/addons/background/package.json @@ -30,6 +30,9 @@ "prop-types": "^15.6.1", "react-lifecycles-compat": "^3.0.2" }, + "devDependencies": { + "vue": "^2.5.16" + }, "peerDependencies": { "react": "*" } diff --git a/addons/background/src/__tests__/index.js b/addons/background/src/__tests__/react.js similarity index 97% rename from addons/background/src/__tests__/index.js rename to addons/background/src/__tests__/react.js index 1a3fdb5c52f4..5bfd67fcba6c 100644 --- a/addons/background/src/__tests__/index.js +++ b/addons/background/src/__tests__/react.js @@ -1,7 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { BackgroundDecorator } from '../index'; +import { BackgroundDecorator } from '../react'; const EventEmitter = require('events'); diff --git a/addons/background/src/__tests__/vue.js b/addons/background/src/__tests__/vue.js new file mode 100644 index 000000000000..8cad3d7a4914 --- /dev/null +++ b/addons/background/src/__tests__/vue.js @@ -0,0 +1,42 @@ +import Vue from 'vue'; +import { vueHandler } from '../vue'; + +describe('Vue handler', () => { + it('Returns a component with a created function', () => { + const testChannel = { emit: jest.fn() }; + const testStory = () => ({ template: '
testStory
' }); + const testContext = { + kind: 'Foo', + story: 'bar baz', + }; + const testBackground = [ + { name: 'twitter', value: '#00aced' }, + { name: 'facebook', value: '#3b5998', default: true }, + ]; + const component = vueHandler(testChannel, testBackground)(testStory, testContext); + + expect(component).toMatchObject({ + created: expect.any(Function), + beforeDestroy: expect.any(Function), + render: expect.any(Function), + }); + }); + + it('Subscribes to the channel on creation', () => { + const testChannel = { emit: jest.fn() }; + const testStory = () => ({ render: h => h('div', ['testStory']) }); + const testContext = { + kind: 'Foo', + story: 'bar baz', + }; + const testBackground = [ + { name: 'twitter', value: '#00aced' }, + { name: 'facebook', value: '#3b5998', default: true }, + ]; + + new Vue(vueHandler(testChannel, testBackground)(testStory, testContext)).$mount(); + + expect(testChannel.emit).toHaveBeenCalledTimes(1); + expect(testChannel.emit).toHaveBeenCalledWith('background-set', expect.any(Array)); + }); +}); diff --git a/addons/background/src/vue.js b/addons/background/src/vue.js index a91e7c28604e..8fb578c0d05e 100644 --- a/addons/background/src/vue.js +++ b/addons/background/src/vue.js @@ -1,6 +1,6 @@ import addons from '@storybook/addons'; -const vueHandler = (channel, backgrounds) => (getStory, context) => ({ +export const vueHandler = (channel, backgrounds) => (getStory, context) => ({ data() { return { context, From 460aa29626e042bb57fd8569abffd879b9738ec8 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Wed, 25 Apr 2018 00:37:04 -0700 Subject: [PATCH 7/9] update storyshot --- .../addon-backgrounds.stories.storyshot | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 examples/vue-kitchen-sink/src/stories/__snapshots__/addon-backgrounds.stories.storyshot diff --git a/examples/vue-kitchen-sink/src/stories/__snapshots__/addon-backgrounds.stories.storyshot b/examples/vue-kitchen-sink/src/stories/__snapshots__/addon-backgrounds.stories.storyshot new file mode 100644 index 000000000000..085173afdc95 --- /dev/null +++ b/examples/vue-kitchen-sink/src/stories/__snapshots__/addon-backgrounds.stories.storyshot @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots Addon|Backgrounds story 1 1`] = ` + +`; + +exports[`Storyshots Addon|Backgrounds story 2 1`] = ` + +`; From 8f5755c10cedd0edec19b5e0c1a4ffc4f1a3acb7 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Thu, 26 Apr 2018 01:02:50 -0700 Subject: [PATCH 8/9] vue export, tests + docs --- addons/background/README.md | 29 ++------ addons/background/src/__tests__/react.js | 2 +- addons/background/src/index.js | 69 +++++++++++++++++-- addons/background/src/react.js | 66 ------------------ addons/background/vue.js | 1 + .../src/stories/addon-backgrounds.stories.js | 2 +- 6 files changed, 74 insertions(+), 95 deletions(-) delete mode 100644 addons/background/src/react.js create mode 100644 addons/background/vue.js diff --git a/addons/background/README.md b/addons/background/README.md index a0ae78a76bdb..cecda21cfecd 100644 --- a/addons/background/README.md +++ b/addons/background/README.md @@ -70,31 +70,16 @@ storiesOf("Button", module) .add("with text", () => ); ``` -In the case of Vue, use it similarly to React! - -```js -import { storiesOf } from '@storybook/vue'; -import backgrounds from '@storybook/addon-backgrounds'; - -storiesOf('Addon|Backgrounds', module) - .addDecorator( - backgrounds([ - { name: 'twitter', value: '#00aced' }, - { name: 'facebook', value: '#3b5998', default: true }, - ]) - ) - .add('story 1', () => { - const content = 'You should be able to switch backgrounds for this story'; - - return { - template: ``, - }; - }) -``` - > In the case of Mithril, use these imports: > > ```js > import { storiesOf } from '@storybook/mithril'; > import backgrounds from "@storybook/addon-backgrounds/mithril"; > ``` + +> In the case of Vue, use these imports: +> +> ```js +> import { storiesOf } from '@storybook/vue'; +> import backgrounds from "@storybook/addon-backgrounds/vue"; +> ``` diff --git a/addons/background/src/__tests__/react.js b/addons/background/src/__tests__/react.js index 5bfd67fcba6c..1a3fdb5c52f4 100644 --- a/addons/background/src/__tests__/react.js +++ b/addons/background/src/__tests__/react.js @@ -1,7 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { BackgroundDecorator } from '../react'; +import { BackgroundDecorator } from '../index'; const EventEmitter = require('events'); diff --git a/addons/background/src/index.js b/addons/background/src/index.js index cc18cbf1aa8e..3fdf626475b4 100644 --- a/addons/background/src/index.js +++ b/addons/background/src/index.js @@ -1,7 +1,66 @@ -import { window } from 'global'; -import ReactBackground from './react'; -import VueBackground from './vue'; +import React from 'react'; +import { polyfill } from 'react-lifecycles-compat'; +import PropTypes from 'prop-types'; -const Background = window.STORYBOOK_ENV === 'vue' ? VueBackground : ReactBackground; +import addons from '@storybook/addons'; -export default Background; +export class BackgroundDecorator extends React.Component { + constructor(props) { + super(props); + + const { channel } = props; + + // A channel is explicitly passed in for testing + if (channel) { + this.channel = channel; + } else { + this.channel = addons.getChannel(); + } + + this.state = {}; + } + + componentDidMount() { + this.channel.emit('background-set', this.props.backgrounds); + } + + componentWillUnmount() { + this.channel.emit('background-unset'); + } + + render() { + return this.state.story; + } +} + +BackgroundDecorator.getDerivedStateFromProps = ({ story }, { prevStory }) => { + if (story !== prevStory) { + return { + story: story(), + prevStory: story, + }; + } + return null; +}; + +BackgroundDecorator.propTypes = { + backgrounds: PropTypes.arrayOf(PropTypes.object), + channel: PropTypes.shape({ + emit: PropTypes.func, + on: PropTypes.func, + removeListener: PropTypes.func, + }), + // eslint-disable-next-line react/no-unused-prop-types + story: PropTypes.func.isRequired, +}; + +BackgroundDecorator.defaultProps = { + backgrounds: [], + channel: undefined, +}; + +polyfill(BackgroundDecorator); + +export default backgrounds => story => ( + +); diff --git a/addons/background/src/react.js b/addons/background/src/react.js deleted file mode 100644 index 3fdf626475b4..000000000000 --- a/addons/background/src/react.js +++ /dev/null @@ -1,66 +0,0 @@ -import React from 'react'; -import { polyfill } from 'react-lifecycles-compat'; -import PropTypes from 'prop-types'; - -import addons from '@storybook/addons'; - -export class BackgroundDecorator extends React.Component { - constructor(props) { - super(props); - - const { channel } = props; - - // A channel is explicitly passed in for testing - if (channel) { - this.channel = channel; - } else { - this.channel = addons.getChannel(); - } - - this.state = {}; - } - - componentDidMount() { - this.channel.emit('background-set', this.props.backgrounds); - } - - componentWillUnmount() { - this.channel.emit('background-unset'); - } - - render() { - return this.state.story; - } -} - -BackgroundDecorator.getDerivedStateFromProps = ({ story }, { prevStory }) => { - if (story !== prevStory) { - return { - story: story(), - prevStory: story, - }; - } - return null; -}; - -BackgroundDecorator.propTypes = { - backgrounds: PropTypes.arrayOf(PropTypes.object), - channel: PropTypes.shape({ - emit: PropTypes.func, - on: PropTypes.func, - removeListener: PropTypes.func, - }), - // eslint-disable-next-line react/no-unused-prop-types - story: PropTypes.func.isRequired, -}; - -BackgroundDecorator.defaultProps = { - backgrounds: [], - channel: undefined, -}; - -polyfill(BackgroundDecorator); - -export default backgrounds => story => ( - -); diff --git a/addons/background/vue.js b/addons/background/vue.js new file mode 100644 index 000000000000..42311b17563f --- /dev/null +++ b/addons/background/vue.js @@ -0,0 +1 @@ +module.exports = require('./dist/vue'); diff --git a/examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js b/examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js index 3621cf9d65d7..aacee49f3522 100644 --- a/examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js +++ b/examples/vue-kitchen-sink/src/stories/addon-backgrounds.stories.js @@ -1,5 +1,5 @@ import { storiesOf } from '@storybook/vue'; -import backgrounds from '@storybook/addon-backgrounds'; +import backgrounds from '@storybook/addon-backgrounds/vue'; storiesOf('Addon|Backgrounds', module) .addDecorator( From a24fc429faf802a7859604d5b63b917328435721 Mon Sep 17 00:00:00 2001 From: Wei-Wei Wu Date: Thu, 26 Apr 2018 01:04:47 -0700 Subject: [PATCH 9/9] undo rename --- addons/background/src/__tests__/{react.js => index.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename addons/background/src/__tests__/{react.js => index.js} (100%) diff --git a/addons/background/src/__tests__/react.js b/addons/background/src/__tests__/index.js similarity index 100% rename from addons/background/src/__tests__/react.js rename to addons/background/src/__tests__/index.js