UNPKG

react-native-ui-lib

Version:

[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://stand-with-ukraine.pp.ua)

158 lines (156 loc) 5.38 kB
import React, { PureComponent } from 'react'; import { StyleSheet, Animated } from 'react-native'; import { Constants, asBaseComponent } from "../../commons/new"; import { Colors, Shadows, Spacings } from "../../style"; import View from "../view"; import Image from "../image"; import Button from "../button"; export let FloatingButtonLayouts = /*#__PURE__*/function (FloatingButtonLayouts) { FloatingButtonLayouts["VERTICAL"] = "Vertical"; FloatingButtonLayouts["HORIZONTAL"] = "Horizontal"; return FloatingButtonLayouts; }({}); const gradientImage = () => require("./gradient.png"); /** * @description: Hovering button with gradient background * @modifiers: margin, background, color * @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/FloatingButtonScreen.tsx * @gif: https://github.com/wix/react-native-ui-lib/blob/master/demo/showcase/FloatingButton/FloatingButton.gif?raw=true */ class FloatingButton extends PureComponent { static displayName = 'FloatingButton'; static floatingButtonLayouts = FloatingButtonLayouts; static defaultProps = { duration: 300, buttonLayout: FloatingButtonLayouts.VERTICAL }; constructor(props) { super(props); this.initialVisibility = props.visible; this.firstLoad = true; this.visibleAnimated = new Animated.Value(Number(!!props.visible)); } componentDidUpdate(prevProps) { const { visible, duration } = this.props; if (prevProps.visible !== visible) { Animated.timing(this.visibleAnimated, { toValue: Number(!!visible), duration, useNativeDriver: true }).start(); } } getAnimatedStyle = () => { return { opacity: this.visibleAnimated, transform: [{ translateY: this.visibleAnimated.interpolate({ inputRange: [0, 1], outputRange: [Constants.screenHeight / 2, 0] }) }] }; }; get isSecondaryHorizontal() { const { secondaryButton, buttonLayout } = this.props; return secondaryButton && buttonLayout === FloatingButtonLayouts.HORIZONTAL; } get isSecondaryVertical() { const { secondaryButton, buttonLayout } = this.props; return secondaryButton && buttonLayout === FloatingButtonLayouts.VERTICAL; } renderButton() { const { bottomMargin, button, fullWidth, testID } = this.props; const bottom = this.isSecondaryVertical ? Spacings.s4 : bottomMargin || Spacings.s8; const left = this.isSecondaryHorizontal || fullWidth ? Spacings.s4 : undefined; const right = this.isSecondaryHorizontal ? 20 : fullWidth ? Spacings.s4 : undefined; const shadowStyle = !button?.outline && !button?.link && styles.shadow; const marginStyle = { marginTop: 16, marginBottom: bottom, marginLeft: left, marginRight: right }; return <Button size={Button.sizes.large} flex={!!this.isSecondaryHorizontal} style={[shadowStyle, marginStyle]} testID={`${testID}.button`} {...button} />; } renderOverlay = () => { if (!this.props.hideBackgroundOverlay) { return <View pointerEvents={'none'} style={styles.image}> <Image style={styles.image} source={gradientImage()} resizeMode={'stretch'} tintColor={Colors.$backgroundDefault} /> </View>; } }; renderSecondaryButton() { const { secondaryButton, bottomMargin, testID, buttonLayout } = this.props; const bgColor = secondaryButton?.backgroundColor || Colors.$backgroundDefault; const isHorizontal = buttonLayout === FloatingButtonLayouts.HORIZONTAL; const buttonStyle = isHorizontal ? [styles.shadow, styles.secondaryMargin, { backgroundColor: bgColor }] : { marginBottom: bottomMargin || Spacings.s7 }; return <Button outline={isHorizontal} flex={isHorizontal} link={!isHorizontal} size={Button.sizes.large} testID={`${testID}.secondaryButton`} {...secondaryButton} style={buttonStyle} enableShadow={false} />; } render() { const { withoutAnimation, visible, fullWidth, testID } = this.props; // NOTE: keep this.firstLoad as true as long as the visibility changed to true this.firstLoad && !visible ? this.firstLoad = true : this.firstLoad = false; // NOTE: On first load, don't show if it should not be visible if (this.firstLoad === true && !this.initialVisibility) { return false; } if (!visible && withoutAnimation) { return false; } return <View row={this.isSecondaryHorizontal} center={this.isSecondaryHorizontal || !fullWidth} pointerEvents="box-none" animated style={[styles.container, this.getAnimatedStyle()]} testID={testID}> {this.renderOverlay()} {this.isSecondaryHorizontal && this.renderSecondaryButton()} {this.renderButton()} {this.isSecondaryVertical && this.renderSecondaryButton()} </View>; } } const styles = StyleSheet.create({ container: { top: undefined, zIndex: Constants.isAndroid ? 99 : undefined }, image: { ...StyleSheet.absoluteFillObject, width: '100%', height: '100%' }, shadow: { ...Shadows.sh20.bottom }, secondaryMargin: { marginTop: Spacings.s4, marginBottom: Spacings.s7, marginLeft: 20 } }); export default asBaseComponent(FloatingButton);