From 12cc28f50d68e8b62e07f448c74c01ca8b114822 Mon Sep 17 00:00:00 2001 From: dmitriy Date: Sat, 14 Jan 2017 00:01:38 +0200 Subject: [PATCH 01/38] - first iteration --- src/ColoredTabs/ColoredTabs.js | 105 ++++++++++++++++++++++++++++ src/ColoredTabs/TabItem.js | 106 +++++++++++++++++++++++++++++ src/ColoredTabs/index.js | 1 + uiexplorer/examples/ColoredTabs.js | 27 ++++++++ uiexplorer/examples/index.js | 1 + 5 files changed, 240 insertions(+) create mode 100644 src/ColoredTabs/ColoredTabs.js create mode 100644 src/ColoredTabs/TabItem.js create mode 100644 src/ColoredTabs/index.js create mode 100644 uiexplorer/examples/ColoredTabs.js diff --git a/src/ColoredTabs/ColoredTabs.js b/src/ColoredTabs/ColoredTabs.js new file mode 100644 index 0000000..df8946f --- /dev/null +++ b/src/ColoredTabs/ColoredTabs.js @@ -0,0 +1,105 @@ +import React, { Component, PropTypes, Children, cloneElement } from 'react' +import { View, StyleSheet } from 'react-native' +// import StylePropType from '../utils/StylePropType' +import TabItem from './TabItem' + +export default class ColoredTabs extends Component { + static propTypes = { + children: PropTypes.node, + // theme: PropTypes.oneOf(['light', 'dark']), + // style: StylePropType, + selected: PropTypes.string, + } + + // static defaultProps = { + // theme: 'light', + // } + + static TabItem = TabItem + + constructor(props) { + super(props) + this.state = { selected: props.selected, children: props.children } + } + + handleTabPress = (id) => { + this.setState({ + selected: id, + }) + } + + render() { + // const { children } = this.props + console.log('render') + + return ( + + + {Children.map(this.props.children.filter(c => c), (child) => { + console.log(child.props.name) + console.log(child.props.id) + if (child.props.id === this.state.selected) { + console.log('if worked selected ' + child.props.id) + // child.setState({ active: true }) + } else { + // child.setState({ active: false }) + } + // return child + return child.props.id === this.state.selected ? cloneElement(child, { active: true, onPress: this.handleTabPress }) : cloneElement(child, { active: false, onPress: this.handleTabPress }) + })} + + + ) + } +} + +// +// +// +// +// + +// +// +// +// + +// {Children.map(children, child => cloneElement(child, { theme }))} + // {Children.map(this.props.children, child => child)} + +const styles = StyleSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + }, + title: { + marginLeft: 3, + marginBottom: 13, + fontSize: 15, + fontWeight: '600', + }, + titleDark: { + color: 'white', + }, + tabContainer: { + height: 60, + flex: 1, + flexDirection: 'row', + justifyContent: 'space-around', + alignItems: 'flex-end', + }, +}) diff --git a/src/ColoredTabs/TabItem.js b/src/ColoredTabs/TabItem.js new file mode 100644 index 0000000..cbbfb81 --- /dev/null +++ b/src/ColoredTabs/TabItem.js @@ -0,0 +1,106 @@ +import React, { Component, PropTypes } from 'react' +import { View, Text, TouchableOpacity, TouchableWithoutFeedback, StyleSheet } from 'react-native' +// import StylePropType from '../utils/StylePropType' + +export default class TabItem extends Component { + static propTypes = { + id: PropTypes.string, + active: PropTypes.bool, + color: PropTypes.string, + name: PropTypes.string, + onPress: PropTypes.func, + } + + static defaultProps = { + active: false, + onPess: () => (console.log('onPess')), + } + + constructor(props) { + super(props) + this.state = { + currentStyle: props.active ? styles.tabContainerActive : styles.tabContainer, + active: props.active, + } + console.log('constructor state ' + this.state) + } + + handlePress = () => { + // this.setState({ active: true }) + this.props.onPress(this.props.id) + } + + render() { + const { + color, + name, + } = this.props + + console.log('item render ' + this.props.id + ' ' + this.state.active + ' ' + this.props.active) + // this.setState({ active: this.props.active }) + + return ( + + + {name.toUpperCase()} + + + ) + } +} + +const styles = StyleSheet.create({ + tabContainer: { + margin: -5, + borderTopLeftRadius: 5, + borderTopRightRadius: 5, + flex: 1, + justifyContent: 'center', + alignItems: 'center', + height: 40, + }, + tabContainerActive: { + margin: -5, + borderTopLeftRadius: 5, + borderTopRightRadius: 5, + flex: 1, + justifyContent: 'center', + alignItems: 'center', + height: 50, + zIndex: 1, + }, + text: { + textAlign: 'center', + color: 'white', + padding: 8, + fontWeight: '500', + }, + containerDark: { + backgroundColor: '#82909d', + }, + containerLight: { + borderWidth: 1, + borderColor: '#dadada', + backgroundColor: '#ffffff', + }, + active: { + backgroundColor: '#742948', + }, + name: { + fontWeight: '600', + }, + nameDark: { + color: 'white', + }, + nameLight: { + color: '#4a4a4a', + }, + activeNameLight: { + color: 'white', + }, +}) diff --git a/src/ColoredTabs/index.js b/src/ColoredTabs/index.js new file mode 100644 index 0000000..311923b --- /dev/null +++ b/src/ColoredTabs/index.js @@ -0,0 +1 @@ +export { default } from './ColoredTabs' diff --git a/uiexplorer/examples/ColoredTabs.js b/uiexplorer/examples/ColoredTabs.js new file mode 100644 index 0000000..f582541 --- /dev/null +++ b/uiexplorer/examples/ColoredTabs.js @@ -0,0 +1,27 @@ +import React from 'react' +import { View, Text, StyleSheet } from 'react-native' +import register from '../core/utils/register' +import ColoredTabs from '../../src/ColoredTabs' + +register.addExample({ + type: 'components', + title: '', + description: 'Star-rating component', + examples: [{ + title: 'Default', + description: 'Without props', + render: () => ( + + + + + + < /ColoredTabs> + ), + }], +}) + +// +// +// +// diff --git a/uiexplorer/examples/index.js b/uiexplorer/examples/index.js index 7003ec5..df8bb69 100644 --- a/uiexplorer/examples/index.js +++ b/uiexplorer/examples/index.js @@ -7,6 +7,7 @@ import './Carousel' import './LabelRating' import './Label' import './RangeSlider' +import './ColoredTabs' // Utils import './ThemeConstants' From 7395dc6945daa1cfd96e3a4685571a25fec54dfd Mon Sep 17 00:00:00 2001 From: dmitriy Date: Mon, 16 Jan 2017 12:30:16 +0200 Subject: [PATCH 02/38] - added onPress listener --- src/ColoredTabs/ColoredTabs.js | 2 ++ uiexplorer/examples/ColoredTabs.js | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ColoredTabs/ColoredTabs.js b/src/ColoredTabs/ColoredTabs.js index df8946f..5ac9cfc 100644 --- a/src/ColoredTabs/ColoredTabs.js +++ b/src/ColoredTabs/ColoredTabs.js @@ -9,6 +9,7 @@ export default class ColoredTabs extends Component { // theme: PropTypes.oneOf(['light', 'dark']), // style: StylePropType, selected: PropTypes.string, + onPress: PropTypes.func, } // static defaultProps = { @@ -26,6 +27,7 @@ export default class ColoredTabs extends Component { this.setState({ selected: id, }) + this.props.onPress(id) } render() { diff --git a/uiexplorer/examples/ColoredTabs.js b/uiexplorer/examples/ColoredTabs.js index f582541..0017bf2 100644 --- a/uiexplorer/examples/ColoredTabs.js +++ b/uiexplorer/examples/ColoredTabs.js @@ -10,8 +10,8 @@ register.addExample({ examples: [{ title: 'Default', description: 'Without props', - render: () => ( - + render: ({ action }) => ( // eslint-disable-line react/prop-types + @@ -21,6 +21,7 @@ register.addExample({ }], }) + // // // From aadc6f9d7889374bef04c53b935627cfe373f203 Mon Sep 17 00:00:00 2001 From: dmitriy Date: Mon, 16 Jan 2017 22:38:26 +0200 Subject: [PATCH 03/38] - added unit and e2e tests --- __tests__/e2e/07_ColoredTabs.test.js | 49 +++++ .../__snapshots__/Storyshots.test.js.snap | 204 ++++++++++++++++++ src/ColoredTabs/ColoredTabs.js | 66 +----- src/ColoredTabs/{TabItem.js => Item.js} | 41 +--- uiexplorer/examples/ColoredTabs.js | 21 +- 5 files changed, 269 insertions(+), 112 deletions(-) create mode 100644 __tests__/e2e/07_ColoredTabs.test.js rename src/ColoredTabs/{TabItem.js => Item.js} (57%) diff --git a/__tests__/e2e/07_ColoredTabs.test.js b/__tests__/e2e/07_ColoredTabs.test.js new file mode 100644 index 0000000..f360297 --- /dev/null +++ b/__tests__/e2e/07_ColoredTabs.test.js @@ -0,0 +1,49 @@ +import test from 'tape-async' +import helper from 'tipsi-appium-helper' + +const { driver, select, idFromXPath } = helper + +test('', async (t) => { + const tabsGroupId = select({ + ios: idFromXPath(`// + XCUIElementTypeApplication[1]/XCUIElementTypeWindow[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/ + XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[2]/XCUIElementTypeOther[1]/ + XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeScrollView[1]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/ + XCUIElementTypeOther[2]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1] + `), + android: idFromXPath(`// + android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.View[1]/ + android.view.View[2]/android.view.View[1]/android.widget.ScrollView[1]/android.view.View[1]/android.view.View[1] + `), + }) + const tagItemId = select({ + ios: idFromXPath(` + ${tabsGroupId}/XCUIElementTypeOther[tabId] + `), + android: idFromXPath(` + ${tabsGroupId}/android.view.View[tabId] + `), + }) + + try { + await helper.openExampleFor('') + + for (const tabId of [1, 2, 3, 4]) { + const currentTabId = select({ + ios: tagItemId.replace('tabId', tabId), + android: tagItemId.replace('tabId', tabId + 1), + }) + await driver.waitForVisible(currentTabId, 20000) + await driver.click(currentTabId) + + t.pass(`tab ${tabId} clicked`) + } + + t.pass(' example should be visible') + } catch (error) { + await helper.screenshot() + await helper.source() + + throw error + } +}) diff --git a/__tests__/unit/__snapshots__/Storyshots.test.js.snap b/__tests__/unit/__snapshots__/Storyshots.test.js.snap index 10cb5bd..d57c0b2 100644 --- a/__tests__/unit/__snapshots__/Storyshots.test.js.snap +++ b/__tests__/unit/__snapshots__/Storyshots.test.js.snap @@ -7215,6 +7215,210 @@ exports[`UIExplorer components Step - Use step prop to specify v `; +exports[`UIExplorer components Simple example - Props: onPress 1`] = ` + + + + + ONE + + + + + TWO + + + + + THREE + + + + + FOUR + + + + +`; + exports[`UIExplorer components Count - Prop: count (Number) 1`] = ` - {Children.map(this.props.children.filter(c => c), (child) => { - console.log(child.props.name) - console.log(child.props.id) - if (child.props.id === this.state.selected) { - console.log('if worked selected ' + child.props.id) - // child.setState({ active: true }) - } else { - // child.setState({ active: false }) - } - // return child - return child.props.id === this.state.selected ? cloneElement(child, { active: true, onPress: this.handleTabPress }) : cloneElement(child, { active: false, onPress: this.handleTabPress }) - })} + {Children.map(this.props.children.filter(c => c), child => ( + child.props.id === this.state.selected ? + cloneElement(child, { active: true, onPress: this.handleTabPress }) : + cloneElement(child, { active: false, onPress: this.handleTabPress }) + ))} ) } } -// -// -// -// -// - -// -// -// -// - -// {Children.map(children, child => cloneElement(child, { theme }))} - // {Children.map(this.props.children, child => child)} - const styles = StyleSheet.create({ container: { flex: 1, @@ -88,15 +45,6 @@ const styles = StyleSheet.create({ justifyContent: 'center', alignItems: 'center', }, - title: { - marginLeft: 3, - marginBottom: 13, - fontSize: 15, - fontWeight: '600', - }, - titleDark: { - color: 'white', - }, tabContainer: { height: 60, flex: 1, diff --git a/src/ColoredTabs/TabItem.js b/src/ColoredTabs/Item.js similarity index 57% rename from src/ColoredTabs/TabItem.js rename to src/ColoredTabs/Item.js index cbbfb81..c5ba2bf 100644 --- a/src/ColoredTabs/TabItem.js +++ b/src/ColoredTabs/Item.js @@ -1,8 +1,7 @@ import React, { Component, PropTypes } from 'react' -import { View, Text, TouchableOpacity, TouchableWithoutFeedback, StyleSheet } from 'react-native' -// import StylePropType from '../utils/StylePropType' +import { View, Text, TouchableWithoutFeedback, StyleSheet } from 'react-native' -export default class TabItem extends Component { +export default class Item extends Component { static propTypes = { id: PropTypes.string, active: PropTypes.bool, @@ -16,17 +15,7 @@ export default class TabItem extends Component { onPess: () => (console.log('onPess')), } - constructor(props) { - super(props) - this.state = { - currentStyle: props.active ? styles.tabContainerActive : styles.tabContainer, - active: props.active, - } - console.log('constructor state ' + this.state) - } - handlePress = () => { - // this.setState({ active: true }) this.props.onPress(this.props.id) } @@ -36,9 +25,6 @@ export default class TabItem extends Component { name, } = this.props - console.log('item render ' + this.props.id + ' ' + this.state.active + ' ' + this.props.active) - // this.setState({ active: this.props.active }) - return ( @@ -80,27 +66,4 @@ const styles = StyleSheet.create({ padding: 8, fontWeight: '500', }, - containerDark: { - backgroundColor: '#82909d', - }, - containerLight: { - borderWidth: 1, - borderColor: '#dadada', - backgroundColor: '#ffffff', - }, - active: { - backgroundColor: '#742948', - }, - name: { - fontWeight: '600', - }, - nameDark: { - color: 'white', - }, - nameLight: { - color: '#4a4a4a', - }, - activeNameLight: { - color: 'white', - }, }) diff --git a/uiexplorer/examples/ColoredTabs.js b/uiexplorer/examples/ColoredTabs.js index 0017bf2..0282777 100644 --- a/uiexplorer/examples/ColoredTabs.js +++ b/uiexplorer/examples/ColoredTabs.js @@ -1,5 +1,4 @@ import React from 'react' -import { View, Text, StyleSheet } from 'react-native' import register from '../core/utils/register' import ColoredTabs from '../../src/ColoredTabs' @@ -8,21 +7,15 @@ register.addExample({ title: '', description: 'Star-rating component', examples: [{ - title: 'Default', - description: 'Without props', + title: 'Simple example', + description: 'Props: onPress', render: ({ action }) => ( // eslint-disable-line react/prop-types - - - - - + (console.log(`Tab with id ${id} is clicked!`) + +const Example = () => ( + + + + + + < /ColoredTabs> +) +``` + +#### Preview + +![tabs_ios](https://cloud.githubusercontent.com/assets/4946753/22029399/1f3905c2-dce3-11e6-8c83-5142fdeb4351.png) +![tabs_android](https://cloud.githubusercontent.com/assets/4946753/22029396/1af713e6-dce3-11e6-8f1a-64e4706bf581.png) + ### `` Component to draw customisable dashed lines @@ -347,13 +393,4 @@ For example let's create `Button` component: }) ``` -4. Update `uiexplorer/examples` entry file (index.js) to export example for our new component: - - ```js - // uiexplorer/examples/index.js - import './StarRating' - // ... - import './Button' // Add this line - ``` - -5. Now you can open `UIExplorer` and click on `