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/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 + +} +