UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

246 lines (245 loc) 9.15 kB
import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import React, { useState, useRef, useEffect, useImperativeHandle } from "react"; import { ComponentDefaults } from "../../utils/typings"; import { padZero } from "../../utils/pad-zero"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { type: 'default', paused: false, startTime: Date.now(), endTime: Date.now(), remainingTime: 0, millisecond: false, format: 'HH:mm:ss', autoStart: true, time: 0, destroy: false }); var InternalCountDown = function(props, ref) { var _ref = _object_spread({}, defaultProps, props), type = _ref.type, paused = _ref.paused, startTime = _ref.startTime, endTime = _ref.endTime, remainingTime = _ref.remainingTime, millisecond = _ref.millisecond, format = _ref.format, autoStart = _ref.autoStart, time = _ref.time, destroy = _ref.destroy, className = _ref.className, style = _ref.style, onEnd = _ref.onEnd, onPaused = _ref.onPaused, onRestart = _ref.onRestart, onUpdate = _ref.onUpdate, children = _ref.children, rest = _object_without_properties(_ref, [ "type", "paused", "startTime", "endTime", "remainingTime", "millisecond", "format", "autoStart", "time", "destroy", "className", "style", "onEnd", "onPaused", "onRestart", "onUpdate", "children" ]); var classPrefix = 'nut-countdown'; var _useState = _sliced_to_array(useState(0), 2), restTimeStamp = _useState[0], setRestTime = _useState[1]; var stateRef = useRef({ pauseTime: 0, curr: 0, isPaused: paused, isIninted: false, timer: 0, restTime: 0, counting: !paused && autoStart, handleEndTime: Date.now(), diffTime: 0 }); // 时间戳转换 或 获取当前时间的时间戳 var getTimeStamp = function(timeStr) { if (!timeStr) return Date.now(); var t = timeStr; t = Number(t) > 0 ? +t : t.toString().replace(/-/g, '/'); return new Date(t).getTime(); }; // 倒计时 interval var initTime = function() { if (remainingTime) { stateRef.current.handleEndTime = Date.now() + Number(remainingTime); } else { stateRef.current.handleEndTime = endTime; stateRef.current.diffTime = Date.now() - getTimeStamp(startTime) // 时间差 ; } if (!stateRef.current.counting) stateRef.current.counting = true; tick(); }; var tick = function() { stateRef.current.timer = requestAnimationFrame(function() { if (stateRef.current.counting) { var currentTime = Date.now() - stateRef.current.diffTime; var remainTime = Math.max(stateRef.current.handleEndTime - currentTime, 0); stateRef.current.restTime = remainTime; setRestTime(remainTime); if (!remainTime) { stateRef.current.counting = false; pause(); onEnd && onEnd(); } if (remainTime > 0) { tick(); } } }); }; // 将倒计时剩余时间格式化 参数: t 时间戳 type custom 自定义类型 var formatRemainTime = function(t, type) { var ts = t; var rest = { d: 0, h: 0, m: 0, s: 0, ms: 0 }; var SECOND = 1000; var MINUTE = 60 * SECOND; var HOUR = 60 * MINUTE; var DAY = 24 * HOUR; if (ts > 0) { rest.d = ts >= SECOND ? Math.floor(ts / DAY) : 0; rest.h = Math.floor(ts % DAY / HOUR); rest.m = Math.floor(ts % HOUR / MINUTE); rest.s = Math.floor(ts % MINUTE / SECOND); rest.ms = Math.floor(ts % SECOND); } return type === 'custom' ? rest : parseFormat(_object_spread({}, rest)); }; var parseFormat = function(time) { var d = time.d; var h = time.h, m = time.m, s = time.s, ms = time.ms; var formatCache = format; if (formatCache.includes('DD')) { formatCache = formatCache.replace('DD', padZero(d)); } else { h += Number(d) * 24; } if (formatCache.includes('HH')) { formatCache = formatCache.replace('HH', padZero(h)); } else { m += Number(h) * 60; } if (formatCache.includes('mm')) { formatCache = formatCache.replace('mm', padZero(m)); } else { s += Number(m) * 60; } if (formatCache.includes('ss')) { formatCache = formatCache.replace('ss', padZero(s)); } else { ms += Number(s) * 1000; } if (formatCache.includes('S')) { var msC = padZero(ms, 3).toString(); if (formatCache.includes('SSS')) { formatCache = formatCache.replace('SSS', msC); } else if (formatCache.includes('SS')) { formatCache = formatCache.replace('SS', msC.slice(0, 2)); } else if (formatCache.includes('S')) { formatCache = formatCache.replace('S', msC.slice(0, 1)); } } var isTextDom = type === 'text' ? '<span class="nut-countdown-number-text">$1</span>' : '<span class="nut-countdown-number">$1</span>'; formatCache = formatCache.replace(/(\d+)/g, type === 'primary' ? '<span class="nut-countdown-number-primary">$1</span>' : isTextDom); return formatCache; }; var pause = function() { cancelAnimationFrame(stateRef.current.timer); stateRef.current.counting = false; onPaused && onPaused(stateRef.current.restTime); }; useImperativeHandle(ref, function() { return { start: function() { if (!stateRef.current.counting && !autoStart) { stateRef.current.counting = true; stateRef.current.handleEndTime = Date.now() + Number(stateRef.current.restTime); tick(); onRestart && onRestart(stateRef.current.restTime); } }, pause: function() { cancelAnimationFrame(stateRef.current.timer); stateRef.current.counting = false; onPaused && onPaused(stateRef.current.restTime); }, reset: function() { if (!autoStart) { pause(); stateRef.current.restTime = time; setRestTime(time); } } }; }); // 监听值变更 useEffect(function() { var tranTime = formatRemainTime(stateRef.current.restTime, 'custom'); onUpdate && onUpdate(tranTime); }, [ restTimeStamp ]); // 监听暂停 useEffect(function() { if (stateRef.current.isIninted) { if (paused) { if (stateRef.current.counting) { pause(); } } else { if (!stateRef.current.counting) { stateRef.current.counting = true; stateRef.current.handleEndTime = Date.now() + Number(stateRef.current.restTime); tick(); } onRestart && onRestart(stateRef.current.restTime); } } }, [ paused ]); // 监听开始结束时间变更 useEffect(function() { if (stateRef.current.isIninted) { initTime(); } }, [ endTime, startTime, remainingTime ]); // 初始化 useEffect(function() { if (autoStart) { initTime(); } else { stateRef.current.restTime = time; setRestTime(time); } if (!stateRef.current.isIninted) { stateRef.current.isIninted = true; } return componentWillUnmount; }, []); var componentWillUnmount = function() { destroy && cancelAnimationFrame(stateRef.current.timer); }; var renderTime = function() { return formatRemainTime(stateRef.current.restTime); }(); return /*#__PURE__*/ React.createElement(React.Fragment, null, children || /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({ className: "".concat(classPrefix, " ").concat(className), style: _object_spread({}, style) }, rest), { dangerouslySetInnerHTML: { __html: "".concat(renderTime) } }))); }; export var CountDown = /*#__PURE__*/ React.forwardRef(InternalCountDown); CountDown.displayName = 'NutCountDown';