UNPKG

native-base

Version:

Essential cross-platform UI components for React Native

193 lines (174 loc) 5.96 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import get from 'lodash.get'; import React from 'react'; import { Animated, Easing, StyleSheet } from 'react-native'; import { makeStyledComponent } from '../../../utils/styled'; import { useTheme, useThemeProps } from '../../../hooks'; import { canUseDom } from '../../../utils'; import { default as Box } from '../../primitives/Box'; import { themeTools } from '../../../theme'; import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps'; const StyleAnimatedView = makeStyledComponent(Animated.View); const CircularProgress = ({ value, isIndeterminate, max, min, ...props }, ref) => { const theme = useTheme(); const isDomUsable = canUseDom(); if (min) { value = value - min; } let sizeProps; let newProps = useThemeProps('CircularProgress', props); let [, remainingProps] = themeTools.extractInObject(props, ['size']); // removing size from props so that Box don't accept size passed for CircularProgress if (!newProps.size) { sizeProps = { height: newProps.height, width: newProps.width }; } else { sizeProps = { height: newProps.size, width: newProps.size }; } // fetching size from theme for passing into style prop const themeHeight = get(theme, 'space.' + sizeProps.height); const themeWidth = get(theme, 'space.' + sizeProps.width); const styleSize = { height: themeHeight ? parseInt(themeHeight.slice(themeHeight.Length, -2), 10) : sizeProps.height, width: themeWidth ? parseInt(themeWidth.slice(themeWidth.Length, -2), 10) : sizeProps.width }; const defaultThickness = newProps.thickness; const degree = new Animated.Value(0); if (isIndeterminate) { if (isDomUsable) { Animated.loop(Animated.timing(degree, { toValue: 1, duration: 600, easing: Easing.linear, useNativeDriver: false })).start(); } } const [viewHeight, setViewHeight] = React.useState(0); const layout = e => { let height = e.nativeEvent.layout.height; setViewHeight(height); }; const defaultStyling = { borderBottomLeftRadius: viewHeight / 2, borderBottomRightRadius: viewHeight / 2, borderTopLeftRadius: viewHeight / 2, borderTopRightRadius: viewHeight / 2, borderLeftWidth: defaultThickness, borderBottomWidth: defaultThickness, position: 'absolute', borderLeftColor: 'transparent', borderBottomColor: 'transparent', ...styleSize }; const styles = StyleSheet.create({ firstProgressLayer: { borderTopWidth: defaultThickness, borderRightWidth: defaultThickness, ...defaultStyling, transform: [{ rotateZ: '-135deg' }] }, secondProgressLayer: { borderTopWidth: defaultThickness, borderRightWidth: defaultThickness, ...defaultStyling, transform: [{ rotateZ: '45deg' }] }, offsetLayer: { borderTopWidth: defaultThickness, borderRightWidth: defaultThickness, ...defaultStyling, borderRadius: viewHeight / 2, transform: [{ rotateZ: '-135deg' }] }, animateStyle: { borderTopWidth: defaultThickness, borderRightWidth: defaultThickness, ...defaultStyling, transform: [{ rotateZ: degree.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'] }) }] } }); let halfSide = (max ? min ? max - min : max : 100) / 2; // calculating the halfvalue of the progress according to min and max const propStyle = (percent, base_degrees) => { const rotateBy = base_degrees + percent * 180 / halfSide; return { transform: [{ rotateZ: rotateBy + 'deg' }] }; }; const renderThirdLayer = percent => { if (percent > halfSide) { return /*#__PURE__*/React.createElement(Box, { borderTopColor: newProps.color, borderRightColor: newProps.color, style: [styles.secondProgressLayer, propStyle(percent - halfSide, 45)] }); } else { return /*#__PURE__*/React.createElement(Box, { borderTopColor: newProps.trackColor, borderRightColor: newProps.trackColor, style: styles.offsetLayer }); } }; let firstProgressLayerStyle; if (value > halfSide) { firstProgressLayerStyle = propStyle(halfSide, -135); } else { firstProgressLayerStyle = propStyle(value, -135); } //TODO: refactor for responsive prop if (useHasResponsiveProps(props)) { return null; } return /*#__PURE__*/React.createElement(Box, _extends({}, sizeProps, { rounded: viewHeight / 2, borderWidth: defaultThickness, borderColor: newProps.trackColor, justifyContent: "center", alignItems: "center" }, remainingProps, { ref: ref, accessible: true, accessibilityRole: "progressbar", accessibilityValue: { min, max, now: value } }), !isIndeterminate ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Box, { onLayout: layout, borderTopColor: newProps.color, borderRightColor: newProps.color, style: [styles.firstProgressLayer, firstProgressLayerStyle] }), renderThirdLayer(value), /*#__PURE__*/React.createElement(Box, { _text: newProps._text }, remainingProps.children)) : /*#__PURE__*/React.createElement(StyleAnimatedView, { onLayout: layout, borderTopColor: newProps.color, borderRightColor: newProps.color, style: styles.animateStyle })); }; export default /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef(CircularProgress)); //# sourceMappingURL=CircularProgress.js.map