mirror of
https://github.com/expo/react-native-action-sheet.git
synced 2026-11-15 09:18:06 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0cf2b8c8d | ||
|
|
5549e36a92 | ||
|
|
b605fb8a3b | ||
|
|
b95117a8cd | ||
|
|
9ed955dbba | ||
|
|
d85c167b55 | ||
|
|
128a48f2ff |
No files matched your search
+6
-3
@@ -9,13 +9,16 @@
|
||||
"changelogTitle": "# Changelog"
|
||||
}
|
||||
],
|
||||
"@semantic-release/npm",
|
||||
[
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": ["CHANGELOG.md", "package.json"]
|
||||
"assets": [
|
||||
"CHANGELOG.md",
|
||||
"package.json"
|
||||
]
|
||||
}
|
||||
],
|
||||
"@semantic-release/npm",
|
||||
"@semantic-release/github"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
# [3.8.0](https://github.com/expo/react-native-action-sheet/compare/v3.7.0...v3.8.0) (2020-05-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add destructiveColor option ([#171](https://github.com/expo/react-native-action-sheet/issues/171)) ([5549e36](https://github.com/expo/react-native-action-sheet/commit/5549e36a92d8afcc0ce2bf6a601e83209b5ce080))
|
||||
* Improvements to Android accessibility ([#168](https://github.com/expo/react-native-action-sheet/issues/168)) ([b605fb8](https://github.com/expo/react-native-action-sheet/commit/b605fb8a3b6421c244f7f18d934bb5ea0753d461))
|
||||
|
||||
# [3.7.0](https://github.com/expo/react-native-action-sheet/compare/v3.6.0...v3.7.0) (2020-05-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* adds `useModal` prop wrap action sheet in a modal ([9ed955d](https://github.com/expo/react-native-action-sheet/commit/9ed955dbba7259cbcf5e31ef3d4ed091ae4a3145)), closes [#169](https://github.com/expo/react-native-action-sheet/issues/169)
|
||||
|
||||
# [3.6.0](https://github.com/expo/react-native-action-sheet/compare/v3.5.0...v3.6.0) (2020-03-30)
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ The same options available on React Native's [ActionSheetIOS](https://facebook.g
|
||||
| -----------------| -------| -------- | ------- |
|
||||
| anchor | number | No | |
|
||||
|
||||
#### `anchor` (optional)
|
||||
#### `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
|
||||
@@ -117,9 +117,12 @@ The below props allow modification of the Android ActionSheet. They have no effe
|
||||
| textStyle | TextStyle | No | |
|
||||
| titleTextStyle | TextStyle | No | |
|
||||
| messageTextStyle | TextStyle | No | |
|
||||
| autoFocus | boolean | No | false |
|
||||
| showSeparators | boolean | No | false |
|
||||
| containerStyle | ViewStyle | No | |
|
||||
| separatorStyle | ViewStyle | No | |
|
||||
| useModal | boolean | No | false |
|
||||
| destructiveColor | string | No | #d32f2f |
|
||||
|
||||
#### `icons` (optional)
|
||||
|
||||
@@ -137,6 +140,10 @@ Apply any text style props to the title if present.
|
||||
#### `messageTextStyle` (optional)
|
||||
Apply any text style props to the message if present.
|
||||
|
||||
#### `autoFocus`: (optional)
|
||||
If true, will give the first option screen reader focus automatically when the action sheet becomes visible.
|
||||
On iOS, this is the default behavior of the native action sheet.
|
||||
|
||||
#### `showSeparators`: (optional)
|
||||
Show separators between items. On iOS, separators always show so this prop has no effect.
|
||||
|
||||
@@ -146,6 +153,12 @@ Apply any view style props to the container rather than use the default look (e.
|
||||
#### `separatorStyle`: (optional)
|
||||
Modify the look of the separators rather than use the default look.
|
||||
|
||||
#### `useModal`: (optional)
|
||||
Wrap the ActionSheet with a Modal, in order to show in front of other Modals that were already opened ([issue reference](https://github.com/expo/react-native-action-sheet/issues/164)).
|
||||
|
||||
#### `destructiveColor`: (optional)
|
||||
Modify color for text of destructive option.
|
||||
|
||||
## Try it out
|
||||
|
||||
Try it in Expo: https://expo.io/@community/react-native-action-sheet-example
|
||||
|
||||
+39
-2
@@ -1,9 +1,16 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet, Text, View, ScrollView, SafeAreaView } from 'react-native';
|
||||
import {
|
||||
Modal,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ScrollView,
|
||||
SafeAreaView,
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
import {
|
||||
ActionSheetProvider,
|
||||
connectActionSheet,
|
||||
ActionSheetOptions,
|
||||
ActionSheetProps,
|
||||
} from '@expo/react-native-action-sheet';
|
||||
import ShowActionSheetButton from './ShowActionSheetButton';
|
||||
@@ -12,11 +19,13 @@ type Props = ActionSheetProps;
|
||||
|
||||
interface State {
|
||||
selectedIndex: number | null;
|
||||
isModalOpen: boolean;
|
||||
}
|
||||
|
||||
class App extends React.Component<Props, State> {
|
||||
state: State = {
|
||||
selectedIndex: null,
|
||||
isModalOpen: false,
|
||||
};
|
||||
|
||||
_updateSelectionText = (selectedIndex: number) => {
|
||||
@@ -36,6 +45,10 @@ class App extends React.Component<Props, State> {
|
||||
return <Text style={styles.sectionHeaderText}>{text}</Text>;
|
||||
};
|
||||
|
||||
_toggleModal = () => {
|
||||
this.setState({ isModalOpen: !this.state.isModalOpen });
|
||||
};
|
||||
|
||||
_renderButtons() {
|
||||
const { showActionSheetWithOptions } = this.props;
|
||||
return (
|
||||
@@ -117,6 +130,26 @@ class App extends React.Component<Props, State> {
|
||||
onSelection={this._updateSelectionText}
|
||||
showActionSheetWithOptions={showActionSheetWithOptions}
|
||||
/>
|
||||
{this._renderSectionHeader('Special Cases')}
|
||||
<TouchableOpacity onPress={this._toggleModal}>
|
||||
<Text style={styles.link}>Open Modal</Text>
|
||||
</TouchableOpacity>
|
||||
{this.state.isModalOpen && (
|
||||
<Modal>
|
||||
<View style={{ flex: 1, padding: 30 }}>
|
||||
<ShowActionSheetButton
|
||||
useModal
|
||||
title="Options Only"
|
||||
onSelection={this._updateSelectionText}
|
||||
showActionSheetWithOptions={showActionSheetWithOptions}
|
||||
/>
|
||||
|
||||
<TouchableOpacity onPress={this._toggleModal}>
|
||||
<Text style={styles.link}>Close Modal</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Modal>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -184,4 +217,8 @@ const styles = StyleSheet.create({
|
||||
fontSize: 16,
|
||||
marginTop: 20,
|
||||
},
|
||||
link: {
|
||||
fontSize: 15,
|
||||
textDecorationLine: 'underline',
|
||||
},
|
||||
});
|
||||
@@ -8,7 +8,7 @@ const icon = (name: string) => <MaterialIcons key={name} name={name} size={24} /
|
||||
interface Props {
|
||||
title: string;
|
||||
showActionSheetWithOptions: (
|
||||
optons: ActionSheetOptions,
|
||||
options: ActionSheetOptions,
|
||||
callback: (buttonIndex: number) => void
|
||||
) => void;
|
||||
onSelection: (index: number) => void;
|
||||
@@ -18,6 +18,7 @@ interface Props {
|
||||
withSeparators?: boolean;
|
||||
withCustomStyles?: boolean;
|
||||
withAnchor?: boolean;
|
||||
useModal?: boolean;
|
||||
}
|
||||
|
||||
// A custom button that shows examples of different share sheet configurations
|
||||
@@ -30,6 +31,7 @@ export default class ShowActionSheetButton extends React.PureComponent<Props> {
|
||||
withCustomStyles: false,
|
||||
withAnchor: false,
|
||||
onSelection: null,
|
||||
useModal: false,
|
||||
};
|
||||
|
||||
_anchorRef = React.createRef<Button>();
|
||||
@@ -44,6 +46,7 @@ export default class ShowActionSheetButton extends React.PureComponent<Props> {
|
||||
withCustomStyles,
|
||||
onSelection,
|
||||
showActionSheetWithOptions,
|
||||
useModal,
|
||||
} = this.props;
|
||||
|
||||
// Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
|
||||
@@ -110,6 +113,8 @@ export default class ShowActionSheetButton extends React.PureComponent<Props> {
|
||||
messageTextStyle,
|
||||
// Android only,
|
||||
containerStyle,
|
||||
// Android only,
|
||||
useModal,
|
||||
},
|
||||
(buttonIndex: number) => {
|
||||
// Do something here depending on the button index selected
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@expo/react-native-action-sheet",
|
||||
"version": "3.3.0",
|
||||
"version": "3.8.0",
|
||||
"description": "A cross-platform ActionSheet for React Native",
|
||||
"react-native": "lib/module/index.js",
|
||||
"types": "lib/typescript/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet, Text, Image, View, ScrollView } from 'react-native';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
Image,
|
||||
View,
|
||||
ScrollView,
|
||||
findNodeHandle,
|
||||
AccessibilityInfo,
|
||||
Platform,
|
||||
UIManager,
|
||||
} from 'react-native';
|
||||
import TouchableNativeFeedbackSafe from './TouchableNativeFeedbackSafe';
|
||||
import { ActionSheetOptions } from '../types';
|
||||
|
||||
@@ -14,6 +24,28 @@ const BLACK_54PC_TRANSPARENT = '#0000008a';
|
||||
const BLACK_87PC_TRANSPARENT = '#000000de';
|
||||
const DESTRUCTIVE_COLOR = '#d32f2f';
|
||||
|
||||
/**
|
||||
* Can be used as a React ref for a component to auto-focus for accessibility on render.
|
||||
* @param ref The component to auto-focus
|
||||
*/
|
||||
const focusViewOnRender = (ref: React.Component | null) => {
|
||||
if (ref) {
|
||||
const reactTag = findNodeHandle(ref);
|
||||
if (reactTag) {
|
||||
if (Platform.OS === 'android') {
|
||||
// @ts-ignore: sendAccessibilityEvent is missing from @types/react-native
|
||||
UIManager.sendAccessibilityEvent(
|
||||
reactTag,
|
||||
// @ts-ignore: AccessibilityEventTypes is missing from @types/react-native
|
||||
UIManager.AccessibilityEventTypes.typeViewFocused
|
||||
);
|
||||
} else {
|
||||
AccessibilityInfo.setAccessibilityFocus(reactTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default class ActionGroup extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
title: null,
|
||||
@@ -75,11 +107,13 @@ export default class ActionGroup extends React.Component<Props> {
|
||||
options,
|
||||
icons,
|
||||
destructiveButtonIndex,
|
||||
destructiveColor = DESTRUCTIVE_COLOR,
|
||||
onSelect,
|
||||
startIndex,
|
||||
length,
|
||||
textStyle,
|
||||
tintColor,
|
||||
autoFocus,
|
||||
showSeparators,
|
||||
} = this.props;
|
||||
const optionViews: React.ReactNode[] = [];
|
||||
@@ -92,16 +126,18 @@ export default class ActionGroup extends React.Component<Props> {
|
||||
const defaultColor = tintColor
|
||||
? tintColor
|
||||
: (textStyle || {}).color || BLACK_87PC_TRANSPARENT;
|
||||
const color = i === destructiveButtonIndex ? DESTRUCTIVE_COLOR : defaultColor;
|
||||
const color = i === destructiveButtonIndex ? destructiveColor : defaultColor;
|
||||
const iconSource = icons != null ? icons[i] : null;
|
||||
|
||||
optionViews.push(
|
||||
<TouchableNativeFeedbackSafe
|
||||
ref={autoFocus && i === 0 ? focusViewOnRender : undefined}
|
||||
key={i}
|
||||
pressInDelay={0}
|
||||
background={nativeFeedbackBackground}
|
||||
onPress={() => onSelect(i)}
|
||||
style={styles.button}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={options[i]}>
|
||||
{this._renderIconElement(iconSource, color)}
|
||||
<Text style={[styles.text, textStyle, { color }]}>{options[i]}</Text>
|
||||
|
||||
+35
-10
@@ -3,6 +3,7 @@ import {
|
||||
Animated,
|
||||
BackHandler,
|
||||
Easing,
|
||||
Modal,
|
||||
StyleSheet,
|
||||
TouchableWithoutFeedback,
|
||||
View,
|
||||
@@ -53,7 +54,8 @@ export default class ActionSheet extends React.Component<Props, State> {
|
||||
(this._actionSheetHeight = nativeEvent.layout.height);
|
||||
|
||||
render() {
|
||||
const { isVisible, overlayOpacity } = this.state;
|
||||
const { isVisible, overlayOpacity, options } = this.state;
|
||||
const useModal = options ? options.useModal === true : false;
|
||||
const overlay = isVisible ? (
|
||||
<Animated.View
|
||||
style={[
|
||||
@@ -64,15 +66,31 @@ export default class ActionSheet extends React.Component<Props, State> {
|
||||
]}
|
||||
/>
|
||||
) : null;
|
||||
return (
|
||||
|
||||
// While the sheet is visible, hide the rest of the app's content from screen readers.
|
||||
const appContent = (
|
||||
<View
|
||||
pointerEvents={this.props.pointerEvents}
|
||||
style={{
|
||||
flex: 1,
|
||||
}}>
|
||||
style={styles.flexContainer}
|
||||
importantForAccessibility={isVisible ? 'no-hide-descendants' : 'auto'}>
|
||||
{React.Children.only(this.props.children)}
|
||||
{overlay}
|
||||
{isVisible ? this._renderSheet() : null}
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View pointerEvents={this.props.pointerEvents} style={styles.flexContainer}>
|
||||
{appContent}
|
||||
{isVisible && !useModal && (
|
||||
<React.Fragment>
|
||||
{overlay}
|
||||
{this._renderSheet()}
|
||||
</React.Fragment>
|
||||
)}
|
||||
{isVisible && useModal && (
|
||||
<Modal animationType="none" transparent={true} onRequestClose={this._selectCancelButton}>
|
||||
{overlay}
|
||||
{this._renderSheet()}
|
||||
</Modal>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -89,18 +107,20 @@ export default class ActionSheet extends React.Component<Props, State> {
|
||||
icons,
|
||||
tintIcons,
|
||||
destructiveButtonIndex,
|
||||
destructiveColor,
|
||||
textStyle,
|
||||
tintColor,
|
||||
title,
|
||||
titleTextStyle,
|
||||
message,
|
||||
messageTextStyle,
|
||||
autoFocus,
|
||||
showSeparators,
|
||||
containerStyle,
|
||||
separatorStyle,
|
||||
} = options;
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={this._selectCancelButton}>
|
||||
<TouchableWithoutFeedback importantForAccessibility="yes" onPress={this._selectCancelButton}>
|
||||
<Animated.View
|
||||
needsOffscreenAlphaCompositing={isAnimating}
|
||||
style={[
|
||||
@@ -123,6 +143,7 @@ export default class ActionSheet extends React.Component<Props, State> {
|
||||
icons={icons}
|
||||
tintIcons={tintIcons === undefined ? true : tintIcons}
|
||||
destructiveButtonIndex={destructiveButtonIndex}
|
||||
destructiveColor={destructiveColor}
|
||||
onSelect={this._onSelect}
|
||||
startIndex={0}
|
||||
length={optionsArray.length}
|
||||
@@ -132,6 +153,7 @@ export default class ActionSheet extends React.Component<Props, State> {
|
||||
titleTextStyle={titleTextStyle}
|
||||
message={message || undefined}
|
||||
messageTextStyle={messageTextStyle}
|
||||
autoFocus={autoFocus}
|
||||
showSeparators={showSeparators}
|
||||
containerStyle={containerStyle}
|
||||
separatorStyle={separatorStyle}
|
||||
@@ -143,7 +165,7 @@ export default class ActionSheet extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
showActionSheetWithOptions = (options: ActionSheetOptions, onSelect: (i: number) => void) => {
|
||||
const { isVisible, isAnimating, overlayOpacity, sheetOpacity } = this.state;
|
||||
const { isVisible, overlayOpacity, sheetOpacity } = this.state;
|
||||
|
||||
if (isVisible) {
|
||||
this._deferNextShow = this.showActionSheetWithOptions.bind(this, options, onSelect);
|
||||
@@ -252,6 +274,9 @@ export default class ActionSheet extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
flexContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
overlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
|
||||
@@ -23,7 +23,10 @@ export interface ActionSheetOptions extends ActionSheetIOSOptions {
|
||||
textStyle?: TextStyle;
|
||||
titleTextStyle?: TextStyle;
|
||||
messageTextStyle?: TextStyle;
|
||||
autoFocus?: boolean;
|
||||
showSeparators?: boolean;
|
||||
containerStyle?: ViewStyle;
|
||||
separatorStyle?: ViewStyle;
|
||||
useModal?: boolean;
|
||||
destructiveColor?: string;
|
||||
}
|
||||
Reference in new issue
Block a user