diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9381d85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# IntelliJ +# +.idea + +# OSX +# +.DS_Store + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log +package-lock.log \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..191ade8 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1584395542416 + + + 1584397289497 + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 7388049..ac3dc90 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ -# react-native-select-two +## react-native-select-two ## Component like [Select2](https://select2.org/) on web for React Native -![Single select](https://raw.githubusercontent.com/xuho/demo-images/master/react-native-select2-single-select.gif) ## Add it to your project - Using NPM @@ -17,70 +16,79 @@ 1. [react-native-modal](https://github.com/react-native-community/react-native-modal) 2. [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons) +1. Insall package + - Using NPM + `npm install react-native-select-two` + - Using Yarn + `yarn add react-native-select-two` +2. Import package + `import Select2 from 'react-native-select-two';` ## Usage + + ```javascript -import React, { Component } from "react" -import { View, Text, StyleSheet } from "react-native" -import Select2 from "react-native-select-two" +import React, { Component } from 'react'; +import { View, Text, StyleSheet } from 'react-native'; +import Select2 from 'react-native-select-two'; const mockData = [ - { id: 1, name: "React Native Developer", checked: true }, // set default checked for render option item - { id: 2, name: "Android Developer" }, - { id: 3, name: "iOS Developer" } -] + { id: 1, name: 'React Native Developer', checked: true }, // set default checked for render option item + { id: 2, name: 'Android Developer' }, + { id: 3, name: 'iOS Developer' } +]; // create a component class CreateNewAppointment extends Component { - render() { - return ( - - { - this.setState({ data }) - }} - onRemoveItem={data => { - this.setState({ data }) - }} - /> - - ) - } + render() { + return ( + + { + this.setState({ data }); + }} + onRemoveItem={data => { + this.setState({ data }); + }} + /> + + ); + } } ``` -### Multiple select +## Usage +### Single select +![Single select](https://raw.githubusercontent.com/xuho/demo-images/master/react-native-select2-single-select.gif) +### Multiple select ![Multiple select](https://raw.githubusercontent.com/xuho/demo-images/master/react-native-select2-multipe-select.gif) -## Properties - -| Property name | Type | Default | Description | -| ------------------------- | -------------- | ------------------------------- | ------------------------------------------------------------------------------------------- | -| **style** | _Object_ | none | Custom style for component | -| **modalStyle** | _Object_ | none | Custom style for modal | -| **title** | _String_ | none | String display when you don't select any item | -| **data** | _Array_ | \*required | Datasource of list options: an array of objects (each object have `name` and `id` property) | -| **onSelect** | _Function_ | none | The callback function trigger after you press select button | -| **onRemoveItem** | _Function_ | none | The callback function trigger after you press tags to remove them | -| **popupTitle** | _String_ | none | Title of modal select item | -| **colorTheme** | _string/color_ | #16a45f | Color for componet | -| **isSelectSingle** | _Bool_ | false | Selelect only one option | -| **showSearchBox** | _Bool_ | true | Show or hide search field | -| **cancelButtonText** | _string_ | Hủy | Cancel button text title | -| **selectButtonText** | _String_ | Chọn | Select button text title | -| **searchPlaceHolderText** | _String_ | Nhập vào từ khóa | Placeholder text for search field | -| **listEmptyTitle** | _String_ | Không tìm thấy lựa chọn phù hợp | Title to show when there's no item to be render | -| **defaultFontName** | _String_ | none | Set custom font for all component | -| **selectedTitleStyle** | _Object_ | none | Set custom style for display selected title text | -| **buttonTextStyle** | _Object_ | none | Set custom button text style | -| **buttonStyle** | _Object_ | none | Set custom button style | + + +## Props + +- **`style`** _(Object)_ - Custom style for component +- **`title`** _(String)_ String display when you don't select any item +- **`data`** _(Array)_ - Datasource of list options: an array of objects (each object have ```name``` property) +- **`onSelect`** _(Function)_ - The callback function trigger after you press select button +- **`onRemoveItem`** _(Function)_ - The callback function trigger after you press tags to remove them +- **`popupTitle`** _(String)_ - Title of modal select item +- **`colorTheme`** _(String)_ - Color theme +- **`isSelectSingle`** _(Bool)_ - Set ```false``` if you want select multiple +- **`showSearchBox`** _(Bool)_ - Set ```false``` if you want hide search box, default value is ```true``` +- **`cancelButtonText`** _(String)_ - Cancel button text title +- **`selectButtonText`** _(String)_ - Select button text title +- **`defaultFontName`** _(String)_ - Set custom font for all components +- **`selectedTitlteStyle`** _(Object)_ - Set custom style for display selected title text +- **`buttonTextStyle`** _(Object)_ - Set custom button text style +- **`buttonStyle`** _(Object)_ - Set custom button style **MIT Licensed** diff --git a/index.js b/index.js index 5c94a58..dea1ce1 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,16 @@ //import liraries -import React, { Component } from 'react'; -import { Text, StyleSheet, TouchableOpacity, View, FlatList, TextInput, Dimensions, Animated, Platform } from 'react-native'; +import React, {Component} from 'react'; +import { + Text, + StyleSheet, + TouchableOpacity, + View, + FlatList, + TextInput, + Dimensions, + Animated, + Platform +} from 'react-native'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import Modal from 'react-native-modal'; import Button from './lib/Button'; @@ -8,8 +18,9 @@ import TagItem from './lib/TagItem'; import utilities from './lib/utilities'; import PropTypes from 'prop-types'; -const { height } = Dimensions.get('window'); +const {height} = Dimensions.get('window'); const INIT_HEIGHT = height * 0.6; + // create a component class Select2 extends Component { static defaultProps = { @@ -35,23 +46,45 @@ class Select2 extends Component { this.init(); }; - UNSAFE_componentWillReceiveProps(newProps) { + /** + * @description Add to be able to access this class programmatically + * @author Taha el mahdaoui (taha.elmahdaoui@devkit-sio.net) + * @date 2020-03-16 + * */ + componentWillMount() { + if (this.props.ref) { + this.props.ref(this); + } + } + + componentWillReceiveProps(newProps) { this.init(newProps); } + /** + * @description Add an open method to open the select2 programmatically + * @author Taha el mahdaoui (taha.elmahdaoui@devkit-sio.net) + * @date 2020-03-16 + * */ + open() { + this.setState({ + show: true, + }); + } + init(newProps) { let preSelectedItem = []; - let { data } = newProps || this.props; + let {data} = newProps || this.props; data.map(item => { if (item.checked) { preSelectedItem.push(item); } }) - this.setState({ data, preSelectedItem }); + this.setState({data, preSelectedItem}); } get dataRender() { - let { data, keyword } = this.state; + let {data, keyword} = this.state; let listMappingKeyword = []; data.map(item => { if (utilities.changeAlias(item.name).includes(utilities.changeAlias(keyword))) { @@ -62,12 +95,12 @@ class Select2 extends Component { } get defaultFont() { - let { defaultFontName } = this.props; - return defaultFontName ? { fontFamily: defaultFontName } : {}; + let {defaultFontName} = this.props; + return defaultFontName ? {fontFamily: defaultFontName} : {}; } cancelSelection() { - let { data, preSelectedItem } = this.state; + let {data, preSelectedItem} = this.state; data.map(item => { item.checked = false; for (let _selectedItem of preSelectedItem) { @@ -77,12 +110,12 @@ class Select2 extends Component { } } }); - this.setState({ data, show: false, keyword: '', selectedItem: preSelectedItem }); + this.setState({data, show: false, keyword: '', selectedItem: preSelectedItem}); } onItemSelected = (item, isSelectSingle) => { let selectedItem = []; - let { data } = this.state; + let {data} = this.state; item.checked = !item.checked; for (let index in data) { if (data[index].id === item.id) { @@ -94,11 +127,11 @@ class Select2 extends Component { data.map(item => { if (item.checked) selectedItem.push(item); }) - this.setState({ data, selectedItem }); + this.setState({data, selectedItem}); } keyExtractor = (item, idx) => idx.toString(); - renderItem = ({ item, idx }) => { - let { colorTheme, isSelectSingle } = this.props; + renderItem = ({item, idx}) => { + let {colorTheme, isSelectSingle} = this.props; return ( + name={item.checked ? 'check-circle-outline' : 'radiobox-blank'} + color={item.checked ? colorTheme : '#777777'} size={20}/> ); } renderEmpty = () => { - let { listEmptyTitle } = this.props; + let {listEmptyTitle} = this.props; return ( {listEmptyTitle} ); } - closeModal = () => this.setState({ show: false }); - showModal = () => this.setState({ show: true }); + closeModal = () => this.setState({show: false}); + showModal = () => this.setState({show: true}); render() { let { - style, modalStyle, title, onSelect, onRemoveItem, popupTitle, colorTheme, + style, title, onSelect, onRemoveItem, popupTitle, colorTheme, isSelectSingle, cancelButtonText, selectButtonText, searchPlaceHolderText, - selectedTitleStyle, buttonTextStyle, buttonStyle, showSearchBox + selectedTitlteStyle, buttonTextStyle, buttonStyle, showSearchBox } = this.props; - let { show, selectedItem, preSelectedItem } = this.state; + let {show, selectedItem, preSelectedItem} = this.state; return ( - + - + {popupTitle || title} - + { showSearchBox ? this.setState({ keyword })} + onChangeText={keyword => this.setState({keyword})} onFocus={() => { Animated.spring(this.animatedHeight, { toValue: INIT_HEIGHT + (Platform.OS === 'ios' ? height * 0.2 : 0), @@ -197,7 +230,12 @@ class Select2 extends Component { textColor={colorTheme} backgroundColor='#fff' textStyle={buttonTextStyle} - style={[styles.button, buttonStyle, { marginRight: 5, marginLeft: 10, borderWidth: 1, borderColor: colorTheme }]} /> + style={[styles.button, buttonStyle, { + marginRight: 5, + marginLeft: 10, + borderWidth: 1, + borderColor: colorTheme + }]}/>