mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-06 07:21:16 +08:00
104 lines
3.1 KiB
JavaScript
104 lines
3.1 KiB
JavaScript
/* 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
|
|
? <OnDeviceUI
|
|
stories={this._stories}
|
|
events={this._events}
|
|
url={webUrl}
|
|
animated={params.onDeviceUIAnimated}
|
|
/>
|
|
: <StoryView url={webUrl} events={this._events} />;
|
|
};
|
|
}
|
|
|
|
_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);
|
|
}
|
|
}
|