diff --git a/package.json b/package.json index 2a66fc1..44dd857 100644 --- a/package.json +++ b/package.json @@ -5,14 +5,17 @@ "main": "dist", "dependencies": { "babel-runtime": "^6.23.0", + "lodash": "^4.17.11", "moment": "^2.18.1", + "npm": "^6.9.0", "prop-types": "^15.5.8", - "react": "15.x.x", - "react-native": ">=0.40.0", + "react": "^16.6.x", + "react-dom": "^16.6.x", + "react-native": "0.55.x", "react-native-elements": "^0.11.2", "react-native-linear-gradient": "^2.0.0", "react-native-looped-carousel": "^0.1.7", - "react-native-vector-icons": "^4.0.0", + "react-native-vector-icons": "^6.2.0", "react-slick": "^0.14.11", "slick-carousel": "^1.6.0" }, @@ -23,12 +26,9 @@ "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-react-native": "^1.9.1", "json-loader": "^0.5.4", - "react": "15.x.x", - "react-dom": "15.x.x", - "react-native-web": "0.0.94" + "react-native-web": "^0.9.x" }, "scripts": { - "prepublish": ". ./scripts/transpile.sh", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", diff --git a/src/AutoComplete/index.android.js b/src/AutoComplete/index.android.js new file mode 100644 index 0000000..b88b9d0 --- /dev/null +++ b/src/AutoComplete/index.android.js @@ -0,0 +1,247 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import _ from 'lodash' +import { + Keyboard, + VirtualizedList, + Text, + Platform, + StyleSheet, + TextInput, + TouchableOpacity, + View +} from 'react-native'; + +const inbuiltStyles = StyleSheet.create({ + container: { + width: '100%', + ...Platform.select({ + web: { + zIndex: 999, + } + }) + // flexDirection:'row' + } +}); + +export default class AutoComplete extends React.Component { + constructor(props) { + super(props); + this.state = { + cursor: 0, + counter: 0, + allData: props.list, + fullData: props.list, + data: props.list, + query: '', + showList: false, + }; + } + + + //////////////////////////////////////////////////// + handleSearch = (text) => { + const data = _.filter(this.state.fullData, user => { + return this.containsQuery(user, text); + }); + this.setState({query: text, value: text, data, showList: true}) + }; + + containsQuery = ({name}, query) => { + if (name.toLowerCase().includes(query.toLowerCase())) { + return true; + } else { + return false; + } + }; + ///////////////////////////////////////////////////// + + + // arrow up/down button should select next/previous list element and enter key press should simulate item selection + handleKeyDown(e) { + e.persist(); + const {cursor, data} = this.state + if (e.keyCode === 38 && cursor > 0) { + let counter = this.state.counter + --counter; + let c = this.state.cursor; + --c; + this.setState({cursor: c, counter}, () => this.handleScroll('up')) + } else if (e.keyCode === 40 && cursor <= data.length - 1) { + let counter = this.state.counter + ++counter; + let c = this.state.cursor; + ++c; + this.setState({cursor: c, counter}, () => this.handleScroll('down')) + } else { + if (e.key === 'Enter') { + if (this.state.cursor !== 0) { + if (this.props.onItemSelected) + { + this.props.onItemSelected(this.VTListRef.props.data[--this.state.cursor]) + this.setState({value: this.VTListRef.props.data[this.state.cursor][this.props.searchQuery]}) + } + + /*const eventItemName = e.target.nextElementSibling.children[0].children[0].getElementsByClassName('active')[0].children[0].innerText + this.setState({ + showList: false, + }, () => { + this.props.list.map(item => { + if (item[this.props.searchQuery] === eventItemName) { + if (this.props.onItemSelected) { + this.props.onItemSelected(item); + this.setState({value: item[this.props.searchQuery]}) + } + } + }) + });*/ + } + } + } + } + + handleScroll = (scrollType) => { + if (scrollType === 'down') { + if (this.state.counter % Math.floor(this.state.listContainerHeight / this.props.listItemStyle.height) === 0 && this.state.cursor > 0) + this.VTListRef.scrollToIndex({index: this.state.cursor - 1}) + } else if (this.state.cursor > 0) + this.VTListRef.scrollToIndex({index: this.state.cursor - 1}) + } + + + render() { + let index = 0; + const {cursor} = this.state + const propStyles = this.props; + return ( + + { + this.setState({ + showList: false, + cursor: 0, + counter: 0 + }) + }} + onChangeText={value => this.handleSearch(value)} + onKeyPress={(e) => this.handleKeyDown(e)} + /> + {this.state.showList ? + { + let {height} = event.nativeEvent.layout + this.setState({listContainerHeight: height}) + }} + style={[{position: 'absolute', zIndex: 999, marginTop: 40, backgroundColor: '#fff'} + , propStyles.listContainerStyle]}> + data.length} + ref={(ref) => { + this.VTListRef = ref; + }} + keyboardShouldPersistTaps='handled' + getItem={(data, index) => data[index]} + keyExtractor={(item, index) => item.name} + renderItem={ + (rowData, key) => ( + { + let {height} = event.nativeEvent.layout + this.setState({listItemHeight: height}) + }} + style={{backgroundColor: cursor === index ? 'rgba(1, 140, 207, 0.46)' : null}}> + { + this.setState({ + showList: false, + query: rowData.item, + value: rowData.item[this.props.searchQuery] + }, () => { + Keyboard.dismiss() + if (this.props.onItemSelected) + this.props.onItemSelected(this.state.query); + }); + }}> + + {rowData.item[this.props.searchQuery]} + + + + ) + } + /> + + : null + } + + ) + } + +} + +AutoComplete.defaultProps = { + ignoreCase: false, + searchQuery: 'name', + list: [{ + name: 'React', + email: 'react@gmail.com' + }, + { + name: 'Redux', + email: 'Redux@gmail.com' + }, + { + name: 'CSS', + email: 'css3@gmail.com' + }, + { + name: "React Native", + email: 'RN@gmail.com' + }, + { + name: 'GraphQL', + email: 'GraphQL@gmail.com' + }, + { + name: 'python', + email: 'python@gmail.com' + }, + { + name: 'django', + email: 'django@gmail.com' + }, + { + name: 'JavaScript', + email: 'javascript@gmail.com' + }, + { + name: 'Java', + email: 'oracle@gmail.com' + } + ] +}; + +AutoComplete.propTypes = { + placeholder: PropTypes.string, + searchQuery: PropTypes.string, + listContainerStyle: PropTypes.object, + listItemStyle: PropTypes.object, + autoCompleteInputStyle: PropTypes.object, + list: PropTypes.array.isRequired, + ignoreCase: PropTypes.bool, + onItemSelected: PropTypes.func, +}; diff --git a/src/AutoComplete/index.ios.js b/src/AutoComplete/index.ios.js new file mode 100644 index 0000000..b88b9d0 --- /dev/null +++ b/src/AutoComplete/index.ios.js @@ -0,0 +1,247 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import _ from 'lodash' +import { + Keyboard, + VirtualizedList, + Text, + Platform, + StyleSheet, + TextInput, + TouchableOpacity, + View +} from 'react-native'; + +const inbuiltStyles = StyleSheet.create({ + container: { + width: '100%', + ...Platform.select({ + web: { + zIndex: 999, + } + }) + // flexDirection:'row' + } +}); + +export default class AutoComplete extends React.Component { + constructor(props) { + super(props); + this.state = { + cursor: 0, + counter: 0, + allData: props.list, + fullData: props.list, + data: props.list, + query: '', + showList: false, + }; + } + + + //////////////////////////////////////////////////// + handleSearch = (text) => { + const data = _.filter(this.state.fullData, user => { + return this.containsQuery(user, text); + }); + this.setState({query: text, value: text, data, showList: true}) + }; + + containsQuery = ({name}, query) => { + if (name.toLowerCase().includes(query.toLowerCase())) { + return true; + } else { + return false; + } + }; + ///////////////////////////////////////////////////// + + + // arrow up/down button should select next/previous list element and enter key press should simulate item selection + handleKeyDown(e) { + e.persist(); + const {cursor, data} = this.state + if (e.keyCode === 38 && cursor > 0) { + let counter = this.state.counter + --counter; + let c = this.state.cursor; + --c; + this.setState({cursor: c, counter}, () => this.handleScroll('up')) + } else if (e.keyCode === 40 && cursor <= data.length - 1) { + let counter = this.state.counter + ++counter; + let c = this.state.cursor; + ++c; + this.setState({cursor: c, counter}, () => this.handleScroll('down')) + } else { + if (e.key === 'Enter') { + if (this.state.cursor !== 0) { + if (this.props.onItemSelected) + { + this.props.onItemSelected(this.VTListRef.props.data[--this.state.cursor]) + this.setState({value: this.VTListRef.props.data[this.state.cursor][this.props.searchQuery]}) + } + + /*const eventItemName = e.target.nextElementSibling.children[0].children[0].getElementsByClassName('active')[0].children[0].innerText + this.setState({ + showList: false, + }, () => { + this.props.list.map(item => { + if (item[this.props.searchQuery] === eventItemName) { + if (this.props.onItemSelected) { + this.props.onItemSelected(item); + this.setState({value: item[this.props.searchQuery]}) + } + } + }) + });*/ + } + } + } + } + + handleScroll = (scrollType) => { + if (scrollType === 'down') { + if (this.state.counter % Math.floor(this.state.listContainerHeight / this.props.listItemStyle.height) === 0 && this.state.cursor > 0) + this.VTListRef.scrollToIndex({index: this.state.cursor - 1}) + } else if (this.state.cursor > 0) + this.VTListRef.scrollToIndex({index: this.state.cursor - 1}) + } + + + render() { + let index = 0; + const {cursor} = this.state + const propStyles = this.props; + return ( + + { + this.setState({ + showList: false, + cursor: 0, + counter: 0 + }) + }} + onChangeText={value => this.handleSearch(value)} + onKeyPress={(e) => this.handleKeyDown(e)} + /> + {this.state.showList ? + { + let {height} = event.nativeEvent.layout + this.setState({listContainerHeight: height}) + }} + style={[{position: 'absolute', zIndex: 999, marginTop: 40, backgroundColor: '#fff'} + , propStyles.listContainerStyle]}> + data.length} + ref={(ref) => { + this.VTListRef = ref; + }} + keyboardShouldPersistTaps='handled' + getItem={(data, index) => data[index]} + keyExtractor={(item, index) => item.name} + renderItem={ + (rowData, key) => ( + { + let {height} = event.nativeEvent.layout + this.setState({listItemHeight: height}) + }} + style={{backgroundColor: cursor === index ? 'rgba(1, 140, 207, 0.46)' : null}}> + { + this.setState({ + showList: false, + query: rowData.item, + value: rowData.item[this.props.searchQuery] + }, () => { + Keyboard.dismiss() + if (this.props.onItemSelected) + this.props.onItemSelected(this.state.query); + }); + }}> + + {rowData.item[this.props.searchQuery]} + + + + ) + } + /> + + : null + } + + ) + } + +} + +AutoComplete.defaultProps = { + ignoreCase: false, + searchQuery: 'name', + list: [{ + name: 'React', + email: 'react@gmail.com' + }, + { + name: 'Redux', + email: 'Redux@gmail.com' + }, + { + name: 'CSS', + email: 'css3@gmail.com' + }, + { + name: "React Native", + email: 'RN@gmail.com' + }, + { + name: 'GraphQL', + email: 'GraphQL@gmail.com' + }, + { + name: 'python', + email: 'python@gmail.com' + }, + { + name: 'django', + email: 'django@gmail.com' + }, + { + name: 'JavaScript', + email: 'javascript@gmail.com' + }, + { + name: 'Java', + email: 'oracle@gmail.com' + } + ] +}; + +AutoComplete.propTypes = { + placeholder: PropTypes.string, + searchQuery: PropTypes.string, + listContainerStyle: PropTypes.object, + listItemStyle: PropTypes.object, + autoCompleteInputStyle: PropTypes.object, + list: PropTypes.array.isRequired, + ignoreCase: PropTypes.bool, + onItemSelected: PropTypes.func, +}; diff --git a/src/AutoComplete/index.js b/src/AutoComplete/index.js index 5abd8bc..b88b9d0 100644 --- a/src/AutoComplete/index.js +++ b/src/AutoComplete/index.js @@ -1,114 +1,246 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { ListView, Text, TextInput, TouchableOpacity, View } from 'react-native'; +import _ from 'lodash' +import { + Keyboard, + VirtualizedList, + Text, + Platform, + StyleSheet, + TextInput, + TouchableOpacity, + View +} from 'react-native'; -const styles = { +const inbuiltStyles = StyleSheet.create({ container: { - width: 200, - }, - autoCompleteInput: { - width: 200, - height: 40, - }, - listContainer: { - zIndex: 1, - position: 'absolute', - marginTop: 40, - backgroundColor: '#FFF', - width: 'inherit' - }, - listItem: { - height: 40, - justifyContent: 'center', - borderWidth: 2, - borderStyle: 'solid', - borderColor: '#e0e0e0', - borderTopWidth: 0, - }, -}; + width: '100%', + ...Platform.select({ + web: { + zIndex: 999, + } + }) + // flexDirection:'row' + } +}); export default class AutoComplete extends React.Component { constructor(props) { super(props); - - const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); this.state = { + cursor: 0, + counter: 0, allData: props.list, - dataSource: ds.cloneWithRows([]), + fullData: props.list, + data: props.list, query: '', showList: false, }; } + + //////////////////////////////////////////////////// + handleSearch = (text) => { + const data = _.filter(this.state.fullData, user => { + return this.containsQuery(user, text); + }); + this.setState({query: text, value: text, data, showList: true}) + }; + + containsQuery = ({name}, query) => { + if (name.toLowerCase().includes(query.toLowerCase())) { + return true; + } else { + return false; + } + }; + ///////////////////////////////////////////////////// + + + // arrow up/down button should select next/previous list element and enter key press should simulate item selection + handleKeyDown(e) { + e.persist(); + const {cursor, data} = this.state + if (e.keyCode === 38 && cursor > 0) { + let counter = this.state.counter + --counter; + let c = this.state.cursor; + --c; + this.setState({cursor: c, counter}, () => this.handleScroll('up')) + } else if (e.keyCode === 40 && cursor <= data.length - 1) { + let counter = this.state.counter + ++counter; + let c = this.state.cursor; + ++c; + this.setState({cursor: c, counter}, () => this.handleScroll('down')) + } else { + if (e.key === 'Enter') { + if (this.state.cursor !== 0) { + if (this.props.onItemSelected) + { + this.props.onItemSelected(this.VTListRef.props.data[--this.state.cursor]) + this.setState({value: this.VTListRef.props.data[this.state.cursor][this.props.searchQuery]}) + } + + /*const eventItemName = e.target.nextElementSibling.children[0].children[0].getElementsByClassName('active')[0].children[0].innerText + this.setState({ + showList: false, + }, () => { + this.props.list.map(item => { + if (item[this.props.searchQuery] === eventItemName) { + if (this.props.onItemSelected) { + this.props.onItemSelected(item); + this.setState({value: item[this.props.searchQuery]}) + } + } + }) + });*/ + } + } + } + } + + handleScroll = (scrollType) => { + if (scrollType === 'down') { + if (this.state.counter % Math.floor(this.state.listContainerHeight / this.props.listItemStyle.height) === 0 && this.state.cursor > 0) + this.VTListRef.scrollToIndex({index: this.state.cursor - 1}) + } else if (this.state.cursor > 0) + this.VTListRef.scrollToIndex({index: this.state.cursor - 1}) + } + + render() { + let index = 0; + const {cursor} = this.state + const propStyles = this.props; return ( - - + this.setState({showList: false})} - onChangeText={this.onQueryChange}/> - {this.state.showList - && - - ( - { - this.setState({ - showList: false, query: rowData - }, () => { - if (this.props.onItemSelected) - this.props.onItemSelected(this.state.query); - }); - }}> - - {rowData} - - - ) - } - /> - + value={this.state.value} + underlineColorAndroid={'transparent'} + onBlur={() => { + this.setState({ + showList: false, + cursor: 0, + counter: 0 + }) + }} + onChangeText={value => this.handleSearch(value)} + onKeyPress={(e) => this.handleKeyDown(e)} + /> + {this.state.showList ? + { + let {height} = event.nativeEvent.layout + this.setState({listContainerHeight: height}) + }} + style={[{position: 'absolute', zIndex: 999, marginTop: 40, backgroundColor: '#fff'} + , propStyles.listContainerStyle]}> + data.length} + ref={(ref) => { + this.VTListRef = ref; + }} + keyboardShouldPersistTaps='handled' + getItem={(data, index) => data[index]} + keyExtractor={(item, index) => item.name} + renderItem={ + (rowData, key) => ( + { + let {height} = event.nativeEvent.layout + this.setState({listItemHeight: height}) + }} + style={{backgroundColor: cursor === index ? 'rgba(1, 140, 207, 0.46)' : null}}> + { + this.setState({ + showList: false, + query: rowData.item, + value: rowData.item[this.props.searchQuery] + }, () => { + Keyboard.dismiss() + if (this.props.onItemSelected) + this.props.onItemSelected(this.state.query); + }); + }}> + + {rowData.item[this.props.searchQuery]} + + + + ) + } + /> + + : null } ) } - onQueryChange = (value) => { - this.setState({query: value}); - this.filter(value); - }; - - filter = (query) => { - query = query.trim(); - let filteredData = this.state.allData.filter((item) => { - if (this.props.ignoreCase) - return item.toLowerCase().includes(query.toLowerCase()); - - return item.includes(query); - }); - - const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); - this.setState({ - dataSource: ds.cloneWithRows(filteredData), - showList: true - } - ); - }; } AutoComplete.defaultProps = { ignoreCase: false, + searchQuery: 'name', + list: [{ + name: 'React', + email: 'react@gmail.com' + }, + { + name: 'Redux', + email: 'Redux@gmail.com' + }, + { + name: 'CSS', + email: 'css3@gmail.com' + }, + { + name: "React Native", + email: 'RN@gmail.com' + }, + { + name: 'GraphQL', + email: 'GraphQL@gmail.com' + }, + { + name: 'python', + email: 'python@gmail.com' + }, + { + name: 'django', + email: 'django@gmail.com' + }, + { + name: 'JavaScript', + email: 'javascript@gmail.com' + }, + { + name: 'Java', + email: 'oracle@gmail.com' + } + ] }; AutoComplete.propTypes = { placeholder: PropTypes.string, + searchQuery: PropTypes.string, + listContainerStyle: PropTypes.object, + listItemStyle: PropTypes.object, + autoCompleteInputStyle: PropTypes.object, list: PropTypes.array.isRequired, ignoreCase: PropTypes.bool, onItemSelected: PropTypes.func, diff --git a/src/CheckBox/index.android.js b/src/CheckBox/index.android.js new file mode 100644 index 0000000..b575e0e --- /dev/null +++ b/src/CheckBox/index.android.js @@ -0,0 +1,157 @@ +import React from 'react' +import PropTypes from 'prop-types'; +import {View, Text, TouchableOpacity} from 'react-native' + +export default class CheckBox extends React.Component { + constructor(props) { + super(props); + let arr = [] + let i = 0; + props.choices.map(item => { + const obj = { + [`selected${i}`]: false + + } + arr.push(obj) + i++ + }) + + this.state = { + selectedArray: arr + } + } + + + _onPress = (item, index) => { + this.state.selectedArray[index][`selected${index}`]=!this.state.selectedArray[index][`selected${index}`] + this.setState({ + active_index: index + }); + if (this.props.onSelect&&this.state.selectedArray[index][`selected${index}`]===true) { + this.props.onSelect(item, index) + } + + } + + + checkboxTickmark = (isSelected,key) => { + return ( + = 30 ? ((this.props.buttonSize / 2) - 8) : 10, + backgroundColor: this.state.selectedArray[key][`selected${key}`]===true ? this.props.buttonColor : "transparent", + }}/> + ) + } + + checkboxButton = (item, i) => { + let isSelected = false + if (this.state.active_index === i) { + isSelected = true; + } + return ( + + this._onPress(item, i)} + > + + { + this.checkboxTickmark(isSelected,i) + } + + + + {item.option} + + + ) + } + + render() { + return ( + + {this.props.title} + + {this.props.choices.map((choice, key) => this.checkboxButton(choice, key))} + + + ); + } +} + +CheckBox.defaultProps = { + titleStyle: { + fontSize: 21, + color: '#3c3c3c', + fontFamily: 'Nunito' + }, + horizontalLabelOrientation: true, + buttonColor: '#3c3c3c', + buttonSize:15 +} +CheckBox.propTypes = { + /** + * Callback to be invoked when a Check Box Button is selected + */ + onSelect: PropTypes.func, + /** + * Title of the Check Box Button Group + */ + title: PropTypes.string, + /** + * Style of the Check Box Button Title + */ + titleStyle: PropTypes.object, + /** + * Size of the Check Box Button Group wrapper + */ + buttonGroupStyle: PropTypes.object, + /** + * An array of objects of the format {option:''} + */ + choices: PropTypes.arrayOf(PropTypes.shape({ + option: PropTypes.string.isRequired, + })).isRequired, + /** + * A boolean value to set Check Box Button orientation whether Horizontal or Vertical + */ + horizontalButtonOrientation: PropTypes.bool, + /** + * A boolean value to set Check Box Button label's orientation whether Horizontal or Vertical + */ + horizontalLabelOrientation: PropTypes.bool, + /** + * Size of the Check Box Button + */ + buttonSize: PropTypes.number, + /** + * Color of the Check Box Button + */ + buttonColor: PropTypes.string, + +} \ No newline at end of file diff --git a/src/CheckBox/index.ios.js b/src/CheckBox/index.ios.js new file mode 100644 index 0000000..b575e0e --- /dev/null +++ b/src/CheckBox/index.ios.js @@ -0,0 +1,157 @@ +import React from 'react' +import PropTypes from 'prop-types'; +import {View, Text, TouchableOpacity} from 'react-native' + +export default class CheckBox extends React.Component { + constructor(props) { + super(props); + let arr = [] + let i = 0; + props.choices.map(item => { + const obj = { + [`selected${i}`]: false + + } + arr.push(obj) + i++ + }) + + this.state = { + selectedArray: arr + } + } + + + _onPress = (item, index) => { + this.state.selectedArray[index][`selected${index}`]=!this.state.selectedArray[index][`selected${index}`] + this.setState({ + active_index: index + }); + if (this.props.onSelect&&this.state.selectedArray[index][`selected${index}`]===true) { + this.props.onSelect(item, index) + } + + } + + + checkboxTickmark = (isSelected,key) => { + return ( + = 30 ? ((this.props.buttonSize / 2) - 8) : 10, + backgroundColor: this.state.selectedArray[key][`selected${key}`]===true ? this.props.buttonColor : "transparent", + }}/> + ) + } + + checkboxButton = (item, i) => { + let isSelected = false + if (this.state.active_index === i) { + isSelected = true; + } + return ( + + this._onPress(item, i)} + > + + { + this.checkboxTickmark(isSelected,i) + } + + + + {item.option} + + + ) + } + + render() { + return ( + + {this.props.title} + + {this.props.choices.map((choice, key) => this.checkboxButton(choice, key))} + + + ); + } +} + +CheckBox.defaultProps = { + titleStyle: { + fontSize: 21, + color: '#3c3c3c', + fontFamily: 'Nunito' + }, + horizontalLabelOrientation: true, + buttonColor: '#3c3c3c', + buttonSize:15 +} +CheckBox.propTypes = { + /** + * Callback to be invoked when a Check Box Button is selected + */ + onSelect: PropTypes.func, + /** + * Title of the Check Box Button Group + */ + title: PropTypes.string, + /** + * Style of the Check Box Button Title + */ + titleStyle: PropTypes.object, + /** + * Size of the Check Box Button Group wrapper + */ + buttonGroupStyle: PropTypes.object, + /** + * An array of objects of the format {option:''} + */ + choices: PropTypes.arrayOf(PropTypes.shape({ + option: PropTypes.string.isRequired, + })).isRequired, + /** + * A boolean value to set Check Box Button orientation whether Horizontal or Vertical + */ + horizontalButtonOrientation: PropTypes.bool, + /** + * A boolean value to set Check Box Button label's orientation whether Horizontal or Vertical + */ + horizontalLabelOrientation: PropTypes.bool, + /** + * Size of the Check Box Button + */ + buttonSize: PropTypes.number, + /** + * Color of the Check Box Button + */ + buttonColor: PropTypes.string, + +} \ No newline at end of file diff --git a/src/CheckBox/index.js b/src/CheckBox/index.js index 1383252..b575e0e 100644 --- a/src/CheckBox/index.js +++ b/src/CheckBox/index.js @@ -1,49 +1,157 @@ -import React from 'react'; +import React from 'react' import PropTypes from 'prop-types'; -import { CheckBox as CB } from 'react-native-elements'; - +import {View, Text, TouchableOpacity} from 'react-native' export default class CheckBox extends React.Component { constructor(props) { super(props); + let arr = [] + let i = 0; + props.choices.map(item => { + const obj = { + [`selected${i}`]: false + + } + arr.push(obj) + i++ + }) + this.state = { - checked: this.props.checked + selectedArray: arr } } - render() { + + _onPress = (item, index) => { + this.state.selectedArray[index][`selected${index}`]=!this.state.selectedArray[index][`selected${index}`] + this.setState({ + active_index: index + }); + if (this.props.onSelect&&this.state.selectedArray[index][`selected${index}`]===true) { + this.props.onSelect(item, index) + } + + } + + + checkboxTickmark = (isSelected,key) => { return ( - + = 30 ? ((this.props.buttonSize / 2) - 8) : 10, + backgroundColor: this.state.selectedArray[key][`selected${key}`]===true ? this.props.buttonColor : "transparent", + }}/> ) } - onClick = () => { - this.setState({ - checked: !this.state.checked - }, this.afterSetStateCallback); - }; + checkboxButton = (item, i) => { + let isSelected = false + if (this.state.active_index === i) { + isSelected = true; + } + return ( + + this._onPress(item, i)} + > + + { + this.checkboxTickmark(isSelected,i) + } + + + + {item.option} + + + ) + } - afterSetStateCallback = () => { - if (typeof this.props.onCheckedChange === 'function') - this.props.onCheckedChange(this.state.checked) + render() { + return ( + + {this.props.title} + + {this.props.choices.map((choice, key) => this.checkboxButton(choice, key))} + + + ); } } CheckBox.defaultProps = { - checked: false, - checkboxColor: 'black', -}; - + titleStyle: { + fontSize: 21, + color: '#3c3c3c', + fontFamily: 'Nunito' + }, + horizontalLabelOrientation: true, + buttonColor: '#3c3c3c', + buttonSize:15 +} CheckBox.propTypes = { - title: PropTypes.string.isRequired, - checked: PropTypes.bool, - onCheckedChange: PropTypes.func, - checkboxColor: PropTypes.string, -}; \ No newline at end of file + /** + * Callback to be invoked when a Check Box Button is selected + */ + onSelect: PropTypes.func, + /** + * Title of the Check Box Button Group + */ + title: PropTypes.string, + /** + * Style of the Check Box Button Title + */ + titleStyle: PropTypes.object, + /** + * Size of the Check Box Button Group wrapper + */ + buttonGroupStyle: PropTypes.object, + /** + * An array of objects of the format {option:''} + */ + choices: PropTypes.arrayOf(PropTypes.shape({ + option: PropTypes.string.isRequired, + })).isRequired, + /** + * A boolean value to set Check Box Button orientation whether Horizontal or Vertical + */ + horizontalButtonOrientation: PropTypes.bool, + /** + * A boolean value to set Check Box Button label's orientation whether Horizontal or Vertical + */ + horizontalLabelOrientation: PropTypes.bool, + /** + * Size of the Check Box Button + */ + buttonSize: PropTypes.number, + /** + * Color of the Check Box Button + */ + buttonColor: PropTypes.string, + +} \ No newline at end of file diff --git a/src/ProgressBar/index.android.js b/src/ProgressBar/index.android.js index fbc737c..31832af 100644 --- a/src/ProgressBar/index.android.js +++ b/src/ProgressBar/index.android.js @@ -1,23 +1,123 @@ +import React, {Component} from 'react' import PropTypes from 'prop-types'; -import React from 'react'; -import { ProgressBarAndroid } from 'react-native'; +import { + StyleSheet, + Text, + View, + Animated, +} from 'react-native'; + +const styles = StyleSheet.create({ + container: { + width: '100%', + justifyContent: 'center' + }, + + progress_bar_status: { + color: '#3c3c3c', + alignItems: 'center', + justifyContent: 'center', + fontSize: 15, + fontWeight: 'bold', + alignSelf: 'center' + } +}); + + +export default class ProgressBar extends Component { + + constructor(props) { + super(props); + this.progress = new Animated.Value(0); + this.state = {}; + } + + componentWillReceiveProps(nextProps, nextContext) { + if (this.state.completeStatus !== nextProps.completeStatus) { + this._initProgress() + } + } + + _initProgress = () => { + this.progress.addListener((progress) => { + this.setState({ + progress: parseInt(progress.value) + '%' + }); + }); + Animated.timing(this.progress, { + duration: 2000, + toValue: this.props.completeStatus, + // useNativeDriver: true + }).start(); + } + + componentDidUpdate(prevProps, prevState) { + if (prevProps.completeStatus !== this.props.completeStatus) { + this._initProgress() + } + } -export default class ProgressBar extends React.Component { render() { + const animated_width = this.progress.interpolate({ + inputRange: [0, 100], + outputRange: ['0%','100%'] + }); + const {progressColor, ...passThroughProps} = this.props + const {progressBarStatusStyle, ...passThroughStyles} = passThroughProps || {} + const {progressBarContainerStyle, ...moreStyleProps} = passThroughStyles || {} + return ( - - ) + + + + + {this.state.progress} + + + + + ); } + +} + +ProgressBar.defaultProps={ + progressBarStatusStyle: { + height:20, + borderRadius:4 + }, + progressBarContainerStyle:{ + borderWidth: 1, + borderRadius:4, + borderColor: '#333', + backgroundColor: '#ccc' + }, + progressColor:'#5AC6FF' } ProgressBar.propTypes = { - color: PropTypes.string, - indeterminate: PropTypes.bool, - progress: PropTypes.number, -}; \ No newline at end of file + /** + * Percentage of completion without the percentage symbol + */ + completeStatus: PropTypes.number.isRequired, + /** + * Style of the Progress status + */ + progressBarStatusStyle:PropTypes.object, + /** + * Style of the Progress status container + */ + progressBarContainerStyle:PropTypes.object, + /** + * Color of the Progressing bar + */ + progressColor:PropTypes.string + + +} + diff --git a/src/ProgressBar/index.ios.js b/src/ProgressBar/index.ios.js index 27efca1..31832af 100644 --- a/src/ProgressBar/index.ios.js +++ b/src/ProgressBar/index.ios.js @@ -1,22 +1,123 @@ +import React, {Component} from 'react' import PropTypes from 'prop-types'; -import React from 'react'; -import { ProgressViewIOS } from 'react-native'; +import { + StyleSheet, + Text, + View, + Animated, +} from 'react-native'; + +const styles = StyleSheet.create({ + container: { + width: '100%', + justifyContent: 'center' + }, + + progress_bar_status: { + color: '#3c3c3c', + alignItems: 'center', + justifyContent: 'center', + fontSize: 15, + fontWeight: 'bold', + alignSelf: 'center' + } +}); + + +export default class ProgressBar extends Component { + + constructor(props) { + super(props); + this.progress = new Animated.Value(0); + this.state = {}; + } + + componentWillReceiveProps(nextProps, nextContext) { + if (this.state.completeStatus !== nextProps.completeStatus) { + this._initProgress() + } + } + + _initProgress = () => { + this.progress.addListener((progress) => { + this.setState({ + progress: parseInt(progress.value) + '%' + }); + }); + Animated.timing(this.progress, { + duration: 2000, + toValue: this.props.completeStatus, + // useNativeDriver: true + }).start(); + } + + componentDidUpdate(prevProps, prevState) { + if (prevProps.completeStatus !== this.props.completeStatus) { + this._initProgress() + } + } -export default class ProgressBar extends React.Component { render() { + const animated_width = this.progress.interpolate({ + inputRange: [0, 100], + outputRange: ['0%','100%'] + }); + const {progressColor, ...passThroughProps} = this.props + const {progressBarStatusStyle, ...passThroughStyles} = passThroughProps || {} + const {progressBarContainerStyle, ...moreStyleProps} = passThroughStyles || {} + return ( - - ) + + + + + {this.state.progress} + + + + + ); } + +} + +ProgressBar.defaultProps={ + progressBarStatusStyle: { + height:20, + borderRadius:4 + }, + progressBarContainerStyle:{ + borderWidth: 1, + borderRadius:4, + borderColor: '#333', + backgroundColor: '#ccc' + }, + progressColor:'#5AC6FF' } ProgressBar.propTypes = { - color: PropTypes.string, - // TODO: Find a way to make indeterminate progress bar - // indeterminate: PropTypes.bool, - progress: PropTypes.number, -}; \ No newline at end of file + /** + * Percentage of completion without the percentage symbol + */ + completeStatus: PropTypes.number.isRequired, + /** + * Style of the Progress status + */ + progressBarStatusStyle:PropTypes.object, + /** + * Style of the Progress status container + */ + progressBarContainerStyle:PropTypes.object, + /** + * Color of the Progressing bar + */ + progressColor:PropTypes.string + + +} + diff --git a/src/ProgressBar/index.js b/src/ProgressBar/index.js index 6b8064e..d7142b7 100644 --- a/src/ProgressBar/index.js +++ b/src/ProgressBar/index.js @@ -1,27 +1,122 @@ +import React, {Component} from 'react' import PropTypes from 'prop-types'; -import React from 'react'; -import { ProgressBar as PB } from 'react-native-web'; +import { + StyleSheet, + Text, + View, + Animated, +} from 'react-native'; + +const styles = StyleSheet.create({ + container: { + width: '100%', + justifyContent: 'center' + }, + + progress_bar_status: { + color: '#3c3c3c', + alignItems: 'center', + justifyContent: 'center', + fontSize: 15, + fontWeight: 'bold', + alignSelf: 'center' + } +}); + + +export default class ProgressBar extends Component { + + constructor(props) { + super(props); + this.progress = new Animated.Value(0); + this.state = {}; + } + + componentWillReceiveProps(nextProps, nextContext) { + if (this.state.completeStatus !== nextProps.completeStatus) { + this._initProgress() + } + } + + _initProgress = () => { + this.progress.addListener((progress) => { + this.setState({ + progress: parseInt(progress.value) + '%' + }); + }); + Animated.timing(this.progress, { + duration: 2000, + toValue: this.props.completeStatus, + useNativeDriver: true + }).start(); + } + + componentDidUpdate(prevProps, prevState) { + if (prevProps.completeStatus !== this.props.completeStatus) { + this._initProgress() + } + } -export default class ProgressBar extends React.Component { render() { + const animated_width = this.progress.interpolate({ + inputRange: [0, 100], + outputRange: ['0%','100%'] + }); + const {progressColor, ...passThroughProps} = this.props + const {progressBarStatusStyle, ...passThroughStyles} = passThroughProps || {} + const {progressBarContainerStyle, ...moreStyleProps} = passThroughStyles || {} + return ( - - ) + + + + + {this.state.progress} + + + + + ); } + } -ProgressBar.defaultProps = { - trackColor: '#e0e0e0' -}; +ProgressBar.defaultProps={ + progressBarStatusStyle: { + height:20, + borderRadius:4, + }, + progressBarContainerStyle:{ + borderWidth: 1, + borderRadius:4, + borderColor: '#333', + backgroundColor: '#ccc' + }, + progressColor:'#5AC6FF' +} ProgressBar.propTypes = { - color: PropTypes.string, - indeterminate: PropTypes.bool, - progress: PropTypes.number, - trackColor: PropTypes.string, -}; \ No newline at end of file + /** + * Percentage of completion without the percentage symbol + */ + completeStatus: PropTypes.number.isRequired, + /** + * Style of the Progress status + */ + progressBarStatusStyle:PropTypes.object, + /** + * Style of the Progress status container + */ + progressBarContainerStyle:PropTypes.object, + /** + * Color of the Progressing bar + */ + progressColor:PropTypes.string + +} + diff --git a/src/Radio/RadioButton.js b/src/Radio/RadioButton.js deleted file mode 100644 index c5b04a6..0000000 --- a/src/Radio/RadioButton.js +++ /dev/null @@ -1,50 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { CheckBox as RB } from 'react-native-elements'; - - -export default class RadioButton extends React.Component { - constructor(props) { - super(props); - this.state = { - checked: this.props.checked - } - } - - componentWillReceiveProps(nextProps) { - this.setState({ - checked: nextProps.checked - }) - } - - render() { - return ( - - ) - } - - onClick = () => { - this.setState({ - checked: !this.state.checked - }, this.afterSetStateCallback); - }; - - afterSetStateCallback = () => { - if (this.props.onCheckedChange) - this.props.onCheckedChange(this.props.id, this.state.checked) - } -} - -RadioButton.propTypes = { - title: PropTypes.string.isRequired, - checked: PropTypes.bool.isRequired, - onCheckedChange: PropTypes.func, - color: PropTypes.string, -}; \ No newline at end of file diff --git a/src/Radio/RadioGroup.js b/src/Radio/RadioGroup.js deleted file mode 100644 index 0a92e25..0000000 --- a/src/Radio/RadioGroup.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { View } from 'react-native'; -import Label from '../Label'; -import RadioButton from '../Radio/RadioButton'; - -export default class RadioGroup extends React.Component { - constructor(props) { - super(props); - - this.state = { - selectedId: -1 - } - } - - componentWillMount() { - let selectedId = -1; - this.props.children.map((child) => { - // Set a pre selected radio button's id as selectedId - if (child.props.checked) - selectedId = child.props.id; - }); - - this.setState({selectedId}); - } - - render() { - - let choices = this.props.children.map((child) => { - return (); - }); - - return ( - - - ) - } - - onItemChange = (itemId, isChecked) => { - if (this.state.selectedId === itemId && !isChecked) - itemId = -1; - - this.setState({ - selectedId: itemId - }, () => { - this.props.onSelectionChange(this.state.selectedId); - }); - }; -} - -RadioGroup.propTypes = { - title: PropTypes.string.isRequired, - onSelectionChange: PropTypes.func, -}; - diff --git a/src/Radio/index.android.js b/src/Radio/index.android.js new file mode 100644 index 0000000..31b053c --- /dev/null +++ b/src/Radio/index.android.js @@ -0,0 +1,136 @@ +import React from 'react' +import PropTypes from 'prop-types'; +import {View, Text, TouchableOpacity} from 'react-native' + +export default class RadioButton extends React.Component { + constructor(props) { + super(props); + this.state = {} + } + + + _onPress = (item, index) => { + this.setState({ + active_index: index + }); + if (this.props.onSelect) { + this.props.onSelect(item, index) + } + + } + + + renderRadioCircle = (isSelected) => { + return ( + =30?((this.props.buttonSize/2)-8):10, + backgroundColor: isSelected ? this.props.buttonColor : "transparent", + }}/> + ) + } + + renderRadioButton = (item, i) => { + let isSelected = false + if (this.state.active_index === i) { + isSelected = true; + } + return ( + + this._onPress(item, i)} + > + + { + this.renderRadioCircle(isSelected) + } + + + + {item.option} + + + ) + + } + + render() { + return ( + + {this.props.title} + + {this.props.choices.map((choice, key) => this.renderRadioButton(choice, key))} + + + ); + } +} + +RadioButton.defaultProps = { + titleStyle: { + fontSize: 21, + color: '#3c3c3c', + fontFamily: 'Nunito' + }, + horizontalLabelOrientation:true, + buttonColor:'#3c3c3c' +} +RadioButton.propTypes = { + /** + * Callback to be invoked when a Radio Button is selected + */ + onSelect: PropTypes.func, + /** + * Title of the Radio Button Group + */ + title: PropTypes.string, + /** + * Style of the Radio Button Title + */ + titleStyle: PropTypes.object, + /** + * Size of the Radio Button Group wrapper + */ + buttonGroupStyle: PropTypes.object, + /** + * An array of objects of the format {option:''} + */ + choices: PropTypes.arrayOf(PropTypes.shape({ + option: PropTypes.string.isRequired, + })).isRequired, + /** + * A boolean value to set Radio Button orientation whether Horizontal or Vertical + */ + horizontalButtonOrientation: PropTypes.bool, + /** + * A boolean value to set Radio Button label's orientation whether Horizontal or Vertical + */ + horizontalLabelOrientation: PropTypes.bool, + /** + * Size of the Radio Button + */ + buttonSize:PropTypes.number, + /** + * Color of the Radio Button + */ + buttonColor:PropTypes.string, + +} \ No newline at end of file diff --git a/src/Radio/index.ios.js b/src/Radio/index.ios.js new file mode 100644 index 0000000..4a5dfe8 --- /dev/null +++ b/src/Radio/index.ios.js @@ -0,0 +1,138 @@ +import React from 'react' +import PropTypes from 'prop-types'; +import {View, Text, TouchableOpacity} from 'react-native' + +export default class RadioButton extends React.Component { + constructor(props) { + super(props); + this.state = {} + } + + + _onPress = (item, index) => { + this.setState({ + active_index: index + }); + if (this.props.onSelect) { + this.props.onSelect(item, index) + } + + } + + + renderRadioCircle = (isSelected) => { + return ( + =30?((this.props.buttonSize/2)-8):10, + backgroundColor: isSelected ? this.props.buttonColor : "", + }}/> + ) + } + + renderRadioButton = (item, i) => { + let isSelected = false + if (this.state.active_index === i) { + isSelected = true; + } + return ( + + this._onPress(item, i)} + > + + { + this.renderRadioCircle(isSelected) + } + + + + {item.option} + + + ) + + } + + render() { + return ( + + + {this.props.title} + + + {this.props.choices.map((choice, key) => this.renderRadioButton(choice, key))} + + + ); + } +} + +RadioButton.defaultProps = { + titleStyle: { + fontSize: 21, + color: '#3c3c3c', + fontFamily: 'Nunito' + }, + horizontalLabelOrientation:true, + buttonColor:'#3c3c3c' +} +RadioButton.propTypes = { + /** + * Callback to be invoked when a Radio Button is selected + */ + onSelect: PropTypes.func, + /** + * Title of the Radio Button Group + */ + title: PropTypes.string, + /** + * Style of the Radio Button Title + */ + titleStyle: PropTypes.object, + /** + * Size of the Radio Button Group wrapper + */ + buttonGroupStyle: PropTypes.object, + /** + * An array of objects of the format {option:''} + */ + choices: PropTypes.arrayOf(PropTypes.shape({ + option: PropTypes.string.isRequired, + })).isRequired, + /** + * A boolean value to set Radio Button orientation whether Horizontal or Vertical + */ + horizontalButtonOrientation: PropTypes.bool, + /** + * A boolean value to set Radio Button label's orientation whether Horizontal or Vertical + */ + horizontalLabelOrientation: PropTypes.bool, + /** + * Size of the Radio Button + */ + buttonSize:PropTypes.number, + /** + * Color of the Radio Button + */ + buttonColor:PropTypes.string, + +} \ No newline at end of file diff --git a/src/Radio/index.js b/src/Radio/index.js new file mode 100644 index 0000000..73506a6 --- /dev/null +++ b/src/Radio/index.js @@ -0,0 +1,137 @@ +import React from 'react' +import PropTypes from 'prop-types'; +import {View, Text, TouchableOpacity} from 'react-native' + + +export default class RadioButton extends React.Component { + constructor(props) { + super(props); + this.state = {} + } + + + _onPress = (item, index) => { + this.setState({ + active_index: index + }); + if (this.props.onSelect) { + this.props.onSelect(item, index) + } + + } + + + renderRadioCircle = (isSelected) => { + return ( + =30?((this.props.buttonSize/2)-8):10, + backgroundColor: isSelected ? this.props.buttonColor : "transparent", + }}/> + ) + } + + renderRadioButton = (item, i) => { + let isSelected = false + if (this.state.active_index === i) { + isSelected = true; + } + return ( + + this._onPress(item, i)} + > + + { + this.renderRadioCircle(isSelected) + } + + + + {item.option} + + + ) + + } + + render() { + return ( + + {this.props.title} + + {this.props.choices.map((choice, key) => this.renderRadioButton(choice, key))} + + + ); + } +} + +RadioButton.defaultProps = { + titleStyle: { + fontSize: 21, + color: '#3c3c3c', + fontFamily: 'Nunito' + }, + horizontalLabelOrientation:true, + buttonColor:'#3c3c3c' +} +RadioButton.propTypes = { + /** + * Callback to be invoked when a Radio Button is selected + */ + onSelect: PropTypes.func, + /** + * Title of the Radio Button Group + */ + title: PropTypes.string, + /** + * Style of the Radio Button Title + */ + titleStyle: PropTypes.object, + /** + * Size of the Radio Button Group wrapper + */ + buttonGroupStyle: PropTypes.object, + /** + * An array of objects of the format {option:''} + */ + choices: PropTypes.arrayOf(PropTypes.shape({ + option: PropTypes.string.isRequired, + })).isRequired, + /** + * A boolean value to set Radio Button orientation whether Horizontal or Vertical + */ + horizontalButtonOrientation: PropTypes.bool, + /** + * A boolean value to set Radio Button label's orientation whether Horizontal or Vertical + */ + horizontalLabelOrientation: PropTypes.bool, + /** + * Size of the Radio Button + */ + buttonSize:PropTypes.number, + /** + * Color of the Radio Button + */ + buttonColor:PropTypes.string, + +} \ No newline at end of file