@wordpress/components
Version:
UI components for WordPress.
285 lines (256 loc) • 9.51 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { createElement } from "@wordpress/element";
/**
* External dependencies
*/
import { TouchableOpacity, Text, View, TextInput, I18nManager, AccessibilityInfo } from 'react-native';
import { isEmpty, get } from 'lodash';
/**
* WordPress dependencies
*/
import { Icon } from '@wordpress/components';
import { check } from '@wordpress/icons';
import { Component } from '@wordpress/element';
import { __, _x, sprintf } from '@wordpress/i18n';
import { withPreferredColorScheme } from '@wordpress/compose';
/**
* Internal dependencies
*/
import styles from './styles.scss';
import platformStyles from './cellStyles.scss';
import TouchableRipple from './ripple';
class BottomSheetCell extends Component {
constructor(props) {
super(...arguments);
this.state = {
isEditingValue: props.autoFocus || false,
isScreenReaderEnabled: false
};
this.handleScreenReaderToggled = this.handleScreenReaderToggled.bind(this);
this.isCurrent = false;
}
componentDidUpdate(prevProps, prevState) {
if (!prevState.isEditingValue && this.state.isEditingValue) {
this._valueTextInput.focus();
}
}
componentDidMount() {
this.isCurrent = true;
AccessibilityInfo.addEventListener('screenReaderChanged', this.handleScreenReaderToggled);
AccessibilityInfo.isScreenReaderEnabled().then(isScreenReaderEnabled => {
if (this.isCurrent) {
this.setState({
isScreenReaderEnabled
});
}
});
}
componentWillUnmount() {
this.isCurrent = false;
AccessibilityInfo.removeEventListener('screenReaderChanged', this.handleScreenReaderToggled);
}
handleScreenReaderToggled(isScreenReaderEnabled) {
this.setState({
isScreenReaderEnabled
});
}
typeToKeyboardType(type, step) {
let keyboardType = `default`;
if (type === `number`) {
if (step && Math.abs(step) < 1) {
keyboardType = `decimal-pad`;
} else {
keyboardType = `number-pad`;
}
}
return keyboardType;
}
render() {
const {
accessible,
accessibilityLabel,
accessibilityHint,
accessibilityRole,
disabled = false,
activeOpacity,
onPress,
onLongPress,
label,
value,
valuePlaceholder = '',
icon,
leftAlign,
labelStyle = {},
valueStyle = {},
cellContainerStyle = {},
cellRowContainerStyle = {},
onChangeValue,
onSubmit,
children,
editable = true,
isSelected = false,
separatorType,
style = {},
getStylesFromColorScheme,
customActionButton,
type,
step,
borderless,
...valueProps
} = this.props;
const showValue = value !== undefined;
const isValueEditable = editable && onChangeValue !== undefined;
const cellLabelStyle = getStylesFromColorScheme(styles.cellLabel, styles.cellTextDark);
const cellLabelCenteredStyle = getStylesFromColorScheme(styles.cellLabelCentered, styles.cellTextDark);
const cellLabelLeftAlignNoIconStyle = getStylesFromColorScheme(styles.cellLabelLeftAlignNoIcon, styles.cellTextDark);
const defaultMissingIconAndValue = leftAlign ? cellLabelLeftAlignNoIconStyle : cellLabelCenteredStyle;
const defaultLabelStyle = showValue || customActionButton || icon ? cellLabelStyle : defaultMissingIconAndValue;
const drawSeparator = separatorType && separatorType !== 'none' || separatorStyle === undefined;
const drawTopSeparator = drawSeparator && separatorType === 'topFullWidth';
const cellContainerStyles = [styles.cellContainer, cellContainerStyle];
const rowContainerStyles = [styles.cellRowContainer, cellRowContainerStyle];
const isInteractive = isValueEditable || onPress !== undefined || onLongPress !== undefined;
const onCellPress = () => {
if (isValueEditable) {
startEditing();
} else if (onPress !== undefined) {
onPress();
}
};
const finishEditing = () => {
this.setState({
isEditingValue: false
});
};
const startEditing = () => {
if (this.state.isEditingValue === false) {
this.setState({
isEditingValue: true
});
}
};
const separatorStyle = () => {
//eslint-disable-next-line @wordpress/no-unused-vars-before-return
const defaultSeparatorStyle = this.props.getStylesFromColorScheme(styles.separator, styles.separatorDark);
const cellSeparatorStyle = this.props.getStylesFromColorScheme(styles.cellSeparator, styles.cellSeparatorDark);
const leftMarginStyle = { ...cellSeparatorStyle,
...platformStyles.separatorMarginLeft
};
switch (separatorType) {
case 'leftMargin':
return leftMarginStyle;
case 'fullWidth':
case 'topFullWidth':
return defaultSeparatorStyle;
case 'none':
return undefined;
case undefined:
if (showValue && icon) {
return leftMarginStyle;
}
return defaultSeparatorStyle;
}
};
const getValueComponent = () => {
const styleRTL = I18nManager.isRTL && styles.cellValueRTL;
const cellValueStyle = this.props.getStylesFromColorScheme(styles.cellValue, styles.cellTextDark);
const finalStyle = { ...cellValueStyle,
...valueStyle,
...styleRTL
}; // To be able to show the `middle` ellipsizeMode on editable cells
// we show the TextInput just when the user wants to edit the value,
// and the Text component to display it.
// We also show the TextInput to display placeholder.
const shouldShowPlaceholder = isValueEditable && value === '';
return this.state.isEditingValue || shouldShowPlaceholder ? createElement(TextInput, _extends({
ref: c => this._valueTextInput = c,
numberOfLines: 1,
style: finalStyle,
value: value,
placeholder: valuePlaceholder,
placeholderTextColor: '#87a6bc',
onChangeText: onChangeValue,
editable: isValueEditable,
pointerEvents: this.state.isEditingValue ? 'auto' : 'none',
onFocus: startEditing,
onBlur: finishEditing,
onSubmitEditing: onSubmit,
keyboardType: this.typeToKeyboardType(type, step)
}, valueProps)) : createElement(Text, {
style: { ...cellValueStyle,
...valueStyle
},
numberOfLines: 1,
ellipsizeMode: 'middle'
}, value);
};
const getAccessibilityLabel = () => {
if (accessible === false) {
return;
}
if (accessibilityLabel || !showValue) {
return accessibilityLabel || label;
}
return isEmpty(value) ? sprintf(
/* translators: accessibility text. Empty state of a inline textinput cell. %s: The cell's title */
_x('%s. Empty', 'inline textinput cell'), label) : // Separating by ',' is necessary to make a pause on urls (non-capitalized text)
sprintf(
/* translators: accessibility text. Inline textinput title and value.%1: Cell title, %2: cell value. */
_x('%1$s, %2$s', 'inline textinput cell'), label, value);
};
const iconStyle = getStylesFromColorScheme(styles.icon, styles.iconDark);
const resetButtonStyle = getStylesFromColorScheme(styles.resetButton, styles.resetButtonDark);
const containerPointerEvents = this.state.isScreenReaderEnabled && accessible ? 'none' : 'auto';
const {
title,
handler
} = customActionButton || {};
const opacity = activeOpacity !== undefined ? activeOpacity : get(platformStyles, 'activeOpacity.opacity');
return createElement(TouchableRipple, {
accessible: accessible !== undefined ? accessible : !this.state.isEditingValue,
accessibilityLabel: getAccessibilityLabel(),
accessibilityRole: accessibilityRole || 'button',
accessibilityHint: isValueEditable ?
/* translators: accessibility text */
__('Double tap to edit this value') : accessibilityHint,
disabled: disabled || !isInteractive,
activeOpacity: opacity,
onPress: onCellPress,
onLongPress: onLongPress,
style: [styles.clipToBounds, style],
borderless: borderless
}, drawTopSeparator && createElement(View, {
style: separatorStyle()
}), createElement(View, {
style: cellContainerStyles,
pointerEvents: containerPointerEvents
}, createElement(View, {
style: rowContainerStyles
}, createElement(View, {
style: styles.cellRowContainer
}, icon && createElement(View, {
style: styles.cellRowContainer
}, createElement(Icon, {
icon: icon,
size: 24,
fill: iconStyle.color,
isPressed: false
}), createElement(View, {
style: platformStyles.labelIconSeparator
})), label && createElement(Text, {
style: [defaultLabelStyle, labelStyle]
}, label)), customActionButton && createElement(TouchableOpacity, {
onPress: handler,
accessibilityRole: 'button'
}, createElement(Text, {
style: resetButtonStyle
}, title))), isSelected && createElement(Icon, {
icon: check,
fill: platformStyles.isSelected.color
}), showValue && getValueComponent(), children), !drawTopSeparator && createElement(View, {
style: separatorStyle()
}));
}
}
export default withPreferredColorScheme(BottomSheetCell);
//# sourceMappingURL=cell.native.js.map