native-base
Version:
Essential cross-platform UI components for React Native
193 lines (174 loc) • 5.96 kB
JavaScript
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