提交 0aaecda9 编写于 作者: W wangbei16

feat: 更新组件

上级 8538aae5
const vfs = require('vinyl-fs')
const path = require('path')
const base = process.cwd()
const docs = path.join(base, 'docs')
const components = path.join(base, 'src/packages')
const { rm } = require('fs/promises')
rm(docs, { recursive: true, force: true })
.then((res) => {
if (res === undefined) {
vfs.src([`${components}/**/*.md`]).pipe(vfs.dest(docs))
}
})
.catch((err) => {
console.log('rm docs err:', err)
})
......@@ -263,16 +263,6 @@
"show": true,
"author": "swag~jun"
},
{
"version": "1.0.0",
"name": "Notify",
"type": "component",
"cName": "消息通知",
"desc": "在页面顶部展示消息提示",
"sort": 8,
"show": false,
"author": "vickyYE"
},
{
"version": "1.0.0",
"name": "CircleProgress",
......@@ -292,16 +282,6 @@
"show": true,
"desc": "弹出层容器,用于展示弹窗、信息提示等内容,支持多个弹出层叠加展示",
"author": "szg2008"
},
{
"version": "1.0.0",
"name": "NoticeBar",
"type": "component",
"cName": "通告栏",
"desc": "用于循环播放展示一组消息通知。",
"sort": 11,
"show": true,
"author": "vickyYe"
}
]
},
......
import React from 'react'
import { NoticeBar } from './noticebar'
import Icon from '../icon'
const NoticeBarDemo = () => {
const horseLamp1 = ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
horseLamp2 = ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
horseLamp3 = ['惊喜红包免费领1', '爆款准点秒2', '买超值优惠3', '赢百万京豆4'],
horseLamp4 = ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
text =
'华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!'
const demoStyles: React.CSSProperties = {
padding: '0 10px',
background: 'rgba(251, 248, 220, 1)',
color: '#d9500b',
}
const hello = () => {
console.log('hello world')
}
const go = (item: any) => {
console.log(item)
}
return (
<>
<div className="demo" style={{ paddingBottom: '30px' }}>
<h2>基础用法</h2>
<NoticeBar text={text} background={`rgba(251, 248, 220, 1)`} color={`#D9500B`}></NoticeBar>
<h2>禁用滚动</h2>
<NoticeBar
text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
scrollable={false}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
></NoticeBar>
<h2>通告栏模式--关闭模式</h2>
<NoticeBar
closeMode={true}
click={hello}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
>
华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI
WATCH等好礼,更多产品信息请持续关注!
</NoticeBar>
<h2>通告栏模式--链接模式</h2>
<NoticeBar
leftIcon={
'https://img13.360buyimg.com/imagetools/jfs/t1/72082/2/3006/1197/5d130c8dE1c71bcd6/e48a3b60804c9775.png'
}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
>
<a href="https://www.jd.com">京东商城</a>
</NoticeBar>
<h2>纵向滚动</h2>
<div style={demoStyles}>
<NoticeBar
direction="vertical"
list={horseLamp1}
speed={10}
standTime={1000}
click={(item: any) => {
go(item)
}}
closeMode={true}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
></NoticeBar>
</div>
<h2>纵向复杂滚动动画</h2>
<div style={demoStyles}>
<NoticeBar
direction="vertical"
list={horseLamp2}
speed={10}
standTime={2000}
complexAm={true}
></NoticeBar>
</div>
<h2>纵向自定义滚动内容</h2>
<div style={demoStyles}>
<NoticeBar direction="vertical" height={50} speed={10} standTime={1000}>
{horseLamp3.map((item, index) => {
return (
<div
className="custom-item"
style={{ height: '50px', lineHeight: '50px' }}
key={index}
>
{item}
</div>
)
})}
</NoticeBar>
</div>
<h2>纵向自定义右侧图标</h2>
<div style={demoStyles}>
<NoticeBar
className={'custom'}
direction="vertical"
list={horseLamp4}
speed={10}
standTime={1000}
rightIcon={<Icon name={'fabulous'} size="16" color="#f0250f" />}
></NoticeBar>
</div>
</div>
</>
)
}
export default NoticeBarDemo
# NoticeBar通告栏
### 介绍
用于循环播放展示一组消息通知。
### 安装
```javascript
import { NoticeBar } from '@nutui/nutui-react';
```
## 代码演示
### 基本用法
```tsx
<NoticeBar text={text} background={`rgba(251, 248, 220, 1)`} color={`#D9500B`}></NoticeBar>
```
```javascript
const text = '华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!'
```
### 禁用滚动
文字内容多于一行时,可通过scrollable参数控制是否开启滚动
```tsx
<NoticeBar
text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
scrollable={false}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
></NoticeBar>
```
### 通告栏模式--关闭模式
```tsx
<NoticeBar
closeMode={true}
click={hello}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
>
华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI
WATCH等好礼,更多产品信息请持续关注!
</NoticeBar>
```
```javascript
const hello = () => {
console.log('hello world')
}
```
### 通告栏模式--链接模式
```tsx
<NoticeBar
leftIcon={
'https://img13.360buyimg.com/imagetools/jfs/t1/72082/2/3006/1197/5d130c8dE1c71bcd6/e48a3b60804c9775.png'
}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
>
<a href="https://www.jd.com">京东商城</a>
</NoticeBar>
```
### 纵向滚动
```tsx
<NoticeBar
direction="vertical"
list={horseLamp1}
speed={10}
standTime={1000}
click={(item) => {
go(item)
}}
closeMode={true}
background={`rgba(251, 248, 220, 1)`}
color={`#D9500B`}
></NoticeBar>
```
```javascript
const horseLamp1 = ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
const go = (item: any) => {
console.log(item)
}
```
### 复杂滚动动画
```tsx
<NoticeBar
direction="vertical"
list={horseLamp2}
speed={10}
standTime={2000}
complexAm={true}
></NoticeBar>
```
```javascript
const horseLamp2 = ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
}
```
### 自定义滚动内容
```tsx
<NoticeBar direction="vertical" height={50} speed={10} standTime={1000}>
{horseLamp3.map((item, index) => {
return (
<div
className="custom-item"
style={{ height: '50px', lineHeight: '50px' }}
key={index}
>
{item}
</div>
)
})}
</NoticeBar>
```
```javascript
const horseLamp3 = ['惊喜红包免费领1', '爆款准点秒2', '买超值优惠3', '赢百万京豆4']
}
```
### 纵向自定义右侧图标
```tsx
<NoticeBar
className={'custom'}
direction="vertical"
list={horseLamp4}
speed={10}
standTime={1000}
rightIcon={<Icon name={'fabulous'} size="16" color="#f0250f" />}
></NoticeBar>
```
```javascript
const horseLamp4 = ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆']
```
## API
### Prop
| 字段 | 说明 | 类型 | 默认值 |
| ---------- | ---------------------------------------------------------- | ------------- | ------ |
| direction | 滚动的方向,可选 across、vertical | String | across |
| text | 提示的信息 | String | 空 |
| closeMode | 是否启用关闭模式 | Boolean | false |
| leftIcon | close为没有左边icon,其他为自定义的图片链接,没有为默认图片 | String | 空 |
| color | 导航栏的文字颜色 | String | 空 |
| background | 导航栏的背景颜色 | String | 空 |
| delay | 延时多少秒 | String/Number | 1 |
| scrollable | 是否可以滚动 | Boolean | true |
| speed | 滚动速率 (px/s) | Number | 50 |
### Prop(direction=vertical)
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| list | 纵向滚动数据列表 | Array | [] |
| speed | 滚动的速度 | Number | 50 |
| standTime | 停留时间(毫秒) | Number | 1000 |
| complexAm | 稍复杂的动画,耗能会高 | Boolean | false |
| height | 每一个滚动列的高度(px),注意:在使用 slot 插槽定义滚动单元时,按照实际高度修改此值 | Number | 40 |
| closeMode | 是否启用右侧关闭图标,可以通过slot[name=rightIcon]自定义图标 | Boolean | false |
### Event
| 字段 | 说明 | 回调参数 |
| ----- | ---------------- | ------------ |
| click | 外层点击事件回调 | event: Event |
| close | 关闭通知栏时触发 | event: Event |
import { NoticeBar } from './noticebar'
export default NoticeBar
.nut-noticebar {
.nut-noticebar-page {
width: 100%;
display: flex;
height: $noticeBar-height;
font-size: $noticeBar-font-size;
position: relative;
align-items: center;
&.wrapable {
height: auto;
padding: 8px 16px;
.wrap {
height: auto;
.content {
position: relative;
white-space: normal;
word-wrap: break-word;
}
}
}
.withicon {
position: relative;
padding-right: 40px;
}
.left-icon {
height: $noticeBar-left-icon-width;
min-width: $noticeBar-left-icon-width;
margin: 0 5px 0 10px;
background-size: 100% 100%;
}
.right-icon {
display: flex;
align-items: center;
justify-content: center;
width: $noticeBar-right-icon-width;
margin: 0 10px 0 5px;
}
.wrap {
flex: 1;
height: $noticeBar-line-height;
line-height: $noticeBar-line-height;
overflow: hidden;
position: relative;
}
.content {
position: absolute;
white-space: nowrap;
&.nut-ellipsis {
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
// 只跑一次
.play {
animation: nut-notice-bar-play linear both running;
}
.play-infinite {
animation: nut-notice-bar-play-infinite linear infinite both running;
}
.play-vertical {
animation: nut-notice-bar-play-vertical linear infinite both running;
}
}
@keyframes nut-notice-bar-play {
to {
transform: translate3d(-100%, 0, 0);
}
}
@keyframes nut-notice-bar-play-infinite {
to {
transform: translate3d(-100%, 0, 0);
}
}
// 垂直方向的滚动
@keyframes nut-notice-bar-play-vertical {
to {
transform: translateY($noticeBar-height);
}
}
// 纵向
.nut-noticebar-vertical {
position: relative;
display: flex;
justify-content: space-between;
height: $noticeBar-height;
font-size: $noticeBar-font-size;
overflow: hidden;
.horseLamp_list {
margin: 0;
padding: 0;
display: block;
flex: 1;
.horseLamp_list_item {
display: flex;
align-items: center;
height: $noticeBar-height;
}
}
.go {
align-self: center;
}
}
}
import React, {
useState,
useEffect,
useRef,
FunctionComponent,
useImperativeHandle,
MouseEvent,
CSSProperties,
} from 'react'
import './noticebar.scss'
import { number } from 'prop-types'
import Icon from '../icon'
import bem from '@/utils/bem'
import classNames from 'classnames'
export interface NoticeBarProps {
// 滚动方向 across 横向 vertical 纵向
direction: string
className?: string
style?: CSSProperties
list: any
standTime: number
complexAm: boolean
height: number
text: string
closeMode: boolean
wrapable: boolean
leftIcon: string
color: string
background: string
delay: string | number
scrollable: boolean
speed: number
rightIcon?: HTMLElement | any
close?: (list?: any) => void
click?: (item?: any) => void
}
const defaultProps = {
// 滚动方向 across 横向 vertical 纵向
direction: 'across',
list: [],
standTime: 1000,
complexAm: false,
height: 40,
text: '',
closeMode: false,
wrapable: false,
leftIcon: '',
color: '',
background: '',
delay: 1,
scrollable: true,
speed: 50,
} as NoticeBarProps
export const NoticeBar: FunctionComponent<
Partial<NoticeBarProps> & React.HTMLAttributes<HTMLDivElement>
> = (props) => {
const {
children,
className,
style,
direction,
list,
standTime,
complexAm,
height,
text,
closeMode,
wrapable,
leftIcon,
color,
background,
delay,
scrollable,
speed,
rightIcon,
close,
click,
} = { ...defaultProps, ...props }
const wrap = useRef<HTMLDivElement>(null)
const content = useRef<HTMLDivElement>(null)
// const [scrollList,SetScrollList] = useState([])
const [showNoticeBar, SetShowNoticeBar] = useState(true)
let scrollList: any = useRef([])
const [wrapWidth, SetWrapWidth] = useState(0)
const [firstRound, SetFirstRound] = useState(true)
const [duration, SetDuration] = useState(0)
const [offsetWidth, SetOffsetW] = useState(0)
const [animationClass, SetAnimationClass] = useState('')
const [animate, SetAnimate] = useState(false)
const [distance, SetDistance] = useState(0)
const [timer, SetTimer] = useState(0)
const [index, setIndex] = useState<number>(0)
useEffect(() => {
if (direction == 'vertical') {
if (children) {
let arr: any = []
React.Children.map(children, (child) => {
arr.push((child as any).props.children)
})
// SetScrollList([].concat(arr))
scrollList.current = [].concat(arr)
} else {
// SetScrollList([].concat(list))
scrollList.current = [].concat(list)
}
setTimeout(() => {
complexAm ? startRoll() : startRollEasy()
}, Number(standTime))
} else {
initScrollWrap(text)
}
return () => {
clearInterval(timer)
}
}, [])
const cloneChild = (listItem: any, listIndex: any) => {
return React.Children.map(children, function (child: any, index) {
if (child && index == listIndex) {
return React.cloneElement(child, {
key: listIndex,
children: listItem,
})
}
})
}
useEffect(() => {
initScrollWrap(text)
}, [text])
useEffect(() => {
if (list && list.length) {
scrollList.current = [].concat(list)
}
}, [list])
const initScrollWrap = (value: string) => {
if (showNoticeBar == false) {
return
}
setTimeout(() => {
if (!wrap.current || !content.current) {
return
}
const wrapW = wrap.current.getBoundingClientRect().width
const offsetW = content.current.getBoundingClientRect().width
if (scrollable && offsetW > wrapW) {
SetWrapWidth(wrapW)
SetOffsetW(offsetW)
SetDuration(offsetW / speed)
SetAnimationClass('play')
} else {
SetAnimationClass('')
}
})
}
const handleClick = (event: MouseEvent) => {
click && click(event)
}
const onClickIcon = (event: MouseEvent) => {
event.stopPropagation()
SetShowNoticeBar(!closeMode)
close && close(event)
}
const onAnimationEnd = () => {
SetFirstRound(false)
setTimeout(() => {
SetDuration((offsetWidth + wrapWidth) / speed)
SetAnimationClass('play-infinite')
}, 0)
}
/**
* 利益点滚动方式一
*/
const startRollEasy = () => {
showhorseLamp()
let timerCurr = window.setInterval(
showhorseLamp,
~~(height / speed / 4) * 1000 + Number(standTime)
)
SetTimer(timerCurr)
}
const showhorseLamp = () => {
SetAnimate(true)
setTimeout(() => {
scrollList.current.push(scrollList.current[0])
scrollList.current.shift()
SetAnimate(false)
}, ~~(height / speed / 4) * 1000)
}
const startRoll = () => {
let timerCurr = setInterval(() => {
let chunk = 100
for (let i = 0; i < chunk; i++) {
scroll(i, i < chunk - 1 ? false : true)
}
}, Number(standTime) + 100 * speed)
SetTimer(timerCurr)
}
const scroll = (n: number, last: boolean) => {
SetAnimate(true)
setTimeout(() => {
let long = distance
long -= height / 100
SetDistance(long)
if (last) {
scrollList.current.push(scrollList.current[0])
scrollList.current.shift()
SetDistance(0)
SetAnimate(false)
}
}, n * speed)
}
/**
* 点击滚动单元
*/
const go = (item: any) => {
click && click(item)
}
const handleClickIcon = () => {
close && close(scrollList[0])
}
const iconShow = () => {
if (leftIcon == 'close') {
return false
} else {
return true
}
}
const contentStyle = {
paddingLeft: firstRound ? 0 : wrapWidth + 'px',
animationDelay: (firstRound ? props.delay : 0) + 's',
animationDuration: duration + 's',
}
const barStyle = {
color: color,
background: background,
height: direction == 'vertical' ? `${height}px` : '',
}
const horseLampStyle = {
transform: complexAm ? `translateY(${distance}px)` : '',
transition: animate ? `all ${~~(height / speed / 4)}s` : '',
marginTop: animate ? `-${height}px` : '',
}
const b = bem('noticebar')
const noticebarClass = classNames({
'nut-noticebar-page': true,
withicon: closeMode,
close: closeMode,
wrapable: wrapable,
})
return (
<div className={`${b()} ${className ? className : ''}`} style={style}>
{showNoticeBar && direction == 'across' ? (
<div className={noticebarClass} style={barStyle} onClick={handleClick}>
<div
className="left-icon"
style={{ backgroundImage: `url(${leftIcon ? leftIcon : ''})` }}
>
{!leftIcon ? <Icon name={'notice'} size="16" color={color} /> : null}
</div>
<div ref={wrap} className="wrap">
<div
ref={content}
className={`content ${animationClass} ${!scrollable && !wrapable && 'nut-ellipsis'}`}
style={contentStyle}
onAnimationEnd={onAnimationEnd}
>
{children}
{text}
</div>
</div>
{closeMode ? (
<div className="right-icon" onClick={onClickIcon}>
<Icon name={'close'} color={color} />
</div>
) : null}
</div>
) : scrollList.current.length > 0 && direction == 'vertical' ? (
<div className="nut-noticebar-vertical" style={barStyle}>
{children ? (
<div className="horseLamp_list" style={horseLampStyle}>
 
{scrollList.current.map((item: any, index: any) => {
return cloneChild(item, index)
})}
</div>
) : (
<ul className="horseLamp_list" style={horseLampStyle}>
{scrollList.current.map((item: any, index: any) => {
return (
<li
className="horseLamp_list_item"
style={{ height: height }}
key={index}
onClick={() => {
go(item)
}}
>
{item}
</li>
)
})}
</ul>
)}
<div
className="go"
onClick={() => {
handleClickIcon()
}}
>
{rightIcon ? (
rightIcon
) : closeMode ? (
<Icon name="cross" color={color} size="11px" />
) : null}
</div>
</div>
) : null}
</div>
)
}
NoticeBar.defaultProps = defaultProps
NoticeBar.displayName = 'NutNoticeBar'
import React from 'react'
import { Notify } from './notify'
const NotifyDemo = () => {
return (
<>
<div className="demo">
<h2>基础用法</h2>
<Notify></Notify>
</div>
</>
)
}
export default NotifyDemo
# Notify组件
### 介绍
基于 xxxxxxx
### 安装
## 代码演示
### 基础用法1
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| name | 图标名称或图片链接 | String | - |
| color | 图标颜色 | String | - |
| size | 图标大小,如 '20px' '2em' '2rem' | String | - |
| class-prefix | 类名前缀,用于使用自定义图标 | String | 'nutui-iconfont' |
| tag | HTML 标签 | String | 'i' |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| click | 点击图标时触发 | event: Event |
import { Notify } from './notify'
export default Notify
import React, { FunctionComponent, useEffect, useState } from 'react'
import './notify.scss'
export interface NotifyProps {
id: string
color: string
msg: string
duration: number
className: string
background: string
type: string
visible: boolean
onClick: () => void
onClose: () => void
unmount: () => void
}
const defaultProps = {
color: '',
msg: '',
duration: 3000,
className: '',
background: '',
type: 'danger',
visible: false,
} as NotifyProps
export const Notify: FunctionComponent<
Partial<NotifyProps> & React.HTMLAttributes<HTMLDivElement>
> = (props) => {
const { children, id, color, msg, duration, className, background, type, visible } = {
...defaultProps,
...props,
}
let timer: null | number = null
useEffect(() => {}, [])
return <div className="nut-notify">{children ? children : msg}</div>
}
Notify.defaultProps = defaultProps
Notify.displayName = 'NutNotify'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册