{"id":4059,"url":"https://github.com/peacechen/react-native-modal-selector","last_synced_at":"2026-01-14T16:38:27.112Z","repository":{"id":37549480,"uuid":"80253939","full_name":"peacechen/react-native-modal-selector","owner":"peacechen","description":"A cross-platform (iOS / Android), selector/picker component for React Native that is highly customizable and supports sections.","archived":false,"fork":true,"pushed_at":"2022-10-24T18:39:16.000Z","size":1418,"stargazers_count":370,"open_issues_count":40,"forks_count":130,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-08-04T00:47:26.727Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"d-a-n/react-native-modal-picker","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/peacechen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-27T23:11:38.000Z","updated_at":"2025-03-06T09:25:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/peacechen/react-native-modal-selector","commit_stats":null,"previous_names":[],"tags_count":51,"template":false,"template_full_name":null,"purl":"pkg:github/peacechen/react-native-modal-selector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peacechen%2Freact-native-modal-selector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peacechen%2Freact-native-modal-selector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peacechen%2Freact-native-modal-selector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peacechen%2Freact-native-modal-selector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/peacechen","download_url":"https://codeload.github.com/peacechen/react-native-modal-selector/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peacechen%2Freact-native-modal-selector/sbom","scorecard":{"id":725699,"data":{"date":"2025-08-11","repo":{"name":"github.com/peacechen/react-native-modal-selector","commit":"202fb12805cdb2b07bdba5e87be05c6998448d8d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Code-Review","score":3,"reason":"Found 9/30 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 9 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T12:44:10.168Z","repository_id":37549480,"created_at":"2025-08-22T12:44:10.169Z","updated_at":"2025-08-22T12:44:10.169Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28426117,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T16:32:27.303Z","status":"ssl_error","status_checked_at":"2026-01-14T16:28:36.419Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-05T20:16:59.830Z","updated_at":"2026-01-14T16:38:27.095Z","avatar_url":"https://github.com/peacechen.png","language":"TypeScript","funding_links":[],"categories":["Components"],"sub_categories":["UI"],"readme":"# react-native-modal-selector [![npm version](https://badge.fury.io/js/react-native-modal-selector.svg)](https://badge.fury.io/js/react-native-modal-selector)\n\nA cross-platform (iOS / Android), selector/picker component for React Native that is highly customizable and supports sections.\n\nThis project is the official continuation of the abandoned `react-native-modal-picker` repo. Contributors are welcome to [request a promotion to collaborator status](https://github.com/peacechen/react-native-modal-selector/issues/1).\n\n## Demo\n\n\u003cimg src=\"https://github.com/peacechen/react-native-modal-selector/blob/master/docs/demo.gif\" /\u003e\n\n## Install\n\n```sh\nnpm install react-native-modal-selector\n```\n\n## Usage\n\nYou can either use this component in its default mode, as a wrapper around your existing component or provide a custom component (where you need to control opening of the modal yourself). In default mode a customizable button is rendered.\n\nSee `SampleApp` for an example how to use this component.\n\n```jsx\nimport ModalSelector from 'react-native-modal-selector'\n\nclass SampleApp extends Component {\n\n    constructor(props) {\n        super(props);\n\n        this.state = {\n            textInputValue: ''\n        }\n    }\n\n    render() {\n        let index = 0;\n        const data = [\n            { key: index++, section: true, label: 'Fruits' },\n            { key: index++, label: 'Red Apples' },\n            { key: index++, label: 'Cherries' },\n            { key: index++, label: 'Cranberries', accessibilityLabel: 'Tap here for cranberries' },\n            // etc...\n            // Can also add additional custom keys which are passed to the onChange callback\n            { key: index++, label: 'Vegetable', customKey: 'Not a fruit' }\n        ];\n\n        return (\n            \u003cView style={{flex:1, justifyContent:'space-around', padding:50}}\u003e\n\n                // Default mode\n                \u003cModalSelector\n                    data={data}\n                    initValue=\"Select something yummy!\"\n                    onChange={(option)=\u003e{ alert(`${option.label} (${option.key}) nom nom nom`) }} /\u003e\n\n                // Wrapper\n                \u003cModalSelector\n                    data={data}\n                    initValue=\"Select something yummy!\"\n                    supportedOrientations={['landscape']}\n                    accessible={true}\n                    scrollViewAccessibilityLabel={'Scrollable options'}\n                    cancelButtonAccessibilityLabel={'Cancel Button'}\n                    onChange={(option)=\u003e{ this.setState({textInputValue:option.label})}}\u003e\n\n                    \u003cTextInput\n                        style={{borderWidth:1, borderColor:'#ccc', padding:10, height:30}}\n                        editable={false}\n                        placeholder=\"Select something yummy!\"\n                        value={this.state.textInputValue} /\u003e\n\n                \u003c/ModalSelector\u003e\n\n                // Custom component\n                \u003cModalSelector\n                    data={data}\n                    ref={selector =\u003e { this.selector = selector; }}\n                    customSelector={\u003cSwitch onValueChange={() =\u003e this.selector.open()} /\u003e}\n                /\u003e\n            \u003c/View\u003e\n        );\n    }\n}\n```\n\n## Data Format\n\nThe selector accepts a specific format of data:\n```javascript\n[{ key: 5, label: 'Red Apples' }]\n```\n\nOptionally provide a `component` key which overrides the default label text. Optionally provide a unique `testID` for each item:\n```javascript\n[{\n  key: 5,\n  label: 'Red Apples',\n  // The next keys are optional --\n  component: \u003cView style={{backgroundColor: 'red'}}\u003e\u003cText style={{color: 'white'}}\u003eRed Apples custom component ☺\u003c/Text\u003e\u003c/View\u003e,\n  testID: '5-red-apples'\n}]\n```\n\n\u003cimg src=\"https://user-images.githubusercontent.com/6295083/51210593-d3fbae00-18d8-11e9-8f51-d1ca4f9f8267.png\" /\u003e\n\nIf your data has a specific format, you can define extractors of data, example:\n```javascript\nthis.setState({data: [{ id: 5, name: 'Red Apples' }]});\n\nreturn (\n  \u003cModalSelector\n    data={this.state.data}\n    keyExtractor= {item =\u003e item.id}\n    labelExtractor= {item =\u003e item.name}\n  /\u003e\n);\n```\n\n## API\n\n### Props\n\nProp                | Type     | Optional | Default      | Description\n------------------- | -------- | -------- | ------------ | -----------\n`data`              | array    | No       | []           | array of objects with a unique `key` and `label` to select in the modal. Optional `component` overrides label text. Optional unique `testID` for each item.\n`onChange`          | function | Yes      | () =\u003e {}     | callback function, when the users has selected an option\n`onModalOpen`       | function | Yes      | () =\u003e {}     | callback function, when modal is opening\n`onModalClose`      | function | Yes      | (item) =\u003e {} | callback function, when modal is closing. Returns the selected item.\n`keyExtractor`      | function | Yes      | (data) =\u003e data.key   | extract the key from the data item\n`labelExtractor`    | function | Yes      | (data) =\u003e data.label | extract the label from the data item\n`componentExtractor`| function | Yes      | (data) =\u003e data.component | extract the component from the data item\n`visible`           | bool     | Yes      | false        | control open/close state of modal\n`closeOnChange`     | bool     | Yes      | true         | control if modal closes on select\n`initValue`         | string   | Yes      | `Select me!` | text that is initially shown on the button\n`cancelText`        | string   | Yes      | `cancel`     | text of the cancel button\n`disabled`          | bool     | Yes      | false        | `true` disables opening of the modal\n`supportedOrientations`    | ['portrait', 'landscape'] | Yes      | both      | orientations the modal supports\n`keyboardShouldPersistTaps`| `string` / `bool`         | Yes      | `always`  | passed to underlying ScrollView\n`listType`          | string   | Yes      | `SCROLLVIEW` | scroller type: `SCROLLVIEW` or `FLATLIST`\n`animationType`     | string   | Yes      | `slide`      | type of animation to be used to show the modal. Must be one of `none`, `slide` or `fade`.\n`style`             | object   | Yes      |              | style definitions for the root element\n`childrenContainerStyle`| object   | Yes      | {}           | style definitions for the children container view\n`touchableStyle`    | object   | Yes      | {}           | style definitions for the touchable element\n`touchableActiveOpacity`    | number   | Yes      | 0.2           | opacity for the touchable element on touch\n`selectStyle`       | object   | Yes      | {}           | style definitions for the select element (available in default mode only!). NOTE: Due to breaking changes in React Native, RN \u003c 0.39.0 should pass `flex:1` explicitly to `selectStyle` as a prop.\n`selectTextStyle`   | object   | Yes      | {}           | style definitions for the select element (available in default mode only!)\n`overlayStyle`      | object   | Yes      | { flex: 1, padding: '5%', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.7)' } | style definitions for the overlay background element. RN \u003c= 0.41 should override this with pixel value for padding.\n`sectionStyle`      | object   | Yes      | {}           | style definitions for the section element\n`sectionTextStyle`  | object   | Yes      | {}           | style definitions for the select text element\n`selectedItemTextStyle` | object | Yes    | {}           | style definitions for the currently selected text element\n`optionStyle`       | object   | Yes      | {}           | style definitions for the option element\n`optionTextStyle`   | object   | Yes      | {}           | style definitions for the option text element\n`optionContainerStyle`| object | Yes      | {}           | style definitions for the option container element\n`cancelStyle`       | object   | Yes      | {}           | style definitions for the cancel element\n`cancelTextStyle`   | object   | Yes      | {}           | style definitions for the cancel text element\n`initValueTextStyle`| object   | Yes      | {}           | style definitions for the initValue text element\n`cancelContainerStyle`| object | Yes      | {}           | style definitions for the cancel container\n`backdropPressToClose`| bool   | Yes  | false        | `true` makes the modal close when the overlay is pressed\n`passThruProps`| object   | Yes  | {}        | props to pass through to the container View and each option TouchableOpacity (e.g. testID for testing)\n`selectTextPassThruProps`| object   | Yes  | {}        | props to pass through to the select text component\n`optionTextPassThruProps`| object   | Yes  | {}        | props to pass through to the options text components in the modal\n`cancelTextPassThruProps`| object   | Yes  | {}        | props to pass through to the cancel text components in the modal\n`scrollViewPassThruProps`| object   | Yes  | {}        | props to pass through to the internal ScrollView\n`openButtonContainerAccessible`| bool   | Yes  | false        | `true` enables accessibility for the open button container. Note: if `false` be sure to define accessibility props directly in the wrapped component.\n`listItemAccessible`| bool   | Yes  | false        | `true` enables accessibility for data items. Note: data items should have an `accessibilityLabel` property if this is enabled\n`cancelButtonAccessible`| bool   | Yes  | false        | `true` enables accessibility for cancel button.\n`scrollViewAccessible`| bool   | Yes  | false        | `true` enables accessibility for the scroll view. Only enable this if you don't want to interact with individual data items.\n`scrollViewAccessibilityLabel` | string   | Yes      | undefined | Accessibility label for the modal ScrollView\n`cancelButtonAccessibilityLabel` | string   | Yes      | undefined | Accessibility label for the cancel button\n`modalOpenerHitSlop` | object | Yes | {} | How far touch can stray away from touchable that opens modal ([RN docs](https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html#hitslop))\n`customSelector`     | node   | Yes | undefined          | Render a custom node instead of the built-in select box.\n`selectedKey`        | any    | Yes | ''                 | Key of the item to be initially selected\n`enableShortPress`          | bool   | Yes | true               | enables short press. This is regular touch behavior.\n`enableLongPress`           | bool   | Yes | false              | enables long press. When true, `onModalOpen` returns `{longPress: true}`\n`optionsTestIDPrefix`       | string   | Yes | `'default'`      | This prefixes each selectable option's testID prop if no testID keys are provided in `props.data` array objects. Default for each option's testID: 'default-\\\u003coptionLabel\\\u003e'\n`header`     | node   | Yes | undefined          | Render a header above the list\n`onEndReached`     | function                  | Yes | undefined          | Called once when the scroll position gets of the rendered content.\n\n### Methods\n\n* `open()`: open the modal.\n* `close()`: close the modal.\n* `getSelectedItem()`: get current selected item, updated by onChange event.\n\n## See also\n\n* A similar project is [hepter/react-native-modal-selector-searchable](https://github.com/hepter/react-native-modal-selector-searchable), which is a fork of this module that adds searching capabilities.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeacechen%2Freact-native-modal-selector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeacechen%2Freact-native-modal-selector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeacechen%2Freact-native-modal-selector/lists"}