├── exampleapp
├── .watchmanconfig
├── .editorconfig
├── app.json
├── babel.config.js
├── z.jpg
├── .prettierrc.js
├── .buckconfig
├── .gitattributes
├── index.js
├── metro.config.js
├── __tests__
│ ├── App.js
│ └── __snapshots__
│ │ └── App.js.snap
├── package.json
├── .gitignore
├── .flowconfig
├── AppFunctional.tsx
├── App.js
└── AppWithTypes.tsx
├── lib
├── .vscode
│ ├── settings.json
│ └── launch.json
├── helpers.js
├── components
│ ├── index.js
│ ├── ItemIcon.js
│ ├── RowSubItem.js
│ └── RowItem.js
└── sectioned-multi-select.js
├── index.js
├── previews
├── example_recording-1.gif
├── example_recording-2.gif
├── example_recording-3.gif
└── example_recording-4.gif
├── .prettierrc.js
├── .gitignore
├── .eslintrc.json
├── .github
└── workflows
│ └── main.yml
├── LICENSE
├── package.json
├── index.d.ts
├── Recipes.md
├── CHANGELOG.md
└── README.md
/exampleapp/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/lib/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | }
--------------------------------------------------------------------------------
/exampleapp/.editorconfig:
--------------------------------------------------------------------------------
1 | # Windows files
2 | [*.bat]
3 | end_of_line = crlf
4 |
--------------------------------------------------------------------------------
/exampleapp/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "exampleapp",
3 | "displayName": "exampleapp"
4 | }
--------------------------------------------------------------------------------
/exampleapp/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/exampleapp/z.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/renrizzolo/react-native-sectioned-multi-select/HEAD/exampleapp/z.jpg
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import SectionedMultiSelect from './lib/sectioned-multi-select'
2 |
3 | export default SectionedMultiSelect
4 |
--------------------------------------------------------------------------------
/previews/example_recording-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/renrizzolo/react-native-sectioned-multi-select/HEAD/previews/example_recording-1.gif
--------------------------------------------------------------------------------
/previews/example_recording-2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/renrizzolo/react-native-sectioned-multi-select/HEAD/previews/example_recording-2.gif
--------------------------------------------------------------------------------
/previews/example_recording-3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/renrizzolo/react-native-sectioned-multi-select/HEAD/previews/example_recording-3.gif
--------------------------------------------------------------------------------
/previews/example_recording-4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/renrizzolo/react-native-sectioned-multi-select/HEAD/previews/example_recording-4.gif
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bracketSpacing: true,
3 | singleQuote: true,
4 | semi: false,
5 | trailingComma: 'none'
6 | }
7 |
--------------------------------------------------------------------------------
/exampleapp/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bracketSpacing: true,
3 | singleQuote: true,
4 | semi: false,
5 | trailingComma: 'none'
6 | }
7 |
--------------------------------------------------------------------------------
/exampleapp/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/exampleapp/.gitattributes:
--------------------------------------------------------------------------------
1 | # Windows files should use crlf line endings
2 | # https://help.github.com/articles/dealing-with-line-endings/
3 | *.bat text eol=crlf
4 |
--------------------------------------------------------------------------------
/lib/helpers.js:
--------------------------------------------------------------------------------
1 | export const callIfFunction = (maybeFn) =>
2 | maybeFn
3 | ? maybeFn && typeof maybeFn === 'function'
4 | ? maybeFn()
5 | : maybeFn
6 | : null
7 |
--------------------------------------------------------------------------------
/lib/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as RowItem } from './RowItem'
2 | export { default as RowSubItem } from './RowSubItem'
3 | export { default as ItemIcon } from './ItemIcon'
4 |
--------------------------------------------------------------------------------
/exampleapp/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import { AppRegistry } from 'react-native'
6 | import App from './App'
7 | import { name as appName } from './app.json'
8 |
9 | AppRegistry.registerComponent(appName, () => App)
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 |
9 | # Dependency directories
10 | node_modules/
11 |
12 | # exampleapp
13 | exampleapp/android/
14 | exampleapp/ios/
15 | exampleapp/third-party/
--------------------------------------------------------------------------------
/exampleapp/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | module.exports = {
9 | transformer: {
10 | getTransformOptions: async () => ({
11 | transform: {
12 | experimentalImportSupport: false,
13 | inlineRequires: true,
14 | },
15 | }),
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/lib/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node",
9 | "request": "launch",
10 | "name": "Launch Program",
11 | "program": "${file}"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "browser": true
5 | },
6 | "plugins": ["react"],
7 | "extends": [
8 | "prettier",
9 | "@react-native-community",
10 | "plugin:react-native-a11y/all"
11 | ],
12 | "rules": {
13 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
14 | "react/require-default-props": [0],
15 | "semi": ["error", "never"],
16 | "comma-dangle": ["error", "never"],
17 | "no-underscore-dangle": ["error", { "allowAfterThis": true }],
18 | "react-native/no-inline-styles": 0
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: 'Close stale issues and PRs'
2 | on:
3 | schedule:
4 | - cron: '30 1 * * *'
5 |
6 | jobs:
7 | stale:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/stale@v4
11 | with:
12 | stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
13 | stale-pr-message: 'This PR is stale because it has been open 45 days with no activity.'
14 | close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
15 | days-before-stale: 30
16 | days-before-close: 5
17 | days-before-pr-close: -1
18 |
--------------------------------------------------------------------------------
/exampleapp/__tests__/App.js:
--------------------------------------------------------------------------------
1 | import 'react-native'
2 | import React from 'react'
3 | import SectionedMultiSelect from 'react-native-sectioned-multi-select'
4 | import App from '../App'
5 | // Note: test renderer must be required after react-native.
6 | import renderer from 'react-test-renderer'
7 |
8 | // 'it probably didn't break'
9 |
10 | const tree = renderer.create()
11 | it('renders example app correctly', () => {
12 | tree
13 | })
14 | it('matches the snapshot', () => {
15 | // make assertions on tree
16 | expect(tree.toJSON()).toMatchSnapshot()
17 | })
18 |
19 | const testInstance = tree.root
20 | it('has an expected prop', () => {
21 | expect(testInstance.findAllByType(SectionedMultiSelect)[0].props.single).toBe(
22 | false
23 | )
24 | })
25 |
--------------------------------------------------------------------------------
/lib/components/ItemIcon.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { Image } from 'react-native'
4 |
5 | const ItemIcon = ({ iconRenderer: Icon, icon, iconKey, itemIconStyle }) => {
6 | return typeof icon === 'object' || typeof icon === 'number' ? (
7 |
19 | ) : (
20 |
21 | )
22 | }
23 | ItemIcon.propTypes = {
24 | iconKey: PropTypes.string,
25 | itemIconStyle: PropTypes.object,
26 | icon: PropTypes.oneOfType([
27 | PropTypes.string,
28 | PropTypes.shape({
29 | uri: PropTypes.string
30 | }),
31 | PropTypes.number
32 | ]).isRequired
33 | }
34 | export default ItemIcon
35 |
--------------------------------------------------------------------------------
/exampleapp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "exampleapp",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "test": "jest",
10 | "lint": "eslint ."
11 | },
12 | "dependencies": {
13 | "react": "17.0.2",
14 | "react-native": "0.66.4",
15 | "react-native-sectioned-multi-select": "github:renrizzolo/react-native-sectioned-multi-select#master",
16 | "react-native-vector-icons": "^9.0.0"
17 | },
18 | "devDependencies": {
19 | "@babel/core": "^7.12.9",
20 | "@babel/runtime": "^7.12.5",
21 | "@react-native-community/eslint-config": "^3.0.1",
22 | "@types/react": "^17.0.37",
23 | "@types/react-native": "^0.66.9",
24 | "babel-jest": "^27.4.5",
25 | "eslint": "^7.32.0",
26 | "jest": "^27.4.5",
27 | "metro-react-native-babel-preset": "^0.66.2",
28 | "react-test-renderer": "17.0.2"
29 | },
30 | "jest": {
31 | "preset": "react-native"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/exampleapp/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # Android/IntelliJ
25 | #
26 | build/
27 | .idea
28 | .gradle
29 | local.properties
30 | *.iml
31 | *.hprof
32 |
33 | # node.js
34 | #
35 | node_modules/
36 | npm-debug.log
37 | yarn-error.log
38 |
39 | # BUCK
40 | buck-out/
41 | \.buckd/
42 | *.keystore
43 | !debug.keystore
44 |
45 | # fastlane
46 | #
47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
48 | # screenshots whenever they are needed.
49 | # For more information about the recommended setup visit:
50 | # https://docs.fastlane.tools/best-practices/source-control/
51 |
52 | */fastlane/report.xml
53 | */fastlane/Preview.html
54 | */fastlane/screenshots
55 |
56 | # Bundle artifact
57 | *.jsbundle
58 |
59 | # CocoaPods
60 | /ios/Pods/
61 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ren
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-sectioned-multi-select",
3 | "version": "0.10.0",
4 | "description": "a multi (or single) select component with support for sub categories, search, chips.",
5 | "main": "index.js",
6 | "directories": {
7 | "lib": "lib"
8 | },
9 | "scripts": {
10 | "lint": "eslint ./lib/**/*.{js,jsx} --fix",
11 | "format": "prettier ./lib/**/*.{js,jsx} --write && npm run lint --fix",
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "dependencies": {
15 | "lodash.isequal": "^4.5.0",
16 | "memoize-one": "^6.0.0"
17 | },
18 | "devDependencies": {
19 | "@react-native-community/eslint-config": "^3.0.1",
20 | "eslint": "^7.32.0",
21 | "eslint-plugin-flowtype": "^8.0.3",
22 | "eslint-plugin-react-native-a11y": "^3.0.0",
23 | "prettier": "^2.5.1"
24 | },
25 | "peerDependencies": {
26 | "prop-types": "^15.6.0"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "git+https://github.com/renrizzolo/react-native-sectioned-multi-select.git"
31 | },
32 | "keywords": [
33 | "select",
34 | "multiselect",
35 | "picker",
36 | "category",
37 | "react",
38 | "native"
39 | ],
40 | "author": "Ren Rizzolo",
41 | "license": "MIT",
42 | "bugs": {
43 | "url": "https://github.com/renrizzolo/react-native-sectioned-multi-select/issues"
44 | },
45 | "homepage": "https://github.com/renrizzolo/react-native-sectioned-multi-select#readme"
46 | }
47 |
--------------------------------------------------------------------------------
/exampleapp/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | ; We fork some components by platform
3 | .*/*[.]android.js
4 |
5 | ; Ignore "BUCK" generated dirs
6 | /\.buckd/
7 |
8 | ; Ignore polyfills
9 | node_modules/react-native/Libraries/polyfills/.*
10 |
11 | ; Flow doesn't support platforms
12 | .*/Libraries/Utilities/LoadingView.js
13 |
14 | [untyped]
15 | .*/node_modules/@react-native-community/cli/.*/.*
16 |
17 | [include]
18 |
19 | [libs]
20 | node_modules/react-native/interface.js
21 | node_modules/react-native/flow/
22 |
23 | [options]
24 | emoji=true
25 |
26 | exact_by_default=true
27 |
28 | format.bracket_spacing=false
29 |
30 | module.file_ext=.js
31 | module.file_ext=.json
32 | module.file_ext=.ios.js
33 |
34 | munge_underscores=true
35 |
36 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1'
37 | module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub'
38 |
39 | suppress_type=$FlowIssue
40 | suppress_type=$FlowFixMe
41 | suppress_type=$FlowFixMeProps
42 | suppress_type=$FlowFixMeState
43 |
44 | [lints]
45 | sketchy-null-number=warn
46 | sketchy-null-mixed=warn
47 | sketchy-number=warn
48 | untyped-type-import=warn
49 | nonstrict-import=warn
50 | deprecated-type=warn
51 | unsafe-getters-setters=warn
52 | unnecessary-invariant=warn
53 | signature-verification-failure=warn
54 |
55 | [strict]
56 | deprecated-type
57 | nonstrict-import
58 | sketchy-null
59 | unclear-type
60 | unsafe-getters-setters
61 | untyped-import
62 | untyped-type-import
63 |
64 | [version]
65 | ^0.158.0
66 |
--------------------------------------------------------------------------------
/exampleapp/AppFunctional.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef } from 'react'
2 | import { View, Button, Text, ScrollView, TouchableOpacity } from 'react-native'
3 | import SectionedMultiSelect from 'react-native-sectioned-multi-select'
4 | import Icon from 'react-native-vector-icons/MaterialIcons'
5 | import { Colors } from 'react-native/Libraries/NewAppScreen'
6 |
7 | type ItemType = {
8 | title: string
9 | id: number
10 | }
11 | const items = [
12 | {
13 | id: 1,
14 | title: 'Item 1 234234'
15 | },
16 | {
17 | id: 2,
18 | title: 'Item 2 asdfsa'
19 | },
20 | {
21 | id: 3,
22 | title: 'Item 3 asdf d'
23 | },
24 | {
25 | id: 4,
26 | title: 'Item 4d a'
27 | }
28 | ]
29 |
30 | const App: React.FC = () => {
31 | const ref = useRef>()
32 | const [selectedItems, setSelectedItems] = React.useState([])
33 |
34 | const removeAll = () => {
35 | ref.current?._removeAllItems()
36 | }
37 | const toggle = () => {
38 | ref.current?._toggleSelector()
39 | }
40 | console.log(selectedItems)
41 | return (
42 |
43 |
44 | uniqueKey="id"
45 | displayKey="title"
46 | onSelectedItemsChange={setSelectedItems}
47 | selectedItems={selectedItems}
48 | items={items}
49 | ref={ref}
50 | customChipsRenderer={(props) => (
51 |
64 | {selectedItems.map((itemId) => {
65 | const item = items.find(({ id }) => id === itemId)
66 | return (
67 |
81 |
89 | {item.title}
90 |
91 | ref.current?._removeItem(item)}
94 | >
95 |
96 |
97 |
98 | )
99 | })}
100 |
101 | )}
102 | IconRenderer={Icon}
103 | icons={{
104 | check: {
105 | name: 'check-circle',
106 | style: {
107 | color: Colors.secondary
108 | },
109 | size: 22
110 | },
111 | search: {
112 | name: 'search',
113 | color: '#333',
114 | size: 22
115 | }
116 | }}
117 | />
118 |
119 |
120 |
121 | )
122 | }
123 |
124 | export default App
125 |
--------------------------------------------------------------------------------
/lib/components/RowSubItem.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import isEqual from 'lodash.isequal'
3 | import { View, TouchableOpacity, Text } from 'react-native'
4 | import ItemIcon from './ItemIcon'
5 | import { callIfFunction } from '../helpers'
6 |
7 | class RowSubItem extends Component {
8 | shouldComponentUpdate(nextProps) {
9 | if (nextProps.selectedItems !== this.props.selectedItems) {
10 | if (
11 | this.props.selectedItems.includes(
12 | this.props.subItem[this.props.uniqueKey]
13 | ) &&
14 | !nextProps.selectedItems.includes(
15 | this.props.subItem[this.props.uniqueKey]
16 | )
17 | ) {
18 | return true
19 | }
20 | if (
21 | !this.props.selectedItems.includes(
22 | this.props.subItem[this.props.uniqueKey]
23 | ) &&
24 | nextProps.selectedItems.includes(
25 | this.props.subItem[this.props.uniqueKey]
26 | )
27 | ) {
28 | return true
29 | }
30 | if (this.props.highlightChildren || this.props.selectChildren) {
31 | if (
32 | this.props.highlightedChildren.includes(
33 | this.props.subItem[this.props.uniqueKey]
34 | )
35 | ) {
36 | return true
37 | }
38 | if (
39 | nextProps.highlightedChildren.includes(
40 | this.props.subItem[this.props.uniqueKey]
41 | )
42 | ) {
43 | return true
44 | }
45 | }
46 | }
47 | if (!isEqual(this.props.mergedStyles, nextProps.mergedStyles)) {
48 | return true
49 | }
50 | if (!isEqual(this.props.mergedColors, nextProps.mergedColors)) {
51 | return true
52 | }
53 | return false
54 | }
55 |
56 | _itemSelected = () => {
57 | const { subItem, uniqueKey, selectedItems } = this.props
58 | return selectedItems.includes(subItem[uniqueKey])
59 | }
60 |
61 | _toggleItem = () => {
62 | const { subItem } = this.props
63 | this.props.toggleSubItem(subItem)
64 | }
65 |
66 | _renderSelectedIcon = () => {
67 | const {
68 | selectedIconComponent,
69 | unselectedIconComponent,
70 | mergedColors,
71 | selectChildren,
72 | highlightedChildren,
73 | uniqueKey,
74 | subItem,
75 | icons,
76 | iconRenderer: Icon
77 | } = this.props
78 | const highlightChild =
79 | !selectChildren && highlightedChildren.includes(subItem[uniqueKey])
80 | const itemSelected = this._itemSelected()
81 | return itemSelected || highlightChild ? (
82 |
83 | {selectedIconComponent ? (
84 | callIfFunction(selectedIconComponent)
85 | ) : (
86 |
95 | )}
96 |
97 | ) : unselectedIconComponent ? (
98 | callIfFunction(unselectedIconComponent)
99 | ) : null
100 | }
101 |
102 | render() {
103 | const {
104 | mergedStyles,
105 | mergedColors,
106 | subItem,
107 | uniqueKey,
108 | subItemFontFamily,
109 | selectChildren,
110 | selectedIconOnLeft,
111 | highlightedChildren,
112 | itemNumberOfLines,
113 | displayKey,
114 | iconKey,
115 | iconRenderer: Icon
116 | } = this.props
117 |
118 | const highlightChild =
119 | !selectChildren && highlightedChildren.includes(subItem[uniqueKey])
120 | const itemSelected = this._itemSelected()
121 |
122 | return (
123 |
131 |
149 | {selectedIconOnLeft && this._renderSelectedIcon()}
150 |
151 | {iconKey && subItem[iconKey] && (
152 |
158 | )}
159 |
174 | {subItem[displayKey]}
175 |
176 | {!selectedIconOnLeft && this._renderSelectedIcon()}
177 |
178 |
179 | )
180 | }
181 | }
182 |
183 | export default RowSubItem
184 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import * as ReactNative from 'react-native'
3 |
4 | type IconProps = {
5 | name: string
6 | size?: number
7 | [x: string]: any
8 | }
9 |
10 | export interface Styles {
11 | container?: ReactNative.StyleProp
12 | modalWrapper?: ReactNative.StyleProp
13 | selectToggle?: ReactNative.StyleProp
14 | selectToggleText?: ReactNative.StyleProp
15 | item?: ReactNative.StyleProp
16 | subItem?: ReactNative.StyleProp
17 | itemText?: ReactNative.StyleProp
18 | selectedItemText?: ReactNative.StyleProp
19 | selectedSubItemText?: ReactNative.StyleProp
20 | subItemText?: ReactNative.StyleProp
21 | searchBar?: ReactNative.StyleProp
22 | center?: ReactNative.StyleProp
23 | separator?: ReactNative.StyleProp
24 | subSeparator?: ReactNative.StyleProp
25 | chipsWrapper?: ReactNative.StyleProp
26 | chipContainer?: ReactNative.StyleProp
27 | chipText?: ReactNative.StyleProp
28 | chipIcon?: ReactNative.StyleProp
29 | searchTextInput?: ReactNative.StyleProp
30 | scrollView?: ReactNative.StyleProp
31 | button?: ReactNative.StyleProp
32 | cancelButton?: ReactNative.StyleProp
33 | confirmText?: ReactNative.StyleProp
34 | toggleIcon?: ReactNative.StyleProp
35 | selectedItem?: ReactNative.StyleProp
36 | selectedSubItem?: ReactNative.StyleProp
37 | backdrop?: ReactNative.StyleProp
38 | listContainer?: ReactNative.StyleProp
39 | }
40 |
41 | export interface Colors {
42 | primary?: string
43 | success?: string
44 | cancel?: string
45 | text?: string
46 | subText?: string
47 | selectToggleTextColor?: string
48 | searchPlaceholderTextColor?: string
49 | searchSelectionColor?: string
50 | chipColor?: string
51 | itemBackground?: string
52 | subItemBackground?: string
53 | disabled?: string
54 | }
55 |
56 | export interface SectionedMultiSelectProps {
57 | single?: boolean
58 | selectedItems?: any[]
59 | items?: ItemType[]
60 | displayKey?: string
61 | uniqueKey: string
62 | subKey?: string
63 | onSelectedItemsChange: (items: any[]) => void
64 | showDropDowns?: boolean
65 | showChips?: boolean
66 | readOnlyHeadings?: boolean
67 | selectText?: string
68 | selectedText?: string | (() => void)
69 | renderSelectText?: (props: this) => void
70 | confirmText?: string
71 | hideConfirm?: boolean
72 | styles?: Styles
73 | colors?: Colors
74 | searchPlaceholderText?: string
75 | noResultsComponent?: React.ReactNode
76 | loadingComponent?: React.ReactNode
77 | loading?: boolean
78 | subItemFontFamily?: object
79 | itemFontFamily?: object
80 | searchTextFontFamily?: object
81 | confirmFontFamily?: object
82 | showRemoveAll?: boolean
83 | removeAllText?: string
84 | modalSupportedOrientations?: ReactNative.ModalProps['supportedOrientations']
85 | modalAnimationType?: string
86 | modalWithSafeAreaView?: boolean
87 | modalWithTouchable?: boolean
88 | hideSearch?: boolean
89 | footerComponent?: React.ReactNode
90 | stickyFooterComponent?: React.ReactNode
91 | selectToggleIconComponent?: React.ReactNode
92 | cancelIconComponent?: React.ReactNode
93 | searchIconComponent?: React.ReactNode
94 | selectedIconComponent?: React.ReactNode
95 | unselectedIconComponent?: React.ReactNode
96 | dropDownToggleIconUpComponent?: React.ReactNode
97 | dropDownToggleIconDownComponent?: React.ReactNode
98 | chipRemoveIconComponent?: React.ReactNode
99 | selectChildren?: boolean
100 | highlightChildren?: boolean
101 | onSelectedItemObjectsChange?: (items: ItemType[]) => void
102 | itemNumberOfLines?: number
103 | selectLabelNumberOfLines?: number
104 | showCancelButton?: boolean
105 | hideSelect?: boolean
106 | onConfirm?: () => void
107 | onCancel?: () => void
108 | headerComponent?: React.ReactNode
109 | alwaysShowSelectText?: boolean
110 | searchAdornment?: (searchText: string) => void
111 | expandDropDowns?: boolean
112 | animateDropDowns?: boolean
113 | customLayoutAnimation?: object
114 | onChangeSearchText?: (searchTerm: string) => void
115 | filterItems?: (searchTerm: string) => void
116 | onToggleSelector?: (selected: boolean) => void
117 | noItemsComponent?: React.ReactNode
118 | customChipsRenderer?: (chipProperties: {
119 | colors: Colors
120 | displayKey: string
121 | items: ItemType[]
122 | selectedItems: any[]
123 | styles: Styles
124 | subKey: string
125 | uniqueKey: string
126 | }) => void
127 | chipsPosition?: 'top' | 'bottom'
128 | autoFocus?: boolean
129 | iconKey?: string
130 | disabled?: boolean
131 | selectedIconOnLeft?: boolean
132 | parentChipsRemoveChildren?: boolean
133 | hideChipRemove?: boolean
134 | IconRenderer: React.ReactNode
135 | itemsFlatListProps?: Omit<
136 | ReactNative.FlatListProps,
137 | 'data' | 'renderItem'
138 | >
139 | subItemsFlatListProps?: Omit<
140 | ReactNative.FlatListProps,
141 | 'data' | 'renderItem'
142 | >
143 |
144 | icons?: Partial<{
145 | search: IconProps
146 | arrowUp: IconProps
147 | arrowDown: IconProps
148 | close: IconProps
149 | check: IconProps
150 | cancel: IconProps
151 | }>
152 | }
153 | export default class SectionedMultiSelect extends React.Component<
154 | SectionedMultiSelectProps
155 | > {
156 | _toggleSelector: () => void
157 | _removeAllItems: () => void
158 | _removeItem: (item: ItemType) => void
159 | _selectAllItems: () => void
160 | _findItem: (id: any) => ItemType | undefined
161 | _itemSelected: (item: ItemType) => boolean
162 | _getSearchTerm: () => string
163 | _submitSelection: () => void
164 | _cancelSelection: () => void
165 | }
166 |
--------------------------------------------------------------------------------
/Recipes.md:
--------------------------------------------------------------------------------
1 | # Recipes
2 |
3 | Examples of commonly requested functions/patterns. Required props/functions ommited for brevity.
4 |
5 | ## Ref
6 |
7 | Some of these examples use a ref to the component like this:
8 |
9 | Function component:
10 |
11 | ```JS
12 | import React, { useRef } from 'react'
13 |
14 | const App = () => {
15 | const ref = useRef(null)
16 | // ref.current._toggleSelector()
17 | return (
18 | <>
19 |
23 |