Compare commits

...
172 Commits
Author SHA1 Message Date
semantic-release-bot ead0ed7dc1 chore(release): 3.5.0 [skip ci]
# [3.5.0](https://github.com/expo/react-native-action-sheet/compare/v3.4.1...v3.5.0) (2020-02-04)

### Features

* add anchor option for iPads ([#155](https://github.com/expo/react-native-action-sheet/issues/155)) ([370e6e8](https://github.com/expo/react-native-action-sheet/commit/370e6e855fbacbfc683cc6ab16304f26c159e6b5))
2020-02-04 06:13:09 -06:00
Brad Bumbalough 27cef1a658 Merge pull request #157 from expo/chore/ipad-example
chore: ipad anchor in example app
2020-02-04 06:07:22 -06:00
Brad Bumbalough bfae6b4ebc chore: update readme with anchor option 2020-02-04 06:03:58 -06:00
Brad Bumbalough eecc79ffb0 chore: update example app with iPad anchor 2020-02-04 06:03:49 -06:00
Kashish Grover 370e6e855f feat: add anchor option for iPads (#155) 2020-02-04 05:54:18 -06:00
Brad Bumbalough 6fa494f9de Merge pull request #156 from expo/chore/remove-gh-action
chore: remove github actions
2020-02-04 05:53:25 -06:00
Brad Bumbalough fc86afb87e chore: remove github actions 2020-02-04 05:52:30 -06:00
Evan Bacon 40aee02227 Update README.md 2019-12-31 23:08:24 -08:00
Brad Bumbalough ac6f9f6ccd chore: cleanup changelog file 2019-12-13 07:50:40 -06:00
semantic-release-bot 0131ebbb44 chore(release): 3.4.1 [skip ci]
## [3.4.1](https://github.com/expo/react-native-action-sheet/compare/v3.4.0...v3.4.1) (2019-12-13)

### Bug Fixes

* **iOS:** crash when using Android only options ([#144](https://github.com/expo/react-native-action-sheet/issues/144)) ([8016008](https://github.com/expo/react-native-action-sheet/commit/8016008781cbe418dc03f04a324d5e5ef5bcdaa7))
2019-12-13 07:46:57 -06:00
Brad Bumbalough 0627e77fba Merge pull request #148 from expo/chore/changelog
chore: commit changelog when releasing
2019-12-13 07:46:06 -06:00
Brad Bumbalough d114cfb321 chore: commit changelog when releasing 2019-12-13 07:43:56 -06:00
Hashir Ch 8016008781 fix(iOS): crash when using Android only options (#144) 2019-12-13 07:15:56 -06:00
Colin Darie 39fc431c97 feat(android): allow customizing container styles (#142)
* Android: container style configurable (background)
* Add containerStyle prop description to readme
* Add containerStyle prop to example app
2019-11-18 22:12:18 -06:00
Hammad Jutt 76397fa7c4 feat: Allow pointerEvents prop to pass through to containing view (#124) 2019-11-18 21:41:57 -06:00
Brad Bumbalough 8448370658 Merge pull request #141 from expo/chore/yarn-release
chore: use yarn instead of npm for action
2019-11-05 07:31:39 -06:00
Brad Bumbalough 223d35fb85 chore: use yarn instead of npm for action 2019-11-05 07:30:58 -06:00
Brad Bumbalough 979da65d59 Merge pull request #140 from expo/fix/android-nested-action-sheet
[Android] Fix nested action sheets... again
2019-11-05 07:23:19 -06:00
Brad Bumbalough b4f1ae39f9 fix: android calling nested action sheets
- Shouldn't wait until isAnimating since onSelect gets called before _animateOut().
2019-11-04 22:48:40 -06:00
Brad Bumbalough 817582e054 chore: add nested action sheet example 2019-11-04 22:47:30 -06:00
Brad Bumbalough 1a34e86f43 chore: remove package-lock.json
- Accidentally commited this in #136.
2019-11-04 22:40:19 -06:00
Brad Bumbalough e571b97653 chore: sync package-lock and fix audit issues (#139) 2019-10-30 07:44:44 -05:00
Brad Bumbalough a4e11daeec chore(release): configure semantic-release (#136)
- Updates changelog
- Deploys to npm, github tag
- Create github workflow to run release on merges to master
2019-10-30 07:36:54 -05:00
Brad Bumbalough 08a929d477 chore(release): configure semantic-release
- Updates changelog
- Deploys to npm, github tag
- Create github workflow to run release on merges to master
2019-10-30 07:35:28 -05:00
soh335 cd966b48ad style(types): export ActionSheetProps (#135)
When using connectActionSheet, component props should have Context.
So need to type `showActionSheetWithOptions: (options:
ActionSheetOptions, callback: (i: number) => void) => void;` many times.

Context is exported, but it is too common name and cant import from
`'@expo/react-native-action-sheet'`.
2019-10-30 07:31:49 -05:00
dependabot[bot] 3fc5e9f478 fix: update eslint-utils to resolve security issue (#137)
Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.3.1 to 1.4.3.
- [Release notes](https://github.com/mysticatea/eslint-utils/releases)
- [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.3.1...v1.4.3)

Signed-off-by: dependabot[bot] <[email protected]>
2019-10-28 17:25:01 -05:00
Brad Bumbalough 7f83be5f7a 3.3.0 2019-10-26 14:44:45 -05:00
Brent Vatne 4e3914df1b Merge pull request #131 from colinux/android-fix-separator-key
Android: fix duplicate separator key when key arg == 0
2019-10-26 12:02:37 -07:00
Colin Darie 22c0c52c6a Android: fix duplicate separator key when arg key == 0
In the previous implementation when key == 0, the generated key was "0" (and not "separator-0"), which is the same as the option row key, so React complained about it.
2019-10-07 00:04:15 +02:00
Brent Vatne 032e7c632b Publish 3.2.0 2019-09-27 16:57:45 -07:00
Brent Vatne d4a8c0398e Merge pull request #130 from Naturalclar/feat/pr102ToTsx
feat: make actionsheet non-cancelable for empty index
2019-09-27 16:54:38 -07:00
Brent Vatne 638173e2ec Update index.tsx 2019-09-27 16:53:09 -07:00
Brent Vatne a2b40112a9 Merge pull request #122 from bradbumbalough/bb/android-show-multiple-actionsheet
Supports nested ActionSheets in Android
2019-09-27 16:51:25 -07:00
Jesse Katsumata 31a25c27be feat: make actionsheet non-cancelable for empty index 2019-09-27 11:35:00 +09:00
Brad Bumbalough 7e0f6173b3 Supports nested ActionSheets in Android
- Closes #112
2019-09-26 10:30:57 -05:00
Brent Vatne 113353e853 Release 3.1.0 2019-09-25 16:39:43 -07:00
Brent Vatne a5c88169a7 Update example 2019-09-25 16:39:34 -07:00
Brent Vatne 384386f85b Merge pull request #127 from kesha-antonov/master
[Android] Fix showActionSheetWithOptions context
2019-09-25 15:51:49 -07:00
Brent Vatne ebbca8a1ac Merge pull request #128 from rikardwissing/fix/hoist-statics
Hoist statics on components with connected action sheet
2019-09-25 15:51:13 -07:00
Brent Vatne 764fef3359 Merge pull request #119 from SimenB/hook
feat: add useActionSheet hook
2019-09-25 15:50:44 -07:00
rikardwissing c27e88deb5 Hoist statics on components with connected action sheet 2019-09-10 12:29:23 +02:00
Kesha Antonov 3091a2ab25 Update index.tsx 2019-08-15 08:37:31 +03:00
Simen Bekkhus 46ec2db2d3 Update README.md 2019-08-08 12:36:12 +02:00
Brent Vatne 22753e0c0c Release 3.0.3 2019-07-16 12:08:47 -07:00
Brent Vatne a58dff38d0 Merge pull request #121 from nd-02110114/ios-option
Hotfix in package.json
2019-07-16 12:04:47 -07:00
nd-02110114 3df9bae02f 🔥 (npmignore) remove unused .npmignore 2019-07-16 10:48:01 +09:00
nd-02110114 5051be3c0e 🔥 (package.json) remove src in publish 2019-07-16 10:45:33 +09:00
nd-02110114 44d5ae3e77 🐛 (package.json) fix types & react-native in package.json 2019-07-16 10:34:34 +09:00
nd-02110114 5d42516a87 ⬆️ (example) update dependencies. 2019-07-14 11:24:25 +09:00
nd-02110114 e19ae91d3d 🚨 (example) fix tsc error 2019-07-14 10:45:06 +09:00
nd-02110114 f5ec6b4ab8 📝 (readme) fix width for gif 2019-07-14 10:31:05 +09:00
nd-02110114 fb302a5bce 📝 (readme) add badge 2019-07-14 10:25:28 +09:00
Simen Bekkhus 973dfb4f3f feat: add useActionSheet hook 2019-07-13 22:59:36 +02:00
Brent Vatne 874930c050 Publish bob version 2019-07-13 10:15:53 -07:00
Brent Vatne de9635aa2c Merge pull request #117 from nd-02110114/improve-dx
Improve DX
2019-07-13 09:46:09 -07:00
Brent Vatne cf5251594a Release 3.0.1 2019-07-13 09:09:52 -07:00
Brent Vatne 2c82eaa89c Remove emptuy files field 2019-07-13 09:09:31 -07:00
nd-02110114 e1964bce80 📝 (readme) update readme 2019-07-13 19:20:51 +09:00
nd-02110114 02f99ebb83 ✨ (example) update example 2019-07-13 19:19:43 +09:00
nd-02110114 dc2176e463 🔧 use bob, eslint, prettier 2019-07-13 19:13:11 +09:00
Brent Vatne 16d1ef0b41 Publish 3.0.0 with TypeScript! 2019-07-12 11:27:56 -07:00
Brent Vatne 7666619df5 Merge pull request #110 from nd-02110114/convert-ts
Flow to Typescript
2019-07-12 11:21:42 -07:00
nd-02110114 39f4e94550 🚨 (src) apply prettier 2019-04-01 14:10:27 +09:00
nd-02110114 eacda36ec0 📝 (readme) fix README 2019-04-01 13:48:41 +09:00
nd-02110114 3b26304031 📝 (src) improve README 2019-04-01 13:36:42 +09:00
nd-02110114 41a06917b0 ♻️ (src) remove unused export 2019-03-31 11:32:32 +09:00
nd-02110114 337057a635 ♻️ (src) create context.ts 2019-03-31 11:19:51 +09:00
nd-02110114 424660ada5 ♻️ (src) fix type annnotation 2019-03-30 11:31:13 +09:00
nd-02110114 2e74084272 ♻️ (src) fix type annotation 2019-03-29 23:21:36 +09:00
nd-02110114 56d379bc23 👌 (src) fix by following review 2019-03-29 09:38:13 +09:00
nd-02110114 2ea391f668 ➖ (npm modules) delete unused @types 2019-03-29 09:33:04 +09:00
nd-02110114 d58d80fd89 ➖ (package.json) remove hoist-non-react-statics 2019-03-28 17:50:50 +09:00
nd-02110114 e9b2c8399c ✨ (example) add new example 2019-03-28 17:17:28 +09:00
nd-02110114 5618219c30 ♻️ (src) use new context api 2019-03-28 17:16:46 +09:00
nd-02110114 40f945a035 💥 (src) convert flow to ts 2019-03-26 00:31:45 +09:00
Evan Bacon 5ee7d9af74 Update ActionSheet.js 2019-01-30 16:04:02 -08:00
Brent Vatne 68ff6a1df9 Merge pull request #99 from expo/@evanbacon/expo-web/action-sheet
[Web] Added support for running with expo for web
2019-01-30 15:41:29 -08:00
Evan Bacon 3be83131c6 Updated docs 2019-01-30 15:19:52 -08:00
Evan Bacon 8e943863db Added Web 2019-01-30 15:16:21 -08:00
Peter Piekarczyk 040980edcf 2.0.1 2019-01-04 09:34:18 -06:00
Peter Piekarczyk 231630b875 2.0.1-1 2019-01-04 09:29:51 -06:00
Peter Piekarczyk 3c2ccec2d1 2.0.1-0 2019-01-04 09:29:45 -06:00
Peter Piekarczyk e35a4bffbb Merge pull request #96 from omerman/patch-1
Fixes an IOS issue for when not passing tintColor.
2019-01-04 09:27:25 -06:00
Omer c87602ea3b Remove tintColor default prop assignment. 2019-01-02 16:08:24 +02:00
Omer 8c1a319a3a Fixes an IOS issue for when not passing tintColor
Fixes "JSON value '<null>' of type NSNull cannot be converted to a UIColor. Did you forget to call processColor() on the JS side?"
2018-12-26 10:01:47 +02:00
Peter Piekarczyk ac17d305db Android UI & API Improvements #78 from jstheoriginal/master
Android UI & API Improvements
2018-12-11 16:43:22 -06:00
Justin Stanley 2b9d8e5ec6 Clarified tint ability of icons in the readme. 2018-11-11 13:37:42 -06:00
Justin Stanley fe8df1b685 Cleaned up App.js
Added SafeAreaView, added section headers to show Universal examples vs Android option examples, moved styles to static stylesheet.
2018-11-11 12:46:18 -06:00
Justin Stanley 74473dc4bd Fixed error with View.propTypes.style propType.
Changed it to PropTypes.object instead.
2018-11-11 12:45:21 -06:00
Justin Stanley 2ca8d6217e Removed unused NativeModules import. 2018-11-11 11:29:02 -06:00
Justin Stanley cebaef95a3 Updated the README formatting & wording for Options/Usage 2018-11-11 11:26:38 -06:00
Justin Stanley 15460b6a08 Added the new options/styles to ActionSheetProvider.
- it allows the user to apply it globally so they don’t need to be provided each time the method is called.
2018-11-11 11:25:59 -06:00
Justin Stanley afb0fefd7b Updated version to 2.0.0. 2018-11-11 10:02:58 -06:00
Justin Stanley 04a99ae94b Added missing semicolons & separatorStyle key should be optional. 2018-11-11 10:00:40 -06:00
Justin Stanley 432ae92569 Merge remote-tracking branch 'upstream/master' 2018-11-11 09:50:32 -06:00
Justin Stanley 2fa0e21086 Added separatorStyle prop so you can change the separator style if desired.
- Also defaulted title and message to null in _renderSheet.
2018-11-10 18:28:56 -06:00
Justin Stanley 33d77f4d04 Destructured options & more state items in _renderSheet 2018-11-10 18:09:14 -06:00
Justin Stanley 883399be33 defaultProps for ActionGroup due to user-supplied object
- instead, I’ve defaulted tintIcons (true) and textStyle ({}) at the render source
2018-11-10 18:03:41 -06:00
Justin Stanley 59e34c83b4 Use !! with && to render instead of ternary defaulting to null.
- Gave default empty object prop to textStyle
- Moved destructive colour to a constant
2018-11-10 17:13:55 -06:00
Peter Piekarczyk 2e75f9551d Merge pull request #83 from jsdario/patch-1
Allows Android textStyle to be declared at the Provider
2018-09-30 21:12:04 -05:00
Peter Piekarczyk 2fc359b9c0 Merge pull request #92 from dozoisch/patch-1
add types to NPM file list
2018-09-05 09:07:46 -05:00
Hugo Dozois 945028d34f add types to NPM file list 2018-09-04 15:58:46 -04:00
Peter Piekarczyk ed82cb0047 add yarn.lock 2018-08-21 18:03:50 -05:00
Justin Stanley 42740e93a0 Improved ShowActionSheetButton helper class.
Moved buttons in example to a helper function since it’s long.
2018-08-21 14:41:35 -05:00
Justin Stanley 3c95b8a86d Added new Android-only prop: tintIcons.
- Defaults to true (same as current implementation).
- If set to false, the images will be rendered at their default colours (allows for full colour icons).
- Fixed incorrect typeof check for iconSource.
- Updated readme to reference new prop.
2018-08-21 14:40:04 -05:00
Justin Stanley f35de5dd25 Added icons to Android-only props in README. 2018-08-21 13:36:32 -05:00
Justin Stanley 8ef0ee36e7 Fixed crash on iOS if the icons array contains elements (like vector icons) rather than image source paths. 2018-08-21 13:36:11 -05:00
Justin Stanley 3a9bc50e84 You can now pass either react nodes or image sources in the icons array.
Also fixed the type for icons as it was an array of numbers previously.
2018-08-20 21:43:08 -05:00
Justin Stanley 7fe0aff0fe Use shorthand for null to set title and message to undefined.
Also undid change to formatting of return in render.
2018-08-20 19:38:06 -05:00
Justin Stanley 98528d9399 Use MaterialIcons for example icons rather than including images. 2018-08-20 19:34:44 -05:00
Justin Stanley 8ec19d3bfc Changed the show action sheet button functions into a component for clarity. 2018-08-20 19:24:13 -05:00
Justin Stanley 3e2a8d6c1d Removed flow type annotations from example app. 2018-08-20 18:58:10 -05:00
Brent Vatne bf5b9680aa Remove package-lock 2018-08-20 10:48:10 -07:00
Peter Piekarczyk cbba57e9c7 1.1.0 2018-08-17 10:11:20 -05:00
Peter Piekarczyk ebd285c342 Merge pull request #85 from henrikra/master
Add TypeScript types
2018-08-15 14:53:01 -05:00
Justin Stanley 81f64772c7 Removed unused SafeAreaView. 2018-07-27 09:38:29 -05:00
Justin Stanley fa027c0f81 Added a few more Android only comments to example. 2018-07-27 01:44:47 -05:00
Justin Stanley f9376eb0ca Tweaked the example message so it works for iOS as well. 2018-07-27 01:39:15 -05:00
Justin Stanley 72d2e2a0ea Updated readme. 2018-07-27 01:25:41 -05:00
Justin Stanley acfd89c465 Added tintColor to Android to match iOS option. 2018-07-27 01:25:11 -05:00
Justin Stanley b2862ba08c Made Android Action Sheet match native Material sheet.
Added new Android props:
- title
- message
- titleTextStyle
- messageTextStyle
- showSeparators (defaults to false)

Made the Android sheet look as close to the specs at https://material.io/design/components/sheets-bottom.html#specs as possible.

Cleaned up the existing code.

Added examples for a bunch of different scenarios in the example app.

Fixed an existing crash where icons actually crashed due if you didn’t provide the textStyle prop.

Fixed a crash on iOS if you passed a null title or message.
2018-07-27 01:03:22 -05:00
Henrik Raitasola dad86d74e8 Rename 2018-07-12 14:35:05 +03:00
Henrik Raitasola f1b58141b0 Add tests 2018-07-12 14:34:28 +03:00
Henrik Raitasola dbd9da903c Add TypeScript types 2018-07-12 14:00:03 +03:00
Jesús Darío dfe724247c Allows Android textStyle to be declared at the Provider 2018-06-05 13:53:30 +02:00
Justin Stanley 150cf5fcca resolved merge conflict. 2018-03-05 21:56:31 -06:00
Peter Piekarczyk da74bb03c4 Merge pull request #52 from wsxyeah/master
Add material design style for Android
2018-02-24 10:48:05 -08:00
Brent Vatne eb3249f978 Remove package-lock, update privacy of example 2018-02-19 16:28:12 -08:00
Brent Vatne f1065b7ad6 Update example app 2018-02-19 16:26:28 -08:00
Brent Vatne ad32e911e6 Merge pull request #76 from peterpme/master
Update Documentation to Include Example (updates #37)
2018-02-19 16:25:54 -08:00
Peter Piekarczyk 621b0ad795 Update README.md 2018-02-19 16:23:07 -08:00
Peter Piekarczyk 768a12ed0f Exponent -> Expo 2018-02-19 16:21:06 -08:00
Brent Vatne bde52949cb Merge pull request #74 from xcarpentier/patch-1
Update main.js
2018-02-19 16:15:39 -08:00
Brent Vatne 1d8837090f Merge pull request #70 from peterpme/master
Expo SDK 17 -> 24 (Example is broken due to low version)
2018-02-19 16:15:18 -08:00
Brent Vatne ffdb5335d6 Release 1.0.2 2018-02-19 16:10:04 -08:00
Xavier Carpentier 07b7676691 Update main.js 2018-02-13 13:38:26 +01:00
quinlanj ca5c544b9e Merge pull request #71 from expo/quin_shipit_reverts
reverting erroneous shipits
2018-01-10 17:08:03 -08:00
Quinlan Jung bf2c37859f Chose ide's 82887ca778 over brentvatne's ac2e2960ee version bump
Revert "[shipit] fixed package.json to 4764e8ccb7~"

This reverts commit 15856cca3d.
2018-01-10 16:51:56 -08:00
Quinlan Jung 215a0326a7 Revert "[shipit] fixed ActionSheet.android.js to 79cf6a607d~"
This reverts commit 3c2a61de8e.
2018-01-10 16:49:34 -08:00
Peter Piekarczyk 12623f953c bump expo version 17 -> 24 2017-12-29 19:16:41 -08:00
Brent Vatne ac2e2960ee Bump version
fbshipit-source-id: 4764e8ccb7
2017-12-12 22:25:21 +00:00
Exponent GitHub Bot 15856cca3d [shipit] fixed package.json to 4764e8ccb7~ 2017-12-12 22:24:13 +00:00
ajackster 2f3ba1b72d Added scroll view to menu on Android
Closes expo/react-native-action-sheet#30

fbshipit-source-id: dd742ec61d
2017-12-12 22:21:44 +00:00
James Ide 2ff7205f96 Run prettier 1.7 with 100-col on libraries
Used the latest prettier with 100-col config on most libraries except expo-sdk and snack-sdk. Will do those individually and later.

fbshipit-source-id: 79cf6a607d
2017-12-12 22:21:43 +00:00
Exponent GitHub Bot 3c2a61de8e [shipit] fixed ActionSheet.android.js to 79cf6a607d~ 2017-12-12 22:20:20 +00:00
James Ide 82887ca778 1.0.1 2017-09-15 12:27:52 -05:00
Kesha Antonov e73314d994 add prop-types pkg. upd deps 2017-09-15 10:27:28 -07:00
Shaoxing Wang e901568a98 Add material design style for Android 2017-07-21 09:31:57 +08:00
Brent Vatne 54fe453a5d Bump version 2017-06-28 14:53:57 -07:00
Brent Vatne d5dc960e0f Merge pull request #45 from kesha-antonov/fix_rn_0.44_comp
BackAndroid -> BackHandler
2017-06-28 14:52:48 -07:00
Ben Roth 83c98addea Update example to SDK 17
fbshipit-source-id: a542d1a
2017-06-15 01:08:56 +00:00
Kesha Antonov 1fdcc54c92 BackAndroid -> BackHandler 2017-04-27 07:27:52 +03:00
Adam Miskiewicz 2d1d25325a Run Prettier on ALL js.
fbshipit-source-id: 4471f45
2017-04-14 01:31:38 +00:00
Brent Vatne 8bf86b1bf8 Bump version
fbshipit-source-id: 8c343d0
2017-03-22 19:04:49 +00:00
Jason Schloer 60fbd7d117 const exports looks like it was a bad idea.
This should fix the issue I mention in #26. Essentially reverts an unnecessary change I made in the last pull request. Still not 100% convinced that this is the best way to do these exports, so feel free to offer other suggestions.

Closes exponent/react-native-action-sheet#27

fbshipit-source-id: b8ae451
2017-03-22 19:04:49 +00:00
Brent Vatne 34a3ca1498 Exponent -> Expo
fbshipit-source-id: 38cbe83
2017-03-07 00:03:40 +00:00
Sibelius Seraphini 9b769eadc4 Copies non-react specific statics on @connectActionSheet, fix #34
Closes exponent/react-native-action-sheet#35

fbshipit-source-id: 21062c2
2017-02-21 20:08:21 +00:00
James Ide 5d59088fea Rename exponentjs references in our libraries
fbshipit-source-id: 21072ac
2016-12-21 19:01:06 +00:00
tim.farley b25206f7e6 define title styles when message is present in normal styles obj 2016-12-02 16:43:48 -07:00
Tim Farley ccfc3b448a Merge pull request #2 from dtdo-timfarley/android-support-for-message-prop
Adds support for message prop in Android
2016-12-02 16:11:16 -07:00
tim.farley 38150163c1 Adds support for message prop in Android 2016-12-02 16:09:38 -07:00
Tim Farley 88d27eba92 Merge pull request #1 from dtdo-timfarley/add-support-for-title-in-android
Adds Android support for an optional title prop.
2016-12-02 15:47:30 -07:00
tim.farley 9fee7dc244 Adds Android support for an optional title prop, similar to native iOS title 2016-12-02 15:39:29 -07:00
Brent Vatne b707cec0ae Update README for new changes
fbshipit-source-id: a7cafa3
2016-11-25 23:06:53 +00:00
Brent Vatne 1501652c7f Bump version and add example project
fbshipit-source-id: 75f7ced
2016-11-25 23:06:53 +00:00
Jason Schloer f577ec4908 Added a Provider/connect style implementation
Created a set of wrapper components to isolate the use of context, similar to Redux.
Tested on iOS, but not Android yet.

If you think you'\''d accept a pull request like this, let me know and I'\''ll go ahead and write up some documentation. Thanks

Usage basically looks like
Provider:

connect:

Closes exponentjs/react-native-action-sheet#23

fbshipit-source-id: 14e0919
2016-11-25 23:06:53 +00:00
Brent Vatne 3477e4d284 Bump version
fbshipit-source-id: d77e0bf
2016-09-08 05:34:59 +00:00
Kfir Golan 7dcd315ab2 expose useNativeDriver as a prop of ActionSheet to allow users to disable it
Closes #19

fbshipit-source-id: 558ffce
2016-09-08 05:33:29 +00:00
Swordsman-Inaction 2db7d67870 Feature(Android): ability to change text style
Allow user to change text style of menus on Android

Closes #17

fbshipit-source-id: 4922f8a
2016-09-05 18:44:54 +00:00
Brent Vatne c3c57ea1d9 Bump version. Closes #18
fbshipit-source-id: 93835b8
2016-09-05 03:52:22 +00:00
Swordsman-Inaction 600b2fffc6 Fix(Android): remove useless code. Closes #16
fbshipit-source-id: e97f66e
2016-09-05 03:45:18 +00:00
Brent Vatne f799f58dba Update README to demonstrate import
fbshipit-source-id: 41e2e02
2016-08-30 23:16:30 +00:00
37 changed files with 16015 additions and 566 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
node_modules
exmaple/node_modules
# generated by bob
lib/
+14
View File
@@ -0,0 +1,14 @@
module.exports = {
extends: [
'@react-native-community',
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint',
],
rules: {
// Turn off rules which are useless and annoying for this project
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-member-accessibility': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'react-native/no-inline-styles': 'off',
},
};
-99
View File
@@ -1,99 +0,0 @@
[ignore]
# We fork some components by platform.
.*/*.web.js
.*/node_modules/.*/*.android.js
# Some modules have their own node_modules with overlap
.*/node_modules/node-haste/.*
# Ugh
.*/node_modules/babel.*
.*/node_modules/babylon.*
.*/node_modules/invariant.*
# Ignore react and fbjs where there are overlaps, but don't ignore
# anything that react-native relies on
.*/node_modules/fbjs/lib/Map.js
.*/node_modules/fbjs/lib/ErrorUtils.js
# Flow has a built-in definition for the 'react' module which we prefer to use
# over the currently-untyped source
.*/node_modules/react/react.js
.*/node_modules/react/lib/React.js
.*/node_modules/react/lib/ReactDOM.js
.*/__mocks__/.*
.*/__tests__/.*
.*/commoner/test/source/widget/share.js
# Ignore commoner tests
.*/node_modules/commoner/test/.*
# See https://github.com/facebook/flow/issues/442
.*/react-tools/node_modules/commoner/lib/reader.js
# Ignore jest
.*/node_modules/jest-cli/.*
# Ignore Website
.*/website/.*
# Ignore generators
.*/local-cli/generator.*
# Ignore BUCK generated folders
.*\.buckd/
# Ignore RNPM
.*/local-cli/rnpm/.*
.*/node_modules/is-my-json-valid/test/.*\.json
.*/node_modules/iconv-lite/encodings/tables/.*\.json
.*/node_modules/y18n/test/.*\.json
.*/node_modules/spdx-license-ids/spdx-license-ids.json
.*/node_modules/spdx-exceptions/index.json
.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json
.*/node_modules/resolve/lib/core.json
.*/node_modules/jsonparse/samplejson/.*\.json
.*/node_modules/json5/test/.*\.json
.*/node_modules/ua-parser-js/test/.*\.json
.*/node_modules/builtin-modules/builtin-modules.json
.*/node_modules/binary-extensions/binary-extensions.json
.*/node_modules/url-regex/tlds.json
.*/node_modules/joi/.*\.json
.*/node_modules/isemail/.*\.json
.*/node_modules/tr46/.*\.json
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
[options]
module.system=haste
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
experimental.strict_type_args=true
munge_underscores=true
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
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\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-6]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-6]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version]
^0.26.0
+49
View File
@@ -0,0 +1,49 @@
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IJ
#
.idea
.gradle
local.properties
*.iml
/android/app/*.keystore
/android/app/*.apk
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore
coverage
# generated by bob
lib/
-27
View File
@@ -1,27 +0,0 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
+5
View File
@@ -0,0 +1,5 @@
node_modules
example/node_modules
# generated by bob
lib/
+7
View File
@@ -0,0 +1,7 @@
{
"printWidth": 100,
"tabWidth": 2,
"singleQuote": true,
"jsxBracketSameLine": true,
"trailingComma": "es5"
}
+21
View File
@@ -0,0 +1,21 @@
{
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md",
"changelogTitle": "# Changelog"
}
],
[
"@semantic-release/git",
{
"assets": ["CHANGELOG.md", "package.json"]
}
],
"@semantic-release/npm",
"@semantic-release/github"
]
}
-369
View File
@@ -1,369 +0,0 @@
// @flow
import React, { PropTypes } from 'react';
import {
Animated,
BackAndroid,
Easing,
PixelRatio,
Platform,
StyleSheet,
Text,
NativeModules,
TouchableOpacity,
TouchableNativeFeedback,
TouchableWithoutFeedback,
View,
} from 'react-native';
// Not everybody has this enabled yet
const useNativeDriver = !!NativeModules.NativeAnimatedModule;
type ActionSheetOptions = {
options: Array<string>,
destructiveButtonIndex: ?number,
cancelButtonIndex: ?number,
}
type ActionGroupProps = {
options: Array<string>,
destructiveButtonIndex: ?number,
onSelect: (i: number) => boolean,
startIndex: number,
length: number,
}
type ActionSheetState = {
isVisible: boolean,
isAnimating: boolean,
options: ?ActionSheetOptions,
onSelect: ?(i: number) => void,
overlayOpacity: any,
sheetOpacity: any,
}
type ActionSheetProps = {
children: ?any,
}
const OPACITY_ANIMATION_TIME = 150;
const PIXEL = 1 / PixelRatio.get();
class ActionGroup extends React.Component {
props: ActionGroupProps;
static propTypes = {
options: PropTypes.array.isRequired,
destructiveButtonIndex: PropTypes.number,
onSelect: PropTypes.func.isRequired,
startIndex: PropTypes.number.isRequired,
length: PropTypes.number.isRequired,
};
render() {
let {
options,
destructiveButtonIndex,
onSelect,
startIndex,
length,
} = this.props;
let optionViews = [];
let nativeFeedbackBackground = TouchableNativeFeedbackSafe.Ripple(
'rgba(180, 180, 180, 1)',
false
);
for (let i = startIndex; i < startIndex + length; i++) {
let color = '#444444';
if (i === destructiveButtonIndex) {
color = '#ff3b30';
}
optionViews.push(
<TouchableNativeFeedbackSafe
key={i}
pressInDelay={0}
background={nativeFeedbackBackground}
onPress={() => onSelect(i)}
style={styles.button}>
<Text style={[styles.text, {color}]}>
{options[i]}
</Text>
</TouchableNativeFeedbackSafe>
);
if (i < startIndex + length - 1) {
optionViews.push(
<View key={`separator-${i}`} style={styles.rowSeparator} />
);
}
}
return (
<View style={styles.groupContainer}>
{optionViews}
</View>
);
}
}
// Has same API as https://facebook.github.io/react-native/docs/actionsheetios.html
export default class ActionSheet extends React.Component {
props: ActionSheetProps;
_animateOutCallback: ?() => void = null;
state: ActionSheetState = {
isVisible: false,
isAnimating: false,
options: null,
onSelect: null,
overlayOpacity: new Animated.Value(0),
sheetOpacity: new Animated.Value(0),
};
render() {
let { isVisible } = this.state;
let overlay = isVisible ? (
<Animated.View style={[styles.overlay, {
opacity: this.state.overlayOpacity,
}]} />
) : null;
let sheet = isVisible ? this._renderSheet() : null;
return (
<View style={{flex: 1}}>
{React.Children.only(this.props.children)}
{overlay}
{sheet}
</View>
);
}
_renderSheet() {
if (!this.state.options) {
return;
}
let numOptions = this.state.options.options.length;
return (
<TouchableWithoutFeedback onPress={this._selectCancelButton}>
<Animated.View
needsOffscreenAlphaCompositing={this.state.isAnimating}
style={[styles.sheetContainer, {
opacity: this.state.sheetOpacity,
transform: [{scale: this.state.sheetOpacity.interpolate({inputRange: [0, 0.5, 1], outputRange: [0.6, 1, 1]})}],
}]}>
<View style={styles.sheet}>
<ActionGroup
options={this.state.options.options}
destructiveButtonIndex={this.state.options.destructiveButtonIndex}
onSelect={this._onSelect}
startIndex={0}
length={numOptions}
/>
</View>
</Animated.View>
</TouchableWithoutFeedback>
);
}
showActionSheetWithOptions(
options: ActionSheetOptions,
onSelect: (i: number) => void,
onAnimateOut: () => void
) {
if (this.state.isVisible) {
return;
}
this.setState({
options,
onSelect,
isVisible: true,
isAnimating: true,
});
this.state.overlayOpacity.setValue(0);
this.state.sheetOpacity.setValue(0);
Animated.parallel([
Animated.timing(this.state.overlayOpacity, {
toValue: 0.5,
easing: Easing.in(Easing.linear),
duration: OPACITY_ANIMATION_TIME,
useNativeDriver,
}),
Animated.timing(this.state.sheetOpacity, {
toValue: 1,
easing: Easing.in(Easing.linear),
duration: OPACITY_ANIMATION_TIME,
useNativeDriver,
}),
]).start(result => {
if (result.finished) {
this.setState({
isAnimating: false,
});
}
});
this._animateOutCallback = onAnimateOut;
BackAndroid.addEventListener('actionSheetHardwareBackPress', this._selectCancelButton);
}
_selectCancelButton = () => {
if (!this.state.options) {
return;
}
if (typeof this.state.options.cancelButtonIndex === 'number') {
return this._onSelect(this.state.options.cancelButtonIndex);
} else {
return this._animateOut();
}
}
_onSelect = (index: number): boolean => {
if (this.state.isAnimating) {
return false;
}
this.state.onSelect && this.state.onSelect(index);
return this._animateOut();
}
_animateOut = (): boolean => {
if (this.state.isAnimating) {
return false;
}
BackAndroid.removeEventListener('actionSheetHardwareBackPress', this._selectCancelButton);
this.setState({
isAnimating: true,
});
Animated.parallel([
Animated.timing(this.state.overlayOpacity, {
toValue: 0,
easing: Easing.in(Easing.linear),
duration: OPACITY_ANIMATION_TIME,
useNativeDriver,
}),
Animated.timing(this.state.sheetOpacity, {
toValue: 0,
easing: Easing.in(Easing.linear),
duration: OPACITY_ANIMATION_TIME,
useNativeDriver,
}),
]).start(result => {
if (result.finished) {
this.setState({
isVisible: false,
isAnimating: false,
});
if (typeof this._animateOutCallback === 'function') {
this._animateOutCallback();
this._animateOutCallback = null;
}
}
});
return true;
}
}
let TouchableComponent;
if (Platform.OS === 'android') {
TouchableComponent = Platform.Version <= 20 ? TouchableOpacity : TouchableNativeFeedback;
} else {
TouchableComponent = TouchableOpacity;
}
if (TouchableComponent !== TouchableNativeFeedback) {
TouchableComponent.SelectableBackground = () => ({});
TouchableComponent.SelectableBackgroundBorderless = () => ({});
TouchableComponent.Ripple = (color, borderless) => ({});
}
class TouchableNativeFeedbackSafe extends React.Component {
static SelectableBackground = TouchableComponent.SelectableBackground;
static SelectableBackgroundBorderless = TouchableComponent.SelectableBackgroundBorderless;
static Ripple = TouchableComponent.Ripple;
render() {
if (TouchableComponent === TouchableNativeFeedback) {
return (
<TouchableComponent {...this.props} style={{}}>
<View style={this.props.style}>
{this.props.children}
</View>
</TouchableComponent>
);
} else {
return (
<TouchableComponent {...this.props}>
{this.props.children}
</TouchableComponent>
);
}
}
}
let styles = StyleSheet.create({
groupContainer: {
backgroundColor: '#fefefe',
borderRadius: 4,
borderColor: '#cbcbcb',
borderWidth: PIXEL,
overflow: 'hidden',
marginHorizontal: 16,
marginBottom: 8,
},
button: {
justifyContent: 'center',
alignItems: 'flex-start',
height: 50,
paddingHorizontal: 16,
},
text: {
fontSize: 17,
fontWeight: '700',
},
rowSeparator: {
backgroundColor: '#dddddd',
height: 1,
flex: 1,
},
overlay: {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
backgroundColor: 'black',
},
sheetContainer: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
top: 0,
backgroundColor: 'transparent',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
},
sheet: {
flex: 1,
backgroundColor: 'transparent',
},
});
-21
View File
@@ -1,21 +0,0 @@
'use strict';
import React from 'react';
import {
ActionSheetIOS,
View,
} from 'react-native';
export default class ActionSheet extends React.Component {
render() {
return (
<View style={{flex: 1}}>
{React.Children.only(this.props.children)}
</View>
);
}
showActionSheetWithOptions(options, onSelect) {
ActionSheetIOS.showActionSheetWithOptions(options, onSelect);
}
}
+23
View File
@@ -0,0 +1,23 @@
# Changelog
# [3.5.0](https://github.com/expo/react-native-action-sheet/compare/v3.4.1...v3.5.0) (2020-02-04)
### Features
* add anchor option for iPads ([#155](https://github.com/expo/react-native-action-sheet/issues/155)) ([370e6e8](https://github.com/expo/react-native-action-sheet/commit/370e6e855fbacbfc683cc6ab16304f26c159e6b5))
## [3.4.1](https://github.com/expo/react-native-action-sheet/compare/v3.4.0...v3.4.1) (2019-12-13)
### Bug Fixes
* **iOS:** crash when using Android only options ([#144](https://github.com/expo/react-native-action-sheet/issues/144)) ([8016008](https://github.com/expo/react-native-action-sheet/commit/8016008781cbe418dc03f04a324d5e5ef5bcdaa7))
# [3.4.0](https://github.com/expo/react-native-action-sheet/compare/v3.3.2...v3.4.0) (2019-11-19)
### Features
* **android:** allow customizing container styles ([#142](https://github.com/expo/react-native-action-sheet/issues/142)) ([39fc431](https://github.com/expo/react-native-action-sheet/commit/39fc431c97cb0ec03ab2a8386bd1b836d9f1cd2f))
* Allow pointerEvents prop to pass through to containing view ([#124](https://github.com/expo/react-native-action-sheet/issues/124)) ([76397fa](https://github.com/expo/react-native-action-sheet/commit/76397fa7c4bff7318780ac72600156d753fad3f0))
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 Exponent
Copyright (c) 2015 Expo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+172 -38
View File
@@ -1,61 +1,195 @@
# react-native-action-sheet [![Slack](http://slack.exponentjs.com/badge.svg)](http://slack.exponentjs.com)
# react-native-action-sheet
[![npm](https://img.shields.io/npm/v/@expo/react-native-action-sheet.svg?style=flat-square)](https://www.npmjs.com/package/@expo/react-native-action-sheet)
[![License: MIT](https://img.shields.io/github/license/nd-02110114/goofi-mobile.svg)](https://opensource.org/licenses/MIT)
[![Slack](https://slack.expo.io/badge.svg)](https://slack.expo.io)
ActionSheet is a cross-platform React Native component that uses the native UIActionSheet on iOS and a JS implementation on Android. Almost a drop in replacement for [ActionSheetIOS](https://facebook.github.io/react-native/docs/actionsheetios.html) except it cannot be called statically.
| iOS | Android | Web |
|---------------------------|---------------------------|---------------------------|
| <img src="https://raw.githubusercontent.com/expo/react-native-action-sheet/master/gif/ios.gif" width="200" height="400"/> | <img src="https://raw.githubusercontent.com/expo/react-native-action-sheet/master/gif/android.gif" width="200" height="400"/> | <img src="https://raw.githubusercontent.com/expo/react-native-action-sheet/master/gif/web.gif" width="400" height="400"/> |
## Installation
```
npm install @exponent/react-native-action-sheet
$ npm install @expo/react-native-action-sheet -S
```
or
```
$ yarn add @expo/react-native-action-sheet
```
## Usage
## A basic ActionSheet Setup
Wrap your entire app in `ActionSheet`. We recommend using [context](https://facebook.github.io/react/docs/context.html) to pass `ActionSheet` to the rest of your app.
### 1. Connect your component which uses showActionSheetWithOptions.
```es6
import { connectActionSheet } from '@expo/react-native-action-sheet'
```js
class MainApp extends React.Component {
class App extends React.Component {
/* ... */
}
static childContextTypes = {
actionSheet: PropTypes.func,
};
const ConnectedApp = connectActionSheet(App)
getChildContext() {
return {
actionSheet: () => this._actionSheetRef,
};
}
export default ConnectedApp
```
`App` component can access the actionSheet method as `this.props.showActionSheetWithOptions`
```es6
_onOpenActionSheet = () => {
// Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
const options = ['Delete', 'Save', 'Cancel'];
const destructiveButtonIndex = 0;
const cancelButtonIndex = 2;
this.props.showActionSheetWithOptions(
{
options,
cancelButtonIndex,
destructiveButtonIndex,
},
buttonIndex => {
// Do something here depending on the button index selected
},
);
};
```
You can use a hook instead of the higher order component if you are on React 16.8 or newer.
```es6
import { useActionSheet } from '@expo/react-native-action-sheet'
export default function App () {
const { showActionSheetWithOptions } = useActionSheet();
/* ... */
}
```
### 2. Wrap your top-level component with `<ActionSheetProvider />`
```es6
import { ActionSheetProvider } from '@expo/react-native-action-sheet'
class AppContainer extends React.Component {
render() {
return (
<ActionSheet ref={component => this._actionSheetRef = component}>
// Render the rest of your app here.
</ActionSheet>
<ActionSheetProvider>
<ConnectedApp />
</ActionSheetProvider>
);
}
}
```
To open the action sheet:
## Options
```js
class OtherComponent extends React.Component {
The goal of this library is to mimic the native iOS and Android ActionSheets as closely as possible.
static contextTypes = {
actionSheet: PropTypes.func,
};
This library can also be used in the browser with Expo for web.
_onOpenActionSheet() {
// Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
let options = ['Delete', 'Save', 'Cancel'];
let destructiveButtonIndex = 0;
let cancelButtonIndex = 2;
this.context.actionSheet().showActionSheetWithOptions({
options,
cancelButtonIndex,
destructiveButtonIndex,
},
(buttonIndex) => {
// Do something here
});
}
}
### Universal Props
The same options available on React Native's [ActionSheetIOS](https://facebook.github.io/react-native/docs/actionsheetios.html#showactionsheetwithoptions) component exist for both iOS and Android in this library.
### iOS Only Props
| Name | Type | Required | Default |
| -----------------| -------| -------- | ------- |
| anchor | number | No | |
#### `anchor` (optional)
iPad only option that allows for docking the action sheet to a node. See [ShowActionSheetButton.tsx](/example/ShowActionSheetButton.tsx) for an example on how to implement this.
### Android/Web-Only Props
The below props allow modification of the Android ActionSheet. They have no effect on the look on iOS as the native iOS Action Sheet does not have options for modifying these options.
| Name | Type | Required | Default |
| -----------------| ----------------------------------| -------- | ------- |
| icons | array of required images or icons | No | |
| tintIcons | boolean | No | true |
| textStyle | TextStyle | No | |
| titleTextStyle | TextStyle | No | |
| messageTextStyle | TextStyle | No | |
| showSeparators | boolean | No | false |
| containerStyle | ViewStyle | No | |
| separatorStyle | ViewStyle | No | |
#### `icons` (optional)
Show icons to go along with each option. If image source paths are provided via `require`, images will be rendered for you. Alternatively, you can provide an array of elements such as vector icons, pre-rendered Images, etc.
#### `tintIcons` (optional)
Icons by default will be tinted to match the text color. When set to false, the icons will be the color of the source image. This is useful if you want to use multicolor icons. If you provide your own nodes/pre-rendered icons rather than required images in the `icons` array, you will need to tint them appropriately before providing them in the array of `icons`; `tintColor` will not be applied to icons unless they are images from a required source.
#### `textStyle` (optional)
Apply any text style props to the options. If the `tintColor` option is provided, it takes precedence over a color text style prop.
#### `titleTextStyle` (optional)
Apply any text style props to the title if present.
#### `messageTextStyle` (optional)
Apply any text style props to the message if present.
#### `showSeparators`: (optional)
Show separators between items. On iOS, separators always show so this prop has no effect.
#### `containerStyle`: (optional)
Apply any view style props to the container rather than use the default look (e.g. dark mode).
#### `separatorStyle`: (optional)
Modify the look of the separators rather than use the default look.
## Try it out
Try it in Expo: https://expo.io/@community/react-native-action-sheet-example
## Example
See the [example app](https://github.com/expo/react-native-action-sheet/tree/master/example).
### Usage
```
$ cd example
$ yarn
// build simulator
$ yarn ios
$ yarn android
// web
$ yarn web
```
## Development
### Setup
```
$ git clone [email protected]:expo/react-native-action-sheet.git
$ cd react-native-action-sheet
$ yarn
```
### Build
We use [bob](https://github.com/react-native-community/bob).
```
$ yarn build
```
### Lint & Format
```
// tsc
$ yarn type-check
// ESLint
$ yarn lint
// prettier
$ yarn fmt
```
+3
View File
@@ -0,0 +1,3 @@
node_modules/**/*
.expo/*
npm-debug.*
+187
View File
@@ -0,0 +1,187 @@
import * as React from 'react';
import { StyleSheet, Text, View, ScrollView, SafeAreaView } from 'react-native';
import {
ActionSheetProvider,
connectActionSheet,
ActionSheetOptions,
ActionSheetProps,
} from '@expo/react-native-action-sheet';
import ShowActionSheetButton from './ShowActionSheetButton';
type Props = ActionSheetProps;
interface State {
selectedIndex: number | null;
}
class App extends React.Component<Props, State> {
state: State = {
selectedIndex: null,
};
_updateSelectionText = (selectedIndex: number) => {
this.setState({
selectedIndex,
});
};
_renderSelectionText = () => {
const { selectedIndex } = this.state;
const text =
selectedIndex === null ? 'No Option Selected' : `Option #${selectedIndex + 1} Selected`;
return <Text style={styles.selectionText}>{text}</Text>;
};
_renderSectionHeader = (text: string) => {
return <Text style={styles.sectionHeaderText}>{text}</Text>;
};
_renderButtons() {
const { showActionSheetWithOptions } = this.props;
return (
<View
style={{
alignItems: 'center',
}}>
{this._renderSectionHeader('Universal Options')}
<ShowActionSheetButton
title="Options Only"
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
<ShowActionSheetButton
title="Title"
withTitle
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
<ShowActionSheetButton
title="Title & Message"
withTitle
withMessage
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
<ShowActionSheetButton
title="iPad Anchor"
withAnchor
withTitle
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
<ShowActionSheetButton
title="Nested Action Sheets"
onSelection={index => {
if (index < 3) {
showActionSheetWithOptions(
{
title: 'Sub Action Sheet',
options: ['One', 'Two', 'Three', 'Done'],
cancelButtonIndex: 3,
},
this._updateSelectionText
);
}
}}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
{this._renderSectionHeader('Android-Only Options')}
<ShowActionSheetButton
title="Icons"
withIcons
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
<ShowActionSheetButton
title="Title, Message, & Icons"
withTitle
withMessage
withIcons
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
<ShowActionSheetButton
title="Use Separators"
withTitle
withIcons
withSeparators
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
<ShowActionSheetButton
title="Custom Styles"
withTitle
withMessage
withIcons
withCustomStyles
onSelection={this._updateSelectionText}
showActionSheetWithOptions={showActionSheetWithOptions}
/>
</View>
);
}
render() {
return (
<SafeAreaView style={styles.flex}>
<ScrollView style={styles.flex} contentContainerStyle={styles.contentContainer}>
<Text style={styles.headerText}>
{
'Hello!\n\nThis is a simple example app to demonstrate @expo/react-native-action-sheet.'
}
</Text>
{this._renderButtons()}
{this._renderSelectionText()}
<Text style={styles.notes}>
Note: Icons and custom text styles are only available on Android. Separators can only be
toggled on Android; they always show on iOS.
</Text>
</ScrollView>
</SafeAreaView>
);
}
}
const ConnectedApp = connectActionSheet<{}>(App);
export default class AppContainer extends React.Component {
render() {
return (
<ActionSheetProvider>
<ConnectedApp />
</ActionSheetProvider>
);
}
}
const styles = StyleSheet.create({
flex: {
flex: 1,
},
contentContainer: {
padding: 16,
paddingVertical: 20,
},
headerText: {
textAlign: 'center',
fontSize: 16,
marginBottom: 10,
},
notes: {
marginTop: 32,
},
sectionHeaderText: {
color: 'orange',
textAlign: 'center',
fontWeight: 'bold',
fontSize: 20,
marginTop: 20,
marginBottom: 10,
},
selectionText: {
textAlign: 'center',
color: 'blue',
fontSize: 16,
marginTop: 20,
},
});
+144
View File
@@ -0,0 +1,144 @@
import * as React from 'react';
import { Text, View, TextStyle, ViewStyle, findNodeHandle, Button } from 'react-native';
import { MaterialIcons, Entypo } from '@expo/vector-icons';
import { ActionSheetOptions } from '@expo/react-native-action-sheet';
const icon = (name: string) => <MaterialIcons key={name} name={name} size={24} />;
interface Props {
title: string;
showActionSheetWithOptions: (
optons: ActionSheetOptions,
callback: (buttonIndex: number) => void
) => void;
onSelection: (index: number) => void;
withTitle?: boolean;
withMessage?: boolean;
withIcons?: boolean;
withSeparators?: boolean;
withCustomStyles?: boolean;
withAnchor?: boolean;
}
// A custom button that shows examples of different share sheet configurations
export default class ShowActionSheetButton extends React.PureComponent<Props> {
static defaultProps = {
withTitle: false,
withMessage: false,
withIcons: false,
withSeparators: false,
withCustomStyles: false,
withAnchor: false,
onSelection: null,
};
_anchorRef = React.createRef<Button>();
_showActionSheet = () => {
const {
withAnchor,
withTitle,
withMessage,
withIcons,
withSeparators,
withCustomStyles,
onSelection,
showActionSheetWithOptions,
} = this.props;
// Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
const options = ['Delete', 'Save', 'Share', 'Cancel'];
const icons = withIcons
? [icon('delete'), icon('save'), icon('share'), icon('cancel')]
: undefined;
const title = withTitle ? 'Choose An Action' : undefined;
const message = withMessage
? 'This library tries to mimic the native share sheets as close as possible.'
: undefined;
const destructiveButtonIndex = 0;
const cancelButtonIndex = 3;
const textStyle: TextStyle | undefined = withCustomStyles
? {
fontSize: 20,
fontWeight: '500',
color: 'blue',
}
: undefined;
const titleTextStyle: TextStyle | undefined = withCustomStyles
? {
fontSize: 24,
textAlign: 'center',
fontWeight: '700',
color: 'orange',
}
: undefined;
const messageTextStyle: TextStyle | undefined = withCustomStyles
? {
fontSize: 12,
color: 'purple',
textAlign: 'right',
}
: undefined;
const containerStyle: ViewStyle | undefined = withCustomStyles
? {
backgroundColor: 'lightgrey',
}
: undefined;
const anchor: number | null = this._anchorRef.current
? findNodeHandle(this._anchorRef.current)
: null;
showActionSheetWithOptions(
{
options,
cancelButtonIndex,
destructiveButtonIndex,
title,
message,
icons,
//iPad only
anchor: withAnchor && anchor ? anchor : undefined,
// Android only
tintIcons: true,
// Android only; default is true
showSeparators: withSeparators,
// Affects Android only; default is false
textStyle,
// Android only
titleTextStyle,
// Android only
messageTextStyle,
// Android only,
containerStyle,
},
(buttonIndex: number) => {
// Do something here depending on the button index selected
onSelection(buttonIndex);
}
);
};
render() {
const { title } = this.props;
return (
<View
style={{
margin: 6,
}}>
<Entypo.Button
name="code"
backgroundColor="#3e3e3e"
onPress={this._showActionSheet}
ref={this._anchorRef}>
<Text
style={{
fontSize: 15,
color: '#fff',
}}>
{title}
</Text>
</Entypo.Button>
</View>
);
}
}
+18
View File
@@ -0,0 +1,18 @@
{
"expo": {
"name": "@expo/react-native-action-sheet-example",
"description": "A cross-platform ActionSheet component. https://github.com/expo/react-native-action-sheet",
"slug": "react-native-action-sheet-example",
"privacy": "public",
"sdkVersion": "35.0.0",
"version": "3.0.0",
"orientation": "portrait",
"primaryColor": "#cccccc",
"icon": "https://s3.amazonaws.com/exp-brand-assets/ExponentEmptyManifest_192.png",
"platforms": [
"android",
"ios",
"web"
]
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
+30
View File
@@ -0,0 +1,30 @@
{
"name": "example",
"version": "3.0.0",
"description": "Hello react native action sheet!!",
"private": true,
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"ios": "expo start --ios",
"android": "expo start --android",
"web": "expo start --web",
"type-check": "tsc --noEmit"
},
"dependencies": {
"@expo/react-native-action-sheet": "../src",
"@expo/vector-icons": "^10.0.0",
"expo": "^35.0.0",
"hoist-non-react-statics": "^3.3.0",
"react": "16.8.3",
"react-dom": "16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",
"react-native-web": "^0.11.5"
},
"devDependencies": {
"@types/react": "^16.8.23",
"@types/react-native": "^0.57.65",
"babel-preset-expo": "^7.0.0",
"typescript": "^3.5.3"
}
}
+15
View File
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"esModuleInterop": true,
"jsx": "react-native",
"lib": ["esnext"],
"moduleResolution": "node",
"noEmit": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "esnext",
"typeRoots": ["./node_modules/@types"],
},
"include": ["./**.tsx"],
}
+5353
View File
File diff suppressed because it is too large. Load diff
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 MiB

-1
View File
@@ -1 +0,0 @@
module.exports = require('./ActionSheet');
+65 -10
View File
@@ -1,28 +1,83 @@
{
"name": "@exponent/react-native-action-sheet",
"version": "0.2.1",
"name": "@expo/react-native-action-sheet",
"version": "3.3.0",
"description": "A cross-platform ActionSheet for React Native",
"main": "index.js",
"react-native": "lib/module/index.js",
"types": "lib/typescript/index.d.ts",
"main": "lib/commonjs/index.js",
"module": "lib/module/index.js",
"files": [
"lib"
],
"scripts": {
"flow": "flow; test $? -eq 0 -o $? -eq 2"
"prepare": "bob build",
"build": "bob build",
"type-check": "tsc --noEmit",
"lint": "eslint . --ext .ts,.tsx --fix",
"fmt": "prettier --write \"{src,example}/**/*.{ts,tsx}\"",
"semantic-release": "semantic-release"
},
"repository": {
"type": "git",
"url": "https://github.com/exponentjs/react-native-action-sheet.git"
"url": "https://github.com/expo/react-native-action-sheet.git"
},
"keywords": [
"expo",
"react-native",
"action-sheet"
],
"author": "Jesse Ruder <[email protected]>",
"license": "MIT",
"bugs": {
"url": "https://github.com/exponentjs/react-native-action-sheet/issues"
"url": "https://github.com/expo/react-native-action-sheet/issues"
},
"homepage": "https://github.com/exponentjs/react-native-action-sheet",
"homepage": "https://github.com/expo/react-native-action-sheet",
"devDependencies": {
"flow-bin": "^0.26.0",
"react": "^15.2.0",
"react-native": "^0.28.0"
"@react-native-community/bob": "^0.6.1",
"@react-native-community/eslint-config": "^0.0.5",
"@semantic-release/changelog": "^3.0.5",
"@semantic-release/git": "^7.0.18",
"@types/react": "^16.8.23",
"@types/react-native": "^0.57.65",
"@typescript-eslint/eslint-plugin": "^1.12.0",
"@typescript-eslint/parser": "^1.12.0",
"eslint": "^6.0.1",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-prettier": "3.1.0",
"husky": "^3.0.0",
"lint-staged": "^9.2.0",
"prettier": "^1.18.2",
"react": "^16.8.6",
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
"semantic-release": "^15.13.28",
"typescript": "^3.5.3"
},
"peerDependencies": {
"react": ">=16.3.0"
},
"@react-native-community/bob": {
"source": "src",
"output": "lib",
"targets": [
"commonjs",
"module",
"typescript"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,ts,tsx}": [
"yarn lint",
"yarn fmt",
"git add"
]
},
"dependencies": {
"@types/hoist-non-react-statics": "^3.3.1",
"hoist-non-react-statics": "^3.3.0"
}
}
+162
View File
@@ -0,0 +1,162 @@
import * as React from 'react';
import { StyleSheet, Text, Image, View, ScrollView } from 'react-native';
import TouchableNativeFeedbackSafe from './TouchableNativeFeedbackSafe';
import { ActionSheetOptions } from '../types';
type Props = ActionSheetOptions & {
tintIcons: boolean | null;
onSelect: (i: number) => boolean;
startIndex: number;
length: number;
};
const BLACK_54PC_TRANSPARENT = '#0000008a';
const BLACK_87PC_TRANSPARENT = '#000000de';
const DESTRUCTIVE_COLOR = '#d32f2f';
export default class ActionGroup extends React.Component<Props> {
static defaultProps = {
title: null,
message: null,
showSeparators: false,
tintIcons: true,
textStyle: {},
};
render() {
return (
<View style={[styles.groupContainer, this.props.containerStyle]}>
{this._renderTitleContent()}
<ScrollView>{this._renderOptionViews()}</ScrollView>
</View>
);
}
_renderRowSeparator = (key: string | number) => {
return (
<View key={`separator-${key}`} style={[styles.rowSeparator, this.props.separatorStyle]} />
);
};
_renderTitleContent = () => {
const { title, titleTextStyle, message, messageTextStyle, showSeparators } = this.props;
if (!title && !message) {
return null;
}
return (
<View>
<View style={[styles.titleContainer, { paddingBottom: showSeparators ? 24 : 16 }]}>
{!!title && <Text style={[styles.title, titleTextStyle]}>{title}</Text>}
{!!message && <Text style={[styles.message, messageTextStyle]}>{message}</Text>}
</View>
{!!showSeparators && this._renderRowSeparator('title')}
</View>
);
};
_renderIconElement = (iconSource: React.ReactNode | null, color: string) => {
const { tintIcons } = this.props;
if (!iconSource) {
return null;
}
if (typeof iconSource === 'number') {
const iconStyle = [styles.icon, { tintColor: tintIcons ? color : undefined }];
return <Image fadeDuration={0} source={iconSource} resizeMode="contain" style={iconStyle} />;
} else {
return <View style={styles.icon}>{iconSource}</View>;
}
};
_renderOptionViews = () => {
const {
options,
icons,
destructiveButtonIndex,
onSelect,
startIndex,
length,
textStyle,
tintColor,
showSeparators,
} = this.props;
const optionViews: React.ReactNode[] = [];
const nativeFeedbackBackground = TouchableNativeFeedbackSafe.Ripple(
'rgba(180, 180, 180, 1)',
false
);
for (let i = startIndex; i < startIndex + length; i++) {
const defaultColor = tintColor
? tintColor
: (textStyle || {}).color || BLACK_87PC_TRANSPARENT;
const color = i === destructiveButtonIndex ? DESTRUCTIVE_COLOR : defaultColor;
const iconSource = icons != null ? icons[i] : null;
optionViews.push(
<TouchableNativeFeedbackSafe
key={i}
pressInDelay={0}
background={nativeFeedbackBackground}
onPress={() => onSelect(i)}
style={styles.button}>
{this._renderIconElement(iconSource, color)}
<Text style={[styles.text, textStyle, { color }]}>{options[i]}</Text>
</TouchableNativeFeedbackSafe>
);
if (showSeparators && i < startIndex + length - 1) {
optionViews.push(this._renderRowSeparator(i));
}
}
return optionViews;
};
}
const styles = StyleSheet.create({
button: {
justifyContent: 'flex-start',
alignItems: 'center',
flexDirection: 'row',
height: 56,
paddingHorizontal: 16,
},
groupContainer: {
backgroundColor: '#ffffff',
overflow: 'hidden',
},
icon: {
width: 24,
height: 24,
marginRight: 32,
},
message: {
marginTop: 12,
fontSize: 14,
color: BLACK_54PC_TRANSPARENT,
textAlignVertical: 'center',
},
rowSeparator: {
backgroundColor: '#dddddd',
height: 1,
width: '100%',
},
text: {
fontSize: 16,
color: BLACK_87PC_TRANSPARENT,
textAlignVertical: 'center',
},
title: {
fontSize: 16,
color: BLACK_54PC_TRANSPARENT,
textAlignVertical: 'center',
},
titleContainer: {
alignItems: 'flex-start',
padding: 16,
paddingTop: 24,
},
});
@@ -0,0 +1,44 @@
import * as React from 'react';
import {
Platform,
TouchableNativeFeedback,
TouchableOpacity,
View,
TouchableWithoutFeedbackProps,
} from 'react-native';
// This TouchableOpacity has the same staic method of TouchableNativeFeedback
class CustomTouchableOpacity extends TouchableOpacity {
static SelectableBackground = () => ({});
static SelectableBackgroundBorderless = () => ({});
static Ripple = (color: string, borderless?: boolean) => ({});
}
const TouchableComponent = Platform.select({
web: CustomTouchableOpacity,
default: Platform.Version <= 20 ? CustomTouchableOpacity : TouchableNativeFeedback,
});
type Props = TouchableWithoutFeedbackProps & {
pressInDelay: number;
background: any;
};
export default class TouchableNativeFeedbackSafe extends React.Component<Props> {
static SelectableBackground = TouchableComponent.SelectableBackground;
static SelectableBackgroundBorderless = TouchableComponent.SelectableBackgroundBorderless;
static Ripple = TouchableComponent.Ripple;
render() {
if (TouchableComponent === TouchableNativeFeedback) {
return (
<TouchableComponent {...this.props} style={{}}>
<View style={this.props.style}>{this.props.children}</View>
</TouchableComponent>
);
}
// @ts-ignore: JSX element type 'TouchableComponent' does not have any construct or call signatures
return <TouchableComponent {...this.props}>{this.props.children}</TouchableComponent>;
}
}
+38
View File
@@ -0,0 +1,38 @@
import * as React from 'react';
import { ActionSheetIOS, View, ViewProps } from 'react-native';
import { ActionSheetIOSOptions } from '../types';
interface Props {
readonly children: React.ReactNode;
readonly pointerEvents?: ViewProps['pointerEvents'];
}
type onSelect = (buttonIndex: number) => void;
export default class ActionSheet extends React.Component<Props> {
render() {
return (
<View pointerEvents={this.props.pointerEvents} style={{ flex: 1 }}>
{React.Children.only(this.props.children)}
</View>
);
}
showActionSheetWithOptions(dataOptions: ActionSheetIOSOptions, onSelect: onSelect) {
// ...dataOptions include other keys which use in android and web, thats why `Android-Only options` Crash on IOS
const { cancelButtonIndex, destructiveButtonIndex, options, tintColor } = dataOptions;
const iosOptions: ActionSheetIOSOptions = {
cancelButtonIndex,
destructiveButtonIndex,
options,
tintColor,
// A null title or message on iOS causes a crash
title: dataOptions.title || undefined,
message: dataOptions.message || undefined,
anchor: dataOptions.anchor || undefined,
};
ActionSheetIOS.showActionSheetWithOptions(iosOptions, onSelect);
}
}
+278
View File
@@ -0,0 +1,278 @@
import * as React from 'react';
import {
Animated,
BackHandler,
Easing,
StyleSheet,
TouchableWithoutFeedback,
View,
ViewProps,
} from 'react-native';
import ActionGroup from './ActionGroup';
import { ActionSheetOptions } from '../types';
interface State {
isVisible: boolean;
isAnimating: boolean;
options: ActionSheetOptions | null;
onSelect: ((i: number) => void) | null;
overlayOpacity: any;
sheetOpacity: any;
}
interface Props {
readonly useNativeDriver: boolean | undefined;
readonly pointerEvents?: ViewProps['pointerEvents'];
}
const OPACITY_ANIMATION_IN_TIME = 225;
const OPACITY_ANIMATION_OUT_TIME = 195;
const EASING_OUT = Easing.bezier(0.25, 0.46, 0.45, 0.94);
const EASING_IN = Easing.out(EASING_OUT);
// Has same API as https://facebook.github.io/react-native/docs/actionsheetios.html
export default class ActionSheet extends React.Component<Props, State> {
static defaultProps = {
useNativeDriver: true,
};
_actionSheetHeight = 360;
state: State = {
isVisible: false,
isAnimating: false,
options: null,
onSelect: null,
overlayOpacity: new Animated.Value(0),
sheetOpacity: new Animated.Value(0),
};
_deferNextShow?: () => void = undefined;
_setActionSheetHeight = ({ nativeEvent }: any) =>
(this._actionSheetHeight = nativeEvent.layout.height);
render() {
const { isVisible, overlayOpacity } = this.state;
const overlay = isVisible ? (
<Animated.View
style={[
styles.overlay,
{
opacity: overlayOpacity,
},
]}
/>
) : null;
return (
<View
pointerEvents={this.props.pointerEvents}
style={{
flex: 1,
}}>
{React.Children.only(this.props.children)}
{overlay}
{isVisible ? this._renderSheet() : null}
</View>
);
}
_renderSheet() {
const { options, isAnimating, sheetOpacity } = this.state;
if (!options) {
return null;
}
const {
options: optionsArray,
icons,
tintIcons,
destructiveButtonIndex,
textStyle,
tintColor,
title,
titleTextStyle,
message,
messageTextStyle,
showSeparators,
containerStyle,
separatorStyle,
} = options;
return (
<TouchableWithoutFeedback onPress={this._selectCancelButton}>
<Animated.View
needsOffscreenAlphaCompositing={isAnimating}
style={[
styles.sheetContainer,
{
opacity: sheetOpacity,
transform: [
{
translateY: sheetOpacity.interpolate({
inputRange: [0, 1],
outputRange: [this._actionSheetHeight, 0],
}),
},
],
},
]}>
<View style={styles.sheet} onLayout={this._setActionSheetHeight}>
<ActionGroup
options={optionsArray}
icons={icons}
tintIcons={tintIcons === undefined ? true : tintIcons}
destructiveButtonIndex={destructiveButtonIndex}
onSelect={this._onSelect}
startIndex={0}
length={optionsArray.length}
textStyle={textStyle || {}}
tintColor={tintColor}
title={title || undefined}
titleTextStyle={titleTextStyle}
message={message || undefined}
messageTextStyle={messageTextStyle}
showSeparators={showSeparators}
containerStyle={containerStyle}
separatorStyle={separatorStyle}
/>
</View>
</Animated.View>
</TouchableWithoutFeedback>
);
}
showActionSheetWithOptions = (options: ActionSheetOptions, onSelect: (i: number) => void) => {
const { isVisible, isAnimating, overlayOpacity, sheetOpacity } = this.state;
if (isVisible) {
this._deferNextShow = this.showActionSheetWithOptions.bind(this, options, onSelect);
return;
}
this.setState({
options,
onSelect,
isVisible: true,
isAnimating: true,
});
overlayOpacity.setValue(0);
sheetOpacity.setValue(0);
Animated.parallel([
Animated.timing(overlayOpacity, {
toValue: 0.32,
easing: EASING_OUT,
duration: OPACITY_ANIMATION_IN_TIME,
useNativeDriver: this.props.useNativeDriver,
}),
Animated.timing(sheetOpacity, {
toValue: 1,
easing: EASING_OUT,
duration: OPACITY_ANIMATION_IN_TIME,
useNativeDriver: this.props.useNativeDriver,
}),
]).start(result => {
if (result.finished) {
this.setState({
isAnimating: false,
});
this._deferNextShow = undefined;
}
});
// @ts-ignore: Argument of type '"actionSheetHardwareBackPress"' is not assignable to parameter of type '"hardwareBackPress"'
BackHandler.addEventListener('actionSheetHardwareBackPress', this._selectCancelButton);
};
_selectCancelButton = () => {
const { options } = this.state;
if (!options) {
return false;
}
if (typeof options.cancelButtonIndex === 'undefined') {
return;
} else if (typeof options.cancelButtonIndex === 'number') {
return this._onSelect(options.cancelButtonIndex);
} else {
return this._animateOut();
}
};
_onSelect = (index: number): boolean => {
const { isAnimating, onSelect } = this.state;
if (isAnimating) {
return false;
}
onSelect && onSelect(index);
return this._animateOut();
};
_animateOut = (): boolean => {
const { isAnimating, overlayOpacity, sheetOpacity } = this.state;
if (isAnimating) {
return false;
}
// @ts-ignore: Argument of type '"actionSheetHardwareBackPress"' is not assignable to parameter of type '"hardwareBackPress"'
BackHandler.removeEventListener('actionSheetHardwareBackPress', this._selectCancelButton);
this.setState({
isAnimating: true,
});
Animated.parallel([
Animated.timing(overlayOpacity, {
toValue: 0,
easing: EASING_IN,
duration: OPACITY_ANIMATION_OUT_TIME,
useNativeDriver: this.props.useNativeDriver,
}),
Animated.timing(sheetOpacity, {
toValue: 0,
easing: EASING_IN,
duration: OPACITY_ANIMATION_OUT_TIME,
useNativeDriver: this.props.useNativeDriver,
}),
]).start(result => {
if (result.finished) {
this.setState({
isVisible: false,
isAnimating: false,
});
if (this._deferNextShow) {
this._deferNextShow();
}
}
});
return true;
};
}
const styles = StyleSheet.create({
overlay: {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
backgroundColor: 'black',
},
sheetContainer: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
top: 0,
backgroundColor: 'transparent',
alignItems: 'flex-end',
justifyContent: 'center',
flexDirection: 'row',
},
sheet: {
flex: 1,
backgroundColor: 'transparent',
},
});
+36
View File
@@ -0,0 +1,36 @@
import * as React from 'react';
import ActionSheet from './ActionSheet';
import { Provider } from './context';
import { ActionSheetOptions } from './types';
interface Props {
children: React.ReactNode;
}
export default class ActionSheetProvider extends React.Component<Props> {
_actionSheetRef: React.RefObject<ActionSheet>;
constructor(props: Props) {
super(props);
this._actionSheetRef = React.createRef();
}
getContext = () => {
return {
showActionSheetWithOptions: (options: ActionSheetOptions, callback: (i: number) => void) => {
this._actionSheetRef.current !== null &&
this._actionSheetRef.current.showActionSheetWithOptions(options, callback);
},
};
};
render() {
return (
<Provider value={this.getContext()}>
<ActionSheet ref={this._actionSheetRef}>
{React.Children.only(this.props.children)}
</ActionSheet>
</Provider>
);
}
}
+22
View File
@@ -0,0 +1,22 @@
import * as React from 'react';
import { Consumer } from './context';
import hoistNonReactStatic from 'hoist-non-react-statics';
import { ActionSheetProps } from './types';
export default function connectActionSheet<OwnProps = any>(
WrappedComponent: React.ComponentType<OwnProps & ActionSheetProps>
) {
const ConnectedActionSheet = (props: OwnProps) => {
return (
<Consumer>
{({ showActionSheetWithOptions }) => {
return (
<WrappedComponent {...props} showActionSheetWithOptions={showActionSheetWithOptions} />
);
}}
</Consumer>
);
};
return hoistNonReactStatic(ConnectedActionSheet, WrappedComponent);
}
+14
View File
@@ -0,0 +1,14 @@
import * as React from 'react';
import { ActionSheetOptions, ActionSheetProps } from './types';
const context = React.createContext<ActionSheetProps>({
showActionSheetWithOptions: (options: ActionSheetOptions, callback: (i: number) => void) => {},
});
export function useActionSheet() {
return React.useContext(context);
}
const { Provider, Consumer } = context;
export { Provider, Consumer };
+4
View File
@@ -0,0 +1,4 @@
export { default as ActionSheetProvider } from './ActionSheetProvider';
export { default as connectActionSheet } from './connectActionSheet';
export { useActionSheet } from './context';
export * from './types';
+29
View File
@@ -0,0 +1,29 @@
import * as React from 'react';
import { TextStyle, ViewStyle } from 'react-native';
export interface ActionSheetProps {
showActionSheetWithOptions: (options: ActionSheetOptions, callback: (i: number) => void) => void;
}
// for iOS
export interface ActionSheetIOSOptions {
options: string[];
title?: string;
message?: string;
tintColor?: string;
cancelButtonIndex?: number;
destructiveButtonIndex?: number;
anchor?: number;
}
// for Android or Web
export interface ActionSheetOptions extends ActionSheetIOSOptions {
icons?: React.ReactNode[];
tintIcons?: boolean;
textStyle?: TextStyle;
titleTextStyle?: TextStyle;
messageTextStyle?: TextStyle;
showSeparators?: boolean;
containerStyle?: ViewStyle;
separatorStyle?: ViewStyle;
}
+13
View File
@@ -0,0 +1,13 @@
{
"include": ["src"],
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"moduleResolution": "node",
"lib": ["es2015", "es2016", "esnext"],
"jsx": "react-native",
"esModuleInterop": true
},
"exclude": ["node_modules"]
}
+9257
View File
File diff suppressed because it is too large. Load diff