@prosperitainova/dumbo-react-native
Version:
Dumbo for React Native Library
282 lines (279 loc) • 8.73 kB
JavaScript
"use strict";
import React from 'react';
import { ActionSheetIOS, Platform, Pressable, ScrollView, StyleSheet, View, Modal as ReactModal, Image } from 'react-native';
import { createIcon, pressableFeedbackStyle, styleReferenceBreaker } from '../../helpers';
import { modalPresentations } from '../../constants/constants';
import { getColor } from '../../styles/colors';
import { Overlay } from '../Overlay';
import { Text } from '../Text';
import { zIndexes } from '../../styles/z-index';
import { SafeAreaWrapper } from '../SafeAreaWrapper';
/** Item to pass to ActionSheet */
/** Props for ActionSheet component */
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
* ActionSheet component for the choice option at the bottom of a screen.
* Render a popup (from bottom) to show menu options for when non Yes/No questions are needed.
* Uses the OS ActionSheet if supported. Otherwise renders a custom one with similar styling.
*
* {@link https://github.com/carbon-design-system/carbon-react-native/blob/main/example/src/Views/ActionSheet.tsx | Example code}
*/
export class ActionSheet extends React.Component {
get styles() {
const {
fullBleed
} = this.props;
return StyleSheet.create({
modal: {
zIndex: zIndexes.actionSheet
},
safeAreaWrapper: {
position: 'relative',
flexGrow: 1,
flexDirection: 'row-reverse',
justifyContent: 'center'
},
containerWrapper: {
flexGrow: 1,
flexDirection: 'row-reverse',
margin: fullBleed ? 0 : 16,
maxWidth: 480
},
blurBackground: {
zIndex: zIndexes.behind,
position: 'absolute',
top: 0,
right: 0,
left: 0,
bottom: 0,
flex: 1
},
wrapper: {
backgroundColor: getColor('layer01'),
alignSelf: 'flex-end',
width: '100%'
},
textArea: {
padding: 16,
paddingBottom: 0,
paddingTop: 22,
borderBottomColor: getColor('borderSubtle01'),
borderBottomWidth: 1
},
titleNoBody: {
marginBottom: 8
},
body: {
marginBottom: 8,
color: getColor('textHelper')
},
optionsWrapper: {
maxHeight: '50%'
},
options: {
flexGrow: 0
},
option: {
padding: 13,
paddingLeft: 16,
flexDirection: 'row'
},
cancelButton: {
backgroundColor: getColor('buttonSecondary'),
padding: 13,
paddingLeft: 16
},
cancelButtonText: {
color: getColor('textOnColor')
},
backgroundPress: {
zIndex: zIndexes.behind,
position: 'absolute',
top: 0,
right: 0,
left: 0,
bottom: 0,
flex: 1
},
iconStyle: {
width: 20,
height: 20,
paddingTop: 1
},
iconImageStyle: {
width: 20,
height: 20
},
textStyle: {
flex: 1
}
});
}
handleSystemTrigger = () => {
const {
open,
title,
body,
items,
cancelButtonIndex
} = this.props;
const options = items.filter(item => !item.hidden);
const dangerIndex = options.findIndex(item => item.danger);
if (open) {
ActionSheetIOS.showActionSheetWithOptions({
destructiveButtonIndex: dangerIndex > -1 ? dangerIndex : undefined,
options: options.map(item => item.text),
title: title,
message: body,
cancelButtonIndex: cancelButtonIndex
}, index => {
const action = options[index];
if (action) {
action.onPress();
}
});
}
};
get useSystemActionSheet() {
const {
forceCustomActionSheet
} = this.props;
return Platform.OS === 'ios' && !forceCustomActionSheet;
}
getStateStyle = state => {
return state.pressed ? {
backgroundColor: getColor('buttonSecondaryActive')
} : undefined;
};
getCancelStateStyle = state => {
return state.pressed ? {
backgroundColor: getColor('layerActive01')
} : undefined;
};
get customActionSheet() {
const {
open,
title,
body,
items,
cancelButtonIndex
} = this.props;
const options = items.filter(item => !item.hidden);
const cancel = options.splice(cancelButtonIndex || 0, 1)[0] || {
text: '',
onPress: () => {}
};
if (!open) {
return null;
}
const invisibleButton = /*#__PURE__*/_jsx(Pressable, {
onPress: cancel.onPress,
style: this.styles.backgroundPress,
accessible: false,
accessibilityRole: "none",
accessibilityLabel: cancel.text
});
return /*#__PURE__*/_jsxs(ReactModal, {
style: this.styles.modal,
supportedOrientations: modalPresentations,
transparent: true,
onRequestClose: cancel.onPress,
children: [/*#__PURE__*/_jsx(Overlay, {
style: this.styles.blurBackground
}), /*#__PURE__*/_jsxs(SafeAreaWrapper, {
style: this.styles.safeAreaWrapper,
children: [invisibleButton, /*#__PURE__*/_jsxs(View, {
style: this.styles.containerWrapper,
children: [invisibleButton, /*#__PURE__*/_jsxs(View, {
style: this.styles.wrapper,
children: [/*#__PURE__*/_jsxs(View, {
style: this.styles.textArea,
children: [/*#__PURE__*/_jsx(Text, {
style: body ? undefined : this.styles.titleNoBody,
type: "heading-compact-01",
text: title
}), !!body && /*#__PURE__*/_jsx(Text, {
style: this.styles.body,
type: "helper-text-01",
text: body
})]
}), /*#__PURE__*/_jsx(View, {
style: this.styles.optionsWrapper,
children: /*#__PURE__*/_jsx(ScrollView, {
bounces: false,
style: this.styles.options,
children: options.map((item, index) => {
const finalStyle = styleReferenceBreaker(this.styles.option);
const lastItem = index === options.length - 1;
let imageItem;
if (item.icon?.icon) {
imageItem = createIcon(item.icon.icon, 20, 20);
} else if (item.icon?.image) {
imageItem = /*#__PURE__*/_jsx(Image, {
style: this.styles.iconImageStyle,
resizeMode: "contain",
source: item.icon.image
});
}
if (item.danger) {
finalStyle.backgroundColor = getColor('buttonDangerPrimary');
}
if (item.divider && !lastItem) {
finalStyle.borderBottomColor = finalStyle.borderBottomColor || getColor('borderSubtle00');
finalStyle.borderBottomWidth = finalStyle.borderBottomWidth || 1;
}
return /*#__PURE__*/_jsxs(Pressable, {
style: state => pressableFeedbackStyle(state, finalStyle, this.getStateStyle),
accessibilityLabel: item.text,
onPress: () => {
item.onPress();
},
children: [/*#__PURE__*/_jsx(Text, {
style: this.styles.textStyle,
text: item.text
}), !!imageItem && /*#__PURE__*/_jsx(View, {
style: this.styles.iconStyle,
children: imageItem
})]
}, index);
})
})
}), /*#__PURE__*/_jsx(Pressable, {
style: state => pressableFeedbackStyle(state, this.styles.cancelButton, this.getCancelStateStyle),
accessibilityLabel: cancel.text,
onPress: () => {
cancel.onPress();
},
children: /*#__PURE__*/_jsx(Text, {
style: this.styles.cancelButtonText,
text: cancel.text
})
})]
})]
})]
})]
});
}
componentDidUpdate(previousProps) {
const {
open
} = this.props;
if (previousProps.open !== open) {
if (this.useSystemActionSheet) {
this.handleSystemTrigger();
}
}
}
componentDidMount() {
if (this.useSystemActionSheet) {
this.handleSystemTrigger();
}
}
render() {
if (!this.useSystemActionSheet) {
return this.customActionSheet;
}
return null;
}
}
//# sourceMappingURL=index.js.map