From 8f34761d4fa1f9f1a25ae2a51bf19ca0bd995110 Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Tue, 2 Aug 2016 13:37:34 +0530 Subject: [PATCH 1/8] Update Storybook UI --- dist/client/channel.js | 68 +++++++++++++++++++++++++++++++++ dist/client/manager/provider.js | 51 +++++++++++-------------- package.json | 5 ++- src/client/channel.js | 30 +++++++++++++++ src/client/manager/provider.js | 42 ++++++++------------ 5 files changed, 139 insertions(+), 57 deletions(-) create mode 100644 dist/client/channel.js create mode 100644 src/client/channel.js diff --git a/dist/client/channel.js b/dist/client/channel.js new file mode 100644 index 000000000000..03d988a4e660 --- /dev/null +++ b/dist/client/channel.js @@ -0,0 +1,68 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = require('babel-runtime/core-js/json/stringify'); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _uuid = require('uuid'); + +var _uuid2 = _interopRequireDefault(_uuid); + +var _pageBus = require('page-bus'); + +var _pageBus2 = _interopRequireDefault(_pageBus); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Channel = function () { + function Channel(dataId) { + (0, _classCallCheck3.default)(this, Channel); + + this._dataId = dataId || _uuid2.default.v4(); + this._pageBus = (0, _pageBus2.default)(); + this._listeners = {}; + } + + (0, _createClass3.default)(Channel, [{ + key: 'getDataId', + value: function getDataId() { + return this._dataId; + } + }, { + key: 'on', + value: function on(type, handler) { + var listener = function listener(p) { + return handler(JSON.parse(p)); + }; + // TODO add listener to a map[handler]listener + this._pageBus.on(this._dataId + '.' + type, listener); + } + }, { + key: 'emit', + value: function emit(type, data) { + var payload = (0, _stringify2.default)(data); + this._pageBus.emit(this._dataId + '.' + type, payload); + } + }, { + key: 'removeListener', + value: function removeListener(type, handler) { + // TODO get listener from a map[handler]listener + // this._pageBus.removeListener(type, listener); + } + }]); + return Channel; +}(); + +exports.default = Channel; \ No newline at end of file diff --git a/dist/client/manager/provider.js b/dist/client/manager/provider.js index bf8d4fed38c4..a29205a99df3 100644 --- a/dist/client/manager/provider.js +++ b/dist/client/manager/provider.js @@ -4,10 +4,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); -var _stringify = require('babel-runtime/core-js/json/stringify'); - -var _stringify2 = _interopRequireDefault(_stringify); - var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); @@ -50,6 +46,14 @@ var _pageBus2 = _interopRequireDefault(_pageBus); var _storybookUi = require('@kadira/storybook-ui'); +var _storybookAddons = require('@kadira/storybook-addons'); + +var _storybookAddons2 = _interopRequireDefault(_storybookAddons); + +var _channel = require('../channel'); + +var _channel2 = _interopRequireDefault(_channel); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ReactProvider = function (_Provider) { @@ -60,15 +64,21 @@ var ReactProvider = function (_Provider) { var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(ReactProvider).call(this)); - _this.dataId = _uuid2.default.v4(); + _this.channel = new _channel2.default(); + _storybookAddons2.default.setChannel(_this.channel); return _this; } (0, _createClass3.default)(ReactProvider, [{ + key: 'getPanels', + value: function getPanels() { + return _storybookAddons2.default.getPanels(); + } + }, { key: 'renderPreview', value: function renderPreview(selectedKind, selectedStory) { var queryParams = { - dataId: this.dataId, + dataId: this.channel.getDataId(), selectedKind: selectedKind, selectedStory: selectedStory }; @@ -80,38 +90,21 @@ var ReactProvider = function (_Provider) { }, { key: 'handleAPI', value: function handleAPI(api) { - var dataId = this.dataId; - var bus = (0, _pageBus2.default)(); + var _this2 = this; api.onStory(function (kind, story) { - var payload = { - kind: kind, - story: story - }; - - bus.emit(dataId + '.setCurrentStory', (0, _stringify2.default)(payload)); - }); - - // watch pageBus and put both actions and stories. - bus.on(dataId + '.addAction', function (payload) { - var data = JSON.parse(payload); - api.addAction(data.action); + _this2.channel.emit('setCurrentStory', { kind: kind, story: story }); }); - - bus.on(dataId + '.setStories', function (payload) { - var data = JSON.parse(payload); + this.channel.on('setStories', function (data) { api.setStories(data.stories); }); - - bus.on(dataId + '.selectStory', function (payload) { - var data = JSON.parse(payload); + this.channel.on('selectStory', function (data) { api.selectStory(data.kind, data.story); }); - - bus.on(dataId + '.applyShortcut', function (payload) { - var data = JSON.parse(payload); + this.channel.on('applyShortcut', function (data) { api.handleShortcut(data.event); }); + _storybookAddons2.default.loadAddons(api); } }]); return ReactProvider; diff --git a/package.json b/package.json index ab290bc9060f..94bb58b82f95 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,10 @@ }, "dependencies": { "@kadira/react-split-pane": "^1.4.0", - "@kadira/storybook-ui": "^2.6.1", + "@kadira/storybook-addon-actions": "^1.0.2", + "@kadira/storybook-addon-links": "^1.0.0", + "@kadira/storybook-addons": "^1.3.1", + "@kadira/storybook-ui": "^3.0.0", "airbnb-js-shims": "^1.0.0", "autoprefixer": "^6.3.7", "babel-core": "^6.11.4", diff --git a/src/client/channel.js b/src/client/channel.js new file mode 100644 index 000000000000..62f4ee9f7f80 --- /dev/null +++ b/src/client/channel.js @@ -0,0 +1,30 @@ +import UUID from 'uuid'; +import createPageBus from 'page-bus'; + +export default class Channel { + constructor(dataId) { + this._dataId = dataId || UUID.v4(); + this._pageBus = createPageBus(); + this._listeners = {}; + } + + getDataId() { + return this._dataId; + } + + on(type, handler) { + const listener = p => handler(JSON.parse(p)); + // TODO add listener to a map[handler]listener + this._pageBus.on(`${this._dataId}.${type}`, listener); + } + + emit(type, data) { + const payload = JSON.stringify(data); + this._pageBus.emit(`${this._dataId}.${type}`, payload); + } + + removeListener(type, handler) { + // TODO get listener from a map[handler]listener + // this._pageBus.removeListener(type, listener); + } +} diff --git a/src/client/manager/provider.js b/src/client/manager/provider.js index bf2937123525..5f2a644bf3d0 100644 --- a/src/client/manager/provider.js +++ b/src/client/manager/provider.js @@ -4,16 +4,23 @@ import UUID from 'uuid'; import React from 'react'; import createPageBus from 'page-bus'; import { Provider } from '@kadira/storybook-ui'; +import addons from '@kadira/storybook-addons'; +import Channel from '../channel'; export default class ReactProvider extends Provider { constructor() { super(); - this.dataId = UUID.v4(); + this.channel = new Channel(); + addons.setChannel(this.channel); + } + + getPanels() { + return addons.getPanels(); } renderPreview(selectedKind, selectedStory) { const queryParams = { - dataId: this.dataId, + dataId: this.channel.getDataId(), selectedKind, selectedStory, }; @@ -26,37 +33,18 @@ export default class ReactProvider extends Provider { } handleAPI(api) { - const dataId = this.dataId; - const bus = createPageBus(); - - api.onStory(function (kind, story) { - const payload = { - kind, - story, - }; - - bus.emit(`${dataId}.setCurrentStory`, JSON.stringify(payload)); + api.onStory((kind, story) => { + this.channel.emit('setCurrentStory', { kind, story }); }); - - // watch pageBus and put both actions and stories. - bus.on(`${dataId}.addAction`, function (payload) { - const data = JSON.parse(payload); - api.addAction(data.action); - }); - - bus.on(`${dataId}.setStories`, function (payload) { - const data = JSON.parse(payload); + this.channel.on('setStories', data => { api.setStories(data.stories); }); - - bus.on(`${dataId}.selectStory`, function (payload) { - const data = JSON.parse(payload); + this.channel.on('selectStory', data => { api.selectStory(data.kind, data.story); }); - - bus.on(`${dataId}.applyShortcut`, function (payload) { - const data = JSON.parse(payload); + this.channel.on('applyShortcut', data => { api.handleShortcut(data.event); }); + addons.loadAddons(api); } } From 85fb5db185fdc083fce02835904457268f90a3bb Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Tue, 2 Aug 2016 13:40:01 +0530 Subject: [PATCH 2/8] Setup channel for preview --- dist/client/preview/client_api.js | 20 ++++----- dist/client/preview/config_api.js | 12 ++--- dist/client/preview/index.js | 26 ++++++++--- dist/client/preview/init.js | 4 +- dist/client/preview/page_bus.js | 74 ------------------------------- src/client/preview/client_api.js | 20 ++++----- src/client/preview/config_api.js | 12 ++--- src/client/preview/index.js | 16 +++++-- src/client/preview/init.js | 4 +- src/client/preview/page_bus.js | 35 --------------- 10 files changed, 67 insertions(+), 156 deletions(-) delete mode 100644 dist/client/preview/page_bus.js delete mode 100644 src/client/preview/page_bus.js diff --git a/dist/client/preview/client_api.js b/dist/client/preview/client_api.js index f49b768b194b..b19969ffafca 100644 --- a/dist/client/preview/client_api.js +++ b/dist/client/preview/client_api.js @@ -32,13 +32,13 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de var ClientApi = function () { function ClientApi(_ref) { - var pageBus = _ref.pageBus; + var channel = _ref.channel; var storyStore = _ref.storyStore; (0, _classCallCheck3.default)(this, ClientApi); - // pageBus can be null when running in node - // always check whether pageBus is available - this._pageBus = pageBus; + // channel can be null when running in node + // always check whether channel is available + this._channel = channel; this._storyStore = storyStore; this._addons = {}; this._globalDecorators = []; @@ -121,7 +121,7 @@ var ClientApi = function () { }, { key: 'action', value: function action(name) { - var pageBus = this._pageBus; + var channel = this._channel; return function action() { for (var _len2 = arguments.length, _args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { @@ -141,23 +141,23 @@ var ClientApi = function () { var id = _uuid2.default.v4(); var data = { name: name, args: args }; - if (pageBus) { - pageBus.emit('addAction', { action: { data: data, id: id } }); + if (channel) { + channel.emit('addAction', { action: { data: data, id: id } }); } }; } }, { key: 'linkTo', value: function linkTo(kind, story) { - var pageBus = this._pageBus; + var channel = this._channel; return function linkTo() { var resolvedKind = typeof kind === 'function' ? kind.apply(undefined, arguments) : kind; var resolvedStory = typeof story === 'function' ? story.apply(undefined, arguments) : story; var selection = { kind: resolvedKind, story: resolvedStory }; - if (pageBus) { - pageBus.emit('selectStory', selection); + if (channel) { + channel.emit('selectStory', selection); } }; } diff --git a/dist/client/preview/config_api.js b/dist/client/preview/config_api.js index a02c666d1401..e960753c00e3 100644 --- a/dist/client/preview/config_api.js +++ b/dist/client/preview/config_api.js @@ -20,14 +20,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de var ConfigApi = function () { function ConfigApi(_ref) { - var pageBus = _ref.pageBus; + var channel = _ref.channel; var storyStore = _ref.storyStore; var reduxStore = _ref.reduxStore; (0, _classCallCheck3.default)(this, ConfigApi); - // pageBus can be null when running in node - // always check whether pageBus is available - this._pageBus = pageBus; + // channel can be null when running in node + // always check whether channel is available + this._channel = channel; this._storyStore = storyStore; this._reduxStore = reduxStore; } @@ -39,7 +39,7 @@ var ConfigApi = function () { var stories = this._storyStore.dumpStoryBook(); // send to the parent frame. - this._pageBus.emit('setStories', { stories: stories }); + this._channel.emit('setStories', { stories: stories }); // clear the error if exists. this._reduxStore.dispatch((0, _actions.clearError)()); @@ -76,7 +76,7 @@ var ConfigApi = function () { }); } - if (this._pageBus) { + if (this._channel) { render(); } else { loaders(); diff --git a/dist/client/preview/index.js b/dist/client/preview/index.js index 59eeea9228ed..a99db515d39c 100644 --- a/dist/client/preview/index.js +++ b/dist/client/preview/index.js @@ -15,10 +15,6 @@ var _story_store = require('./story_store'); var _story_store2 = _interopRequireDefault(_story_store); -var _page_bus = require('./page_bus'); - -var _page_bus2 = _interopRequireDefault(_page_bus); - var _client_api = require('./client_api'); var _client_api2 = _interopRequireDefault(_client_api); @@ -39,6 +35,16 @@ var _init = require('./init'); var _init2 = _interopRequireDefault(_init); +var _channel = require('../channel'); + +var _channel2 = _interopRequireDefault(_channel); + +var _actions = require('./actions'); + +var _storybookAddons = require('@kadira/storybook-addons'); + +var _storybookAddons2 = _interopRequireDefault(_storybookAddons); + var _redux = require('redux'); var _reducer = require('./reducer'); @@ -56,9 +62,15 @@ var context = { storyStore: storyStore, reduxStore: reduxStore }; if (isBrowser) { var queryParams = _qs2.default.parse(window.location.search.substring(1)); - var pageBus = new _page_bus2.default(queryParams.dataId, reduxStore); - (0, _assign2.default)(context, { pageBus: pageBus, window: window, queryParams: queryParams }); - pageBus.init(); + if (!queryParams.dataId) { + throw new Error('dataId is not supplied via queryString'); + } + var channel = new _channel2.default(queryParams.dataId); + channel.on('setCurrentStory', function (data) { + reduxStore.dispatch((0, _actions.selectStory)(data.kind, data.story)); + }); + (0, _assign2.default)(context, { channel: channel, window: window, queryParams: queryParams }); + _storybookAddons2.default.setChannel(channel); (0, _init2.default)(context); } diff --git a/dist/client/preview/init.js b/dist/client/preview/init.js index 2513cf510751..bdfdf6d040b9 100644 --- a/dist/client/preview/init.js +++ b/dist/client/preview/init.js @@ -8,7 +8,7 @@ exports.default = function (context) { var queryParams = context.queryParams; var reduxStore = context.reduxStore; var window = context.window; - var pageBus = context.pageBus; + var channel = context.channel; // set the story if correct params are loaded via the URL. if (queryParams.selectedKind) { @@ -19,7 +19,7 @@ exports.default = function (context) { window.onkeydown = function (e) { var parsedEvent = (0, _key_events2.default)(e); if (parsedEvent) { - pageBus.emit('applyShortcut', { event: parsedEvent }); + channel.emit('applyShortcut', { event: parsedEvent }); } }; }; diff --git a/dist/client/preview/page_bus.js b/dist/client/preview/page_bus.js deleted file mode 100644 index 2469e94466b3..000000000000 --- a/dist/client/preview/page_bus.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _pageBus = require('page-bus'); - -var _pageBus2 = _interopRequireDefault(_pageBus); - -var _actions = require('./actions'); - -var _jsonStringifySafe = require('json-stringify-safe'); - -var _jsonStringifySafe2 = _interopRequireDefault(_jsonStringifySafe); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var PageBus = function () { - function PageBus(dataId, reduxStore) { - (0, _classCallCheck3.default)(this, PageBus); - - this._reduxStore = reduxStore; - this._dataId = dataId; - this._pageBus = (0, _pageBus2.default)(); - } - - (0, _createClass3.default)(PageBus, [{ - key: '_ensureDataId', - value: function _ensureDataId() { - if (!this._dataId) { - throw new Error('dataId is not supplied via queryString'); - } - } - }, { - key: '_on', - value: function _on(key, cb) { - return this._pageBus.on(this._dataId + '.' + key, cb); - } - }, { - key: 'init', - value: function init() { - var _this = this; - - this._ensureDataId(); - this._on('setCurrentStory', function (payloadString) { - var _JSON$parse = JSON.parse(payloadString); - - var kind = _JSON$parse.kind; - var story = _JSON$parse.story; - - _this._reduxStore.dispatch((0, _actions.selectStory)(kind, story)); - }); - } - }, { - key: 'emit', - value: function emit(key, payload) { - this._ensureDataId(); - var payloadString = (0, _jsonStringifySafe2.default)(payload); - return this._pageBus.emit(this._dataId + '.' + key, payloadString); - } - }]); - return PageBus; -}(); - -exports.default = PageBus; \ No newline at end of file diff --git a/src/client/preview/client_api.js b/src/client/preview/client_api.js index 8c12bf8d7608..b633e5d6e2f2 100644 --- a/src/client/preview/client_api.js +++ b/src/client/preview/client_api.js @@ -1,10 +1,10 @@ import UUID from 'uuid'; export default class ClientApi { - constructor({ pageBus, storyStore }) { - // pageBus can be null when running in node - // always check whether pageBus is available - this._pageBus = pageBus; + constructor({ channel, storyStore }) { + // channel can be null when running in node + // always check whether channel is available + this._channel = channel; this._storyStore = storyStore; this._addons = {}; this._globalDecorators = []; @@ -79,7 +79,7 @@ export default class ClientApi { } action(name) { - const pageBus = this._pageBus; + const channel = this._channel; return function action(..._args) { let args = Array.from(_args); @@ -95,22 +95,22 @@ export default class ClientApi { const id = UUID.v4(); const data = { name, args }; - if (pageBus) { - pageBus.emit('addAction', { action: { data, id } }); + if (channel) { + channel.emit('addAction', { action: { data, id } }); } }; } linkTo(kind, story) { - const pageBus = this._pageBus; + const channel = this._channel; return function linkTo(...args) { const resolvedKind = typeof kind === 'function' ? kind(...args) : kind; const resolvedStory = typeof story === 'function' ? story(...args) : story; const selection = { kind: resolvedKind, story: resolvedStory }; - if (pageBus) { - pageBus.emit('selectStory', selection); + if (channel) { + channel.emit('selectStory', selection); } }; } diff --git a/src/client/preview/config_api.js b/src/client/preview/config_api.js index df70f579fa80..56bc6a16fb84 100644 --- a/src/client/preview/config_api.js +++ b/src/client/preview/config_api.js @@ -7,10 +7,10 @@ import { import { clearDecorators } from './'; export default class ConfigApi { - constructor({ pageBus, storyStore, reduxStore }) { - // pageBus can be null when running in node - // always check whether pageBus is available - this._pageBus = pageBus; + constructor({ channel, storyStore, reduxStore }) { + // channel can be null when running in node + // always check whether channel is available + this._channel = channel; this._storyStore = storyStore; this._reduxStore = reduxStore; } @@ -20,7 +20,7 @@ export default class ConfigApi { const stories = this._storyStore.dumpStoryBook(); // send to the parent frame. - this._pageBus.emit('setStories', { stories }); + this._channel.emit('setStories', { stories }); // clear the error if exists. this._reduxStore.dispatch(clearError()); @@ -51,7 +51,7 @@ export default class ConfigApi { }); } - if (this._pageBus) { + if (this._channel) { render(); } else { loaders(); diff --git a/src/client/preview/index.js b/src/client/preview/index.js index ab3c0548ed4f..8f15804c89f9 100644 --- a/src/client/preview/index.js +++ b/src/client/preview/index.js @@ -1,11 +1,13 @@ import 'es6-shim'; import StoryStore from './story_store'; -import PageBus from './page_bus'; import ClientApi from './client_api'; import ConfigApi from './config_api'; import render from './render'; import qs from 'qs'; import init from './init'; +import Channel from '../channel'; +import { selectStory } from './actions'; +import addons from '@kadira/storybook-addons'; import { createStore } from 'redux'; import reducer from './reducer'; @@ -19,9 +21,15 @@ const context = { storyStore, reduxStore }; if (isBrowser) { const queryParams = qs.parse(window.location.search.substring(1)); - const pageBus = new PageBus(queryParams.dataId, reduxStore); - Object.assign(context, { pageBus, window, queryParams }); - pageBus.init(); + if (!queryParams.dataId) { + throw new Error('dataId is not supplied via queryString'); + } + const channel = new Channel(queryParams.dataId); + channel.on('setCurrentStory', data => { + reduxStore.dispatch(selectStory(data.kind, data.story)); + }); + Object.assign(context, { channel, window, queryParams }); + addons.setChannel(channel); init(context); } diff --git a/src/client/preview/init.js b/src/client/preview/init.js index ba818c17d1ef..8b49f36b91a8 100644 --- a/src/client/preview/init.js +++ b/src/client/preview/init.js @@ -2,7 +2,7 @@ import { selectStory } from './actions'; import keyEvents from '@kadira/storybook-ui/dist/libs/key_events'; export default function (context) { - const { queryParams, reduxStore, window, pageBus } = context; + const { queryParams, reduxStore, window, channel } = context; // set the story if correct params are loaded via the URL. if (queryParams.selectedKind) { reduxStore.dispatch(selectStory(queryParams.selectedKind, queryParams.selectedStory)); @@ -12,7 +12,7 @@ export default function (context) { window.onkeydown = (e) => { const parsedEvent = keyEvents(e); if (parsedEvent) { - pageBus.emit('applyShortcut', { event: parsedEvent }); + channel.emit('applyShortcut', { event: parsedEvent }); } }; } diff --git a/src/client/preview/page_bus.js b/src/client/preview/page_bus.js deleted file mode 100644 index c8d5f2cd8542..000000000000 --- a/src/client/preview/page_bus.js +++ /dev/null @@ -1,35 +0,0 @@ -import createPageBus from 'page-bus'; -import { selectStory } from './actions'; -import stringify from 'json-stringify-safe'; - -export default class PageBus { - constructor(dataId, reduxStore) { - this._reduxStore = reduxStore; - this._dataId = dataId; - this._pageBus = createPageBus(); - } - - _ensureDataId() { - if (!this._dataId) { - throw new Error('dataId is not supplied via queryString'); - } - } - - _on(key, cb) { - return this._pageBus.on(`${this._dataId}.${key}`, cb); - } - - init() { - this._ensureDataId(); - this._on('setCurrentStory', (payloadString) => { - const { kind, story } = JSON.parse(payloadString); - this._reduxStore.dispatch(selectStory(kind, story)); - }); - } - - emit(key, payload) { - this._ensureDataId(); - const payloadString = stringify(payload); - return this._pageBus.emit(`${this._dataId}.${key}`, payloadString); - } -} From 2feb70146c9f54af14545a897b11a7055ffe9d48 Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Tue, 2 Aug 2016 13:40:45 +0530 Subject: [PATCH 3/8] Load addons from user or load default addons --- dist/server/addons.js | 5 +++++ dist/server/config.js | 13 +++++++++++++ src/server/addons.js | 2 ++ src/server/config.js | 13 +++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 dist/server/addons.js create mode 100644 src/server/addons.js diff --git a/dist/server/addons.js b/dist/server/addons.js new file mode 100644 index 000000000000..652f0da2eef3 --- /dev/null +++ b/dist/server/addons.js @@ -0,0 +1,5 @@ +'use strict'; + +require('@kadira/storybook-addon-actions/register'); + +require('@kadira/storybook-addon-links/register'); \ No newline at end of file diff --git a/dist/server/config.js b/dist/server/config.js index 0e3e58b1baa4..f4168ec1eb46 100644 --- a/dist/server/config.js +++ b/dist/server/config.js @@ -43,6 +43,19 @@ exports.default = function (configType, baseConfig, configDir) { } config.entry.preview.push(storybookConfigPath); + // Check whether addons.js file exists inside the storybook. + // Load the default addons.js file if it's missing. + var storybookDefaultAddonsPath = _path2.default.resolve(__dirname, 'addons.js'); + var storybookCustomAddonsPath = _path2.default.resolve(configDir, 'addons.js'); + if (_fs2.default.existsSync(storybookCustomAddonsPath)) { + logger.info('=> Loading custom addons config.'); + config.entry.preview.unshift(storybookCustomAddonsPath); + config.entry.manager.unshift(storybookCustomAddonsPath); + } else { + config.entry.preview.unshift(storybookDefaultAddonsPath); + config.entry.manager.unshift(storybookDefaultAddonsPath); + } + // Check whether user has a custom webpack config file and // return the (extended) base configuration if it's not available. var customConfigPath = _path2.default.resolve(configDir, 'webpack.config.js'); diff --git a/src/server/addons.js b/src/server/addons.js new file mode 100644 index 000000000000..e8590efcf2fd --- /dev/null +++ b/src/server/addons.js @@ -0,0 +1,2 @@ +import '@kadira/storybook-addon-actions/register'; +import '@kadira/storybook-addon-links/register'; diff --git a/src/server/config.js b/src/server/config.js index 45c85245287c..dcb4288aa9d6 100644 --- a/src/server/config.js +++ b/src/server/config.js @@ -81,6 +81,19 @@ export default function (configType, baseConfig, configDir) { } config.entry.preview.push(storybookConfigPath); + // Check whether addons.js file exists inside the storybook. + // Load the default addons.js file if it's missing. + const storybookDefaultAddonsPath = path.resolve(__dirname, 'addons.js'); + const storybookCustomAddonsPath = path.resolve(configDir, 'addons.js'); + if (fs.existsSync(storybookCustomAddonsPath)) { + logger.info('=> Loading custom addons config.'); + config.entry.preview.unshift(storybookCustomAddonsPath); + config.entry.manager.unshift(storybookCustomAddonsPath); + } else { + config.entry.preview.unshift(storybookDefaultAddonsPath); + config.entry.manager.unshift(storybookDefaultAddonsPath); + } + // Check whether user has a custom webpack config file and // return the (extended) base configuration if it's not available. const customConfigPath = path.resolve(configDir, 'webpack.config.js'); From a1135b9a3acb2cca663a87961546c0af4121ae9b Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Tue, 2 Aug 2016 13:41:41 +0530 Subject: [PATCH 4/8] Allow easy importing default set of addons For an example addons.js: ```js import '@kadira/storybook/addons'; import '@kadira/storybook-addon-hello/register'; ``` --- addons.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 addons.js diff --git a/addons.js b/addons.js new file mode 100644 index 000000000000..56451c97db51 --- /dev/null +++ b/addons.js @@ -0,0 +1 @@ +require('./dist/server/addons'); From c756f757edfd4dbb1aa6f11a757194993f96ad04 Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Tue, 2 Aug 2016 14:40:37 +0530 Subject: [PATCH 5/8] Export correct action, linkTo functions --- dist/client/index.js | 26 ++++++++++++--- dist/client/preview/client_api.js | 55 +++---------------------------- dist/client/preview/index.js | 4 +-- src/client/index.js | 6 ++-- src/client/preview/client_api.js | 45 +++---------------------- src/client/preview/index.js | 2 -- 6 files changed, 35 insertions(+), 103 deletions(-) diff --git a/dist/client/index.js b/dist/client/index.js index 090f7cf52032..6a606601d81d 100644 --- a/dist/client/index.js +++ b/dist/client/index.js @@ -3,7 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.getStorybook = exports.configure = exports.addDecorator = exports.setAddon = exports.linkTo = exports.action = exports.storiesOf = undefined; +exports.linkTo = exports.action = exports.getStorybook = exports.configure = exports.addDecorator = exports.setAddon = exports.storiesOf = undefined; + +var _storybookAddonActions = require('@kadira/storybook-addon-actions'); + +Object.defineProperty(exports, 'action', { + enumerable: true, + get: function get() { + return _storybookAddonActions.action; + } +}); + +var _storybookAddonLinks = require('@kadira/storybook-addon-links'); + +Object.defineProperty(exports, 'linkTo', { + enumerable: true, + get: function get() { + return _storybookAddonLinks.linkTo; + } +}); var _preview = require('./preview'); @@ -12,9 +30,9 @@ var previewApi = _interopRequireWildcard(_preview); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } var storiesOf = exports.storiesOf = previewApi.storiesOf; -var action = exports.action = previewApi.action; -var linkTo = exports.linkTo = previewApi.linkTo; var setAddon = exports.setAddon = previewApi.setAddon; var addDecorator = exports.addDecorator = previewApi.addDecorator; var configure = exports.configure = previewApi.configure; -var getStorybook = exports.getStorybook = previewApi.getStorybook; \ No newline at end of file +var getStorybook = exports.getStorybook = previewApi.getStorybook; + +// NOTE export these to keep backwards compatibility \ No newline at end of file diff --git a/dist/client/preview/client_api.js b/dist/client/preview/client_api.js index b19969ffafca..5ac868656266 100644 --- a/dist/client/preview/client_api.js +++ b/dist/client/preview/client_api.js @@ -4,10 +4,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); -var _from = require('babel-runtime/core-js/array/from'); - -var _from2 = _interopRequireDefault(_from); - var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); @@ -32,13 +28,13 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de var ClientApi = function () { function ClientApi(_ref) { - var channel = _ref.channel; + var pageBus = _ref.pageBus; var storyStore = _ref.storyStore; (0, _classCallCheck3.default)(this, ClientApi); - // channel can be null when running in node - // always check whether channel is available - this._channel = channel; + // pageBus can be null when running in node + // always check whether pageBus is available + this._pageBus = pageBus; this._storyStore = storyStore; this._addons = {}; this._globalDecorators = []; @@ -118,49 +114,6 @@ var ClientApi = function () { return api; } - }, { - key: 'action', - value: function action(name) { - var channel = this._channel; - - return function action() { - for (var _len2 = arguments.length, _args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - _args[_key2] = arguments[_key2]; - } - - var args = (0, _from2.default)(_args); - - // Remove events from the args. Otherwise, it creates a huge JSON string. - args = args.map(function (arg) { - if (arg && typeof arg.preventDefault === 'function') { - return '[SyntheticEvent]'; - } - return arg; - }); - - var id = _uuid2.default.v4(); - var data = { name: name, args: args }; - - if (channel) { - channel.emit('addAction', { action: { data: data, id: id } }); - } - }; - } - }, { - key: 'linkTo', - value: function linkTo(kind, story) { - var channel = this._channel; - - return function linkTo() { - var resolvedKind = typeof kind === 'function' ? kind.apply(undefined, arguments) : kind; - var resolvedStory = typeof story === 'function' ? story.apply(undefined, arguments) : story; - var selection = { kind: resolvedKind, story: resolvedStory }; - - if (channel) { - channel.emit('selectStory', selection); - } - }; - } }, { key: 'getStorybook', value: function getStorybook() { diff --git a/dist/client/preview/index.js b/dist/client/preview/index.js index a99db515d39c..abff2ed0a9ef 100644 --- a/dist/client/preview/index.js +++ b/dist/client/preview/index.js @@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.configure = exports.getStorybook = exports.clearDecorators = exports.addDecorator = exports.setAddon = exports.linkTo = exports.action = exports.storiesOf = undefined; +exports.configure = exports.getStorybook = exports.clearDecorators = exports.addDecorator = exports.setAddon = exports.storiesOf = undefined; var _assign = require('babel-runtime/core-js/object/assign'); @@ -79,8 +79,6 @@ var configApi = new _config_api2.default(context); // do exports var storiesOf = exports.storiesOf = clientApi.storiesOf.bind(clientApi); -var action = exports.action = clientApi.action.bind(clientApi); -var linkTo = exports.linkTo = clientApi.linkTo.bind(clientApi); var setAddon = exports.setAddon = clientApi.setAddon.bind(clientApi); var addDecorator = exports.addDecorator = clientApi.addDecorator.bind(clientApi); var clearDecorators = exports.clearDecorators = clientApi.clearDecorators.bind(clientApi); diff --git a/src/client/index.js b/src/client/index.js index 0dd292ce2f1c..3bcdb23705fd 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -1,9 +1,11 @@ import * as previewApi from './preview'; export const storiesOf = previewApi.storiesOf; -export const action = previewApi.action; -export const linkTo = previewApi.linkTo; export const setAddon = previewApi.setAddon; export const addDecorator = previewApi.addDecorator; export const configure = previewApi.configure; export const getStorybook = previewApi.getStorybook; + +// NOTE export these to keep backwards compatibility +export { action } from '@kadira/storybook-addon-actions'; +export { linkTo } from '@kadira/storybook-addon-links'; diff --git a/src/client/preview/client_api.js b/src/client/preview/client_api.js index b633e5d6e2f2..0ec331bf4476 100644 --- a/src/client/preview/client_api.js +++ b/src/client/preview/client_api.js @@ -1,10 +1,10 @@ import UUID from 'uuid'; export default class ClientApi { - constructor({ channel, storyStore }) { - // channel can be null when running in node - // always check whether channel is available - this._channel = channel; + constructor({ pageBus, storyStore }) { + // pageBus can be null when running in node + // always check whether pageBus is available + this._pageBus = pageBus; this._storyStore = storyStore; this._addons = {}; this._globalDecorators = []; @@ -78,43 +78,6 @@ export default class ClientApi { return api; } - action(name) { - const channel = this._channel; - - return function action(..._args) { - let args = Array.from(_args); - - // Remove events from the args. Otherwise, it creates a huge JSON string. - args = args.map(arg => { - if (arg && typeof arg.preventDefault === 'function') { - return '[SyntheticEvent]'; - } - return arg; - }); - - const id = UUID.v4(); - const data = { name, args }; - - if (channel) { - channel.emit('addAction', { action: { data, id } }); - } - }; - } - - linkTo(kind, story) { - const channel = this._channel; - - return function linkTo(...args) { - const resolvedKind = typeof kind === 'function' ? kind(...args) : kind; - const resolvedStory = typeof story === 'function' ? story(...args) : story; - const selection = { kind: resolvedKind, story: resolvedStory }; - - if (channel) { - channel.emit('selectStory', selection); - } - }; - } - getStorybook() { return this._storyStore.getStoryKinds().map(kind => { const stories = this._storyStore.getStories(kind).map(name => { diff --git a/src/client/preview/index.js b/src/client/preview/index.js index 8f15804c89f9..0d8fd7ff4c39 100644 --- a/src/client/preview/index.js +++ b/src/client/preview/index.js @@ -38,8 +38,6 @@ const configApi = new ConfigApi(context); // do exports export const storiesOf = clientApi.storiesOf.bind(clientApi); -export const action = clientApi.action.bind(clientApi); -export const linkTo = clientApi.linkTo.bind(clientApi); export const setAddon = clientApi.setAddon.bind(clientApi); export const addDecorator = clientApi.addDecorator.bind(clientApi); export const clearDecorators = clientApi.clearDecorators.bind(clientApi); From d6b7496bd8eb9c92658712bce5f2b0a17897056f Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Tue, 2 Aug 2016 14:43:26 +0530 Subject: [PATCH 6/8] Rename pageBus to channel --- dist/client/preview/client_api.js | 8 ++++---- src/client/preview/client_api.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dist/client/preview/client_api.js b/dist/client/preview/client_api.js index 5ac868656266..e748f7ba9754 100644 --- a/dist/client/preview/client_api.js +++ b/dist/client/preview/client_api.js @@ -28,13 +28,13 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de var ClientApi = function () { function ClientApi(_ref) { - var pageBus = _ref.pageBus; + var channel = _ref.channel; var storyStore = _ref.storyStore; (0, _classCallCheck3.default)(this, ClientApi); - // pageBus can be null when running in node - // always check whether pageBus is available - this._pageBus = pageBus; + // channel can be null when running in node + // always check whether channel is available + this._channel = channel; this._storyStore = storyStore; this._addons = {}; this._globalDecorators = []; diff --git a/src/client/preview/client_api.js b/src/client/preview/client_api.js index 0ec331bf4476..3b6076efb809 100644 --- a/src/client/preview/client_api.js +++ b/src/client/preview/client_api.js @@ -1,10 +1,10 @@ import UUID from 'uuid'; export default class ClientApi { - constructor({ pageBus, storyStore }) { - // pageBus can be null when running in node - // always check whether pageBus is available - this._pageBus = pageBus; + constructor({ channel, storyStore }) { + // channel can be null when running in node + // always check whether channel is available + this._channel = channel; this._storyStore = storyStore; this._addons = {}; this._globalDecorators = []; From bebd823a984b1dc4b23a3252f07eebd4207d5ca9 Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Tue, 2 Aug 2016 14:55:14 +0530 Subject: [PATCH 7/8] Fix tests and lint errors --- dist/client/channel.js | 2 +- dist/client/manager/provider.js | 8 ---- dist/client/preview/client_api.js | 24 +++++----- src/client/channel.js | 2 +- src/client/manager/provider.js | 2 - src/client/preview/__tests__/client_api.js | 52 ---------------------- src/client/preview/client_api.js | 2 - 7 files changed, 12 insertions(+), 80 deletions(-) diff --git a/dist/client/channel.js b/dist/client/channel.js index 03d988a4e660..71be6362efc5 100644 --- a/dist/client/channel.js +++ b/dist/client/channel.js @@ -57,7 +57,7 @@ var Channel = function () { } }, { key: 'removeListener', - value: function removeListener(type, handler) { + value: function removeListener() /* type, handler */{ // TODO get listener from a map[handler]listener // this._pageBus.removeListener(type, listener); } diff --git a/dist/client/manager/provider.js b/dist/client/manager/provider.js index a29205a99df3..3e1c1253ab0d 100644 --- a/dist/client/manager/provider.js +++ b/dist/client/manager/provider.js @@ -32,18 +32,10 @@ var _qs = require('qs'); var _qs2 = _interopRequireDefault(_qs); -var _uuid = require('uuid'); - -var _uuid2 = _interopRequireDefault(_uuid); - var _react = require('react'); var _react2 = _interopRequireDefault(_react); -var _pageBus = require('page-bus'); - -var _pageBus2 = _interopRequireDefault(_pageBus); - var _storybookUi = require('@kadira/storybook-ui'); var _storybookAddons = require('@kadira/storybook-addons'); diff --git a/dist/client/preview/client_api.js b/dist/client/preview/client_api.js index e748f7ba9754..25fffb0b2509 100644 --- a/dist/client/preview/client_api.js +++ b/dist/client/preview/client_api.js @@ -1,29 +1,25 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); +var _toConsumableArray2 = require("babel-runtime/helpers/toConsumableArray"); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); -var _extends2 = require('babel-runtime/helpers/extends'); +var _extends2 = require("babel-runtime/helpers/extends"); var _extends3 = _interopRequireDefault(_extends2); -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); -var _createClass2 = require('babel-runtime/helpers/createClass'); +var _createClass2 = require("babel-runtime/helpers/createClass"); var _createClass3 = _interopRequireDefault(_createClass2); -var _uuid = require('uuid'); - -var _uuid2 = _interopRequireDefault(_uuid); - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ClientApi = function () { @@ -41,22 +37,22 @@ var ClientApi = function () { } (0, _createClass3.default)(ClientApi, [{ - key: 'setAddon', + key: "setAddon", value: function setAddon(addon) { this._addons = (0, _extends3.default)({}, this._addons, addon); } }, { - key: 'addDecorator', + key: "addDecorator", value: function addDecorator(decorator) { this._globalDecorators.push(decorator); } }, { - key: 'clearDecorators', + key: "clearDecorators", value: function clearDecorators() { this._globalDecorators = []; } }, { - key: 'storiesOf', + key: "storiesOf", value: function storiesOf(kind, m) { var _this = this; @@ -115,7 +111,7 @@ var ClientApi = function () { return api; } }, { - key: 'getStorybook', + key: "getStorybook", value: function getStorybook() { var _this2 = this; diff --git a/src/client/channel.js b/src/client/channel.js index 62f4ee9f7f80..0841fcd159fa 100644 --- a/src/client/channel.js +++ b/src/client/channel.js @@ -23,7 +23,7 @@ export default class Channel { this._pageBus.emit(`${this._dataId}.${type}`, payload); } - removeListener(type, handler) { + removeListener(/* type, handler */) { // TODO get listener from a map[handler]listener // this._pageBus.removeListener(type, listener); } diff --git a/src/client/manager/provider.js b/src/client/manager/provider.js index 5f2a644bf3d0..65f8399714ab 100644 --- a/src/client/manager/provider.js +++ b/src/client/manager/provider.js @@ -1,8 +1,6 @@ import Preview from './preview'; import qs from 'qs'; -import UUID from 'uuid'; import React from 'react'; -import createPageBus from 'page-bus'; import { Provider } from '@kadira/storybook-ui'; import addons from '@kadira/storybook-addons'; import Channel from '../channel'; diff --git a/src/client/preview/__tests__/client_api.js b/src/client/preview/__tests__/client_api.js index b8bfb842c37e..65d5d05b8e14 100644 --- a/src/client/preview/__tests__/client_api.js +++ b/src/client/preview/__tests__/client_api.js @@ -39,16 +39,6 @@ class StoryStore { } } -class PageBus { - constructor() { - this.emits = []; - } - - emit(type, ...args) { - this.emits.push({ type, args }); - } -} - describe('preview.client_api', () => { describe('setAddon', () => { it('should register addons', () => { @@ -220,48 +210,6 @@ describe('preview.client_api', () => { }); }); - describe('action', () => { - it('should emit "addAction"', () => { - const api = new ClientAPI({}); - api._pageBus = new PageBus(); - const action = api.action('test-action'); - action(1, 'a', [1], { a: 1 }, { preventDefault() {} }); - expect(api._pageBus.emits.length).to.equal(1); - expect(api._pageBus.emits[0].type).to.equal('addAction'); - expect(typeof api._pageBus.emits[0].args[0].action.id).to.equal('string'); - expect(api._pageBus.emits[0].args[0].action.data).to.deep.equal({ - name: 'test-action', - args: [1, 'a', [1], { a: 1 }, '[SyntheticEvent]'], - }); - }); - }); - - describe('linkTo', () => { - it('should emit "selectStory"', () => { - const api = new ClientAPI({}); - api._pageBus = new PageBus(); - api.linkTo('test-kind', 'test-story')(); - expect(api._pageBus.emits.length).to.equal(1); - expect(api._pageBus.emits[0].type).to.equal('selectStory'); - expect(api._pageBus.emits[0].args[0]).to.deep.equal({ - kind: 'test-kind', - story: 'test-story', - }); - }); - - it('should support function args', () => { - const api = new ClientAPI({}); - api._pageBus = new PageBus(); - api.linkTo(a => `${a}-kind`, a => `${a}-story`)('test'); - expect(api._pageBus.emits.length).to.equal(1); - expect(api._pageBus.emits[0].type).to.equal('selectStory'); - expect(api._pageBus.emits[0].args[0]).to.deep.equal({ - kind: 'test-kind', - story: 'test-story', - }); - }); - }); - describe('getStorybook', () => { it('should return storybook when empty', () => { const storyStore = new StoryStore(); diff --git a/src/client/preview/client_api.js b/src/client/preview/client_api.js index 3b6076efb809..2371a7ffbcf9 100644 --- a/src/client/preview/client_api.js +++ b/src/client/preview/client_api.js @@ -1,5 +1,3 @@ -import UUID from 'uuid'; - export default class ClientApi { constructor({ channel, storyStore }) { // channel can be null when running in node From 3ec3195daf675f2cfad1cbb3ad3381cecc847810 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Tue, 2 Aug 2016 18:06:33 +0530 Subject: [PATCH 8/8] Update some comments. --- addons.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons.js b/addons.js index 56451c97db51..fcad03f18232 100644 --- a/addons.js +++ b/addons.js @@ -1 +1,4 @@ +// We are not using this file inside this project. +// But, this will be useful when a user is configuring it's own addons. +// Then he can import this file to add default set of addons. require('./dist/server/addons');