diff --git a/README.md b/README.md
index f80f7e6..55d6cc4 100644
--- a/README.md
+++ b/README.md
@@ -143,7 +143,8 @@ export default WelcomeComponent;
| showIconAdd | No | boolean | Set false if you want hide the Add Icon. |
| labelActiveTag | No | object | Custom style for active tag label. |
| tagActiveStyle | No | object | Custom style for active tag. |
-| visibleOnOpen | No | boolean |
+| visibleOnOpen | No | boolean |
+| generateAutoKey | No | boolean | If array is including strings, that can generate key automatically. Default value is false |
diff --git a/index.js b/index.js
index 1bf4b87..40219c8 100644
--- a/index.js
+++ b/index.js
@@ -1,31 +1,38 @@
-import React, { Component } from 'react';
-import { View, TextInput, Text, TouchableOpacity, FlatList, Dimensions } from 'react-native';
-import PropTypes from 'prop-types';
-import Icon from 'react-native-vector-icons/Ionicons';
-
-const { width } = Dimensions.get('window');
+import React, { Component } from "react";
+import {
+ View,
+ TextInput,
+ Text,
+ TouchableOpacity,
+ FlatList,
+ Dimensions
+} from "react-native";
+import PropTypes from "prop-types";
+import Icon from "react-native-vector-icons/Ionicons";
+
+const { width } = Dimensions.get("window");
const styles = {
showTagsWrapper: {
minHeight: 40,
maxHeight: 40,
- alignItems: 'center',
- flexDirection: 'row',
+ alignItems: "center",
+ flexDirection: "row"
},
tagSearchWrapper: {
- flexDirection: 'row',
- alignItems: 'center',
+ flexDirection: "row",
+ alignItems: "center",
paddingLeft: 10,
paddingTop: 0,
borderRadius: 3,
maxHeight: 30,
height: 30,
borderWidth: 1,
- borderColor: '#d4d5d6',
- marginBottom: 5,
+ borderColor: "#d4d5d6",
+ marginBottom: 5
},
showTagsContainer: {
- height: 30,
+ height: 30
},
textInputStyle: {
flex: 1,
@@ -33,14 +40,14 @@ const styles = {
height: 30,
maxHeight: 30,
padding: 0,
- textAlignVertical: 'center',
+ textAlignVertical: "center"
// backgroundColor: 'blue',
},
iconStyle: {
flex: 1,
maxWidth: 20,
marginRight: 5,
- textAlign: 'center',
+ textAlign: "center"
},
eachTag: {
padding: 2,
@@ -48,29 +55,29 @@ const styles = {
paddingLeft: 5,
borderRadius: 2,
borderWidth: 1,
- flexDirection: 'row',
+ flexDirection: "row",
marginRight: 5,
- alignItems: 'center',
- borderColor: '#d7d8d9',
+ alignItems: "center",
+ borderColor: "#d7d8d9"
},
eachTagIcon: {
- color: '#676869',
- marginLeft: 5,
+ color: "#676869",
+ marginLeft: 5
},
eachTagIconAdd: {
- color: '#676869',
- marginRight: 5,
+ color: "#676869",
+ marginRight: 5
},
showAvailTagsView: {
- flexDirection: 'row',
- alignItems: 'center',
+ flexDirection: "row",
+ alignItems: "center"
},
showAvailTagsViewNotFound: {
flex: 1,
- justifyContent: 'center',
- alignItems: 'flex-start',
+ justifyContent: "center",
+ alignItems: "flex-start",
padding: 10,
- paddingLeft: 0,
+ paddingLeft: 0
},
showEachAvailTags: {
padding: 2,
@@ -78,30 +85,30 @@ const styles = {
paddingLeft: 5,
borderRadius: 2,
borderWidth: 1,
- flexDirection: 'row',
+ flexDirection: "row",
marginRight: 5,
- alignItems: 'center',
- justifyContent: 'center',
- borderColor: '#d7d8d9',
+ alignItems: "center",
+ justifyContent: "center",
+ borderColor: "#d7d8d9",
marginBottom: 2,
- marginTop: 2,
+ marginTop: 2
},
notFoundStyle: {
fontSize: 14,
- fontWeight: '500',
+ fontWeight: "500"
},
textActionBtn: {
maxHeight: 20,
- flexDirection: 'row',
+ flexDirection: "row"
},
btnAction: {
lineHeight: 20,
- justifyContent: 'flex-start',
- marginLeft: 5,
+ justifyContent: "flex-start",
+ marginLeft: 5
},
labelActiveTag: {
- fontSize: 14,
- },
+ fontSize: 14
+ }
};
const {
@@ -118,10 +125,9 @@ const {
showAvailTagsView,
showEachAvailTags,
notFoundStyle,
- showAvailTagsViewNotFound,
+ showAvailTagsViewNotFound
} = styles;
-
class MultipleTags extends Component {
constructor(props) {
super(props);
@@ -129,12 +135,11 @@ class MultipleTags extends Component {
tags: [],
searchFilterTag: [],
selectedTag: [],
- previousCharacter: '',
+ previousCharacter: "",
show: false,
totalViewWidth: 0,
totalIndex: 0,
- object: false,
-
+ object: false
};
}
@@ -142,30 +147,55 @@ class MultipleTags extends Component {
this.setAvailableTags(this.props);
}
- setAvailableTags({ tags, preselectedTags, objectValueIdentifier, objectKeyIdentifier }) {
+ setAvailableTags({
+ tags,
+ preselectedTags,
+ objectValueIdentifier,
+ objectKeyIdentifier
+ }) {
let object = false;
- object = typeof tags[0] === 'object';
- this.defaultTags = preselectedTags
- .map(item => (object ? {
- [objectKeyIdentifier]: item[objectKeyIdentifier],
- [objectValueIdentifier]: item[objectValueIdentifier].toLowerCase(),
- } : item.toLowerCase()));
- this.allTags = tags
- .map(item => (object ? {
- [objectKeyIdentifier]: item[objectKeyIdentifier],
- [objectValueIdentifier]: item[objectValueIdentifier].toLowerCase(),
- } : item.toLowerCase()));
- this.tags = tags
- .map(item => (object ? {
- [objectKeyIdentifier]: item[objectKeyIdentifier],
- [objectValueIdentifier]: item[objectValueIdentifier].toLowerCase(),
- } : item.toLowerCase()));
+ object = typeof tags[0] === "object";
+ this.defaultTags = preselectedTags.map(
+ (item, index) =>
+ object
+ ? {
+ [objectKeyIdentifier]: this.props.generateAutoKey
+ ? index.toString()
+ : item[objectKeyIdentifier],
+ [objectValueIdentifier]: item[objectValueIdentifier].toLowerCase()
+ }
+ : item.toLowerCase()
+ );
+ this.allTags = tags.map(
+ (item, index) =>
+ object
+ ? {
+ [objectKeyIdentifier]: this.props.generateAutoKey
+ ? index.toString()
+ : item[objectKeyIdentifier],
+ [objectValueIdentifier]: item[objectValueIdentifier].toLowerCase()
+ }
+ : item.toLowerCase()
+ );
+ this.tags = tags.map(
+ (item, index) =>
+ object
+ ? {
+ [objectKeyIdentifier]: this.props.generateAutoKey
+ ? index.toString()
+ : item[objectKeyIdentifier],
+ [objectValueIdentifier]: item[objectValueIdentifier].toLowerCase()
+ }
+ : item.toLowerCase()
+ );
this.arr = [];
- this.defaultTags.forEach((item) => {
+ this.defaultTags.forEach(item => {
if (
object
- ? this.tags.some(x => x[objectKeyIdentifier] === item[objectKeyIdentifier])
+ ? this.tags.some(
+ x => x[objectKeyIdentifier] === item[objectKeyIdentifier]
+ )
: this.tags.includes(item)
) {
this.arr.push(item);
@@ -173,27 +203,33 @@ class MultipleTags extends Component {
});
for (let i = 0; i < this.arr.length; i += 1) {
const item = this.arr[i];
- this.tags = this.tags
- .filter(value => (
+ this.tags = this.tags.filter(
+ value =>
object
? value[objectKeyIdentifier] !== item[objectKeyIdentifier]
- : value !== item),
- );
+ : value !== item
+ );
}
- this.setState({
- tags: this.allTags,
- searchFilterTag: this.tags,
- selectedTag: this.arr,
- object,
- show: this.props.visibleOnOpen,
- }, this.setOnChangeValue);
+ this.setState(
+ {
+ tags: this.allTags,
+ searchFilterTag: this.tags,
+ selectedTag: this.arr,
+ object,
+ show: this.props.visibleOnOpen
+ },
+ this.setOnChangeValue
+ );
}
- setTagsBasedOnQuery(xhracter = '') {
- this.setState({
- previousCharacter: xhracter,
- }, this.scrollToFirstItem);
+ setTagsBasedOnQuery(xhracter = "") {
+ this.setState(
+ {
+ previousCharacter: xhracter
+ },
+ this.scrollToFirstItem
+ );
}
setOnChangeValue() {
@@ -201,7 +237,7 @@ class MultipleTags extends Component {
}
ucwords(str) {
- return (`${str}`).replace(/^([a-z])|\s+([a-z])/g, $1 => $1.toUpperCase());
+ return `${str}`.replace(/^([a-z])|\s+([a-z])/g, $1 => $1.toUpperCase());
}
scrollToFirstItem() {
@@ -215,11 +251,11 @@ class MultipleTags extends Component {
const formerWidth = this.state.totalViewWidth;
this.setState({
totalViewWidth: formerWidth + event.nativeEvent.layout.width,
- totalIndex: index,
+ totalIndex: index
});
} else {
this.setState({
- totalViewWidth: event.nativeEvent.layout.width,
+ totalViewWidth: event.nativeEvent.layout.width
});
}
}
@@ -228,43 +264,53 @@ class MultipleTags extends Component {
const { selectedTag, object, searchFilterTag } = this.state;
const { objectValueIdentifier } = this.props;
-
- this.arr = searchFilterTag
- .filter(value => (object
- ? value[objectValueIdentifier] !== item[objectValueIdentifier]
- : value !== item
- ),
- );
- this.setState({
- searchFilterTag: this.arr,
- selectedTag: [item, ...selectedTag],
- }, this.setOnChangeValue);
+ this.arr = searchFilterTag.filter(
+ value =>
+ object
+ ? value[objectValueIdentifier] !== item[objectValueIdentifier]
+ : value !== item
+ );
+ this.setState(
+ {
+ searchFilterTag: this.arr,
+ selectedTag: [item, ...selectedTag]
+ },
+ this.setOnChangeValue
+ );
}
removeTag(item) {
const { objectValueIdentifier } = this.props;
const { selectedTag, object, searchFilterTag } = this.state;
- this.selectedTag = selectedTag
- .filter(value => (
+ this.selectedTag = selectedTag.filter(
+ value =>
object
? value[objectValueIdentifier] !== item[objectValueIdentifier]
: value !== item
- ));
+ );
- this.setState({
- selectedTag: this.selectedTag,
- searchFilterTag: [item, ...searchFilterTag],
- }, this.setOnChangeValue);
+ this.setState(
+ {
+ selectedTag: this.selectedTag,
+ searchFilterTag: [item, ...searchFilterTag]
+ },
+ this.setOnChangeValue
+ );
}
showAvailableTags() {
- const { searchHitResponse, defaultTotalRenderedTags, objectValueIdentifier, objectKeyIdentifier } = this.props;
+ const {
+ searchHitResponse,
+ defaultTotalRenderedTags,
+ objectValueIdentifier,
+ objectKeyIdentifier
+ } = this.props;
const { object, tags, selectedTag, previousCharacter } = this.state;
this.newValue = previousCharacter.toLowerCase();
this.filteredTags = [];
- tags.map((item) => {
+ tags.map(item => {
if (
object
? item[objectValueIdentifier].includes(this.newValue)
@@ -272,7 +318,9 @@ class MultipleTags extends Component {
) {
if (
object
- ? !selectedTag.some(x => x[objectValueIdentifier] === item[objectValueIdentifier])
+ ? !selectedTag.some(
+ x => x[objectValueIdentifier] === item[objectValueIdentifier]
+ )
: !selectedTag.includes(item)
) {
if (this.filteredTags.length > defaultTotalRenderedTags) {
@@ -288,20 +336,18 @@ class MultipleTags extends Component {
return (
this.showAvailableTagsRef = ref}
+ ref={ref => (this.showAvailableTagsRef = ref)}
horizontal
data={this.filteredTags}
extraData={previousCharacter}
renderItem={data => this.renderItem(data)}
keyExtractor={data => (object ? data[objectKeyIdentifier] : data)}
showsHorizontalScrollIndicator={false}
- getItemLayout={(data, index) => (
- {
- length: width,
- offset: this.state.totalViewHeight + (this.state.totalIndex * 5),
- index,
- }
- )}
+ getItemLayout={(data, index) => ({
+ length: width,
+ offset: this.state.totalViewHeight + this.state.totalIndex * 5,
+ index
+ })}
/>
);
@@ -309,13 +355,17 @@ class MultipleTags extends Component {
return (
- { searchHitResponse }
+ {searchHitResponse}
);
}
showSelectedTags() {
- const { defaultInstructionClosed, defaultInstructionOpen, objectKeyIdentifier } = this.props;
+ const {
+ defaultInstructionClosed,
+ defaultInstructionOpen,
+ objectKeyIdentifier
+ } = this.props;
const { selectedTag, show, object } = this.state;
if (selectedTag[selectedTag.length - 1] !== undefined) {
@@ -333,7 +383,7 @@ class MultipleTags extends Component {
return (
- { show ? defaultInstructionOpen : defaultInstructionClosed }
+ {show ? defaultInstructionOpen : defaultInstructionClosed}
);
@@ -341,7 +391,7 @@ class MultipleTags extends Component {
changeVisibility() {
this.setState({
- show: !this.state.show,
+ show: !this.state.show
});
}
@@ -351,7 +401,7 @@ class MultipleTags extends Component {
sizeIconTag,
showIconAdd,
iconAddName,
- tagActiveStyle,
+ tagActiveStyle
} = this.props;
const { object } = this.state;
const { objectValueIdentifier } = this.props;
@@ -362,14 +412,17 @@ class MultipleTags extends Component {
onLayout={event => this.eachTagWidth(event, index)}
onPress={() => this.addTag(item)}
>
- {
- showIconAdd
- &&
+ {showIconAdd && (
- }
- { object ? this.ucwords(item[objectValueIdentifier]) : this.ucwords(item) }
+ )}
+
+ {" "}
+ {object
+ ? this.ucwords(item[objectValueIdentifier])
+ : this.ucwords(item)}
+
);
}
@@ -379,12 +432,14 @@ class MultipleTags extends Component {
const { object } = this.state;
const { objectValueIdentifier } = this.props;
return (
- this.removeTag(item)}
- >
- { object ? this.ucwords(item[objectValueIdentifier]) : this.ucwords(item) }
-
+ this.removeTag(item)}>
+
+ {" "}
+ {object
+ ? this.ucwords(item[objectValueIdentifier])
+ : this.ucwords(item)}
+
+
@@ -398,50 +453,40 @@ class MultipleTags extends Component {
this.changeVisibility()}>{title}
- this.changeVisibility()}
- style={btnAction}
- >
+ this.changeVisibility()} style={btnAction}>
-
- {this.showSelectedTags()}
-
- {
- !show || (
-
- {
- !search || (
- searchFilterTag.length === 0 || (
-
- this.setTagsBasedOnQuery(value)}
- placeholder="search..."
- />
-
-
- )
- )
- }
-
- {
- searchFilterTag.length === 0 || (
-
- {this.showAvailableTags()}
-
- )
- }
-
- )
- }
+ {this.showSelectedTags()}
+ {!show || (
+
+ {!search ||
+ (searchFilterTag.length === 0 || (
+
+ this.setTagsBasedOnQuery(value)}
+ placeholder="search..."
+ />
+
+
+ ))}
+
+ {searchFilterTag.length === 0 || (
+ {this.showAvailableTags()}
+ )}
+
+ )}
);
}
@@ -465,24 +510,26 @@ MultipleTags.propTypes = {
visibleOnOpen: PropTypes.bool,
objectValueIdentifier: PropTypes.string,
objectKeyIdentifier: PropTypes.string,
+ generateAutoKey: PropTypes.bool
};
MultipleTags.defaultProps = {
preselectedTags: [],
search: true,
- title: 'Tags',
- searchHitResponse: 'No match was found',
- defaultInstructionClosed: 'Press the down arrow button to pick a tag',
- defaultInstructionOpen: 'Pick a tag with the + icon',
+ title: "Tags",
+ searchHitResponse: "No match was found",
+ defaultInstructionClosed: "Press the down arrow button to pick a tag",
+ defaultInstructionOpen: "Pick a tag with the + icon",
sizeIconTag: 15,
showIconAdd: true,
- iconAddName: 'ios-add-circle-outline',
+ iconAddName: "ios-add-circle-outline",
defaultTotalRenderedTags: 30,
labelActiveTag,
tagActiveStyle: {},
visibleOnOpen: false,
- objectValueIdentifier: 'value',
- objectKeyIdentifier: 'key',
+ objectValueIdentifier: "value",
+ objectKeyIdentifier: "key",
+ generateAutoKey: false
};
export default MultipleTags;