From 44cfb53e7a1915aba430b84176b6db6ecd1a8b37 Mon Sep 17 00:00:00 2001 From: Matt Oakes Date: Wed, 5 Jul 2017 12:45:00 +0100 Subject: [PATCH] Add a basic implementation of the native UI for the storybook --- .../preview/components/StoryListView/index.js | 90 +++++++++++++++++++ .../preview/components/StoryListView/style.js | 20 +++++ .../src/preview/components/StoryView/style.js | 4 +- app/react-native/src/preview/index.js | 10 ++- app/react-native/src/preview/story_store.js | 7 +- 5 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 app/react-native/src/preview/components/StoryListView/index.js create mode 100644 app/react-native/src/preview/components/StoryListView/style.js diff --git a/app/react-native/src/preview/components/StoryListView/index.js b/app/react-native/src/preview/components/StoryListView/index.js new file mode 100644 index 000000000000..7f497f2683c6 --- /dev/null +++ b/app/react-native/src/preview/components/StoryListView/index.js @@ -0,0 +1,90 @@ +import React, { Component, PropTypes } from 'react'; +import { SectionList, View, Text, TouchableHighlight } from 'react-native'; +import style from './style'; + +const SectionHeader = ({ title }) => { + return ( + + + {title} + + + ) +} + +const ListItem = ({ title, onPress }) => { + return ( + + + {title} + + + ) +} + +export default class StoryListView extends Component { + constructor(props, ...args) { + super(props, ...args); + this.state = { stories: {} }; + + this.storiesHandler = this.handleStoryAdded.bind(this); + this.setStoryHandler = this.handleSetStory.bind(this); + + this.props.stories.on('storyAdded', this.storiesHandler); + } + + componentDidMount() { + this.storiesHandler(); + } + + componentWillUnmount() { + this.props.stories.removeListener('storyAdded', this.storiesHandler); + } + + handleStoryAdded() { + const data = this.props.stories.dumpStoryBook(); + this.setState({ + sections: data.map((section) => { + return { + key: section.kind, + title: section.kind, + data: section.stories.map((story) => { + return { + key: story, + kind: section.kind, + name: story + } + }) + } + }) + }); + } + + handleSetStory(kind, story) { + this.props.events.emit('setCurrentStory', { kind, story }); + } + + render() { + return ( + this.setStoryHandler(item.kind, item.name)} />} + renderSectionHeader={({ section }) => } + sections={this.state.sections || []} + stickySectionHeadersEnabled={false} + /> + ); + } +} + +StoryListView.propTypes = { + stories: PropTypes.any.isRequired, + events: PropTypes.shape({ + on: PropTypes.func.isRequired, + removeListener: PropTypes.func.isRequired, + }).isRequired, +}; diff --git a/app/react-native/src/preview/components/StoryListView/style.js b/app/react-native/src/preview/components/StoryListView/style.js new file mode 100644 index 000000000000..8295e58cad06 --- /dev/null +++ b/app/react-native/src/preview/components/StoryListView/style.js @@ -0,0 +1,20 @@ +export default { + list: { + flex: 1, + }, + header: { + paddingTop: 24, + paddingBottom: 4, + paddingHorizontal: 16, + }, + headerText: { + fontWeight: 'bold', + }, + item: { + paddingVertical: 4, + paddingHorizontal: 16, + }, + itemText: { + + }, +}; diff --git a/app/react-native/src/preview/components/StoryView/style.js b/app/react-native/src/preview/components/StoryView/style.js index b5fe466b9043..ae7344146d01 100644 --- a/app/react-native/src/preview/components/StoryView/style.js +++ b/app/react-native/src/preview/components/StoryView/style.js @@ -1,9 +1,9 @@ export default { main: { - flex: 1, + flex: 3, }, help: { - flex: 1, + flex: 3, padding: 15, alignItems: 'center', justifyContent: 'center', diff --git a/app/react-native/src/preview/index.js b/app/react-native/src/preview/index.js index c5d253887083..8767479a5f50 100644 --- a/app/react-native/src/preview/index.js +++ b/app/react-native/src/preview/index.js @@ -1,11 +1,13 @@ /* eslint no-underscore-dangle: 0 */ import React from 'react'; +import { View } from 'react-native'; import addons from '@storybook/addons'; import createChannel from '@storybook/channel-websocket'; import { EventEmitter } from 'events'; import StoryStore from './story_store'; import StoryKindApi from './story_kind'; +import StoryListView from './components/StoryListView'; import StoryView from './components/StoryView'; export default class Preview { @@ -70,11 +72,17 @@ export default class Preview { } 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 ; + return ( + + + + + ); }; } diff --git a/app/react-native/src/preview/story_store.js b/app/react-native/src/preview/story_store.js index 86021172b09f..07e91876b125 100644 --- a/app/react-native/src/preview/story_store.js +++ b/app/react-native/src/preview/story_store.js @@ -1,8 +1,11 @@ /* eslint no-underscore-dangle: 0 */ +import { EventEmitter } from 'events'; + let count = 0; -export default class StoryStore { +export default class StoryStore extends EventEmitter { constructor() { + super(); this._data = {}; } @@ -21,6 +24,8 @@ export default class StoryStore { index: count, fn, }; + + this.emit('storyAdded', kind, name, fn); } getStoryKinds() {