/* eslint no-underscore-dangle: 0 */ import React from 'react'; import { NativeModules } from 'react-native'; import parse from 'url-parse'; import addons from '@storybook/addons'; import createChannel from '@storybook/channel-websocket'; import { EventEmitter } from 'events'; import { StoryStore, ClientApi } from '@storybook/core/client'; import OnDeviceUI from './components/OnDeviceUI'; import StoryView from './components/StoryView'; export default class Preview { constructor() { this._addons = {}; this._decorators = []; this._events = new EventEmitter(); this._stories = new StoryStore(); this._clientApi = new ClientApi({ storyStore: this._stories }); [ 'storiesOf', 'setAddon', 'addDecorator', 'addParameters', 'clearDecorators', 'getStorybook', ].forEach(method => { this[method] = this._clientApi[method].bind(this._clientApi); }); } configure(loadStories, module) { loadStories(); if (module && module.hot) { module.hot.accept(() => this._sendSetStories()); // TODO remove all global decorators on dispose } } getStorybookUI(params = {}) { return () => { let webUrl = null; let channel = null; try { channel = addons.getChannel(); } catch (e) { // getChannel throws if the channel is not defined, // which is fine in this case (we will define it below) } if (params.resetStorybook || !channel) { const host = params.host || parse(NativeModules.SourceCode.scriptURL).hostname; const port = params.port !== false ? `:${params.port || 7007}` : ''; const query = params.query || ''; const { secured } = params; const websocketType = secured ? 'wss' : 'ws'; const httpType = secured ? 'https' : 'http'; const url = `${websocketType}://${host}${port}/${query}`; webUrl = `${httpType}://${host}${port}`; channel = createChannel({ url }); addons.setChannel(channel); channel.emit('channelCreated'); } channel.on('getStories', () => this._sendSetStories()); channel.on('setCurrentStory', d => this._selectStory(d)); this._events.on('setCurrentStory', d => this._selectStory(d)); this._sendSetStories(); this._sendGetCurrentStory(); // finally return the preview component return params.onDeviceUI ? : ; }; } _sendSetStories() { const channel = addons.getChannel(); const stories = this._stories.dumpStoryBook(); channel.emit('setStories', { stories }); } _sendGetCurrentStory() { const channel = addons.getChannel(); channel.emit('getCurrentStory'); } _selectStory(selection) { const { kind, story } = selection; const storyFn = this._stories.getStoryWithContext(kind, story); this._events.emit('story', storyFn, selection); } }