@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
426 lines (425 loc) • 17.1 kB
JavaScript
import { _ as _define_property } from "@swc/helpers/_/_define_property";
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { Close, Notice } from "@nutui/icons-react";
import classNames from "classnames";
import { getRect } from "../../hooks/use-client-rect";
import { ComponentDefaults } from "../../utils/typings";
import { useRtl } from "../configprovider";
var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), {
align: 'left',
direction: 'horizontal',
list: [],
duration: 1000,
height: 40,
content: '',
closeable: false,
wrap: false,
leftIcon: /*#__PURE__*/ React.createElement(Notice, {
width: 16,
height: 16
}),
rightIcon: null,
right: null,
delay: 1,
scrollable: null,
speed: 50
});
export var NoticeBar = function(props) {
var rtl = useRtl();
var _$_object_spread = _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 = useRef(null);
var contentRef = useRef(null);
var _useState = _sliced_to_array(useState(true), 2), showNoticeBar = _useState[0], SetShowNoticeBar = _useState[1];
var scrollList = useRef([]);
var _useState1 = _sliced_to_array(useState(0), 2), wrapWidth = _useState1[0], SetWrapWidth = _useState1[1];
var _useState2 = _sliced_to_array(useState(true), 2), firstRound = _useState2[0], SetFirstRound = _useState2[1];
var _useState3 = _sliced_to_array(useState(0), 2), animationDuration = _useState3[0], SetAnimationDuration = _useState3[1];
var _useState4 = _sliced_to_array(useState(0), 2), offsetWidth = _useState4[0], SetOffsetW = _useState4[1];
var _useState5 = _sliced_to_array(useState(''), 2), animationClass = _useState5[0], SetAnimationClass = _useState5[1];
var _useState6 = _sliced_to_array(useState(false), 2), animate = _useState6[0], SetAnimate = _useState6[1];
var _useState7 = _sliced_to_array(useState(0), 2), timer = _useState7[0], SetTimer = _useState7[1];
var _useState8 = _sliced_to_array(useState(null), 2), isCanScroll = _useState8[0], SetIsCanScroll = _useState8[1];
var isVertical = direction === 'vertical';
var _useState9 = _sliced_to_array(useState(null), 2), rect = _useState9[0], setRect = _useState9[1];
var active = 0;
var _useState10 = _sliced_to_array(useState(false), 2), ready = _useState10[0], setReady = _useState10[1];
var container = useRef(null);
var innerRef = useRef(null);
var swiperRef = useRef({
moving: false,
autoplayTimer: null,
width: 0,
height: 0,
offset: 0,
size: 0
});
var _useState11 = _sliced_to_array(useState([]), 2), childOffset = _useState11[0], setChildOffset = _useState11[1];
var _useState12 = _sliced_to_array(useState(0), 2), offset = _useState12[0], setOffset = _useState12[1];
var _useMemo = useMemo(function() {
var childCount = 0;
var childs = React.Children.map(children, function(child) {
if (!/*#__PURE__*/ React.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;
}();
useEffect(function() {
if (isVertical) {
if (children) {
scrollList.current = [].concat(childs);
} else {
scrollList.current = [].concat(list);
startRollEasy();
}
} else {
initScrollWrap(content);
}
return function() {
// 销毁事件
clearInterval(timer);
};
}, []);
useEffect(function() {
initScrollWrap(content);
}, [
content
]);
useEffect(function() {
if (list && list.length) {
scrollList.current = [].concat(list);
}
}, [
list
]);
var initScrollWrap = function(value) {
if (showNoticeBar === false) {
return;
}
setTimeout(function() {
if (!wrapRef.current || !contentRef.current) {
return;
}
var wrapW = getRect(wrapRef.current).width;
var offsetW = 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(event) {
click && click(event);
onClick && onClick(event);
};
var onClickIcon = function(event) {
event.stopPropagation();
SetShowNoticeBar(!closeable);
close && close(event);
onClose && onClose(event);
};
var onAnimationEnd = function() {
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() {
showhorseLamp();
var timerCurr = window.setInterval(showhorseLamp, time + Number(duration));
SetTimer(timerCurr);
};
var showhorseLamp = function() {
SetAnimate(true);
setTimeout(function() {
scrollList.current.push(scrollList.current[0]);
scrollList.current.shift();
SetAnimate(false);
}, time);
};
// 点击滚动单元
var handleClickIcon = function(event) {
event.stopPropagation();
SetShowNoticeBar(!closeable);
close && close(event);
onClose && onClose(event);
};
var isEllipsis = function() {
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() {
var active = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : +0;
var rects = 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);
};
useEffect(function() {
if (ready) {
stopAutoPlay();
autoplay();
}
return function() {
setReady(false);
};
}, [
ready
]);
useEffect(function() {
if (isVertical && children) {
init();
stopAutoPlay();
autoplay();
}
}, [
children,
container === null || container === void 0 ? void 0 : container.current
]);
// 清除定时器
var stopAutoPlay = function() {
clearTimeout(swiperRef.current.autoplayTimer);
swiperRef.current.autoplayTimer = null;
};
// 定时轮播
var autoplay = function() {
if (childCount <= 1) return;
stopAutoPlay();
swiperRef.current.autoplayTimer = setTimeout(function() {
next();
autoplay();
}, Number(duration) + 100 * speed);
};
// 切换方法
var move = function(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() {
resettPosition();
requestFrame(function() {
requestFrame(function() {
swiperRef.current.moving = false;
move({
pace: 1
});
});
});
};
var handleItemClick = function(event, value) {
onItemClick && onItemClick(event, value);
};
var getStyle = function() {
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(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(pace) {
if (pace) {
var _active = active + pace;
return range(_active, -1, childCount);
}
return active;
};
// 计算位移
var getOffset = function(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(fn) {
window.requestAnimationFrame.call(window, fn);
};
// 取值 方法
var range = function(num, min, max) {
return Math.min(Math.max(num, min), max);
};
// 重置首尾位置信息
var resettPosition = function() {
swiperRef.current.moving = true;
if (active <= -1) {
move({
pace: childCount
});
}
if (active >= childCount) {
move({
pace: -childCount
});
}
};
var _obj;
var noticebarClass = classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-box"), true), _define_property(_obj, "".concat(classPrefix, "-box-wrapable"), wrap), _define_property(_obj, "".concat(classPrefix, "-box-").concat(align), true), _obj));
var cls = classNames(classPrefix, className);
useEffect(function() {
return function() {
stopAutoPlay();
};
}, []);
return /*#__PURE__*/ React.createElement("div", {
className: cls,
style: style
}, showNoticeBar && direction === 'horizontal' ? /*#__PURE__*/ React.createElement("div", {
className: noticebarClass,
style: barStyle,
onClick: handleClick
}, leftIcon ? /*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-box-left-icon"
}, leftIcon) : null, /*#__PURE__*/ React.createElement("div", {
ref: wrapRef,
className: "nut-noticebar-box-wrap"
}, /*#__PURE__*/ React.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.createElement("div", {
className: "nut-noticebar-box-right"
}, right) : null, closeable || rightIcon ? /*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-box-right-icon",
onClick: onClickIcon
}, rightIcon || /*#__PURE__*/ React.createElement(Close, {
width: 12,
height: 12
})) : null) : null, showNoticeBar && scrollList.current.length > 0 && isVertical ? /*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-vertical",
style: barStyle,
ref: container,
onClick: handleClick
}, leftIcon ? /*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-box-left-icon"
}, leftIcon) : null, children ? /*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-box-wrap",
ref: innerRef
}, scrollList.current.map(function(item, index) {
return /*#__PURE__*/ React.createElement("div", {
style: itemStyle(index),
key: index,
onClick: function(e) {
handleItemClick(e, item);
}
}, item);
})) : /*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-box-horseLamp-list",
style: horseLampStyle
}, scrollList.current.map(function(item, index) {
return(// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
/*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-box-horseLamp-list-item",
style: {
height: height
},
key: index,
onClick: function(e) {
handleItemClick(e, item);
}
}, item));
})), /*#__PURE__*/ React.createElement("div", {
className: "nut-noticebar-box-right-icon",
onClick: function(e) {
handleClickIcon(e);
}
}, rightIcon || (closeable ? /*#__PURE__*/ React.createElement(Close, {
width: 12,
height: 12
}) : null))) : null);
};
NoticeBar.displayName = 'NutNoticeBar';