From 3e81fcb5b842113e15d3d883d21826d51b4cf543 Mon Sep 17 00:00:00 2001 From: Ibrahim Almuqrin Date: Mon, 8 Apr 2019 04:55:05 +0300 Subject: [PATCH 1/2] Added subDisplayKey option To make it easier to use localized arrays --- README.md | 154 +++++++++++++++++++++++----------- lib/components/RowItem.js | 71 ++++++++-------- lib/components/RowSubItem.js | 5 +- lib/sectioned-multi-select.js | 21 +++-- 4 files changed, 158 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index 9d4a6d2..29a6963 100644 --- a/README.md +++ b/README.md @@ -45,62 +45,113 @@ const icon = require('./icon.png'); const items = [ { - name: "Fruits", + name: { + en: "Fruits", + ar: "فواكه" + }, id: 0, icon: icon, // Make sure the icon const is set, or you can remove this children: [{ - name: "Apple", + name: { + en: "Apple", + ar: "تفاح" + }, id: 10, },{ - name: "Strawberry", + name: { + en: "Strawberry", + ar: "فراولة" + }, id: 17, },{ - name: "Pineapple", + name: { + en: "Pineapple", + ar: "أناناس" + }, id: 13, },{ - name: "Banana", + name: { + en: "Banana", + ar: "موز" + }, id: 14, },{ - name: "Watermelon", + name: { + en: "Watermelon", + ar: "بطيخ" + }, id: 15, },{ - name: "Kiwi fruit", + name: { + en: "Kiwi fruit", + ar: "كيوي" + }, id: 16, }] }, { - name: "Gems", + name: { + en: "Gems", + ar: "ألعاب" + }, id: 1, icon: { uri: "https://cdn4.iconfinder.com/data/icons/free-crystal-icons/512/Gemstone.png" }, // web uri children: [{ - name: "Quartz", + name: { + en: "Quartz", + ar: "كوارتز" + }, id: 20, },{ - name: "Zircon", + name: { + en: "Zircon", + ar: "زيركون" + }, id: 21, },{ - name: "Sapphire", + name: { + en: "Sapphire", + ar: "سفاير" + }, id: 22, },{ - name: "Topaz", + name: { + en: "Topaz", + ar: "توباز" + }, id: 23, }] }, { - name: "Plants", + name: { + en: "Plants", + ar: "نباتات" + }, id: 2, icon: "filter_vintage", // material icons icon name children: [{ - name: "Mother In Law\'s Tongue", + name: { + en: "Mother In Law\'s Tongue", + ar: "لسان العفريت" + }, id: 30, },{ - name: "Yucca", + name: { + en: "Yucca", + ar: "يكة" + }, id: 31, },{ - name: "Monsteria", + name: { + en: "Monsteria", + ar: "قشطة دندروم" + }, id: 32, },{ - name: "Palm", + name: { + en: "Palm", + ar: "نخلة" + }, id: 33, }] }, @@ -118,6 +169,9 @@ export default class App extends Component { } render() { + const { locale } = this.props + const language = locale == 'ar' ? 'ar' : 'en' + return ( @@ -125,6 +179,7 @@ export default class App extends Component { items={items} uniqueKey='id' subKey='children' + subDisplayKey={language} iconKey='icon' selectText='Choose some things...' showDropDowns={true} @@ -180,6 +235,7 @@ Props, there are lots. | uniqueKey | 'id' | string | the unique key for your items | | subKey | 'sub' | string | the array of sub items within items | | displayKey | 'name' | string | the key for the display name / title of the item | +| subDisplayKey | null | string | when the title is in a sub item, set `displayKey` to the parent item and `subDisplayKey` to the child item | | iconKey | | string | the key for the display icon / bitmap of the item | | selectedItems | [] | array | the selected items | | onSelectedItemsChange | | function | function that runs when an item is toggled | @@ -216,38 +272,38 @@ Props, there are lots. | Prop | Default | type | Desc | | ------------------------------- | ------------------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| selectText | 'Select' | string | the text for the select component | -| confirmText | 'Confirm' | string | the text for the confirm button | -| selectedText | 'selected' | string OR function | the text that follows the number of items selected | -| renderSelectText | | function | Function that allows you to set custom Select Text given access to component's `props` | -| searchPlaceholderText | 'Search categories...' | string | the placeholder text for the search input | -| searchAdornment | | | function | receives search input text and is output on the right side of the search input | -| removeAllText | 'Remove all' | string | Text for optional remove all button | -| filterItems | null | function | Use a custom filtering function for the search: receives searchText, items, props. Should return an array of item objects. | -| headerComponent | undefined | object | optional component to display above the search bar | -| footerComponent | undefined | object | optional component to display below the confirm button | -| stickyFooterComponent | undefined | object | optional component to display below the confirm button, but outside of the scroll view | -| noResultsComponent | Sorry, no results | object | the component to display when the search results are empty | -| loadingComponent | `ActivityIndicator` | object | the component to display when `loading` is set to true | -| noItemsComponent | No Items | object | Shown when the items array is empty / null | -| selectToggleIconComponent | Material `keyboard-arrow-down` | object | The icon to the right of the dropdown in its initial state ) | -| searchIconComponent | Material `search` | object | The search input icon (default Magnifying glass) | -| selectedIconComponent | Material `check` | object | The icon component to the left of the selected item (default Checkmark) | -| unselectedIconComponent | | object | The icon component to the left of the unselected item | -| dropDownToggleIconUpComponent | Material `keyboard-arrow-up` | object | The parent dropdown icon in closed state | -| dropDownToggleIconDownComponent | Material `keyboard-arrow-down` | object | The parent dropdown icon in opened state | -| cancelIconComponent | Material `cancel` | object | The cancel button's inner component | -| customChipsRenderer | | function | Use a custom render function for custom chips: receives uniqueKey, subKey, displayKey, items, selectedItems, colors, styles. should return valid jsx | -| chipRemoveIconComponent | Material `close` | object | The chip remove button's icon component | -| styles | {} | object | Styles object - see styles section | -| colors | {...} | object | colors object - see colors section | -| itemFontFamily | Avenir / normal - bold | object | font family for the parent items. Can be a regular style object | -| subItemFontFamily | Avenir / normal - 200 | object | font family for the sub items. Can be a regular style object | -| searchTextFontFamily | Avenir / normal - 200 | object | font family for the search input. Can be a regular style object | -| confirmFontFamily | Avenir / normal - bold | object | font family for the confirm button. | -| itemNumberOfLines | null | number | numberOfLines for item text | -| selectLabelNumberOfLines | 1 | number | numberOfLines for select label text | -| customLayoutAnimation | easeInEaseOut | object | define your own `LayoutAnimation` preset or custom animation | +| selectText | 'Select' | string | the text for the select component | +| confirmText | 'Confirm' | string | the text for the confirm button | +| selectedText | 'selected' | string OR function | the text that follows the number of items selected | +| renderSelectText | | function | Function that allows you to set custom Select Text given access to component's `props` | +| searchPlaceholderText | 'Search categories...' | string | the placeholder text for the search input | +| searchAdornment | | | function | receives search input text and is output on the right side of the search input | +| removeAllText | 'Remove all' | string | Text for optional remove all button | +| filterItems | null | function | Use a custom filtering function for the search: receives searchText, items, props. Should return an array of item objects. | +| headerComponent | undefined | object | optional component to display above the search bar | +| footerComponent | undefined | object | optional component to display below the confirm button | +| stickyFooterComponent | undefined | object | optional component to display below the confirm button, but outside of the scroll view | +| noResultsComponent | Sorry, no results | object | the component to display when the search results are empty | +| loadingComponent | `ActivityIndicator` | object | the component to display when `loading` is set to true | +| noItemsComponent | No Items | object | Shown when the items array is empty / null | +| selectToggleIconComponent | Material `keyboard-arrow-down` | object | The icon to the right of the dropdown in its initial state ) | +| searchIconComponent | Material `search` | object | The search input icon (default Magnifying glass) | +| selectedIconComponent | Material `check` | object | The icon component to the left of the selected item (default Checkmark) | +| unselectedIconComponent | | object | The icon component to the left of the unselected item | +| dropDownToggleIconUpComponent | Material `keyboard-arrow-up` | object | The parent dropdown icon in closed state | +| dropDownToggleIconDownComponent | Material `keyboard-arrow-down` | object | The parent dropdown icon in opened state | +| cancelIconComponent | Material `cancel` | object | The cancel button's inner component | +| customChipsRenderer | | function | Use a custom render function for custom chips: receives uniqueKey, subKey, displayKey, subDisplayKey, items, selectedItems, colors, styles. should return valid jsx | +| chipRemoveIconComponent | Material `close` | object | The chip remove button's icon component | +| styles | {} | object | Styles object - see styles section | +| colors | {...} | object | colors object - see colors section | +| itemFontFamily | Avenir / normal - bold | object | font family for the parent items. Can be a regular style object | +| subItemFontFamily | Avenir / normal - 200 | object | font family for the sub items. Can be a regular style object | +| searchTextFontFamily | Avenir / normal - 200 | object | font family for the search input. Can be a regular style object | +| confirmFontFamily | Avenir / normal - bold | object | font family for the confirm button. | +| itemNumberOfLines | null | number | numberOfLines for item text | +| selectLabelNumberOfLines | 1 | number | numberOfLines for select label text | +| customLayoutAnimation | easeInEaseOut | object | define your own `LayoutAnimation` preset or custom animation | ## Colors diff --git a/lib/components/RowItem.js b/lib/components/RowItem.js index 7bcfa05..2457964 100644 --- a/lib/components/RowItem.js +++ b/lib/components/RowItem.js @@ -50,7 +50,7 @@ class RowItem extends Component { if (this.props.searchTerm !== nextProps.searchTerm) { return true - } + } if (this.state.showSubCategories !== nextState.showSubCategories) { return true } @@ -144,7 +144,7 @@ class RowItem extends Component { height: StyleSheet.hairlineWidth, alignSelf: 'stretch', backgroundColor: '#dadada', - }, this.props.mergedStyles.subSeparator]} + }, this.props.mergedStyles.subSeparator]} /> ) @@ -164,6 +164,7 @@ class RowItem extends Component { dropDownToggleIconDownComponent, itemNumberOfLines, displayKey, + subDisplayKey, selectedItems, iconKey } = this.props @@ -198,25 +199,25 @@ class RowItem extends Component { flex: 1, color: item.disabled ? mergedColors.disabled : mergedColors.text }, - itemFontFamily, + itemFontFamily, mergedStyles.itemText, this._itemSelected(item) && mergedStyles.selectedItemText - ]} + ]} > - {item[displayKey]} + {subDisplayKey?item[displayKey][subDisplayKey]:item[displayKey]} { - this._itemSelected(item) ? - selectedIconComponent ? - selectedIconComponent - : - : + this._itemSelected(item) ? + selectedIconComponent ? + selectedIconComponent + : + : unselectedIconComponent ? unselectedIconComponent: null } @@ -233,34 +234,34 @@ class RowItem extends Component { { this._showSubCategoryDropDown() ? { dropDownToggleIconUpComponent ? dropDownToggleIconUpComponent - : - + : + } - : + : { dropDownToggleIconDownComponent ? dropDownToggleIconDownComponent - : - + : + } } } - { item[subKey] && this._showSubCategoryDropDown() && + { item[subKey] && this._showSubCategoryDropDown() && `${i[uniqueKey]}`} data={item[subKey]} diff --git a/lib/components/RowSubItem.js b/lib/components/RowSubItem.js index d021aa1..bf4ad36 100644 --- a/lib/components/RowSubItem.js +++ b/lib/components/RowSubItem.js @@ -58,12 +58,13 @@ class RowSubItem extends Component { highlightedChildren, itemNumberOfLines, displayKey, + subDisplayKey, iconKey } = this.props const highlightChild = !selectChildren && highlightedChildren.includes(subItem[uniqueKey]) const itemSelected = this._itemSelected() - + return ( - {subItem[displayKey]} + {subDisplayKey? subItem[displayKey][subDisplayKey]:subItem[displayKey]} { itemSelected || highlightChild ? diff --git a/lib/sectioned-multi-select.js b/lib/sectioned-multi-select.js index 3e08b3f..6ba2bda 100644 --- a/lib/sectioned-multi-select.js +++ b/lib/sectioned-multi-select.js @@ -143,7 +143,8 @@ class SectionedMultiSelect extends PureComponent { single: PropTypes.bool, selectedItems: PropTypes.array, items: PropTypes.array, - displayKey: PropTypes.string, + displayKey: PropTypes.string || PropTypes.object, + subDisplayKey: PropTypes.string, uniqueKey: PropTypes.string.isRequired, subKey: PropTypes.string, onSelectedItemsChange: PropTypes.func.isRequired, @@ -217,6 +218,7 @@ class SectionedMultiSelect extends PureComponent { single: false, selectedItems: [], displayKey: 'name', + subDisplayKey: null, showDropDowns: true, showChips: true, readOnlyHeadings: false, @@ -281,7 +283,7 @@ class SectionedMultiSelect extends PureComponent { // componentWillUpdate() { date = new Date();} // componentDidUpdate() {console.log(new Date().valueOf() - date.valueOf())} - getProp = (object, key) => object && object[key] + getProp = (object, key, subKey) => subKey ? object && object[key] && object[key][subKey] : object && object[key] rejectProp = (items, fn) => items.filter(fn) @@ -322,6 +324,7 @@ class SectionedMultiSelect extends PureComponent { single, selectedItems, displayKey, + subDisplayKey, alwaysShowSelectText, renderSelectText, } = this.props @@ -338,7 +341,7 @@ class SectionedMultiSelect extends PureComponent { } else if (single || selectedItems.length === 1) { const item = selectedItems[0] const foundItem = this._findItem(item) - return this.getProp(foundItem, displayKey) || selectText + return this.getProp(foundItem, displayKey, subDisplayKey) || selectText } return `${selectText} (${selectedItems.length} ${selectedText})` } @@ -349,6 +352,7 @@ class SectionedMultiSelect extends PureComponent { subKey, uniqueKey, displayKey, + subDisplayKey, filterItems, } = this.props @@ -362,14 +366,14 @@ class SectionedMultiSelect extends PureComponent { const parts = searchTerm.replace(/[\^$\\.*+?()[\]{}|]/g, '\\$&').trim().split(' ') const regex = new RegExp(`(${parts.join('|')})`, 'i') - if (regex.test(this.getProp(item, displayKey))) { + if (regex.test(this.getProp(item, displayKey, subDisplayKey))) { filteredItems.push(item) } if (item[subKey]) { const newItem = Object.assign({}, item) newItem[subKey] = [] item[subKey].forEach((sub) => { - if (regex.test(this.getProp(sub, displayKey))) { + if (regex.test(this.getProp(sub, displayKey, subDisplayKey))) { newItem[subKey] = [...newItem[subKey], sub] newFilteredItems = this.rejectProp(filteredItems, singleItem => item[uniqueKey] !== singleItem[uniqueKey]) @@ -644,6 +648,7 @@ class SectionedMultiSelect extends PureComponent { const { styles, colors } = this.state const { displayKey, + subDisplayKey, items, selectedItems, subKey, @@ -655,6 +660,7 @@ class SectionedMultiSelect extends PureComponent { customChipsRenderer({ colors, displayKey, + subDisplayKey, items, selectedItems, styles, @@ -735,13 +741,14 @@ class SectionedMultiSelect extends PureComponent { uniqueKey, selectedItems, displayKey, + subDisplayKey, chipRemoveIconComponent, } = this.props const { styles, colors } = this.state return selectedItems.map((singleSelectedItem) => { const item = this._findItem(singleSelectedItem) - if (!item || !item[displayKey]) return null + if (subDisplayKey ? !item || !item[displayKey][subDisplayKey] : !item || !item[displayKey]) return null return ( @@ -773,7 +780,7 @@ class SectionedMultiSelect extends PureComponent { }, styles.chipText]} > - {item[displayKey]} + {subDisplayKey ? item[displayKey][subDisplayKey] : item[displayKey]} { this._removeItem(item) }} From 39fa93e50937c6a338ec10efcd64258ffc5704c3 Mon Sep 17 00:00:00 2001 From: Ibrahim Almuqrin Date: Wed, 10 Apr 2019 11:17:53 +0300 Subject: [PATCH 2/2] Added subDisplayKey option To make it easier to use localized arrays --- README.md | 154 +++++++++++++++++++++++----------- lib/components/RowItem.js | 71 ++++++++-------- lib/components/RowSubItem.js | 5 +- lib/sectioned-multi-select.js | 21 +++-- 4 files changed, 158 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index 9d4a6d2..29a6963 100644 --- a/README.md +++ b/README.md @@ -45,62 +45,113 @@ const icon = require('./icon.png'); const items = [ { - name: "Fruits", + name: { + en: "Fruits", + ar: "فواكه" + }, id: 0, icon: icon, // Make sure the icon const is set, or you can remove this children: [{ - name: "Apple", + name: { + en: "Apple", + ar: "تفاح" + }, id: 10, },{ - name: "Strawberry", + name: { + en: "Strawberry", + ar: "فراولة" + }, id: 17, },{ - name: "Pineapple", + name: { + en: "Pineapple", + ar: "أناناس" + }, id: 13, },{ - name: "Banana", + name: { + en: "Banana", + ar: "موز" + }, id: 14, },{ - name: "Watermelon", + name: { + en: "Watermelon", + ar: "بطيخ" + }, id: 15, },{ - name: "Kiwi fruit", + name: { + en: "Kiwi fruit", + ar: "كيوي" + }, id: 16, }] }, { - name: "Gems", + name: { + en: "Gems", + ar: "ألعاب" + }, id: 1, icon: { uri: "https://cdn4.iconfinder.com/data/icons/free-crystal-icons/512/Gemstone.png" }, // web uri children: [{ - name: "Quartz", + name: { + en: "Quartz", + ar: "كوارتز" + }, id: 20, },{ - name: "Zircon", + name: { + en: "Zircon", + ar: "زيركون" + }, id: 21, },{ - name: "Sapphire", + name: { + en: "Sapphire", + ar: "سفاير" + }, id: 22, },{ - name: "Topaz", + name: { + en: "Topaz", + ar: "توباز" + }, id: 23, }] }, { - name: "Plants", + name: { + en: "Plants", + ar: "نباتات" + }, id: 2, icon: "filter_vintage", // material icons icon name children: [{ - name: "Mother In Law\'s Tongue", + name: { + en: "Mother In Law\'s Tongue", + ar: "لسان العفريت" + }, id: 30, },{ - name: "Yucca", + name: { + en: "Yucca", + ar: "يكة" + }, id: 31, },{ - name: "Monsteria", + name: { + en: "Monsteria", + ar: "قشطة دندروم" + }, id: 32, },{ - name: "Palm", + name: { + en: "Palm", + ar: "نخلة" + }, id: 33, }] }, @@ -118,6 +169,9 @@ export default class App extends Component { } render() { + const { locale } = this.props + const language = locale == 'ar' ? 'ar' : 'en' + return ( @@ -125,6 +179,7 @@ export default class App extends Component { items={items} uniqueKey='id' subKey='children' + subDisplayKey={language} iconKey='icon' selectText='Choose some things...' showDropDowns={true} @@ -180,6 +235,7 @@ Props, there are lots. | uniqueKey | 'id' | string | the unique key for your items | | subKey | 'sub' | string | the array of sub items within items | | displayKey | 'name' | string | the key for the display name / title of the item | +| subDisplayKey | null | string | when the title is in a sub item, set `displayKey` to the parent item and `subDisplayKey` to the child item | | iconKey | | string | the key for the display icon / bitmap of the item | | selectedItems | [] | array | the selected items | | onSelectedItemsChange | | function | function that runs when an item is toggled | @@ -216,38 +272,38 @@ Props, there are lots. | Prop | Default | type | Desc | | ------------------------------- | ------------------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| selectText | 'Select' | string | the text for the select component | -| confirmText | 'Confirm' | string | the text for the confirm button | -| selectedText | 'selected' | string OR function | the text that follows the number of items selected | -| renderSelectText | | function | Function that allows you to set custom Select Text given access to component's `props` | -| searchPlaceholderText | 'Search categories...' | string | the placeholder text for the search input | -| searchAdornment | | | function | receives search input text and is output on the right side of the search input | -| removeAllText | 'Remove all' | string | Text for optional remove all button | -| filterItems | null | function | Use a custom filtering function for the search: receives searchText, items, props. Should return an array of item objects. | -| headerComponent | undefined | object | optional component to display above the search bar | -| footerComponent | undefined | object | optional component to display below the confirm button | -| stickyFooterComponent | undefined | object | optional component to display below the confirm button, but outside of the scroll view | -| noResultsComponent | Sorry, no results | object | the component to display when the search results are empty | -| loadingComponent | `ActivityIndicator` | object | the component to display when `loading` is set to true | -| noItemsComponent | No Items | object | Shown when the items array is empty / null | -| selectToggleIconComponent | Material `keyboard-arrow-down` | object | The icon to the right of the dropdown in its initial state ) | -| searchIconComponent | Material `search` | object | The search input icon (default Magnifying glass) | -| selectedIconComponent | Material `check` | object | The icon component to the left of the selected item (default Checkmark) | -| unselectedIconComponent | | object | The icon component to the left of the unselected item | -| dropDownToggleIconUpComponent | Material `keyboard-arrow-up` | object | The parent dropdown icon in closed state | -| dropDownToggleIconDownComponent | Material `keyboard-arrow-down` | object | The parent dropdown icon in opened state | -| cancelIconComponent | Material `cancel` | object | The cancel button's inner component | -| customChipsRenderer | | function | Use a custom render function for custom chips: receives uniqueKey, subKey, displayKey, items, selectedItems, colors, styles. should return valid jsx | -| chipRemoveIconComponent | Material `close` | object | The chip remove button's icon component | -| styles | {} | object | Styles object - see styles section | -| colors | {...} | object | colors object - see colors section | -| itemFontFamily | Avenir / normal - bold | object | font family for the parent items. Can be a regular style object | -| subItemFontFamily | Avenir / normal - 200 | object | font family for the sub items. Can be a regular style object | -| searchTextFontFamily | Avenir / normal - 200 | object | font family for the search input. Can be a regular style object | -| confirmFontFamily | Avenir / normal - bold | object | font family for the confirm button. | -| itemNumberOfLines | null | number | numberOfLines for item text | -| selectLabelNumberOfLines | 1 | number | numberOfLines for select label text | -| customLayoutAnimation | easeInEaseOut | object | define your own `LayoutAnimation` preset or custom animation | +| selectText | 'Select' | string | the text for the select component | +| confirmText | 'Confirm' | string | the text for the confirm button | +| selectedText | 'selected' | string OR function | the text that follows the number of items selected | +| renderSelectText | | function | Function that allows you to set custom Select Text given access to component's `props` | +| searchPlaceholderText | 'Search categories...' | string | the placeholder text for the search input | +| searchAdornment | | | function | receives search input text and is output on the right side of the search input | +| removeAllText | 'Remove all' | string | Text for optional remove all button | +| filterItems | null | function | Use a custom filtering function for the search: receives searchText, items, props. Should return an array of item objects. | +| headerComponent | undefined | object | optional component to display above the search bar | +| footerComponent | undefined | object | optional component to display below the confirm button | +| stickyFooterComponent | undefined | object | optional component to display below the confirm button, but outside of the scroll view | +| noResultsComponent | Sorry, no results | object | the component to display when the search results are empty | +| loadingComponent | `ActivityIndicator` | object | the component to display when `loading` is set to true | +| noItemsComponent | No Items | object | Shown when the items array is empty / null | +| selectToggleIconComponent | Material `keyboard-arrow-down` | object | The icon to the right of the dropdown in its initial state ) | +| searchIconComponent | Material `search` | object | The search input icon (default Magnifying glass) | +| selectedIconComponent | Material `check` | object | The icon component to the left of the selected item (default Checkmark) | +| unselectedIconComponent | | object | The icon component to the left of the unselected item | +| dropDownToggleIconUpComponent | Material `keyboard-arrow-up` | object | The parent dropdown icon in closed state | +| dropDownToggleIconDownComponent | Material `keyboard-arrow-down` | object | The parent dropdown icon in opened state | +| cancelIconComponent | Material `cancel` | object | The cancel button's inner component | +| customChipsRenderer | | function | Use a custom render function for custom chips: receives uniqueKey, subKey, displayKey, subDisplayKey, items, selectedItems, colors, styles. should return valid jsx | +| chipRemoveIconComponent | Material `close` | object | The chip remove button's icon component | +| styles | {} | object | Styles object - see styles section | +| colors | {...} | object | colors object - see colors section | +| itemFontFamily | Avenir / normal - bold | object | font family for the parent items. Can be a regular style object | +| subItemFontFamily | Avenir / normal - 200 | object | font family for the sub items. Can be a regular style object | +| searchTextFontFamily | Avenir / normal - 200 | object | font family for the search input. Can be a regular style object | +| confirmFontFamily | Avenir / normal - bold | object | font family for the confirm button. | +| itemNumberOfLines | null | number | numberOfLines for item text | +| selectLabelNumberOfLines | 1 | number | numberOfLines for select label text | +| customLayoutAnimation | easeInEaseOut | object | define your own `LayoutAnimation` preset or custom animation | ## Colors diff --git a/lib/components/RowItem.js b/lib/components/RowItem.js index 7bcfa05..2457964 100644 --- a/lib/components/RowItem.js +++ b/lib/components/RowItem.js @@ -50,7 +50,7 @@ class RowItem extends Component { if (this.props.searchTerm !== nextProps.searchTerm) { return true - } + } if (this.state.showSubCategories !== nextState.showSubCategories) { return true } @@ -144,7 +144,7 @@ class RowItem extends Component { height: StyleSheet.hairlineWidth, alignSelf: 'stretch', backgroundColor: '#dadada', - }, this.props.mergedStyles.subSeparator]} + }, this.props.mergedStyles.subSeparator]} /> ) @@ -164,6 +164,7 @@ class RowItem extends Component { dropDownToggleIconDownComponent, itemNumberOfLines, displayKey, + subDisplayKey, selectedItems, iconKey } = this.props @@ -198,25 +199,25 @@ class RowItem extends Component { flex: 1, color: item.disabled ? mergedColors.disabled : mergedColors.text }, - itemFontFamily, + itemFontFamily, mergedStyles.itemText, this._itemSelected(item) && mergedStyles.selectedItemText - ]} + ]} > - {item[displayKey]} + {subDisplayKey?item[displayKey][subDisplayKey]:item[displayKey]} { - this._itemSelected(item) ? - selectedIconComponent ? - selectedIconComponent - : - : + this._itemSelected(item) ? + selectedIconComponent ? + selectedIconComponent + : + : unselectedIconComponent ? unselectedIconComponent: null } @@ -233,34 +234,34 @@ class RowItem extends Component { { this._showSubCategoryDropDown() ? { dropDownToggleIconUpComponent ? dropDownToggleIconUpComponent - : - + : + } - : + : { dropDownToggleIconDownComponent ? dropDownToggleIconDownComponent - : - + : + } } } - { item[subKey] && this._showSubCategoryDropDown() && + { item[subKey] && this._showSubCategoryDropDown() && `${i[uniqueKey]}`} data={item[subKey]} diff --git a/lib/components/RowSubItem.js b/lib/components/RowSubItem.js index d021aa1..bf4ad36 100644 --- a/lib/components/RowSubItem.js +++ b/lib/components/RowSubItem.js @@ -58,12 +58,13 @@ class RowSubItem extends Component { highlightedChildren, itemNumberOfLines, displayKey, + subDisplayKey, iconKey } = this.props const highlightChild = !selectChildren && highlightedChildren.includes(subItem[uniqueKey]) const itemSelected = this._itemSelected() - + return ( - {subItem[displayKey]} + {subDisplayKey? subItem[displayKey][subDisplayKey]:subItem[displayKey]} { itemSelected || highlightChild ? diff --git a/lib/sectioned-multi-select.js b/lib/sectioned-multi-select.js index 3e08b3f..6ba2bda 100644 --- a/lib/sectioned-multi-select.js +++ b/lib/sectioned-multi-select.js @@ -143,7 +143,8 @@ class SectionedMultiSelect extends PureComponent { single: PropTypes.bool, selectedItems: PropTypes.array, items: PropTypes.array, - displayKey: PropTypes.string, + displayKey: PropTypes.string || PropTypes.object, + subDisplayKey: PropTypes.string, uniqueKey: PropTypes.string.isRequired, subKey: PropTypes.string, onSelectedItemsChange: PropTypes.func.isRequired, @@ -217,6 +218,7 @@ class SectionedMultiSelect extends PureComponent { single: false, selectedItems: [], displayKey: 'name', + subDisplayKey: null, showDropDowns: true, showChips: true, readOnlyHeadings: false, @@ -281,7 +283,7 @@ class SectionedMultiSelect extends PureComponent { // componentWillUpdate() { date = new Date();} // componentDidUpdate() {console.log(new Date().valueOf() - date.valueOf())} - getProp = (object, key) => object && object[key] + getProp = (object, key, subKey) => subKey ? object && object[key] && object[key][subKey] : object && object[key] rejectProp = (items, fn) => items.filter(fn) @@ -322,6 +324,7 @@ class SectionedMultiSelect extends PureComponent { single, selectedItems, displayKey, + subDisplayKey, alwaysShowSelectText, renderSelectText, } = this.props @@ -338,7 +341,7 @@ class SectionedMultiSelect extends PureComponent { } else if (single || selectedItems.length === 1) { const item = selectedItems[0] const foundItem = this._findItem(item) - return this.getProp(foundItem, displayKey) || selectText + return this.getProp(foundItem, displayKey, subDisplayKey) || selectText } return `${selectText} (${selectedItems.length} ${selectedText})` } @@ -349,6 +352,7 @@ class SectionedMultiSelect extends PureComponent { subKey, uniqueKey, displayKey, + subDisplayKey, filterItems, } = this.props @@ -362,14 +366,14 @@ class SectionedMultiSelect extends PureComponent { const parts = searchTerm.replace(/[\^$\\.*+?()[\]{}|]/g, '\\$&').trim().split(' ') const regex = new RegExp(`(${parts.join('|')})`, 'i') - if (regex.test(this.getProp(item, displayKey))) { + if (regex.test(this.getProp(item, displayKey, subDisplayKey))) { filteredItems.push(item) } if (item[subKey]) { const newItem = Object.assign({}, item) newItem[subKey] = [] item[subKey].forEach((sub) => { - if (regex.test(this.getProp(sub, displayKey))) { + if (regex.test(this.getProp(sub, displayKey, subDisplayKey))) { newItem[subKey] = [...newItem[subKey], sub] newFilteredItems = this.rejectProp(filteredItems, singleItem => item[uniqueKey] !== singleItem[uniqueKey]) @@ -644,6 +648,7 @@ class SectionedMultiSelect extends PureComponent { const { styles, colors } = this.state const { displayKey, + subDisplayKey, items, selectedItems, subKey, @@ -655,6 +660,7 @@ class SectionedMultiSelect extends PureComponent { customChipsRenderer({ colors, displayKey, + subDisplayKey, items, selectedItems, styles, @@ -735,13 +741,14 @@ class SectionedMultiSelect extends PureComponent { uniqueKey, selectedItems, displayKey, + subDisplayKey, chipRemoveIconComponent, } = this.props const { styles, colors } = this.state return selectedItems.map((singleSelectedItem) => { const item = this._findItem(singleSelectedItem) - if (!item || !item[displayKey]) return null + if (subDisplayKey ? !item || !item[displayKey][subDisplayKey] : !item || !item[displayKey]) return null return ( @@ -773,7 +780,7 @@ class SectionedMultiSelect extends PureComponent { }, styles.chipText]} > - {item[displayKey]} + {subDisplayKey ? item[displayKey][subDisplayKey] : item[displayKey]} { this._removeItem(item) }}