From 3405ccc583039afe32c04c15227ca6beeb266b36 Mon Sep 17 00:00:00 2001 From: yewenwen <357595032@qq.com> Date: Thu, 11 Aug 2022 18:23:20 +0800 Subject: [PATCH 01/14] =?UTF-8?q?feat:=20toast=E7=BB=84=E4=BB=B6props?= =?UTF-8?q?=E8=A1=A5=E9=BD=90+=E5=9B=BD=E9=99=85=E5=8C=96=EF=BC=8Cinput?= =?UTF-8?q?=E7=BB=84=E4=BB=B6issue=E9=97=AE=E9=A2=98=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 2 + src/packages/input/demo.tsx | 9 +- src/packages/input/input.tsx | 2 +- src/packages/toast/Notification.tsx | 22 +++- src/packages/toast/demo.tsx | 154 ++++++++++++++++------ src/packages/toast/doc.en-US.md | 192 ++++++++++++++++++---------- src/packages/toast/doc.md | 129 +++++++++++++------ src/packages/toast/doc.zh-TW.md | 128 +++++++++++++------ src/packages/toast/toast.scss | 29 +++-- src/packages/toast/toast.tsx | 18 ++- src/styles/variables.scss | 11 +- 11 files changed, 482 insertions(+), 214 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 3f2a63380f..6f0b4d5067 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -87,5 +87,7 @@ module.exports = { 'jsx-a11y/no-autofocus': 0, 'react/no-children-prop': 0, 'jsx-a11y/aria-proptypes': 0, + 'react/sort-comp': 0, + 'react/require-default-props': 0, }, } diff --git a/src/packages/input/demo.tsx b/src/packages/input/demo.tsx index 31082dfa23..c07a42b668 100644 --- a/src/packages/input/demo.tsx +++ b/src/packages/input/demo.tsx @@ -59,6 +59,7 @@ const InputDemo = () => { noBorder: '无边框', click: '点击', placeholder1: '在输入时执行格式化', + text1: '校验文本中无数字', placeholder2: '在失焦时执行格式化', placeholder3: '请输入留言', placeholder4: '文本内容对齐', @@ -95,6 +96,7 @@ const InputDemo = () => { noBorder: 'No Border', click: 'Click', placeholder1: 'Format On Change', + text1: 'Check no digits', placeholder2: 'Format On Blur', placeholder3: 'Message', placeholder4: 'Label Align', @@ -252,7 +254,12 @@ const InputDemo = () => { } /> -

{translated.title6}

+

+ {translated.title6} + + ({translated.text1}) + +

{ let val = value - if (type === 'digit') { + if (type === 'digit' || type === 'tel') { val = formatNumber(val, false, false) } if (type === 'number') { diff --git a/src/packages/toast/Notification.tsx b/src/packages/toast/Notification.tsx index 0ed823b3e1..7b46727b67 100644 --- a/src/packages/toast/Notification.tsx +++ b/src/packages/toast/Notification.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react/no-unused-prop-types */ import * as React from 'react' import * as ReactDOM from 'react-dom' import classNames from 'classnames' @@ -7,12 +8,14 @@ import Icon from '@/packages/icon' export interface NotificationProps { id?: string style?: React.CSSProperties - icon?: string + icon: string | null + iconSize: string msg: string | React.ReactNode - bottom?: boolean - duration?: number + bottom: string + duration: number center: boolean type: string + title: string customClass: string size: string | number textAlignCenter: boolean @@ -39,6 +42,7 @@ export default class Notification extends React.PureComponent this.clickCover = this.clickCover.bind(this) } + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, react/sort-comp close() { this.clearCloseTimer() this.props.onClose() @@ -77,8 +81,11 @@ export default class Notification extends React.PureComponent render() { const { + id, style, icon, + iconSize, + title, msg, bottom, center, @@ -97,16 +104,18 @@ export default class Notification extends React.PureComponent 'nut-toast-has-icon': icon, 'nut-toast-cover': cover, 'nut-toast-loading': type === 'loading', - customClass, + [`${customClass}`]: true, [`nut-toast-${size}`]: true, }) return ( <>
{ this.clickCover() @@ -121,9 +130,10 @@ export default class Notification extends React.PureComponent > {icon ? (

- +

) : null} + {title ?
{title}
: null} {msg}
diff --git a/src/packages/toast/demo.tsx b/src/packages/toast/demo.tsx index 3d6ee426b8..1e93f0a0e0 100644 --- a/src/packages/toast/demo.tsx +++ b/src/packages/toast/demo.tsx @@ -1,11 +1,67 @@ import React from 'react' import Toast from './index' -import { Cell } from '../cell/cell' +import Cell from '@/packages/cell' +import Button from '@/packages/button' +import { useTranslate } from '../../sites/assets/locale' + +interface T { + basic: string + toastText: string + toastTitle: string + toastSuccess: string + toastError: string + toastLoading: string + toastWarning: string + toastAll: string + toastBottom: string + toastTransparent: string + toastDuration: string + toastDurationText: string + toastHide: string + toastCustomIcon: string +} const ToastDemo = () => { + const [translated] = useTranslate({ + 'zh-CN': { + basic: '基本用法', + toastText: '文字提示', + toastTitle: '标题展示', + toastSuccess: '成功提示', + toastError: '错误提示', + toastWarning: '警告提示', + toastLoading: '加载提示', + toastAll: 'Toast 不消失', + toastBottom: '自定义底部高度', + toastTransparent: '加载状态透明遮罩', + toastDuration: '设置展示时长', + toastDurationText: '展示时长为10秒', + toastHide: '隐藏Toast', + toastCustomIcon: '自定义Icon', + }, + 'en-US': { + basic: 'Basic Usage', + toastText: 'Text Message', + toastTitle: 'Title', + toastSuccess: 'Success', + toastError: 'Error', + toastWarning: 'Warning', + toastLoading: 'Loading', + toastAll: 'Not Disappear', + toastBottom: 'Custom Bottom Height', + toastTransparent: 'Loading Transparent Cover', + toastDuration: 'Set Display Duration', + toastDurationText: 'Show for 10 seconds', + toastHide: 'Hide Toast', + toastCustomIcon: 'Custom Icon', + }, + }) const textToast = (msg: string) => { Toast.text(msg) } + const titleToast = (msg: string) => { + Toast.text(msg, { title: `${translated.toastTitle}` }) + } const successToast = (msg: string) => { Toast.success(msg) } @@ -21,20 +77,16 @@ const ToastDemo = () => { const duringToast = (msg: string) => { Toast.text(msg, { duration: 10 }) } + const toastBottom = (msg: string) => { + Toast.text(msg, { + center: false, + bottom: '10%', + }) + } const iconToast = (msg: string) => { - Toast.customIcon(msg, { - duration: 0, // duration为0则一直展示 - icon: 'JD', - id: '', - center: true, // toast是否居中展示 - type: 'text', - customClass: '', // 自定义样式名 - bottom: 30, // toast不居中时距离底部位置 - size: 'base', // 设置字体大小,默认base,可选large\small\base - textAlignCenter: true, // 文字是否居中显示,true为居中,false为left - bgColor: 'rgba(0, 0, 0, .8)', + Toast.loading(msg, { cover: true, // 是否展示透明遮罩层 - coverColor: 'rgba(0, 0, 0, 0.4)', // 遮罩颜色设定 + coverColor: '', // 遮罩颜色设定 closeOnClickOverlay: true, // 点击遮罩可关闭 onClose: () => { console.log('closeToast') @@ -44,74 +96,92 @@ const ToastDemo = () => { return ( <> -
-

基础用法

+
+

{translated.basic}

- ) => textToast('网络失败,请稍后再试~')} + ) => textToast(`${translated.toastText}`)} /> - -

成功提示

- ) => successToast('成功提示')} + ) => titleToast(`${translated.toastTitle}`)} /> - -

失败提示

- ) => errorToast('失败提示')} + ) => successToast(`${translated.toastSuccess}`)} /> - -

警告提示

- ) => warningToast('警告提示')} + ) => errorToast(`${translated.toastError}`)} /> - -

加载提示

- ) => loadingToast('加载中')} + ) => warningToast(`${translated.toastWarning}`)} + /> + + ) => loadingToast(`${translated.toastLoading}`)} + /> +

{translated.toastDuration}

+ + ) => duringToast(`${translated.toastDurationText}`)} /> - -

展示时长设置

- ) => duringToast('设置展示时长为10秒')} + ) => { + Toast.text(translated.toastAll, { duration: 0 }) + }} /> + +

{translated.toastBottom}

- ) => Toast.hide()} + ) => toastBottom(`${translated.toastBottom}`)} /> -

自定义icon图标

+

{translated.toastTransparent}

- ) => iconToast('设置icon为JD')} + ) => iconToast(`${translated.toastTransparent}`)} />
diff --git a/src/packages/toast/doc.en-US.md b/src/packages/toast/doc.en-US.md index 6eb06bc099..6821c31101 100644 --- a/src/packages/toast/doc.en-US.md +++ b/src/packages/toast/doc.en-US.md @@ -1,20 +1,20 @@ -# Toast 吐司 +# Toast -### 介绍 +### Intro -用于轻提示。 +For light tips. -### 安装 +### Install ```javascript import { Toast } from '@nutui/nutui-react'; ``` -## 代码演示 +## Demo -### 基础用法 +### Usage -文字提示 +#### Text :::demo @@ -29,11 +29,11 @@ const App = () => { return ( <> - ) => textToast('网络失败,请稍后再试~')} + ) => textToast('text message~')} /> ) @@ -42,7 +42,35 @@ export default App ``` ::: -成功提示 +#### Title + +:::demo + +```tsx +import React, {useState} from "react"; +import { Toast, Cell } from '@nutui/nutui-react'; + +const App = () => { + const titleToast = (msg: string) => { + Toast.text(msg,{title: 'title'}) + } + return ( + <> + + ) => titleToast('title message~')} + /> + + ) +} +export default App +``` +::: + +#### Success :::demo @@ -57,11 +85,11 @@ const App = () => { return ( <> - ) => successToast('成功提示')} + ) => successToast('Success')} /> ) @@ -71,7 +99,7 @@ export default App ::: -失败提示 +#### Fail :::demo @@ -86,11 +114,11 @@ const App = () => { return ( <> - ) => errorToast('失败提示')} + ) => errorToast('Fail')} /> ) @@ -100,7 +128,7 @@ export default App ::: -警告提示 +#### Warn :::demo @@ -115,11 +143,11 @@ const App = () => { return ( <> - ) => warningToast('警告提示')} + ) => warningToast('Warn')} /> ) @@ -129,7 +157,7 @@ export default App ::: -加载提示 +#### Loading :::demo @@ -144,11 +172,11 @@ const App = () => { return ( <> - ) => loadingToast('加载中')} + ) => loadingToast('Loading')} /> ) @@ -158,13 +186,13 @@ export default App ::: -展示时长设置 +#### Set Display Duration :::demo ```tsx import React, {useState} from "react"; -import { Toast, Cell } from '@nutui/nutui-react'; +import { Toast, Cell, Button } from '@nutui/nutui-react'; const App = () => { const duringToast = (msg: string) => { @@ -173,19 +201,27 @@ const App = () => { return ( <> - ) => duringToast('设置展示时长为10秒')} + ) => duringToast('Show for 10 seconds')} /> - ) => Toast.hide()} + ) => {Toast.text('Toast Not Disappear', { duration: 0 })}} /> + ) } @@ -193,8 +229,38 @@ export default App ``` ::: +#### Custom Bottom Height + +:::demo + +```tsx +import React, {useState} from "react"; +import { Toast, Cell } from '@nutui/nutui-react'; + +const App = () => { + const toastBottom = (msg: string) => { + Toast.text(msg, { + center: false, + bottom: '10%', + }) + } + return ( + + ) => toastBottom('Custom Bottom Height')} + /> + ) +} +export default App +``` +::: + + -自定义 icon 图标 +#### Loading with transparent cover :::demo @@ -204,20 +270,10 @@ import { Toast, Cell } from '@nutui/nutui-react'; const App = () => { const iconToast = (msg: string) => { - Toast.customIcon(msg, { - duration: 0, // duration为0则一直展示 - icon: 'JD', - id: '', - center: true, // toast是否居中展示 - type: 'text', - customClass: '', // 自定义样式名 - bottom: 30, // toast不居中时距离底部位置 - size: 'base', // 设置字体大小,默认base,可选large\small\base - textAlignCenter: true, // 文字是否居中显示,true为居中,false为left - bgColor: 'rgba(0, 0, 0, .8)', - cover: true, // 是否展示透明遮罩层 - coverColor: 'rgba(0, 0, 0, 0.4)', // 遮罩颜色设定 - closeOnClickOverlay: true, // 点击遮罩可关闭 + Toast.loading(msg, { + cover: true, + coverColor: 'rgba(0, 0, 0, 0)', + closeOnClickOverlay: true, onClose: () => { console.log('closeToast') }, @@ -226,11 +282,11 @@ const App = () => { return ( <> - ) => iconToast('设置icon为JD')} + ) => iconToast('Loading')} /> ) @@ -243,31 +299,33 @@ export default App ## API -| 方法名 | 说明 | 参数 | 返回值 | -| ---------- | ------------------------ | --------------- | ---------- | -| Toast.text | 展示文字提示 | message| options | toast 实例(message支持传入HTML) | -| Toast.success | 展示成功提示 | message| options| toast 实例 | -| Toast.fail | 展示失败提示 | message| options| toast 实例 | -| Toast.warn | 展示警告提示 | message| options | toast 实例 | -| Toast.hide | 关闭提示 | force:boolean | void | -| Toast.loading | 展示加载提示 | message| options | toast 实例 | +| Methods | Description | Attribute | Return value | +| ---------------- | ------------------------------------------- | --------------- | ---------- | +| Toast.text | Show text toast | message| options | toast instance(message support incoming HTML) | +| Toast.success | Show success toast | message| options| toast instance | +| Toast.fail | Show fail toast | message| options| toast instance| +| Toast.warn | Show warn toast | message| options | toast instance | +| Toast.hide | Close toast | clearAll: boolean | void | +| Toast.loading | Show loading toast | message| options | toast instance | ### Props -| 字段 | 说明 | 类型 | 默认值 | +| Attribute | Description | Type | Default | | ------------------- | -------------- | ------------- | ----------------------------- | -| id | 标识符,相同者共用一个实例
loading类型默认使用一个实例,其他类型默认不共用 | String/Number | - | -| duration | 展示时长(毫秒)
值为 0 时,toast 不会自动消失 | Number | 2000 | -| center | 是否展示在页面中部(为false时展示在底部) | Boolean | true | -| bottom | 距页面底部的距离(像素),option.center为false时生效 | Number | 30 | -| textAlignCenter | 多行文案是否居中 | Boolean | true | -| bgColor | 背景颜色(透明度) | String | "rgba(0, 0, 0, 0.8)" | -| customClass | 自定义类名 | String | "" | -| icon | 自定义图标,**支持图片链接或base64格式** | String | "" | -| size | 文案尺寸,**small**/**base**/**large**三选一 | String | "base" | -| cover | 是否显示遮罩层 | Boolean | false | -| coverColor | 遮罩层颜色,默认透明 | String | "rgba(0,0,0,0)" | -| loadingRotate | loading图标是否旋转,仅对loading类型生效 | Boolean | true | -| onClose | 关闭时触发的事件 | function | null | -| closeOnClickOverlay | 是否在点击遮罩层后关闭提示 | Boolean | false | +| id | Identifier, share one instance at the same time, default to multiple instances| String/Number | - | +| duration | Toast duration(ms), won't disappear if value is 0 | Number | 2000 | +| title `new` | title | String | - | +| center | Whether to display in the middle of the page (display at the bottom when false) | Boolean| true | +| bottom | The distance from the bottom of the page (px or %), which takes effect when option.center is false | String| 30px | +| textAlignCenter | Whether the multi-line copy is centered | Boolean | true | +| bgColor | background color (transparency) | String | rgba(0, 0, 0, 0.8) | +| customClass | Custom Class | String | - | +| icon | Custom Icon | String | - | +| iconSize `new` | Custom iconSize | String | 20 | +| size | Text Size **small**/**base**/**large** | String | base | +| cover | Whether to show the mask layer | Boolean | false | +| coverColor | Cover Color | String | rgba(0,0,0,0) | +| loadingRotate | Whether the loading icon is rotated, only valid for the loading type | Boolean | true | +| onClose |Callback function after close | function | null | +| closeOnClickOverlay | Whether to close when overlay is clicked | Boolean | false | diff --git a/src/packages/toast/doc.md b/src/packages/toast/doc.md index 28d51b57b9..cb6d8cb3ff 100644 --- a/src/packages/toast/doc.md +++ b/src/packages/toast/doc.md @@ -14,7 +14,7 @@ import { Toast } from '@nutui/nutui-react'; ### 基础用法 -文字提示 +#### 文字提示 :::demo @@ -42,7 +42,34 @@ export default App ``` ::: -成功提示 +#### 标题提示 + +:::demo + +```tsx +import React, {useState} from "react"; +import { Toast, Cell } from '@nutui/nutui-react'; + +const App = () => { + const titleToast = (msg: string) => { + Toast.text(msg,{title:'标题提示'}) + } + return ( + <> + + ) => titleToast('Toast 标题提示')} + /> + + ) +} +export default App +``` +::: +#### 成功提示 :::demo @@ -71,7 +98,7 @@ export default App ::: -失败提示 +#### 失败提示 :::demo @@ -100,7 +127,7 @@ export default App ::: -警告提示 +#### 警告提示 :::demo @@ -129,7 +156,7 @@ export default App ::: -加载提示 +#### 加载提示 :::demo @@ -159,14 +186,13 @@ export default App - -展示时长设置 +#### 展示时长设置 :::demo ```tsx import React, {useState} from "react"; -import { Toast, Cell } from '@nutui/nutui-react'; +import { Toast, Cell, Button } from '@nutui/nutui-react'; const App = () => { const duringToast = (msg: string) => { @@ -182,12 +208,20 @@ const App = () => { ) => duringToast('设置展示时长为10秒')} /> - ) => Toast.hide()} + ) => {Toast.text('Toast 不消失', { duration: 0 })}} /> + ) } @@ -195,8 +229,37 @@ export default App ``` ::: +#### Toast自定义底部高度 + +:::demo + +```tsx +import React, {useState} from "react"; +import { Toast, Cell } from '@nutui/nutui-react'; + +const App = () => { + const toastBottom = (msg: string) => { + Toast.text(msg, { + center: false, + bottom: '10%', + }) + } + return ( + + ) => toastBottom('自定义距离')} + /> + ) +} +export default App +``` +::: + -自定义 icon 图标 +#### 加载Loading带透明罩 :::demo @@ -206,19 +269,9 @@ import { Toast, Cell } from '@nutui/nutui-react'; const App = () => { const iconToast = (msg: string) => { - Toast.customIcon(msg, { - duration: 0, // duration为0则一直展示 - icon: 'JD', - id: '', - center: true, // toast是否居中展示 - type: 'text', - customClass: '', // 自定义样式名 - bottom: 30, // toast不居中时距离底部位置 - size: 'base', // 设置字体大小,默认base,可选large\small\base - textAlignCenter: true, // 文字是否居中显示,true为居中,false为left - bgColor: 'rgba(0, 0, 0, .8)', + Toast.loading(msg, { cover: true, // 是否展示透明遮罩层 - coverColor: 'rgba(0, 0, 0, 0.4)', // 遮罩颜色设定 + coverColor: 'rgba(0, 0, 0, 0)', // 遮罩颜色设定 closeOnClickOverlay: true, // 点击遮罩可关闭 onClose: () => { console.log('closeToast') @@ -228,11 +281,11 @@ const App = () => { return ( <> - ) => iconToast('设置icon为JD')} + ) => iconToast('加载状态透明遮罩')} /> ) @@ -259,17 +312,19 @@ export default App | 字段 | 说明 | 类型 | 默认值 | | ------------------- | -------------- | ------------- | ----------------------------- | | id | 标识符,相同者共用一个实例
loading类型默认使用一个实例,其他类型默认不共用 | String/Number | - | -| duration | 展示时长(毫秒)
值为 0 时,toast 不会自动消失 | Number | 2000 | -| center | 是否展示在页面中部(为false时展示在底部) | Boolean | true | -| bottom | 距页面底部的距离(像素),option.center为false时生效 | Number | 30 | -| textAlignCenter | 多行文案是否居中 | Boolean | true | -| bgColor | 背景颜色(透明度) | String | "rgba(0, 0, 0, 0.8)" | -| customClass | 自定义类名 | String | "" | -| icon | 自定义图标,**支持图片链接或base64格式** | String | "" | -| size | 文案尺寸,**small**/**base**/**large**三选一 | String | "base" | +| duration | 展示时长(毫秒)
值为 0 时,toast 不会自动消失 | Number | 2000 | +| title `new` | 标题 | string | - | +| center | 是否展示在页面中部(为false时展示在底部) | Boolean | true | +| bottom | 距页面底部的距离(像素),option.center为false时生效 | Number | 30 | +| textAlignCenter | 多行文案是否居中 | Boolean | true | +| bgColor | 背景颜色(透明度) | String | "rgba(0, 0, 0, 0.8)" | +| customClass | 自定义类名 | String | "" | +| icon | 自定义图标,**支持图片链接或base64格式** | String | "" | +| iconSize `new` | 自定义图标尺寸 | String | 20 | +| size | 文案尺寸,**small**/**base**/**large**三选一 | String | "base" | | cover | 是否显示遮罩层 | Boolean | false | -| coverColor | 遮罩层颜色,默认透明 | String | "rgba(0,0,0,0)" | -| loadingRotate | loading图标是否旋转,仅对loading类型生效 | Boolean | true | -| onClose | 关闭时触发的事件 | function | null | -| closeOnClickOverlay | 是否在点击遮罩层后关闭提示 | Boolean | false | +| coverColor | 遮罩层颜色,默认透明 | String | "rgba(0,0,0,0)" | +| loadingRotate | loading图标是否旋转,仅对loading类型生效 | Boolean | true | +| onClose | 关闭时触发的事件 | function | null | +| closeOnClickOverlay | 是否在点击遮罩层后关闭提示 | Boolean | false | diff --git a/src/packages/toast/doc.zh-TW.md b/src/packages/toast/doc.zh-TW.md index 5ad2ea9bdf..cb6d8cb3ff 100644 --- a/src/packages/toast/doc.zh-TW.md +++ b/src/packages/toast/doc.zh-TW.md @@ -14,7 +14,7 @@ import { Toast } from '@nutui/nutui-react'; ### 基础用法 -文字提示 +#### 文字提示 :::demo @@ -42,9 +42,34 @@ export default App ``` ::: +#### 标题提示 +:::demo + +```tsx +import React, {useState} from "react"; +import { Toast, Cell } from '@nutui/nutui-react'; -成功提示 +const App = () => { + const titleToast = (msg: string) => { + Toast.text(msg,{title:'标题提示'}) + } + return ( + <> + + ) => titleToast('Toast 标题提示')} + /> + + ) +} +export default App +``` +::: +#### 成功提示 :::demo @@ -73,8 +98,7 @@ export default App ::: - -失败提示 +#### 失败提示 :::demo @@ -103,8 +127,7 @@ export default App ::: - -警告提示 +#### 警告提示 :::demo @@ -133,8 +156,7 @@ export default App ::: - -加载提示 +#### 加载提示 :::demo @@ -164,13 +186,13 @@ export default App -展示时长设置 +#### 展示时长设置 :::demo ```tsx import React, {useState} from "react"; -import { Toast, Cell } from '@nutui/nutui-react'; +import { Toast, Cell, Button } from '@nutui/nutui-react'; const App = () => { const duringToast = (msg: string) => { @@ -186,12 +208,20 @@ const App = () => { ) => duringToast('设置展示时长为10秒')} /> - ) => Toast.hide()} + ) => {Toast.text('Toast 不消失', { duration: 0 })}} /> + ) } @@ -199,9 +229,37 @@ export default App ``` ::: +#### Toast自定义底部高度 + +:::demo + +```tsx +import React, {useState} from "react"; +import { Toast, Cell } from '@nutui/nutui-react'; + +const App = () => { + const toastBottom = (msg: string) => { + Toast.text(msg, { + center: false, + bottom: '10%', + }) + } + return ( + + ) => toastBottom('自定义距离')} + /> + ) +} +export default App +``` +::: -自定义 icon 图标 +#### 加载Loading带透明罩 :::demo @@ -211,19 +269,9 @@ import { Toast, Cell } from '@nutui/nutui-react'; const App = () => { const iconToast = (msg: string) => { - Toast.customIcon(msg, { - duration: 0, // duration为0则一直展示 - icon: 'JD', - id: '', - center: true, // toast是否居中展示 - type: 'text', - customClass: '', // 自定义样式名 - bottom: 30, // toast不居中时距离底部位置 - size: 'base', // 设置字体大小,默认base,可选large\small\base - textAlignCenter: true, // 文字是否居中显示,true为居中,false为left - bgColor: 'rgba(0, 0, 0, .8)', + Toast.loading(msg, { cover: true, // 是否展示透明遮罩层 - coverColor: 'rgba(0, 0, 0, 0.4)', // 遮罩颜色设定 + coverColor: 'rgba(0, 0, 0, 0)', // 遮罩颜色设定 closeOnClickOverlay: true, // 点击遮罩可关闭 onClose: () => { console.log('closeToast') @@ -233,11 +281,11 @@ const App = () => { return ( <> - ) => iconToast('设置icon为JD')} + ) => iconToast('加载状态透明遮罩')} /> ) @@ -264,17 +312,19 @@ export default App | 字段 | 说明 | 类型 | 默认值 | | ------------------- | -------------- | ------------- | ----------------------------- | | id | 标识符,相同者共用一个实例
loading类型默认使用一个实例,其他类型默认不共用 | String/Number | - | -| duration | 展示时长(毫秒)
值为 0 时,toast 不会自动消失 | Number | 2000 | -| center | 是否展示在页面中部(为false时展示在底部) | Boolean | true | -| bottom | 距页面底部的距离(像素),option.center为false时生效 | Number | 30 | -| textAlignCenter | 多行文案是否居中 | Boolean | true | -| bgColor | 背景颜色(透明度) | String | "rgba(0, 0, 0, 0.8)" | -| customClass | 自定义类名 | String | "" | -| icon | 自定义图标,**支持图片链接或base64格式** | String | "" | -| size | 文案尺寸,**small**/**base**/**large**三选一 | String | "base" | +| duration | 展示时长(毫秒)
值为 0 时,toast 不会自动消失 | Number | 2000 | +| title `new` | 标题 | string | - | +| center | 是否展示在页面中部(为false时展示在底部) | Boolean | true | +| bottom | 距页面底部的距离(像素),option.center为false时生效 | Number | 30 | +| textAlignCenter | 多行文案是否居中 | Boolean | true | +| bgColor | 背景颜色(透明度) | String | "rgba(0, 0, 0, 0.8)" | +| customClass | 自定义类名 | String | "" | +| icon | 自定义图标,**支持图片链接或base64格式** | String | "" | +| iconSize `new` | 自定义图标尺寸 | String | 20 | +| size | 文案尺寸,**small**/**base**/**large**三选一 | String | "base" | | cover | 是否显示遮罩层 | Boolean | false | -| coverColor | 遮罩层颜色,默认透明 | String | "rgba(0,0,0,0)" | -| loadingRotate | loading图标是否旋转,仅对loading类型生效 | Boolean | true | -| onClose | 关闭时触发的事件 | function | null | -| closeOnClickOverlay | 是否在点击遮罩层后关闭提示 | Boolean | false | +| coverColor | 遮罩层颜色,默认透明 | String | "rgba(0,0,0,0)" | +| loadingRotate | loading图标是否旋转,仅对loading类型生效 | Boolean | true | +| onClose | 关闭时触发的事件 | function | null | +| closeOnClickOverlay | 是否在点击遮罩层后关闭提示 | Boolean | false | diff --git a/src/packages/toast/toast.scss b/src/packages/toast/toast.scss index 07862a0ef0..edd6edd5e7 100644 --- a/src/packages/toast/toast.scss +++ b/src/packages/toast/toast.scss @@ -13,21 +13,17 @@ position: fixed; left: 0; bottom: 150px; - top: 50%; - transform: translateY(-50%); width: 100%; text-align: center; pointer-events: none; z-index: 9999; &-small { - .nut-toast__inner, - .nut-toast__text { + .nut-toast__inner { font-size: $font-size-small; } } &-large { - .nut-toast__inner, - .nut-toast__text { + .nut-toast__inner { font-size: $font-size-large; } } @@ -37,21 +33,28 @@ justify-content: center; pointer-events: auto; height: 100%; + background: $toast-cover-bg-color; } &__inner { display: inline-block; - font-size: $font-size-base; + font-size: $toast-text-font-size; min-width: 40%; max-width: 65%; text-align: center; - padding: 24px 30px; + padding: $toast-inner-padding; word-break: break-all; - background: rgba(0, 0, 0, 0); - border-radius: 12px; - color: $white; + background: $toast-inner-bg-color; + border-radius: $toast-inner-border-radius; + color: $toast-font-color; + } + &-text { + font-size: $toast-text-font-size; + &:empty { + margin-bottom: -8px; + } } - &__text { - font-size: 14px; + &-title { + font-size: $toast-title-font-size; &:empty { margin-bottom: -8px; } diff --git a/src/packages/toast/toast.tsx b/src/packages/toast/toast.tsx index fa98ae5cbe..522ec827a4 100644 --- a/src/packages/toast/toast.tsx +++ b/src/packages/toast/toast.tsx @@ -3,15 +3,18 @@ import Notification, { NotificationProps } from './Notification' let messageInstance: any = null interface IToastOptions { - id: string + id?: string msg: string + style?: React.CSSProperties duration: number center: boolean type: string - customClass: string - bottom: number + title: string + customClass?: string + bottom: string size: string | number - icon: string + icon: string | null + iconSize: string textAlignCenter: boolean loadingRotate: boolean bgColor: string @@ -24,13 +27,16 @@ interface IToastOptions { const options: IToastOptions = { msg: '', id: '', + style: {}, duration: 1.5, // 时长,duration为0则一直展示 center: true, // toast是否居中展示 type: 'text', + title: '', customClass: '', // 自定义样式名 - bottom: 30, // center为false时生效,距离底部位置 + bottom: '30px', // center为false时生效,距离底部位置 size: 'base', // 设置字体大小,默认base,可选large\small\base - icon: '', // 未实现 + icon: null, // 未实现 + iconSize: '20', textAlignCenter: true, // 文字是否居中显示,true为居中,false为left loadingRotate: true, // 未实现 bgColor: 'rgba(0, 0, 0, .8)', diff --git a/src/styles/variables.scss b/src/styles/variables.scss index f1ad217f32..0a2282d006 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -194,6 +194,15 @@ $avatar-normal-height: 40px; $switch-close-bg-color: #ebebeb; $switch-close--cline-bg-color: #f0f0f0; +// toast +$toast-title-font-size: 16px !default; +$toast-text-font-size: 14px !default; +$toast-font-color: $white !default; +$toast-inner-padding: 24px 30px !default; +$toast-inner-bg-color: rgba(0, 0, 0, 0.8) !default; +$toast-inner-border-radius: 12px !default; +$toast-cover-bg-color: rgba(0, 0, 0, 0) !default; + //backtop $backtop-border-color: #e0e0e0; @@ -585,7 +594,6 @@ $row-content-height: 50px !default; $row-content-line-height: 40px !default; $col-default-margin-bottom: 15px !default; - // searchbar $searchbar-background: $white !default; $searchbar-right-out-color: $black !default; @@ -622,4 +630,3 @@ $countup-lr-margin: 1px !default; $countup-bgcolor: #031f63 !default; $countup-color: #ffffff !default; $countup-width: 24px !default; - From ba555f38f71ee105615dfb6e527cba04a0b9a953 Mon Sep 17 00:00:00 2001 From: yewenwen <357595032@qq.com> Date: Fri, 19 Aug 2022 13:05:48 +0800 Subject: [PATCH 02/14] =?UTF-8?q?feat:=20toast=20review=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=8C=E5=A2=9E=E5=8A=A0toast=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/navbar.spec.tsx.snap | 3 + .../__snapshots__/tabbar.spec.tsx.snap | 3 + src/packages/toast/Notification.tsx | 2 - src/packages/toast/__test__/toast.spec.tsx | 117 ++++++++++++++++++ 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 src/packages/navbar/__test__/__snapshots__/navbar.spec.tsx.snap create mode 100644 src/packages/tabbar/__tests__/__snapshots__/tabbar.spec.tsx.snap create mode 100644 src/packages/toast/__test__/toast.spec.tsx diff --git a/src/packages/navbar/__test__/__snapshots__/navbar.spec.tsx.snap b/src/packages/navbar/__test__/__snapshots__/navbar.spec.tsx.snap new file mode 100644 index 0000000000..6fd08a29b7 --- /dev/null +++ b/src/packages/navbar/__test__/__snapshots__/navbar.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render placeholder element when using placeholder prop 1`] = `"
订单详情
"`; diff --git a/src/packages/tabbar/__tests__/__snapshots__/tabbar.spec.tsx.snap b/src/packages/tabbar/__tests__/__snapshots__/tabbar.spec.tsx.snap new file mode 100644 index 0000000000..b2f7161be1 --- /dev/null +++ b/src/packages/tabbar/__tests__/__snapshots__/tabbar.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render fixed element when using bottom prop 1`] = `"
首页
分类
"`; diff --git a/src/packages/toast/Notification.tsx b/src/packages/toast/Notification.tsx index 7b46727b67..0f248450d8 100644 --- a/src/packages/toast/Notification.tsx +++ b/src/packages/toast/Notification.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-unused-prop-types */ import * as React from 'react' import * as ReactDOM from 'react-dom' import classNames from 'classnames' @@ -42,7 +41,6 @@ export default class Notification extends React.PureComponent this.clickCover = this.clickCover.bind(this) } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, react/sort-comp close() { this.clearCloseTimer() this.props.onClose() diff --git a/src/packages/toast/__test__/toast.spec.tsx b/src/packages/toast/__test__/toast.spec.tsx new file mode 100644 index 0000000000..d750bf0e49 --- /dev/null +++ b/src/packages/toast/__test__/toast.spec.tsx @@ -0,0 +1,117 @@ +// import * as renderer from 'react-test-renderer' +import * as React from 'react' +import '@testing-library/jest-dom' +import { render, fireEvent } from '@testing-library/react' + +import Toast from '@/packages/toast' +import Cell from '@/packages/cell' + +const onClickToast = jest.fn((type, msg, options?) => { + switch (type) { + case 'text': + Toast.text(msg, options) + break + case 'success': + Toast.success(msg, options) + break + case 'fail': + Toast.fail(msg, options) + break + case 'warn': + Toast.warn(msg, options) + break + case 'loading': + Toast.loading(msg, options) + break + default: + break + } +}) + +test('event click-show-toast test', async () => { + const { getByTestId } = render( + onClickToast('text', '文案', { id: 'custom1' })} + /> + ) + fireEvent.click(getByTestId('emit-click')) + expect(onClickToast).toBeCalled() + expect(document.body.querySelector('.nut-toast')).toBeTruthy() +}) + +test('test toast props', async () => { + const { getByTestId } = render( + + onClickToast('text', '文案', { + id: 'custom2', + duration: 5000, + title: 'title展示', + customClass: 'class1', + icon: 'JD', + size: 'small', + }) + } + /> + ) + fireEvent.click(getByTestId('emit-click')) + expect(onClickToast).toBeCalled() + expect(document.querySelector('.nut-toast__text')?.innerHTML).toBe('文案') + expect(document.querySelector('.nut-toast')).toHaveClass('nut-toast-center') + expect(document.querySelector('.nut-toast')).toHaveClass('nut-toast-small') + expect(document.querySelector('.nut-toast')).toHaveClass('nut-toast-has-icon') + // expect(document.querySelector('nut-toast__icon-wrapper')).toBeTruthy() + // expect(document.querySelector('nut-icon-JD')).toBeTruthy() + expect(document.getElementById('toast-custom2')).toBeTruthy() + setTimeout(() => { + expect(document.getElementById('toast-custom2')).not.toBeTruthy() + }, 5000) +}) + +test('event show-success-toast', async () => { + const { getByTestId } = render( + onClickToast('success', 'success')} + /> + ) + fireEvent.click(getByTestId('emit-click')) + expect(onClickToast).toBeCalled() + // expect(document.querySelector('nut-icon-success')).toBeTruthy() + expect(document.querySelector('.nut-toast__text')?.innerHTML).toBe('success') +}) + +test('event show-fail-toast', async () => { + const { getByTestId } = render( + onClickToast('fail', 'fail')} /> + ) + fireEvent.click(getByTestId('emit-click')) + expect(onClickToast).toBeCalled() + // expect(document.querySelector('nut-icon-failure')).toBeTruthy() + expect(document.querySelector('.nut-toast__text')?.innerHTML).toBe('fail') +}) + +test('event show-warn-toast', async () => { + const { getByTestId } = render( + onClickToast('warn', 'warn')} /> + ) + fireEvent.click(getByTestId('emit-click')) + expect(onClickToast).toBeCalled() + // expect(document.querySelector('nut-icon-tips')).toBeTruthy() + expect(document.querySelector('.nut-toast__text')?.innerHTML).toBe('warn') +}) + +test('event show-loading-toast', async () => { + const { getByTestId } = render( + onClickToast('loading', 'loading')} + /> + ) + fireEvent.click(getByTestId('emit-click')) + expect(onClickToast).toBeCalled() + // expect(document.querySelector('nut-icon-loading')).toBeTruthy() + expect(document.querySelector('.nut-toast__text')?.innerHTML).toBe('loading') +}) From feeb31a7f66cabc1a7d1b40a41b8c3d4686ec284 Mon Sep 17 00:00:00 2001 From: yewenwen <357595032@qq.com> Date: Wed, 24 Aug 2022 18:18:39 +0800 Subject: [PATCH 03/14] =?UTF-8?q?feat:=20textarea=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E9=AB=98=E5=BA=A6=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/textarea/demo.tsx | 2 +- src/packages/textarea/textarea.scss | 17 ++++++++- src/packages/textarea/textarea.tsx | 43 +++++++++++++++++++++- src/packages/toast/__test__/toast.spec.tsx | 14 ++++--- 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/packages/textarea/demo.tsx b/src/packages/textarea/demo.tsx index c81b068512..1fd96b5758 100644 --- a/src/packages/textarea/demo.tsx +++ b/src/packages/textarea/demo.tsx @@ -76,7 +76,7 @@ const TextAreaDemo = () => {

{translated.numbers}

+
+ 4 + / + 20 +
+
+ +`; diff --git a/src/packages/textarea/__test__/textarea.spec.tsx b/src/packages/textarea/__test__/textarea.spec.tsx new file mode 100644 index 0000000000..089dbb483f --- /dev/null +++ b/src/packages/textarea/__test__/textarea.spec.tsx @@ -0,0 +1,89 @@ +// import * as renderer from 'react-test-renderer' +import * as React from 'react' +import '@testing-library/jest-dom' +import { render, fireEvent } from '@testing-library/react' +import { useState } from 'react' +import TextArea from '@/packages/textarea' + +test('textarea props test', () => { + const { container } = render( +