From d971cff03b72b9b73fe31c8b8850419fb6d6cee4 Mon Sep 17 00:00:00 2001 From: beichen Date: Thu, 10 Nov 2022 17:03:13 +0800 Subject: [PATCH 01/12] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 74d0e38..5686802 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,15 @@ 轻量级 React 组件库 +

+ + + + + + +

+ ### 使用 #### NPM 安装 From 6b7d3d8f8787657632ebd2f215e199e8adab9bcc Mon Sep 17 00:00:00 2001 From: shaobeichen Date: Thu, 10 Nov 2022 17:27:57 +0800 Subject: [PATCH 02/12] ci: handle ci backmerge --- .github/workflows/release.yml | 3 +++ .releaserc | 20 +++++++++++++++++++- package-lock.json | 29 +++++++++++++++++++++++++++++ package.json | 1 + 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 26bc035..cb4c87f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v3 with: diff --git a/.releaserc b/.releaserc index f7b081b..a54c521 100644 --- a/.releaserc +++ b/.releaserc @@ -2,6 +2,11 @@ "branches": [ { "name": "main" + }, + { + "name": "next", + "channel": "next", + "prerelease": true } ], "plugins": [ @@ -14,11 +19,24 @@ { "assets": [ "package.json", + "package-lock.json", "CHANGELOG.md" ], "message": "release: v${nextRelease.version} [skip ci] \n\n${nextRelease.notes}" } ], - "@semantic-release/github" + "@semantic-release/github", + [ + "@saithodev/semantic-release-backmerge", + { + "branches": [ + { + "from": "main", + "to": "next" + } + ], + "clearWorkspace": true + } + ] ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index afca551..0ce6d70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "devDependencies": { "@babel/core": "^7.19.6", "@rollup/plugin-typescript": "^9.0.2", + "@saithodev/semantic-release-backmerge": "^2.1.2", "@semantic-release/changelog": "^6.0.1", "@semantic-release/commit-analyzer": "^9.0.2", "@semantic-release/git": "^10.0.1", @@ -5169,6 +5170,20 @@ "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", "dev": true }, + "node_modules/@saithodev/semantic-release-backmerge": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/@saithodev/semantic-release-backmerge/-/semantic-release-backmerge-2.1.2.tgz", + "integrity": "sha512-fNd8cmijjFIMp4GcdTAcug/7tr4k+8bAyvSsbLOnfyKCWyq42lg14vFZOryLiyLUAe8gpPlI7XzDPWyFTR5zug==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^2.2.0 || ^3.0.0", + "aggregate-error": "^3.1.0", + "debug": "^4.3.2", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "semantic-release": ">=13.0.0" + } + }, "node_modules/@semantic-release/changelog": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/@semantic-release/changelog/-/changelog-6.0.1.tgz", @@ -41197,6 +41212,20 @@ "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", "dev": true }, + "@saithodev/semantic-release-backmerge": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/@saithodev/semantic-release-backmerge/-/semantic-release-backmerge-2.1.2.tgz", + "integrity": "sha512-fNd8cmijjFIMp4GcdTAcug/7tr4k+8bAyvSsbLOnfyKCWyq42lg14vFZOryLiyLUAe8gpPlI7XzDPWyFTR5zug==", + "dev": true, + "requires": { + "@semantic-release/error": "^2.2.0 || ^3.0.0", + "aggregate-error": "^3.1.0", + "debug": "^4.3.2", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "semantic-release": ">=13.0.0" + } + }, "@semantic-release/changelog": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/@semantic-release/changelog/-/changelog-6.0.1.tgz", diff --git a/package.json b/package.json index 2ce8116..82b9b08 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "devDependencies": { "@babel/core": "^7.19.6", "@rollup/plugin-typescript": "^9.0.2", + "@saithodev/semantic-release-backmerge": "^2.1.2", "@semantic-release/changelog": "^6.0.1", "@semantic-release/commit-analyzer": "^9.0.2", "@semantic-release/git": "^10.0.1", From 32aa3cdfbf758fb773e35520adab75d65cf37399 Mon Sep 17 00:00:00 2001 From: beichen Date: Thu, 10 Nov 2022 17:29:51 +0800 Subject: [PATCH 03/12] Update README.md --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5686802..5fc01f5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -# makaka +

makaka

-轻量级 React 组件库 +

+ 轻量级 React 组件库 +

-

+

From 6bf5980da543ac06240513dfe3bf12735863d9e5 Mon Sep 17 00:00:00 2001 From: shaobeichen Date: Fri, 11 Nov 2022 02:24:25 +0800 Subject: [PATCH 04/12] test: update test command --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 82b9b08..a792edf 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "build-css": "sass ./src/styles/index.scss ./lib/index.css", "copy-readme": "cp ./README.md ./lib/README.md", "clean": "rimraf ./lib", + "test": "react-scripts test --watchAll", + "eject": "react-scripts eject", "release": "npm run semantic-release", "release:beta": "standard-version --release-as major --prerelease beta", "release:major": "standard-version --release-as major", @@ -97,4 +99,4 @@ "typescript": "^4.6.4", "vite": "^3.2.0" } -} +} \ No newline at end of file From baf0aa72887f889b82e39a1bce7c65e5dbcf0d2d Mon Sep 17 00:00:00 2001 From: beichen Date: Fri, 11 Nov 2022 11:07:51 +0800 Subject: [PATCH 05/12] Update package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a792edf..adbd21a 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "build-css": "sass ./src/styles/index.scss ./lib/index.css", "copy-readme": "cp ./README.md ./lib/README.md", "clean": "rimraf ./lib", - "test": "react-scripts test --watchAll", + "test": "react-scripts test --watchAll=false", "eject": "react-scripts eject", "release": "npm run semantic-release", "release:beta": "standard-version --release-as major --prerelease beta", @@ -99,4 +99,4 @@ "typescript": "^4.6.4", "vite": "^3.2.0" } -} \ No newline at end of file +} From 320c49eb577e34e252e1ae9446839f1b6cff1511 Mon Sep 17 00:00:00 2001 From: beichen Date: Fri, 11 Nov 2022 11:09:23 +0800 Subject: [PATCH 06/12] test: add test coverage command --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index adbd21a..3deaccf 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,13 @@ }, "scripts": { "dev": "vite", - "build": "npm run clean && vite build && npm run build-css && npm run copy-readme", + "build": "npm run clean && vite build && npm run build:css && npm run copy-readme", "preview": "vite preview", - "build-css": "sass ./src/styles/index.scss ./lib/index.css", + "build:css": "sass ./src/styles/index.scss ./lib/index.css", "copy-readme": "cp ./README.md ./lib/README.md", "clean": "rimraf ./lib", "test": "react-scripts test --watchAll=false", + "test:coverage": "react-scripts test --watchAll=false -- --coverage", "eject": "react-scripts eject", "release": "npm run semantic-release", "release:beta": "standard-version --release-as major --prerelease beta", From 054384b6ae9c67ea7c9fc25bb9048e1761dc6f59 Mon Sep 17 00:00:00 2001 From: beichen Date: Fri, 11 Nov 2022 11:57:24 +0800 Subject: [PATCH 07/12] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fc01f5..d6d6259 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,10 @@

- + + + + From b0ed0d12b22bbd95a436844e67ccf14418004256 Mon Sep 17 00:00:00 2001 From: beichen Date: Fri, 11 Nov 2022 12:13:52 +0800 Subject: [PATCH 08/12] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index d6d6259..58d54e3 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,12 @@ npm run build 发布 NPM 包通过 Github Actions 自动发布,合并到 main 分支即会自动发包 +### TODOLIST + +- [] 按需加载 +- [] 浏览器引入 [案例](https://ant.design/docs/react/introduce-cn#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%BC%95%E5%85%A5) +- [] 兼容环境 [案例](https://ant.design/docs/react/introduce-cn#%E5%85%BC%E5%AE%B9%E7%8E%AF%E5%A2%83) + ### 参考 [nutui-react](https://nutui.jd.com/react/#/zh-CN/guide/start-react) From 4c0ee44bfaa17b7628467ff0601c770180489b81 Mon Sep 17 00:00:00 2001 From: shaobeichen Date: Sat, 12 Nov 2022 16:17:36 +0800 Subject: [PATCH 09/12] chore: update ci run test --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3deaccf..298b61e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "scripts": { "dev": "vite", - "build": "npm run clean && vite build && npm run build:css && npm run copy-readme", + "build": "npm run test && npm run clean && vite build && npm run build:css && npm run copy-readme", "preview": "vite preview", "build:css": "sass ./src/styles/index.scss ./lib/index.css", "copy-readme": "cp ./README.md ./lib/README.md", @@ -54,7 +54,7 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { - "makaka": "^0.1.0" + "makaka": "^0.3.0" }, "peerDependencies": { "react": "^18.2.0", @@ -100,4 +100,4 @@ "typescript": "^4.6.4", "vite": "^3.2.0" } -} +} \ No newline at end of file From f24efac720113a142147ac90539ee1df4af65c25 Mon Sep 17 00:00:00 2001 From: beichen Date: Thu, 17 Nov 2022 13:45:29 +0800 Subject: [PATCH 10/12] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 58d54e3..1325b83 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ npm run build ### TODOLIST - [] 按需加载 +- [] 组件支持SSR - [] 浏览器引入 [案例](https://ant.design/docs/react/introduce-cn#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%BC%95%E5%85%A5) - [] 兼容环境 [案例](https://ant.design/docs/react/introduce-cn#%E5%85%BC%E5%AE%B9%E7%8E%AF%E5%A2%83) From b59c00165e41cf7f9aa130d8975d04c395d2a7d5 Mon Sep 17 00:00:00 2001 From: shaobeichen Date: Fri, 18 Nov 2022 09:14:07 +0800 Subject: [PATCH 11/12] feat: add toast component --- README.md | 1 + src/components/Toast/_style.scss | 77 ++++++++++++++++++++++++++ src/components/Toast/toast.stories.tsx | 30 ++++++++++ src/components/Toast/toast.test.tsx | 66 ++++++++++++++++++++++ src/components/Toast/toast.tsx | 22 ++++++++ src/main.tsx | 3 + 6 files changed, 199 insertions(+) create mode 100644 src/components/Toast/_style.scss create mode 100644 src/components/Toast/toast.stories.tsx create mode 100644 src/components/Toast/toast.test.tsx create mode 100644 src/components/Toast/toast.tsx diff --git a/README.md b/README.md index 1325b83..c471acb 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ npm run build ### TODOLIST +- [] 样式前缀名 - [] 按需加载 - [] 组件支持SSR - [] 浏览器引入 [案例](https://ant.design/docs/react/introduce-cn#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%BC%95%E5%85%A5) diff --git a/src/components/Toast/_style.scss b/src/components/Toast/_style.scss new file mode 100644 index 0000000..62878b1 --- /dev/null +++ b/src/components/Toast/_style.scss @@ -0,0 +1,77 @@ +.btn { + position: relative; + display: inline-block; + font-weight: $btn-font-weight; + line-height: $btn-line-height; + color: $body-color; + white-space: nowrap; + text-align: center; + vertical-align: middle; + background-image: none; + border: $btn-border-width solid transparent; + @include button-size($btn-padding-x, $btn-padding-y, $btn-font-size, $border-radius); + box-shadow: $btn-box-shadow; + cursor: pointer; + transition: $btn-transition; + &.disabled, + &[disabled] { + cursor: not-allowed; + opacity: $btn-disabled-opacity; + box-shadow: none; + > * { + pointer-events: none; + } + } +} + +.btn-lg { + @include button-size( + $btn-padding-y-lg, + $btn-padding-x-lg, + $btn-font-size-lg, + $btn-border-radius-lg + ); +} +.btn-sm { + @include button-size( + $btn-padding-y-sm, + $btn-padding-x-sm, + $btn-font-size-sm, + $btn-border-radius-sm + ); +} + +.btn-primary { + @include button-style($primary, $primary, $white); +} +.btn-danger { + @include button-style($danger, $danger, $white); +} + +.btn-default { + @include button-style($white, $gray-400, $body-color, $white, $primary, $primary); +} + +.btn-link { + font-weight: $font-weight-normal; + color: $btn-link-color; + text-decoration: $link-decoration; + box-shadow: none; + &:hover { + color: $btn-link-hover-color; + text-decoration: $link-hover-decoration; + } + &:focus, + &.focus { + text-decoration: $link-hover-decoration; + box-shadow: none; + } + &:disabled, + &.disabled { + color: $btn-link-disabled-color; + pointer-events: none; + } +} +.btn-round { + border-radius: 999px; +} diff --git a/src/components/Toast/toast.stories.tsx b/src/components/Toast/toast.stories.tsx new file mode 100644 index 0000000..560a80a --- /dev/null +++ b/src/components/Toast/toast.stories.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import { storiesOf } from '@storybook/react' +import { action } from '@storybook/addon-actions' +import Button, { ButtonType, ButtonSize } from './button' +import '../../styles/index.scss' + +const defaultButton = () => + +const buttonWithSize = () => ( + <> + + + +) + +const buttonWithType = () => ( + <> + + + + + +) + +storiesOf('Button Component', module) + .add('Button', defaultButton) + .add('不同尺寸的 Button', buttonWithSize) + .add('不同类型的 Button', buttonWithType) diff --git a/src/components/Toast/toast.test.tsx b/src/components/Toast/toast.test.tsx new file mode 100644 index 0000000..29ed425 --- /dev/null +++ b/src/components/Toast/toast.test.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import { render, fireEvent } from '@testing-library/react' +import Button, { ButtonProps, ButtonSize, ButtonType } from './button' + +const defaultProps = { + onClick: jest.fn(), +} + +const testProps: ButtonProps = { + btnType: ButtonType.Primary, + size: ButtonSize.Large, + className: 'klass', +} + +const disabledProps: ButtonProps = { + disabled: true, + onClick: jest.fn(), +} + +const roundProps: ButtonProps = { + round: true, +} + +describe('test button components', () => { + it('should render default button', () => { + const wrapper = render() + const element = wrapper.getByText('Click') as HTMLButtonElement + expect(element).toBeInTheDocument() + expect(element.tagName).toEqual('BUTTON') + expect(element.disabled).toBeFalsy() + expect(element).toHaveClass('btn btn-default') + fireEvent.click(element) + expect(defaultProps.onClick).toHaveBeenCalled() + }) + it('should render the components based on different props', () => { + const wrapper = render() + const element = wrapper.getByText('Click') + expect(element).toBeInTheDocument() + expect(element).toHaveClass('btn-primary btn-lg klass') + }) + it('should render a link when btnType equals link and href is provided', () => { + const wrapper = render( + , + ) + const element = wrapper.getByText('Link') + expect(element).toBeInTheDocument() + expect(element.tagName).toEqual('A') + expect(element).toHaveClass('btn btn-link') + }) + it('should render disabled button when disabled set to true', () => { + const wrapper = render() + const element = wrapper.getByText('Click') as HTMLButtonElement + expect(element).toBeInTheDocument() + expect(element.disabled).toBeTruthy() + fireEvent.click(element) + expect(disabledProps.onClick).not.toHaveBeenCalled() + }) + it('should render round button when round set to true', () => { + const wrapper = render() + const element = wrapper.getByText('Click') as HTMLButtonElement + expect(element).toBeInTheDocument() + expect(element).toHaveClass('btn-round') + }) +}) diff --git a/src/components/Toast/toast.tsx b/src/components/Toast/toast.tsx new file mode 100644 index 0000000..514ee72 --- /dev/null +++ b/src/components/Toast/toast.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +interface BaseToastProps { + message?: string + duration?: number +} + +type AnchorToastProps = BaseToastProps & React.AnchorHTMLAttributes +export type ToastProps = Partial + +const Toast: React.FC = (props) => { + const { message, duration } = props + + return

{message}
+} + +Toast.defaultProps = { + message: '', + duration: 3000, +} + +export default Toast diff --git a/src/main.tsx b/src/main.tsx index f17ba08..7089bb8 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,2 +1,5 @@ export { default as Button } from './components/Button/button' export type { ButtonProps } from './components/Button/button' + +export { default as Toast } from './components/Toast/toast' +export type { ToastProps } from './components/Toast/toast' From a7f770ffaae5166133a5565b8b9f0c9ff9027a19 Mon Sep 17 00:00:00 2001 From: shaobeichen Date: Fri, 18 Nov 2022 21:59:21 +0800 Subject: [PATCH 12/12] feat: add toast component --- examples/index.tsx | 5 +- examples/test.tsx | 4 +- src/App.tsx | 3 + src/components/Toast/_style.scss | 87 ++++---------------------- src/components/Toast/toast.stories.tsx | 30 --------- src/components/Toast/toast.test.tsx | 75 +++++----------------- src/components/Toast/toast.tsx | 39 +++++++++--- src/styles/index.scss | 4 +- 8 files changed, 66 insertions(+), 181 deletions(-) diff --git a/examples/index.tsx b/examples/index.tsx index b727b32..74a0c9f 100644 --- a/examples/index.tsx +++ b/examples/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import ReactDOM from 'react-dom' +import ReactDOM from 'react-dom/client' // 这里是重点!!! // App为库的入口,模拟外部引入 import App from '../src/App' @@ -11,7 +11,7 @@ const containerStyle: React.CSSProperties = { transform: 'translate(-50%, -50%)', } -ReactDOM.render( +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
跳转到线上包预览页面 @@ -21,5 +21,4 @@ ReactDOM.render(
, - document.getElementById('root'), ) diff --git a/examples/test.tsx b/examples/test.tsx index 545d9eb..67806b5 100644 --- a/examples/test.tsx +++ b/examples/test.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { createRoot } from 'react-dom/client' +import ReactDOM from 'react-dom/client' import { Button } from 'makaka' import 'makaka/lib/style.css' @@ -31,7 +31,7 @@ const App: React.FC = () => { ) } -createRoot(document.getElementById('root') as HTMLElement).render( +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( , diff --git a/src/App.tsx b/src/App.tsx index 6482f23..136bc0a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,6 @@ import React from 'react' import Button, { ButtonType, ButtonSize } from './components/Button/button' +import Toast from './components/Toast/toast' import './styles/index.scss' const App: React.FC = () => { @@ -17,4 +18,6 @@ const App: React.FC = () => { ) } +Toast('你好,我是一个命令式组件,我通过调用命令生成一个DOM节点。') + export default App diff --git a/src/components/Toast/_style.scss b/src/components/Toast/_style.scss index 62878b1..6e3d458 100644 --- a/src/components/Toast/_style.scss +++ b/src/components/Toast/_style.scss @@ -1,77 +1,14 @@ -.btn { - position: relative; - display: inline-block; - font-weight: $btn-font-weight; - line-height: $btn-line-height; - color: $body-color; - white-space: nowrap; +.toast { + position: fixed; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + background: rgba($color: black, $alpha: 0.7); + color: white; + font-size: 16px; text-align: center; - vertical-align: middle; - background-image: none; - border: $btn-border-width solid transparent; - @include button-size($btn-padding-x, $btn-padding-y, $btn-font-size, $border-radius); - box-shadow: $btn-box-shadow; - cursor: pointer; - transition: $btn-transition; - &.disabled, - &[disabled] { - cursor: not-allowed; - opacity: $btn-disabled-opacity; - box-shadow: none; - > * { - pointer-events: none; - } - } -} - -.btn-lg { - @include button-size( - $btn-padding-y-lg, - $btn-padding-x-lg, - $btn-font-size-lg, - $btn-border-radius-lg - ); -} -.btn-sm { - @include button-size( - $btn-padding-y-sm, - $btn-padding-x-sm, - $btn-font-size-sm, - $btn-border-radius-sm - ); -} - -.btn-primary { - @include button-style($primary, $primary, $white); -} -.btn-danger { - @include button-style($danger, $danger, $white); -} - -.btn-default { - @include button-style($white, $gray-400, $body-color, $white, $primary, $primary); -} - -.btn-link { - font-weight: $font-weight-normal; - color: $btn-link-color; - text-decoration: $link-decoration; - box-shadow: none; - &:hover { - color: $btn-link-hover-color; - text-decoration: $link-hover-decoration; - } - &:focus, - &.focus { - text-decoration: $link-hover-decoration; - box-shadow: none; - } - &:disabled, - &.disabled { - color: $btn-link-disabled-color; - pointer-events: none; - } -} -.btn-round { - border-radius: 999px; + max-width: 400px; + z-index: 9999; + padding: 10px 20px; + border-radius: 14px; } diff --git a/src/components/Toast/toast.stories.tsx b/src/components/Toast/toast.stories.tsx index 560a80a..e69de29 100644 --- a/src/components/Toast/toast.stories.tsx +++ b/src/components/Toast/toast.stories.tsx @@ -1,30 +0,0 @@ -import React from 'react' -import { storiesOf } from '@storybook/react' -import { action } from '@storybook/addon-actions' -import Button, { ButtonType, ButtonSize } from './button' -import '../../styles/index.scss' - -const defaultButton = () => - -const buttonWithSize = () => ( - <> - - - -) - -const buttonWithType = () => ( - <> - - - - - -) - -storiesOf('Button Component', module) - .add('Button', defaultButton) - .add('不同尺寸的 Button', buttonWithSize) - .add('不同类型的 Button', buttonWithType) diff --git a/src/components/Toast/toast.test.tsx b/src/components/Toast/toast.test.tsx index 29ed425..957f32f 100644 --- a/src/components/Toast/toast.test.tsx +++ b/src/components/Toast/toast.test.tsx @@ -1,66 +1,19 @@ -import React from 'react' -import { render, fireEvent } from '@testing-library/react' -import Button, { ButtonProps, ButtonSize, ButtonType } from './button' +import Toast, { ToastProps } from './toast' -const defaultProps = { - onClick: jest.fn(), +const testProps: ToastProps = { + message: '你好,我是命令式组件 Toast 。', } -const testProps: ButtonProps = { - btnType: ButtonType.Primary, - size: ButtonSize.Large, - className: 'klass', -} - -const disabledProps: ButtonProps = { - disabled: true, - onClick: jest.fn(), -} - -const roundProps: ButtonProps = { - round: true, -} - -describe('test button components', () => { - it('should render default button', () => { - const wrapper = render() - const element = wrapper.getByText('Click') as HTMLButtonElement - expect(element).toBeInTheDocument() - expect(element.tagName).toEqual('BUTTON') - expect(element.disabled).toBeFalsy() - expect(element).toHaveClass('btn btn-default') - fireEvent.click(element) - expect(defaultProps.onClick).toHaveBeenCalled() - }) - it('should render the components based on different props', () => { - const wrapper = render() - const element = wrapper.getByText('Click') - expect(element).toBeInTheDocument() - expect(element).toHaveClass('btn-primary btn-lg klass') - }) - it('should render a link when btnType equals link and href is provided', () => { - const wrapper = render( - , - ) - const element = wrapper.getByText('Link') - expect(element).toBeInTheDocument() - expect(element.tagName).toEqual('A') - expect(element).toHaveClass('btn btn-link') - }) - it('should render disabled button when disabled set to true', () => { - const wrapper = render() - const element = wrapper.getByText('Click') as HTMLButtonElement - expect(element).toBeInTheDocument() - expect(element.disabled).toBeTruthy() - fireEvent.click(element) - expect(disabledProps.onClick).not.toHaveBeenCalled() - }) - it('should render round button when round set to true', () => { - const wrapper = render() - const element = wrapper.getByText('Click') as HTMLButtonElement - expect(element).toBeInTheDocument() - expect(element).toHaveClass('btn-round') +describe('test toast components', () => { + it('should render toast', () => { + Toast(testProps) + setTimeout(() => { + const element = document.querySelector('.toast') + expect(element?.innerHTML).toBe(testProps.message) + expect(element).toHaveClass('toast') + setTimeout(() => { + expect(element).not.toBeTruthy() + }, 4000) + }, 0) }) }) diff --git a/src/components/Toast/toast.tsx b/src/components/Toast/toast.tsx index 514ee72..e363a6b 100644 --- a/src/components/Toast/toast.tsx +++ b/src/components/Toast/toast.tsx @@ -1,22 +1,45 @@ import React from 'react' +import { createRoot } from 'react-dom/client' interface BaseToastProps { - message?: string + message?: string | React.ReactNode duration?: number + style?: React.CSSProperties } type AnchorToastProps = BaseToastProps & React.AnchorHTMLAttributes export type ToastProps = Partial -const Toast: React.FC = (props) => { - const { message, duration } = props +const Toast = (props: string | ToastProps) => { + const defaultDuration = 3000 - return
{message}
-} + let message: BaseToastProps['message'] + let duration: BaseToastProps['duration'] = defaultDuration + + if (typeof props === 'string') { + message = props + } else { + message = props.message + duration = props.duration || defaultDuration + } + const content =
{message}
+ + const container = document.createElement('div') + document.body.appendChild(container) + + const root = createRoot(container) + + const init = () => { + const id = setTimeout(() => { + clearTimeout(id) + root.unmount() + document.body.removeChild(container) + }, duration) + } + + init() -Toast.defaultProps = { - message: '', - duration: 3000, + return root.render(content) } export default Toast diff --git a/src/styles/index.scss b/src/styles/index.scss index a46fb20..50f2c5a 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -13,8 +13,8 @@ // button @import '../components/Button/style'; -// alert -// @import '../components/Alert/style'; +// toast +@import '../components/Toast/style'; // menu // @import '../components/Menu/style';