react-native-action-button-warnings-fixed
Version:
customizable multi-action-button component for react-native, now without warnings
218 lines (198 loc) • 5.4 kB
JavaScript
import React, { Component } from "react";
import PropTypes from "prop-types";
import {
StyleSheet,
Text,
View,
Animated,
TouchableNativeFeedback,
TouchableWithoutFeedback,
Dimensions,
} from "react-native";
import {
shadowStyle,
alignItemsMap,
getTouchableComponent,
isAndroid,
touchableBackground,
DEFAULT_ACTIVE_OPACITY
} from "./shared";
const { width: WIDTH } = Dimensions.get("window");
const SHADOW_SPACE = 10;
const TEXT_HEIGHT = 22;
const TextTouchable = isAndroid
? TouchableNativeFeedback
: TouchableWithoutFeedback;
export default class ActionButtonItem extends Component {
static get defaultProps() {
return {
active: true,
spaceBetween: 15,
useNativeFeedback: true,
activeOpacity: DEFAULT_ACTIVE_OPACITY,
fixNativeFeedbackRadius: false,
nativeFeedbackRippleColor: "rgba(255,255,255,0.75)",
numberOfLines: 1,
};
}
static get propTypes() {
return {
active: PropTypes.bool,
useNativeFeedback: PropTypes.bool,
fixNativeFeedbackRadius: PropTypes.bool,
nativeFeedbackRippleColor: PropTypes.string,
activeOpacity: PropTypes.number,
numberOfLines: PropTypes.number,
};
}
render() {
const {
size,
position,
verticalOrientation,
hideShadow,
spacing
} = this.props;
if (!this.props.active) return null;
const animatedViewStyle = {
marginBottom: -SHADOW_SPACE,
alignItems: alignItemsMap[position],
// backgroundColor: this.props.buttonColor,
opacity: this.props.anim,
transform: [
{
translateY: this.props.anim.interpolate({
inputRange: [0, 1],
outputRange: [verticalOrientation === "down" ? -40 : 40, 0]
})
}
]
};
const buttonStyle = {
justifyContent: "center",
alignItems: "center",
width: size,
height: size,
borderRadius: size / 2,
backgroundColor: this.props.buttonColor || this.props.btnColor
};
if (position !== "center")
buttonStyle[position] = (this.props.parentSize - size) / 2;
const Touchable = getTouchableComponent(this.props.useNativeFeedback);
const parentStyle = isAndroid &&
this.props.fixNativeFeedbackRadius
? {
height: size,
marginBottom: spacing,
right: this.props.offsetX,
borderRadius: this.props.size / 2
}
: {
paddingHorizontal: this.props.offsetX,
height: size + SHADOW_SPACE + spacing
};
return (
<Animated.View
pointerEvents="box-none"
style={[animatedViewStyle, parentStyle]}
>
<View>
<Touchable
rejectResponderTermination
testID={this.props.testID}
accessibilityLabel={this.props.accessibilityLabel}
background={touchableBackground(
this.props.nativeFeedbackRippleColor,
this.props.fixNativeFeedbackRadius
)}
activeOpacity={this.props.activeOpacity || DEFAULT_ACTIVE_OPACITY}
onPress={this.props.onPress}
>
<View style={[
buttonStyle,
!hideShadow ? {...shadowStyle, ...this.props.shadowStyle} : null
]}>
{this.props.children}
</View>
</Touchable>
</View>
{this._renderTitle()}
</Animated.View>
);
}
_renderTitle() {
if (!this.props.title) return null;
const {
textContainerStyle,
hideLabelShadow,
offsetX,
parentSize,
size,
position,
spaceBetween,
numberOfLines,
} = this.props;
const offsetTop = Math.max(size / 2 - TEXT_HEIGHT / 2, 0);
const positionStyles = { top: offsetTop };
const hideShadow = hideLabelShadow === undefined
? this.props.hideShadow
: hideLabelShadow;
if (position !== "center") {
positionStyles[position] =
offsetX + (parentSize - size) / 2 + size + spaceBetween;
} else {
positionStyles.right = WIDTH / 2 + size / 2 + spaceBetween;
}
const textStyles = [
styles.textContainer,
positionStyles,
!hideShadow && shadowStyle,
textContainerStyle
];
const title = (
React.isValidElement(this.props.title) ?
this.props.title
: (
<Text
allowFontScaling={false}
style={[styles.text, this.props.textStyle]}
numberOfLines={numberOfLines}
>
{this.props.title}
</Text>
)
)
return (
<TextTouchable
rejectResponderTermination
background={touchableBackground(
this.props.nativeFeedbackRippleColor,
this.props.fixNativeFeedbackRadius
)}
activeOpacity={this.props.activeOpacity || DEFAULT_ACTIVE_OPACITY}
onPress={this.props.onPress}
>
<View style={textStyles}>
{title}
</View>
</TextTouchable>
);
}
}
const styles = StyleSheet.create({
textContainer: {
position: "absolute",
paddingVertical: isAndroid ? 2 : 3,
paddingHorizontal: 8,
borderRadius: 3,
borderWidth: StyleSheet.hairlineWidth,
borderColor: "#eee",
backgroundColor: "white",
height: TEXT_HEIGHT
},
text: {
flex: 1,
fontSize: 12,
color: "#444"
}
});