UNPKG

@baby-journey/rn-segmented-progress-bar

Version:
212 lines (207 loc) 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeSvg = _interopRequireWildcard(require("react-native-svg")); var _helpers = require("./helpers"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); } const IndicatorCircle = _reactNative.Animated.createAnimatedComponent(_reactNativeSvg.Circle); const ProgressCircle = _reactNative.Animated.createAnimatedComponent(_reactNativeSvg.Circle); const max = 100; const duration = 1200; const RNSegmentedProgressBar = (props, ref) => { const { radius, strokeWidth = 10, baseColor = '#ffede1', progressColor = '#F39E93', segments = 3, segmentsGap = 0, indicator, centerComponent } = props; const circleRef = (0, _react.useRef)([]); const animatedValue = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current; const progressAnimatedValues = (0, _react.useRef)([...Array(segments)].map(() => new _reactNative.Animated.Value(0))).current; const indicatorCircleRef = (0, _react.useRef)(null); const tSpanRef = (0, _react.useRef)(null); const indicatorSegmentsGap = (indicator === null || indicator === void 0 ? void 0 : indicator.radius) ?? 0; const halfCircle = radius + strokeWidth + indicatorSegmentsGap; const circleCircumference = 2 * Math.PI * radius; const rotation = -90 + 180 * (segmentsGap / 2 / radius) / Math.PI; const getProgressValues = (0, _react.useCallback)(progress => (0, _helpers.getPathValues)(progress, max, segments), [segments]); const progressDelay = 10; const animation = (0, _react.useCallback)((animatedVal, toValue, delay, durationValue) => { return _reactNative.Animated.timing(animatedVal, { toValue, duration: durationValue, delay, useNativeDriver: true, easing: _reactNative.Easing.linear }); }, []); (0, _react.useEffect)(() => { () => { animatedValue.removeAllListeners(); progressAnimatedValues.forEach(progressAnimatedValue => progressAnimatedValue.removeAllListeners()); }; }, [animatedValue, progressAnimatedValues]); const getMeanSegmentsGap = (0, _react.useCallback)(progress => { const pathValues = getProgressValues(progress); return (progress / pathValues.filter(val => val > 0).length || 1) * segments * segmentsGap / 100; }, [getProgressValues, segments, segmentsGap]); const runIndicator = (0, _react.useCallback)((calculatedStrokeDashoffset, val) => { const { x: cx, y: cy } = (0, _helpers.getArcEndCoordinates)(radius, calculatedStrokeDashoffset, halfCircle, halfCircle, rotation); if (!calculatedStrokeDashoffset) { return; } const calculatedProgress = `${Math.round(val)}%`; if (indicatorCircleRef !== null && indicatorCircleRef !== void 0 && indicatorCircleRef.current && tSpanRef !== null && tSpanRef !== void 0 && tSpanRef.current) { //@ts-ignore indicatorCircleRef.current.setNativeProps({ r: (indicator === null || indicator === void 0 ? void 0 : indicator.radius) || 0, strokeWidth: (indicator === null || indicator === void 0 ? void 0 : indicator.strokeWidth) || 0, cx, cy }); //@ts-ignore tSpanRef === null || tSpanRef === void 0 ? void 0 : tSpanRef.current.setNativeProps({ children: calculatedProgress, dx: cx, dy: cy + 5, font: { textAnchor: 'middle', fontSize: 18 } }); } }, [radius, halfCircle, rotation, indicator === null || indicator === void 0 ? void 0 : indicator.radius, indicator === null || indicator === void 0 ? void 0 : indicator.strokeWidth]); const run = (0, _react.useCallback)(_ref => { let { progress } = _ref; const circleProgressValues = getProgressValues(progress); progressAnimatedValues.forEach((progressAnimated, index) => { progressAnimated.addListener(v => { if (circleRef !== null && circleRef !== void 0 && circleRef.current[index]) { var _circleRef$current$in; var strokeDashoffset = circleCircumference; var val = v.value <= (circleProgressValues[index] ?? 0) ? v.value : circleProgressValues[index] ?? 0; strokeDashoffset = circleProgressValues[index] ? circleCircumference - circleCircumference * val / 100 : circleCircumference; const paintedLength = circleCircumference - strokeDashoffset - segments * (circleProgressValues[index] ?? 0) * segmentsGap / 100; //@ts-ignore circleRef === null || circleRef === void 0 ? void 0 : (_circleRef$current$in = circleRef.current[index]) === null || _circleRef$current$in === void 0 ? void 0 : _circleRef$current$in.setNativeProps({ strokeDashoffset: circleCircumference - paintedLength > circleCircumference ? circleCircumference : circleCircumference - paintedLength }); } }); }); if (indicator !== null && indicator !== void 0 && indicator.show) { animatedValue.addListener(v => { var strokeDashoffset = circleCircumference; var val = v.value <= progress ? v.value : progress; strokeDashoffset = progress ? circleCircumference - circleCircumference * val / 100 : circleCircumference; const paintedLength = circleCircumference - strokeDashoffset; const meanSegmentsGap = getMeanSegmentsGap(progress); const calculatedStrokeDashoffset = paintedLength - meanSegmentsGap; runIndicator(calculatedStrokeDashoffset, progress); }); } // Animate circles sequentially const progressAnimations = _reactNative.Animated.sequence(progressAnimatedValues.map((tav, index) => animation(tav, // Animated value circleProgressValues[index] ?? 0, // To value index === 0 ? progressDelay : 0, // Delay duration * (circleProgressValues[index] ?? 0) / max // Duration ))); if (indicator !== null && indicator !== void 0 && indicator.show) { // Animate percentage circle const percentageAnim = animation(animatedValue, // Animated value progress, // To value progressDelay, // Delay duration * progress / max // Duration ); // Progress Animations run parallelly with percentage circle _reactNative.Animated.parallel([progressAnimations, percentageAnim]).start(); } else { progressAnimations.start(); } }, [animatedValue, animation, segments, circleCircumference, segmentsGap, getMeanSegmentsGap, indicator === null || indicator === void 0 ? void 0 : indicator.show, getProgressValues, runIndicator, progressAnimatedValues]); const getProgress = (0, _react.useMemo)(() => { const progressConfig = { stroke: progressColor, cx: halfCircle, cy: halfCircle, r: radius, origin: `${halfCircle}, ${halfCircle}`, strokeWidth: strokeWidth, strokeDasharray: circleCircumference, strokeDashoffset: circleCircumference }; return progressAnimatedValues.map((_, key) => /*#__PURE__*/_react.default.createElement(ProgressCircle, _extends({ key: key //@ts-ignore , ref: el => circleRef.current[key] = el }, progressConfig, { rotation: rotation + key * 360 / segments, strokeLinecap: "round" }))); }, [segments, circleCircumference, halfCircle, progressColor, radius, rotation, strokeWidth, progressAnimatedValues]); (0, _react.useImperativeHandle)(ref, () => ({ run })); return /*#__PURE__*/_react.default.createElement(_reactNativeSvg.default, { viewBox: `0 0 ${halfCircle * 2} ${halfCircle * 2}`, width: '100%', fill: "none", height: radius * 2 }, centerComponent && /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.centerComponent }, centerComponent), /*#__PURE__*/_react.default.createElement(_reactNativeSvg.G, null, [...Array(segments)].map((_, key) => { return /*#__PURE__*/_react.default.createElement(_reactNativeSvg.Circle, { key: key, cx: halfCircle, cy: halfCircle, r: radius, stroke: baseColor, rotation: rotation + key * 360 / segments, origin: `${halfCircle}, ${halfCircle}`, strokeWidth: strokeWidth, strokeDasharray: circleCircumference, strokeDashoffset: circleCircumference - circleCircumference / segments + segmentsGap, strokeLinecap: "round" }); }), getProgress, (indicator === null || indicator === void 0 ? void 0 : indicator.show) === true && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(IndicatorCircle, { stroke: progressColor, ref: indicatorCircleRef, fill: "white" }), /*#__PURE__*/_react.default.createElement(_reactNativeSvg.TSpan, { stroke: progressColor, fill: progressColor, ref: tSpanRef })))); }; var _default = /*#__PURE__*/(0, _react.memo)( /*#__PURE__*/(0, _react.forwardRef)(RNSegmentedProgressBar)); exports.default = _default; const styles = _reactNative.StyleSheet.create({ centerComponent: { height: '100%', justifyContent: 'center', alignItems: 'center' } }); //# sourceMappingURL=index.js.map