Skip to content

Commit

Permalink
Add a basic implementation of the native UI for the storybook
Browse files Browse the repository at this point in the history
  • Loading branch information
matt-oakes committed Jul 5, 2017
1 parent 33096d4 commit 2fe3e8c
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 4 deletions.
90 changes: 90 additions & 0 deletions app/react-native/src/preview/components/StoryListView/index.js
Original file line number Diff line number Diff line change
@@ -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 (
<View key={title} style={style.header}>
<Text style={style.headerText}>
{title}
</Text>
</View>
)
}

const ListItem = ({ title, onPress }) => {
return (
<TouchableHighlight
key={title}
style={style.item}
onPress={onPress}
>
<Text style={style.itemText}>
{title}
</Text>
</TouchableHighlight>
)
}

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 (
<SectionList
style={style.list}
renderItem={({ item }) => <ListItem title={item.name} onPress={() => this.setStoryHandler(item.kind, item.name)} />}
renderSectionHeader={({ section }) => <SectionHeader title={section.title} />}
sections={this.state.sections || []}
stickySectionHeadersEnabled={false}
/>
);
}
}

StoryListView.propTypes = {
stories: PropTypes.any.isRequired,
events: PropTypes.shape({
on: PropTypes.func.isRequired,
removeListener: PropTypes.func.isRequired,
}).isRequired,
};
20 changes: 20 additions & 0 deletions app/react-native/src/preview/components/StoryListView/style.js
Original file line number Diff line number Diff line change
@@ -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: {

},
};
4 changes: 2 additions & 2 deletions app/react-native/src/preview/components/StoryView/style.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export default {
main: {
flex: 1,
flex: 3,
},
help: {
flex: 1,
flex: 3,
padding: 15,
alignItems: 'center',
justifyContent: 'center',
Expand Down
10 changes: 9 additions & 1 deletion app/react-native/src/preview/index.js
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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 <StoryView url={webUrl} events={this._events} />;
return (
<View style={{ flex: 1, flexDirection: 'row' }}>
<StoryListView stories={this._stories} events={this._events} />
<StoryView url={webUrl} events={this._events} />
</View>
);
};
}

Expand Down
7 changes: 6 additions & 1 deletion app/react-native/src/preview/story_store.js
Original file line number Diff line number Diff line change
@@ -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 = {};
}

Expand All @@ -21,6 +24,8 @@ export default class StoryStore {
index: count,
fn,
};

this.emit('storyAdded', kind, name, fn);
}

getStoryKinds() {
Expand Down

0 comments on commit 2fe3e8c

Please sign in to comment.