Skip to content
2 changes: 2 additions & 0 deletions Libraries/ActionSheetIOS/ActionSheetIOS.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const ActionSheetIOS = {
* - `destructiveButtonIndex` (int or array of ints) - index or indices of destructive buttons in `options`
* - `title` (string) - a title to show above the action sheet
* - `message` (string) - a message to show below the title
* - `disabledButtonIndices` (array of numbers) - a list of button indices which should be disabled
*
* The 'callback' function takes one parameter, the zero-based index
* of the selected item.
Expand All @@ -49,6 +50,7 @@ const ActionSheetIOS = {
+anchor?: ?number,
+tintColor?: ColorValue | ProcessedColorValue,
+userInterfaceStyle?: string,
+disabledButtonIndices?: Array<number>,
|},
callback: (buttonIndex: number) => void,
) {
Expand Down
1 change: 1 addition & 0 deletions Libraries/ActionSheetIOS/NativeActionSheetManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface Spec extends TurboModule {
+anchor?: ?number,
+tintColor?: ?number,
+userInterfaceStyle?: ?string,
+disabledButtonIndices?: Array<number>,
|},
callback: (buttonIndex: number) => void,
) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ namespace JS {
NSString *message() const;
folly::Optional<facebook::react::LazyVector<NSString *>> options() const;
folly::Optional<facebook::react::LazyVector<double>> destructiveButtonIndices() const;
folly::Optional<facebook::react::LazyVector<double>> disabledButtonIndices() const;
folly::Optional<double> cancelButtonIndex() const;
folly::Optional<double> anchor() const;
folly::Optional<double> tintColor() const;
Expand Down Expand Up @@ -2922,6 +2923,11 @@ inline folly::Optional<facebook::react::LazyVector<double>> JS::NativeActionShee
id const p = _v[@"destructiveButtonIndices"];
return RCTBridgingToOptionalVec(p, ^double(id itemValue_0) { return RCTBridgingToDouble(itemValue_0); });
}
inline folly::Optional<facebook::react::LazyVector<double>> JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::disabledButtonIndices() const
{
id const p = _v[@"disabledButtonIndices"];
return RCTBridgingToOptionalVec(p, ^double(id itemValue_0) { return RCTBridgingToDouble(itemValue_0); });
}
inline folly::Optional<double> JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::cancelButtonIndex() const
{
id const p = _v[@"cancelButtonIndex"];
Expand Down
38 changes: 38 additions & 0 deletions RNTester/js/examples/ActionSheetIOS/ActionSheetIOSExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const ScreenshotManager = NativeModules.ScreenshotManager;
const BUTTONS = ['Option 0', 'Option 1', 'Option 2', 'Delete', 'Cancel'];
const DESTRUCTIVE_INDEX = 3;
const CANCEL_INDEX = 4;
const DISABLED_BUTTON_INDICES = [1, 2];

type Props = $ReadOnly<{||}>;
type State = {|clicked: string|};
Expand Down Expand Up @@ -138,6 +139,37 @@ class ActionSheetAnchorExample extends React.Component<
};
}

class ActionSheetDisabledExample extends React.Component<Props, State> {
state = {
clicked: 'none',
};

render() {
return (
<View>
<Text onPress={this.showActionSheet} style={style.button}>
Click to show the ActionSheet
</Text>
<Text>Clicked button: {this.state.clicked}</Text>
</View>
);
}

showActionSheet = () => {
ActionSheetIOS.showActionSheetWithOptions(
{
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
destructiveButtonIndex: DESTRUCTIVE_INDEX,
disabledButtonIndices: DISABLED_BUTTON_INDICES,
},
buttonIndex => {
this.setState({clicked: BUTTONS[buttonIndex]});
},
);
};
}

class ShareActionSheetExample extends React.Component<
$FlowFixMeProps,
$FlowFixMeState,
Expand Down Expand Up @@ -315,6 +347,12 @@ exports.examples = [
return <ActionSheetAnchorExample />;
},
},
{
title: 'Show Action Sheet with disabled buttons',
render(): React.Element<any> {
return <ActionSheetDisabledExample />;
},
},
{
title: 'Show Share Action Sheet',
render(): React.Element<any> {
Expand Down
13 changes: 13 additions & 0 deletions React/CoreModules/RCTActionSheetManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ - (void)presentViewController:(UIViewController *)alertController
NSInteger cancelButtonIndex =
options.cancelButtonIndex() ? [RCTConvert NSInteger:@(*options.cancelButtonIndex())] : -1;
NSArray<NSNumber *> *destructiveButtonIndices;
NSArray<NSNumber *> *disabledButtonIndices = RCTConvertVecToArray(*options.disabledButtonIndices(), ^id(double element) {
return @(element);
});
if (options.destructiveButtonIndices()) {
destructiveButtonIndices = RCTConvertVecToArray(*options.destructiveButtonIndices(), ^id(double element) {
return @(element);
Expand All @@ -98,6 +101,7 @@ - (void)presentViewController:(UIViewController *)alertController
@"destructiveButtonIndices" : destructiveButtonIndices,
@"anchor" : anchor,
@"tintColor" : tintColor,
@"disabledButtonIndices" : disabledButtonIndices,
});
return;
}
Expand Down Expand Up @@ -132,6 +136,15 @@ - (void)presentViewController:(UIViewController *)alertController
index++;
}

for (NSNumber *disabledButtonIndex in disabledButtonIndices) {
if ([disabledButtonIndex integerValue] < buttons.count) {
[alertController.actions[[disabledButtonIndex integerValue]] setEnabled:false];
} else {
RCTLogError(@"Index %@ from `disabledButtonIndices` is out of bounds. Maximum index value is %@.", @([disabledButtonIndex integerValue]), @(buttons.count - 1));
return;
}
}

alertController.view.tintColor = tintColor;
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
Expand Down