├── ios_screenshot.png
├── android_screenshot.png
├── package.json
├── LICENSE
├── README.md
└── index.js
/ios_screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izzisolomon/react-native-options-menu/HEAD/ios_screenshot.png
--------------------------------------------------------------------------------
/android_screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izzisolomon/react-native-options-menu/HEAD/android_screenshot.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-options-menu",
3 | "version": "2.0.1",
4 | "description": "A native looking options dialog for Ios, Android and Web",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/izzisolomon/react-native-options-menu.git"
12 | },
13 | "keywords": [
14 | "react-native",
15 | "react-native-menu",
16 | "react-native-options-menu",
17 | "react-native-popup-menu",
18 | "overflow",
19 | "menu",
20 | "options",
21 | "react-component",
22 | "ios",
23 | "android",
24 | "web"
25 | ],
26 | "author": "Izzi Solomon",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/izzisolomon/react-native-options-menu/issues"
30 | },
31 | "peerDependencies": {
32 | "react-native": ">=0.20.0"
33 | },
34 | "homepage": "https://github.com/izzisolomon/react-native-options-menu#readme"
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-options-menu
2 | A native looking options dialog for IOS, and Android and Web.
3 |
4 | To Download, run: yarn add react-native-options-menu, or npm install -s react-native-options-menu.
5 |
6 | Usage example:
7 |
8 | import OptionsMenu from "react-native-options-menu";
9 | const MoreIcon = require("../../assets/more/more.png");
10 |
11 |
17 |
18 |
19 | Note that button is a required prop (pass in a png of the desired button).
20 |
21 | As an alternative to the button and style props, you can just pass in a full custom component:
22 |
23 |
24 | const myIcon = ()
25 |
30 |
31 |
32 | Destructive index in an iOS only prop. It will appear as a red index.
33 |
34 | Options: an array of strings that will be displayed in the menu.
35 |
36 | Actions: an array of functions to be executed for every menu item. Note that the orders of options an actions have to match.
37 |
38 |
39 | iOS Screenshot:
40 |
41 | 
42 |
43 | Android Screenshot:
44 |
45 | 
46 |
47 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Platform,
4 | ActionSheetIOS,
5 | UIManager,
6 | findNodeHandle,
7 | View,
8 | TouchableOpacity,
9 | Image,
10 | Text,
11 | TextInput
12 | } from "react-native";
13 |
14 | export default class PopupMenu extends React.Component {
15 | constructor(props) {
16 | super(props);
17 | this.state = { open: false };
18 | }
19 |
20 | handleClick = index => {
21 | let options = this.props.options;
22 | for (var i = 0; i < options.length; i++) {
23 | if (index === i) {
24 | if (index === options.length - 1) {
25 | const open = false;
26 | this.setState({ open });
27 | } else {
28 | if (this.props.actions[i] !== null) {
29 | this.props.actions[i]();
30 | }
31 | }
32 | }
33 | }
34 | };
35 |
36 | handlePressWeb = () => {
37 | this.setState({ open: true });
38 | };
39 |
40 | handlePress = () => {
41 | let options = this.props.options;
42 | if (Platform.OS === "ios") {
43 | let destructiveIndex = -1;
44 | if (
45 | Number.isInteger(this.props.destructiveIndex) &&
46 | this.props.destructiveIndex >= 0
47 | ) {
48 | destructiveIndex = this.props.destructiveIndex;
49 | }
50 | ActionSheetIOS.showActionSheetWithOptions(
51 | {
52 | options: options,
53 | destructiveButtonIndex: destructiveIndex,
54 | cancelButtonIndex: options.length - 1
55 | },
56 | buttonIndex => {
57 | this.handleClick(buttonIndex);
58 | }
59 | );
60 | } else if (Platform.OS === "android") {
61 | UIManager.showPopupMenu(
62 | findNodeHandle(this.refs.menu),
63 | options,
64 | () => console.log("something went wrong with the popup menu"),
65 | (e, i) => {
66 | this.handleClick(i);
67 | }
68 | );
69 | }
70 | };
71 | render() {
72 | let options = this.state.open ? (
73 |
88 | {this.props.options.map((option, index) => {
89 | return (
90 |
91 | this.handleClick(index)}
94 | >
95 | {option}
96 |
97 |
98 | {index < this.props.options.length - 1 && (
99 |
106 | )}
107 |
108 | );
109 | })}
110 |
111 | ) : null;
112 |
113 | let component = this.props.button ? (
114 |
115 | ) : (
116 | this.props.customButton
117 | );
118 | if (Platform.OS === "web") {
119 | return (
120 |
121 |
122 |
123 | {component}
124 |
125 |
126 | {options}
127 |
128 | );
129 | } else {
130 | return (
131 |
132 |
133 | {component}
134 |
135 |
136 | );
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------