Skip to content

Commit 44cfb53

Browse files
committed
Add a basic implementation of the native UI for the storybook
1 parent b0df780 commit 44cfb53

5 files changed

Lines changed: 127 additions & 4 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React, { Component, PropTypes } from 'react';
2+
import { SectionList, View, Text, TouchableHighlight } from 'react-native';
3+
import style from './style';
4+
5+
const SectionHeader = ({ title }) => {
6+
return (
7+
<View key={title} style={style.header}>
8+
<Text style={style.headerText}>
9+
{title}
10+
</Text>
11+
</View>
12+
)
13+
}
14+
15+
const ListItem = ({ title, onPress }) => {
16+
return (
17+
<TouchableHighlight
18+
key={title}
19+
style={style.item}
20+
onPress={onPress}
21+
>
22+
<Text style={style.itemText}>
23+
{title}
24+
</Text>
25+
</TouchableHighlight>
26+
)
27+
}
28+
29+
export default class StoryListView extends Component {
30+
constructor(props, ...args) {
31+
super(props, ...args);
32+
this.state = { stories: {} };
33+
34+
this.storiesHandler = this.handleStoryAdded.bind(this);
35+
this.setStoryHandler = this.handleSetStory.bind(this);
36+
37+
this.props.stories.on('storyAdded', this.storiesHandler);
38+
}
39+
40+
componentDidMount() {
41+
this.storiesHandler();
42+
}
43+
44+
componentWillUnmount() {
45+
this.props.stories.removeListener('storyAdded', this.storiesHandler);
46+
}
47+
48+
handleStoryAdded() {
49+
const data = this.props.stories.dumpStoryBook();
50+
this.setState({
51+
sections: data.map((section) => {
52+
return {
53+
key: section.kind,
54+
title: section.kind,
55+
data: section.stories.map((story) => {
56+
return {
57+
key: story,
58+
kind: section.kind,
59+
name: story
60+
}
61+
})
62+
}
63+
})
64+
});
65+
}
66+
67+
handleSetStory(kind, story) {
68+
this.props.events.emit('setCurrentStory', { kind, story });
69+
}
70+
71+
render() {
72+
return (
73+
<SectionList
74+
style={style.list}
75+
renderItem={({ item }) => <ListItem title={item.name} onPress={() => this.setStoryHandler(item.kind, item.name)} />}
76+
renderSectionHeader={({ section }) => <SectionHeader title={section.title} />}
77+
sections={this.state.sections || []}
78+
stickySectionHeadersEnabled={false}
79+
/>
80+
);
81+
}
82+
}
83+
84+
StoryListView.propTypes = {
85+
stories: PropTypes.any.isRequired,
86+
events: PropTypes.shape({
87+
on: PropTypes.func.isRequired,
88+
removeListener: PropTypes.func.isRequired,
89+
}).isRequired,
90+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export default {
2+
list: {
3+
flex: 1,
4+
},
5+
header: {
6+
paddingTop: 24,
7+
paddingBottom: 4,
8+
paddingHorizontal: 16,
9+
},
10+
headerText: {
11+
fontWeight: 'bold',
12+
},
13+
item: {
14+
paddingVertical: 4,
15+
paddingHorizontal: 16,
16+
},
17+
itemText: {
18+
19+
},
20+
};

app/react-native/src/preview/components/StoryView/style.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
export default {
22
main: {
3-
flex: 1,
3+
flex: 3,
44
},
55
help: {
6-
flex: 1,
6+
flex: 3,
77
padding: 15,
88
alignItems: 'center',
99
justifyContent: 'center',

app/react-native/src/preview/index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/* eslint no-underscore-dangle: 0 */
22

33
import React from 'react';
4+
import { View } from 'react-native';
45
import addons from '@storybook/addons';
56
import createChannel from '@storybook/channel-websocket';
67
import { EventEmitter } from 'events';
78
import StoryStore from './story_store';
89
import StoryKindApi from './story_kind';
10+
import StoryListView from './components/StoryListView';
911
import StoryView from './components/StoryView';
1012

1113
export default class Preview {
@@ -70,11 +72,17 @@ export default class Preview {
7072
}
7173
channel.on('getStories', () => this._sendSetStories());
7274
channel.on('setCurrentStory', d => this._selectStory(d));
75+
this._events.on('setCurrentStory', d => this._selectStory(d));
7376
this._sendSetStories();
7477
this._sendGetCurrentStory();
7578

7679
// finally return the preview component
77-
return <StoryView url={webUrl} events={this._events} />;
80+
return (
81+
<View style={{ flex: 1, flexDirection: 'row' }}>
82+
<StoryListView stories={this._stories} events={this._events} />
83+
<StoryView url={webUrl} events={this._events} />
84+
</View>
85+
);
7886
};
7987
}
8088

app/react-native/src/preview/story_store.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
/* eslint no-underscore-dangle: 0 */
2+
import { EventEmitter } from 'events';
3+
24
let count = 0;
35

4-
export default class StoryStore {
6+
export default class StoryStore extends EventEmitter {
57
constructor() {
8+
super();
69
this._data = {};
710
}
811

@@ -21,6 +24,8 @@ export default class StoryStore {
2124
index: count,
2225
fn,
2326
};
27+
28+
this.emit('storyAdded', kind, name, fn);
2429
}
2530

2631
getStoryKinds() {

0 commit comments

Comments
 (0)