UNPKG

@nutui/nutui-react

Version:

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

437 lines (436 loc) 18.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "NoticeBar", { enumerable: true, get: function() { return NoticeBar; } }); var _interop_require_default = require("@swc/helpers/_/_interop_require_default"); var _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard"); var _define_property = require("@swc/helpers/_/_define_property"); var _object_spread = require("@swc/helpers/_/_object_spread"); var _object_spread_props = require("@swc/helpers/_/_object_spread_props"); var _sliced_to_array = require("@swc/helpers/_/_sliced_to_array"); var _react = /*#__PURE__*/ _interop_require_wildcard._(require("react")); var _iconsreact = require("@nutui/icons-react"); var _classnames = /*#__PURE__*/ _interop_require_default._(require("classnames")); var _getrect = require("../../utils/get-rect"); var _typings = require("../../utils/typings"); var _configprovider = require("../configprovider"); var defaultProps = (0, _object_spread_props._)((0, _object_spread._)({}, _typings.ComponentDefaults), { align: 'left', direction: 'horizontal', list: [], duration: 1000, height: 40, content: '', closeable: false, wrap: false, leftIcon: /*#__PURE__*/ _react.default.createElement(_iconsreact.Notice, { width: 16, height: 16 }), rightIcon: null, right: null, delay: 1, scrollable: null, speed: 50 }); var NoticeBar = function NoticeBar(props) { var rtl = (0, _configprovider.useRtl)(); var _$_object_spread = (0, _object_spread._)({}, defaultProps, props), children = _$_object_spread.children, className = _$_object_spread.className, style = _$_object_spread.style, align = _$_object_spread.align, direction = _$_object_spread.direction, list = _$_object_spread.list, duration = _$_object_spread.duration, height = _$_object_spread.height, content = _$_object_spread.content, closeable = _$_object_spread.closeable, wrap = _$_object_spread.wrap, leftIcon = _$_object_spread.leftIcon, rightIcon = _$_object_spread.rightIcon, right = _$_object_spread.right, delay = _$_object_spread.delay, scrollable = _$_object_spread.scrollable, speed = _$_object_spread.speed, close = _$_object_spread.close, click = _$_object_spread.click, onClose = _$_object_spread.onClose, onClick = _$_object_spread.onClick, onItemClick = _$_object_spread.onItemClick; var classPrefix = 'nut-noticebar'; var wrapRef = (0, _react.useRef)(null); var contentRef = (0, _react.useRef)(null); var _useState = (0, _sliced_to_array._)((0, _react.useState)(true), 2), showNoticeBar = _useState[0], SetShowNoticeBar = _useState[1]; var scrollList = (0, _react.useRef)([]); var _useState1 = (0, _sliced_to_array._)((0, _react.useState)(0), 2), wrapWidth = _useState1[0], SetWrapWidth = _useState1[1]; var _useState2 = (0, _sliced_to_array._)((0, _react.useState)(true), 2), firstRound = _useState2[0], SetFirstRound = _useState2[1]; var _useState3 = (0, _sliced_to_array._)((0, _react.useState)(0), 2), animationDuration = _useState3[0], SetAnimationDuration = _useState3[1]; var _useState4 = (0, _sliced_to_array._)((0, _react.useState)(0), 2), offsetWidth = _useState4[0], SetOffsetW = _useState4[1]; var _useState5 = (0, _sliced_to_array._)((0, _react.useState)(''), 2), animationClass = _useState5[0], SetAnimationClass = _useState5[1]; var _useState6 = (0, _sliced_to_array._)((0, _react.useState)(false), 2), animate = _useState6[0], SetAnimate = _useState6[1]; var _useState7 = (0, _sliced_to_array._)((0, _react.useState)(0), 2), timer = _useState7[0], SetTimer = _useState7[1]; var _useState8 = (0, _sliced_to_array._)((0, _react.useState)(null), 2), isCanScroll = _useState8[0], SetIsCanScroll = _useState8[1]; var isVertical = direction === 'vertical'; var _useState9 = (0, _sliced_to_array._)((0, _react.useState)(null), 2), rect = _useState9[0], setRect = _useState9[1]; var active = 0; var _useState10 = (0, _sliced_to_array._)((0, _react.useState)(false), 2), ready = _useState10[0], setReady = _useState10[1]; var container = (0, _react.useRef)(null); var innerRef = (0, _react.useRef)(null); var swiperRef = (0, _react.useRef)({ moving: false, autoplayTimer: null, width: 0, height: 0, offset: 0, size: 0 }); var _useState11 = (0, _sliced_to_array._)((0, _react.useState)([]), 2), childOffset = _useState11[0], setChildOffset = _useState11[1]; var _useState12 = (0, _sliced_to_array._)((0, _react.useState)(0), 2), offset = _useState12[0], setOffset = _useState12[1]; var _useMemo = (0, _react.useMemo)(function() { var childCount = 0; var childs = _react.default.Children.map(children, function(child) { if (!/*#__PURE__*/ _react.default.isValidElement(child)) return null; childCount++; return child; }); return { childs: childs, childCount: childCount }; }, [ children ]), childs = _useMemo.childs, childCount = _useMemo.childCount; // 滚动消息的总高度 var trackSize = childCount * Number(height); // 设置最小偏移量(最后一条的偏移位置) var minOffset = function() { if (rect) { var base = isVertical ? rect.height : rect.width; return base - Number(height) * childCount; } return 0; }(); (0, _react.useEffect)(function() { if (isVertical) { if (children) { scrollList.current = [].concat(childs); } else { scrollList.current = [].concat(list); startRollEasy(); } } else { initScrollWrap(content); } return function() { // 销毁事件 clearInterval(timer); }; }, []); (0, _react.useEffect)(function() { initScrollWrap(content); }, [ content ]); (0, _react.useEffect)(function() { if (list && list.length) { scrollList.current = [].concat(list); } }, [ list ]); var initScrollWrap = function initScrollWrap(value) { if (showNoticeBar === false) { return; } setTimeout(function() { if (!wrapRef.current || !contentRef.current) { return; } var wrapW = (0, _getrect.getRect)(wrapRef.current).width; var offsetW = (0, _getrect.getRect)(contentRef.current).width; var canScroll = align === 'left' && scrollable == null ? offsetW > wrapW : scrollable; SetIsCanScroll(canScroll); if (canScroll) { SetWrapWidth(wrapW); SetOffsetW(offsetW); SetAnimationDuration(offsetW / speed); SetAnimationClass('play'); } else { SetAnimationClass(''); } }, 0); }; var handleClick = function handleClick(event) { click && click(event); onClick && onClick(event); }; var onClickIcon = function onClickIcon(event) { event.stopPropagation(); SetShowNoticeBar(!closeable); close && close(event); onClose && onClose(event); }; var onAnimationEnd = function onAnimationEnd() { SetFirstRound(false); setTimeout(function() { SetAnimationDuration((offsetWidth + wrapWidth) / speed); SetAnimationClass('play-infinite'); }, 0); }; // 滚动时间间隔 var time = height / speed / 4 < 1 ? Number((height / speed / 4).toFixed(1)) * 1000 : ~~(height / speed / 4) * 1000; /** * 滚动方式一,普通垂直滚动 */ var startRollEasy = function startRollEasy() { showhorseLamp(); var timerCurr = window.setInterval(showhorseLamp, time + Number(duration)); SetTimer(timerCurr); }; var showhorseLamp = function showhorseLamp() { SetAnimate(true); setTimeout(function() { scrollList.current.push(scrollList.current[0]); scrollList.current.shift(); SetAnimate(false); }, time); }; // 点击滚动单元 var handleClickIcon = function handleClickIcon(event) { event.stopPropagation(); SetShowNoticeBar(!closeable); close && close(event); onClose && onClose(event); }; var isEllipsis = function isEllipsis() { if (isCanScroll == null && align === 'left') { return wrap; } return !isCanScroll && !wrap; }; var contentStyle = { animationDelay: "".concat(firstRound ? delay : 0, "s"), animationDuration: "".concat(animationDuration, "s"), transform: "translateX(".concat(firstRound ? 0 : "".concat(rtl ? -wrapWidth : wrapWidth, "px"), ")") }; var barStyle = { height: isVertical ? "".concat(height, "px") : '' }; var duringTime = height / speed / 4 < 1 ? Number((height / speed / 4).toFixed(1)) : ~~(height / speed / 4); var noDuring = height / speed < 1 ? (height / speed).toFixed(1) : ~~(height / speed); var horseLampStyle = { transition: animate ? "all ".concat(duringTime === 0 ? noDuring : duringTime, "s") : '', marginTop: animate ? "-".concat(height, "px") : '' }; // 垂直自定义滚动方式 var init = function init() { var active = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : +0; var rects = (0, _getrect.getRect)(container === null || container === void 0 ? void 0 : container.current); var _active = Math.max(Math.min(childCount - 1, active), 0); var _height = rects.height; trackSize = childCount * Number(_height); var targetOffset = getOffset(_active); swiperRef.current.moving = true; if (ready) { swiperRef.current.moving = false; } active = _active; setRect(rects); setOffset(targetOffset); setReady(true); }; (0, _react.useEffect)(function() { if (ready) { stopAutoPlay(); autoplay(); } return function() { setReady(false); }; }, [ ready ]); (0, _react.useEffect)(function() { if (isVertical && children) { init(); stopAutoPlay(); autoplay(); } }, [ children, container === null || container === void 0 ? void 0 : container.current ]); // 清除定时器 var stopAutoPlay = function stopAutoPlay() { clearTimeout(swiperRef.current.autoplayTimer); swiperRef.current.autoplayTimer = null; }; // 定时轮播 var autoplay = function autoplay1() { if (childCount <= 1) return; stopAutoPlay(); swiperRef.current.autoplayTimer = setTimeout(function() { next(); autoplay(); }, Number(duration) + 100 * speed); }; // 切换方法 var move = function move(param) { var _param_pace = param.pace, pace = _param_pace === void 0 ? 0 : _param_pace, _param_offset = param.offset, offset = _param_offset === void 0 ? 0 : _param_offset; if (childCount <= 1) return; var targetActive = getActive(pace); // 父级容器偏移量 var targetOffset = getOffset(targetActive, offset); // 循环滚动,调整开头结尾图片位置 if (Array.isArray(children) && children[0] && targetOffset !== minOffset) { var rightBound = targetOffset < minOffset; childOffset[0] = rightBound ? trackSize : 0; } if (Array.isArray(children) && children[childCount - 1] && targetOffset !== 0) { var leftBound = targetOffset > 0; childOffset[childCount - 1] = leftBound ? -trackSize : 0; } setChildOffset(childOffset); active = targetActive; setOffset(targetOffset); getStyle(targetOffset); }; // 下一页 var next = function next() { resettPosition(); requestFrame(function() { requestFrame(function() { swiperRef.current.moving = false; move({ pace: 1 }); }); }); }; var handleItemClick = function handleItemClick(event, value) { onItemClick && onItemClick(event, value); }; var getStyle = function getStyle() { var moveOffset = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : offset; var target = innerRef.current; if (!target) { return; } var _offset = 0; // 容器高度-元素高度 var val = rect.height - height; _offset = moveOffset + Number(active === childCount - 1 && val / 2); target.style.transitionDuration = "".concat(swiperRef.current.moving ? 0 : duration, "ms"); target.style.height = "".concat(Number(height) * childCount, "px"); target.style.transform = "translate3D(0,".concat(_offset, "px,0)"); }; // 无缝滚动第一个元素位移控制 var itemStyle = function itemStyle(index) { var style = {}; if (height) { style.height = "".concat(height, "px"); style.lineHeight = "".concat(height, "px"); } var offset = childOffset[index]; if (offset) { style.transform = "translate3D(0,".concat(offset, "px,0)"); } return style; }; // 确定当前active 元素 var getActive = function getActive(pace) { if (pace) { var _active = active + pace; return range(_active, -1, childCount); } return active; }; // 计算位移 var getOffset = function getOffset(active) { var offset = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0; var currentPosition = active * Number(height); var targetOffset = offset - currentPosition; return targetOffset; }; // 浏览器 帧 事件 var requestFrame = function requestFrame(fn) { window.requestAnimationFrame.call(window, fn); }; // 取值 方法 var range = function range(num, min, max) { return Math.min(Math.max(num, min), max); }; // 重置首尾位置信息 var resettPosition = function resettPosition() { swiperRef.current.moving = true; if (active <= -1) { move({ pace: childCount }); } if (active >= childCount) { move({ pace: -childCount }); } }; var _obj; var noticebarClass = (0, _classnames.default)((_obj = {}, (0, _define_property._)(_obj, "".concat(classPrefix, "-box"), true), (0, _define_property._)(_obj, "".concat(classPrefix, "-box-wrapable"), wrap), (0, _define_property._)(_obj, "".concat(classPrefix, "-box-").concat(align), true), _obj)); var cls = (0, _classnames.default)(classPrefix, className); (0, _react.useEffect)(function() { return function() { stopAutoPlay(); }; }, []); return /*#__PURE__*/ _react.default.createElement("div", { className: cls, style: style }, showNoticeBar && direction === 'horizontal' ? /*#__PURE__*/ _react.default.createElement("div", { className: noticebarClass, style: barStyle, onClick: handleClick }, leftIcon ? /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-left-icon" }, leftIcon) : null, /*#__PURE__*/ _react.default.createElement("div", { ref: wrapRef, className: "nut-noticebar-box-wrap" }, /*#__PURE__*/ _react.default.createElement("div", { ref: contentRef, className: "nut-noticebar-box-wrap-content ".concat(animationClass, " ").concat(isEllipsis() ? 'nut-ellipsis' : ''), style: contentStyle, onAnimationEnd: onAnimationEnd }, children, content)), right ? /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-right" }, right) : null, closeable || rightIcon ? /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-right-icon", onClick: onClickIcon }, rightIcon || /*#__PURE__*/ _react.default.createElement(_iconsreact.Close, { width: 12, height: 12 })) : null) : null, showNoticeBar && scrollList.current.length > 0 && isVertical ? /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-vertical", style: barStyle, ref: container, onClick: handleClick }, leftIcon ? /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-left-icon" }, leftIcon) : null, children ? /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-wrap", ref: innerRef }, scrollList.current.map(function(item, index) { return /*#__PURE__*/ _react.default.createElement("div", { style: itemStyle(index), key: index, onClick: function onClick(e) { handleItemClick(e, item); } }, item); })) : /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-horseLamp-list", style: horseLampStyle }, scrollList.current.map(function(item, index) { return /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-horseLamp-list-item", style: { height: height }, key: index, onClick: function onClick(e) { handleItemClick(e, item); } }, item); })), /*#__PURE__*/ _react.default.createElement("div", { className: "nut-noticebar-box-right-icon", onClick: function onClick(e) { handleClickIcon(e); } }, rightIcon || (closeable ? /*#__PURE__*/ _react.default.createElement(_iconsreact.Close, { width: 12, height: 12 }) : null))) : null); }; NoticeBar.displayName = 'NutNoticeBar';