From 5cf3917a8b3d204f0b5fec21136dd4d9d8622308 Mon Sep 17 00:00:00 2001 From: jacknan Date: Tue, 21 Nov 2023 10:02:41 +0800 Subject: [PATCH] feat(toast): add mobile-toast (#751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(toast): 增加toast组件 Signed-off-by: jacknan * fix(toast): 删除日志打印 Signed-off-by: jacknan * feat(toast): 优化demo样式 Signed-off-by: jacknan * feat(toast): 刷新设计规范 Signed-off-by: jacknan * feat(toast): 删除无用代码 Signed-off-by: jacknan * feat(toast): 拆分特性demo Signed-off-by: jacknan * feat(toast): 刷新token Signed-off-by: jacknan * feat(toast): 刷新token定义 Signed-off-by: jacknan * feat(toast): 删除无用文件 Signed-off-by: jacknan --------- Signed-off-by: jacknan --- .../sites/demos/mobile/app/toast/base.vue | 28 +++++ .../sites/demos/mobile/app/toast/failed.vue | 26 +++++ .../sites/demos/mobile/app/toast/success.vue | 27 +++++ .../demos/mobile/app/toast/webdoc/toast.en.md | 7 ++ .../demos/mobile/app/toast/webdoc/toast.js | 102 ++++++++++++++++++ .../demos/mobile/app/toast/webdoc/toast.md | 11 ++ examples/sites/demos/mobile/menus.js | 3 +- packages/modules.json | 13 +++ packages/renderless/src/toast/index.ts | 17 +++ packages/renderless/src/toast/vue.ts | 32 ++++++ packages/renderless/types/toast.type.ts | 24 +++++ packages/theme-mobile/src/toast/index.less | 60 +++++++++++ packages/theme-mobile/src/toast/vars.less | 32 ++++++ .../theme/src/svgs/mobile-error-white.svg | 2 +- .../theme/src/svgs/mobile-success-white.svg | 2 +- packages/vue/package.json | 1 + packages/vue/src/toast/index.ts | 28 +++++ packages/vue/src/toast/package.json | 24 +++++ packages/vue/src/toast/src/index.ts | 46 ++++++++ packages/vue/src/toast/src/mobile.vue | 30 ++++++ packages/vue/src/toast/src/service.ts | 46 ++++++++ 21 files changed, 558 insertions(+), 3 deletions(-) create mode 100644 examples/sites/demos/mobile/app/toast/base.vue create mode 100644 examples/sites/demos/mobile/app/toast/failed.vue create mode 100644 examples/sites/demos/mobile/app/toast/success.vue create mode 100644 examples/sites/demos/mobile/app/toast/webdoc/toast.en.md create mode 100644 examples/sites/demos/mobile/app/toast/webdoc/toast.js create mode 100644 examples/sites/demos/mobile/app/toast/webdoc/toast.md create mode 100644 packages/renderless/src/toast/index.ts create mode 100644 packages/renderless/src/toast/vue.ts create mode 100644 packages/renderless/types/toast.type.ts create mode 100644 packages/theme-mobile/src/toast/index.less create mode 100644 packages/theme-mobile/src/toast/vars.less create mode 100644 packages/vue/src/toast/index.ts create mode 100644 packages/vue/src/toast/package.json create mode 100644 packages/vue/src/toast/src/index.ts create mode 100644 packages/vue/src/toast/src/mobile.vue create mode 100644 packages/vue/src/toast/src/service.ts diff --git a/examples/sites/demos/mobile/app/toast/base.vue b/examples/sites/demos/mobile/app/toast/base.vue new file mode 100644 index 0000000000..c17eb4eb3c --- /dev/null +++ b/examples/sites/demos/mobile/app/toast/base.vue @@ -0,0 +1,28 @@ + + + diff --git a/examples/sites/demos/mobile/app/toast/failed.vue b/examples/sites/demos/mobile/app/toast/failed.vue new file mode 100644 index 0000000000..7db548c0a3 --- /dev/null +++ b/examples/sites/demos/mobile/app/toast/failed.vue @@ -0,0 +1,26 @@ + + + diff --git a/examples/sites/demos/mobile/app/toast/success.vue b/examples/sites/demos/mobile/app/toast/success.vue new file mode 100644 index 0000000000..6cd5d480b4 --- /dev/null +++ b/examples/sites/demos/mobile/app/toast/success.vue @@ -0,0 +1,27 @@ + + + diff --git a/examples/sites/demos/mobile/app/toast/webdoc/toast.en.md b/examples/sites/demos/mobile/app/toast/webdoc/toast.en.md new file mode 100644 index 0000000000..e673a519e8 --- /dev/null +++ b/examples/sites/demos/mobile/app/toast/webdoc/toast.en.md @@ -0,0 +1,7 @@ +--- +title: Toast +--- + +# Toast + +
Toast
diff --git a/examples/sites/demos/mobile/app/toast/webdoc/toast.js b/examples/sites/demos/mobile/app/toast/webdoc/toast.js new file mode 100644 index 0000000000..92fdf500b8 --- /dev/null +++ b/examples/sites/demos/mobile/app/toast/webdoc/toast.js @@ -0,0 +1,102 @@ +export default { + column: '2', + owner: '', + demos: [ + { + demoId: 'base', + name: { + 'zh-CN': '基础用法', + 'en-US': 'button type' + }, + desc: { + 'zh-CN': '

基础用法

', + 'en-US': '

button type

' + }, + codeFiles: ['base.vue'] + }, + { + demoId: 'success', + name: { + 'zh-CN': '成功样式', + 'en-US': 'success' + }, + desc: { + 'zh-CN': '

成功提示

', + 'en-US': '

success

' + }, + codeFiles: ['success.vue'] + }, + { + demoId: 'failed', + name: { + 'zh-CN': '失败样式', + 'en-US': 'failed' + }, + desc: { + 'zh-CN': '

失败提示

', + 'en-US': '

failed

' + }, + codeFiles: ['failed.vue'] + } + ], + apis: [ + { + name: 'Toast', // 组件名称展示使用 + type: 'component', // API 类型 + properties: [ + { + name: 'zIndex', + type: 'Number', + defaultValue: '100', + desc: { + 'zh-CN': '

弹框层级

', + 'en-US': '' + }, + demoId: 'base' + }, + { + name: 'type', + type: 'string', + defaultValue: 'text', + desc: { + 'zh-CN': '

类型, text:纯文本 correct:成功 error:失败

', + 'en-US': 'type' + }, + demoId: 'base' + }, + { + name: 'text', + type: 'string', + defaultValue: '', + desc: { + 'zh-CN': '

展示的文本

', + 'en-US': 'display text' + }, + demoId: 'base' + }, + { + name: 'time', + type: 'Number', + defaultValue: '2000', + desc: { + 'zh-CN': '

展示持续时间,单位:ms

', + 'en-US': 'display times' + }, + demoId: 'base' + } + ], + method: [ + { + name: 'timeout', + type: 'Function', + defaultValue: '', + desc: { + 'zh-CN': '

消失前的回调

', + 'en-US': '' + }, + demoId: 'base' + } + ] + } + ] +} diff --git a/examples/sites/demos/mobile/app/toast/webdoc/toast.md b/examples/sites/demos/mobile/app/toast/webdoc/toast.md new file mode 100644 index 0000000000..02a69c72e5 --- /dev/null +++ b/examples/sites/demos/mobile/app/toast/webdoc/toast.md @@ -0,0 +1,11 @@ +--- +title: Toast 轻提示 +--- + +# Toast 轻提示 + +
+ +Toast 轻提示 + +
diff --git a/examples/sites/demos/mobile/menus.js b/examples/sites/demos/mobile/menus.js index c316232b7a..4126e0a154 100644 --- a/examples/sites/demos/mobile/menus.js +++ b/examples/sites/demos/mobile/menus.js @@ -94,7 +94,8 @@ export const cmpMenus = [ { name: 'Badge', nameCn: '徽章', key: 'badge' }, { name: 'Loading', nameCn: '加载', key: 'loading' }, { name: 'Modal', nameCn: '模态框', key: 'modal' }, - { name: 'Popover', nameCn: '气泡', key: 'popover' } + { name: 'Popover', nameCn: '气泡', key: 'popover' }, + { name: 'Toast', nameCn: '轻提示', key: 'toast' } ] }, { diff --git a/packages/modules.json b/packages/modules.json index 5eb4502e0c..6a2d4463db 100644 --- a/packages/modules.json +++ b/packages/modules.json @@ -2559,6 +2559,19 @@ "type": "template", "exclude": false }, + "Toast": { + "path": "vue/src/toast/index.ts", + "type": "component", + "exclude": false, + "mode": [ + "mobile" + ] + }, + "ToastMobile": { + "path": "vue/src/toast/src/mobile.vue", + "type": "template", + "exclude": false + }, "ToggleMenu": { "path": "vue/src/toggle-menu/index.ts", "type": "component", diff --git a/packages/renderless/src/toast/index.ts b/packages/renderless/src/toast/index.ts new file mode 100644 index 0000000000..825674a045 --- /dev/null +++ b/packages/renderless/src/toast/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2022 - present TinyVue Authors. + * Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd. + * + * Use of this source code is governed by an MIT-style license. + * + * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, + * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR + * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + * + */ + +import { IToastRenderlessParamUtils } from 'types/toast.type' + +export const timeout = (emit: IToastRenderlessParamUtils['emit']) => (): void => { + emit('timeout') +} diff --git a/packages/renderless/src/toast/vue.ts b/packages/renderless/src/toast/vue.ts new file mode 100644 index 0000000000..bbefd6f540 --- /dev/null +++ b/packages/renderless/src/toast/vue.ts @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2022 - present TinyVue Authors. + * Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd. + * + * Use of this source code is governed by an MIT-style license. + * + * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, + * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR + * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + * + */ + +import { ISharedRenderlessParamHooks } from 'types/shared.type' +import { timeout } from './index' +import { IToastApi, IToastState, IToastProps } from 'types/toast.type' + +export const api = ['state', 'timeout'] + +export const renderless = (props: IToastProps, { reactive }: ISharedRenderlessParamHooks, { vm, emit }): IToastApi => { + const state: IToastState = reactive({ + text: props.text, + type: props.type, + time: props.time as number + }) + + const api: IToastApi = { + state, + timeout: timeout(emit) + } + + return api +} diff --git a/packages/renderless/types/toast.type.ts b/packages/renderless/types/toast.type.ts new file mode 100644 index 0000000000..d457aefd2d --- /dev/null +++ b/packages/renderless/types/toast.type.ts @@ -0,0 +1,24 @@ +import type { ExtractPropTypes } from 'vue' +import { toastProps } from '@/toast/src' +import type { ISharedRenderlessFunctionParams, ISharedRenderlessParamUtils } from './shared.type' +import { timeout } from '../src/toast' + +export interface IToastState { + text: string | null + type?: string + time: number +} + +export type IToastProps = ExtractPropTypes + +export type IToastRenderlessParams = ISharedRenderlessFunctionParams & { + state: IToastState + props: IToastProps +} + +export interface IToastApi { + state: IToastState + timeout: ReturnType +} + +export type IToastRenderlessParamUtils = ISharedRenderlessParamUtils diff --git a/packages/theme-mobile/src/toast/index.less b/packages/theme-mobile/src/toast/index.less new file mode 100644 index 0000000000..f8ae7c3045 --- /dev/null +++ b/packages/theme-mobile/src/toast/index.less @@ -0,0 +1,60 @@ +/** +* Copyright (c) 2022 - present TinyVue Authors. +* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd. +* +* Use of this source code is governed by an MIT-style license. +* +* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, +* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR +* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. +* +*/ + +@import '../custom.less'; +@import './vars.less'; + +@toast-prefix-cls: ~'@{css-prefix}mobile-toast'; + +.@{toast-prefix-cls} { + .component-css-vars-toast(); + + position: fixed; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; + left: 0; + right: 0; + top: 0; + bottom: 0; + + &-content { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: var(--ti-mobile-toast-padding-size); + background-color: var(--ti-mobile-toast-bg-color-primary); + border-radius: var(--ti-mobile-toast-border-radius); + box-shadow: var(--ti-mobile-toast-shadow, 0 0 20px 0 rgb(0 0 0 / 8%)); + backdrop-filter: blur(5px); + max-width: var(--ti-mobile-toast-width-max); + min-width: 106px; + + &-text { + padding: 7px 0; + } + } + + &-text { + word-wrap: break-word; + word-break: break-all; + font-size: var(--ti-mobile-toast-text-font-size); + color: var(--ti-mobile-toast-text-color-primary, #fff); + } + + &-icon { + padding-bottom: var(--ti-mobile-toast-padding-bottom); + font-size: var(--ti-mobile-toast-icon-size); + } +} diff --git a/packages/theme-mobile/src/toast/vars.less b/packages/theme-mobile/src/toast/vars.less new file mode 100644 index 0000000000..4f27e21cb1 --- /dev/null +++ b/packages/theme-mobile/src/toast/vars.less @@ -0,0 +1,32 @@ +/** +* Copyright (c) 2022 - present TinyVue Authors. +* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd. +* +* Use of this source code is governed by an MIT-style license. +* +* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, +* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR +* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. +* +*/ + +.component-css-vars-toast() { + // 背景色 + --ti-mobile-toast-bg-color-primary: rgb(77 77 77 / 95%); + // 文字颜色 + --ti-mobile-toast-text-color-primary: var(--ti-mobile-color-text-inverse, #fff); + // 组件最大宽度 + --ti-mobile-toast-width-max: 90%; + // 文字尺寸 + --ti-mobile-toast-text-font-size: var(--ti-mobile-font-size-m, 14px); + // 图标尺寸 + --ti-mobile-toast-icon-size: 36px; + // 阴影 + --ti-mobile-toast-shadow: var(--ti-mobile-shadow-s, 0 0 20px 0 rgb(0 0 0 / 8%)); + // 边距 + --ti-mobile-toast-padding-size: var(--ti-mobile-space-4x, 16px); + // 圆角尺寸 + --ti-mobile-toast-border-radius: var(--ti-mobile-border-radius-xl, 16px); + // 图标下边距 + --ti-mobile-toast-padding-bottom: var(--ti-mobile-space-2x, 8px); +} diff --git a/packages/theme/src/svgs/mobile-error-white.svg b/packages/theme/src/svgs/mobile-error-white.svg index 0c2032000f..422036af2a 100644 --- a/packages/theme/src/svgs/mobile-error-white.svg +++ b/packages/theme/src/svgs/mobile-error-white.svg @@ -1,5 +1,5 @@ - + ic/error diff --git a/packages/theme/src/svgs/mobile-success-white.svg b/packages/theme/src/svgs/mobile-success-white.svg index 7a6309cebb..44aabc69fe 100644 --- a/packages/theme/src/svgs/mobile-success-white.svg +++ b/packages/theme/src/svgs/mobile-success-white.svg @@ -1,5 +1,5 @@ - + ic/confirm diff --git a/packages/vue/package.json b/packages/vue/package.json index 3e34a12740..ab3e4543a0 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -226,6 +226,7 @@ "@opentiny/vue-time-select": "workspace:~", "@opentiny/vue-time-spinner": "workspace:~", "@opentiny/vue-timeline-item": "workspace:~", + "@opentiny/vue-toast": "workspace:~", "@opentiny/vue-toggle-menu": "workspace:~", "@opentiny/vue-tooltip": "workspace:~", "@opentiny/vue-top-box": "workspace:~", diff --git a/packages/vue/src/toast/index.ts b/packages/vue/src/toast/index.ts new file mode 100644 index 0000000000..f6e5f0657e --- /dev/null +++ b/packages/vue/src/toast/index.ts @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2022 - present TinyVue Authors. + * Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd. + * + * Use of this source code is governed by an MIT-style license. + * + * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, + * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR + * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + * + */ +import service from './src/service.js' +import '@opentiny/vue-theme-mobile/toast/index.less' +import { version } from './package.json' + +let Toast: any = { + install() {}, + service, + version +} + +if (process.env.BUILD_TARGET === 'runtime') { + if (typeof window !== 'undefined' && window.Vue) { + Toast.install(window.Vue) + } +} + +export default Toast diff --git a/packages/vue/src/toast/package.json b/packages/vue/src/toast/package.json new file mode 100644 index 0000000000..6f39c7fee4 --- /dev/null +++ b/packages/vue/src/toast/package.json @@ -0,0 +1,24 @@ +{ + "name": "@opentiny/vue-toast", + "version": "3.7.0", + "description": "", + "main": "lib/index.js", + "module": "index.ts", + "sideEffects": false, + "type": "module", + "devDependencies": { + "@opentiny-internal/vue-test-utils": "workspace:*", + "vitest": "^0.31.0" + }, + "scripts": { + "build": "pnpm -w build:ui $npm_package_name", + "//postversion": "pnpm build" + }, + "dependencies": { + "@opentiny/vue-common": "workspace:~", + "@opentiny/vue-icon": "workspace:~", + "@opentiny/vue-renderless": "workspace:~", + "@opentiny/vue-locale": "workspace:~" + }, + "license": "MIT" +} diff --git a/packages/vue/src/toast/src/index.ts b/packages/vue/src/toast/src/index.ts new file mode 100644 index 0000000000..94f9ab186d --- /dev/null +++ b/packages/vue/src/toast/src/index.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2022 - present TinyVue Authors. + * Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd. + * + * Use of this source code is governed by an MIT-style license. + * + * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, + * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR + * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + * + */ +import { $props, $prefix, $setup, defineComponent } from '@opentiny/vue-common' +import template from 'virtual-template?mobile' + +export const toastProps = { + ...$props, + type: { + type: String, + validator: (value: string) => Boolean(~['text', 'correct', 'error'].indexOf(value)) + }, + zIndex: { + type: Number, + default: 100 + }, + text: { + type: String, + default: 'text' + }, + time: { + type: [String, Number], + default: 2000 + }, + timeout: { + type: Function, + default: null + } +} + +export default defineComponent({ + name: $prefix + 'Toast', + emits: ['timeout'], + props: toastProps, + setup(props, context) { + return $setup({ props, context, template }) + } +}) diff --git a/packages/vue/src/toast/src/mobile.vue b/packages/vue/src/toast/src/mobile.vue new file mode 100644 index 0000000000..a88fd680f8 --- /dev/null +++ b/packages/vue/src/toast/src/mobile.vue @@ -0,0 +1,30 @@ +
+
+
+ + +
+
{{ state.text }}
+
+
+ + + diff --git a/packages/vue/src/toast/src/service.ts b/packages/vue/src/toast/src/service.ts new file mode 100644 index 0000000000..e653cad983 --- /dev/null +++ b/packages/vue/src/toast/src/service.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2022 - present TinyVue Authors. + * Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd. + * + * Use of this source code is governed by an MIT-style license. + * + * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, + * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR + * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + * + */ + +import { createComponent } from '@opentiny/vue-common' +import Toast from './index' + +const defaults = { + type: 'text' +} + +export default (configs = {}) => { + configs = { ...defaults, ...configs } + let parent = document.body + let instance = createComponent({ + component: Toast, + propsData: {}, + el: document.createElement('div') + }) + + for (const key in configs) { + if (Object.prototype.hasOwnProperty.call(configs, key)) { + instance.state[key] = configs[key] + } + } + + parent.appendChild(instance.$el) + + setTimeout(() => { + if (instance.state.timeout) { + instance.state.timeout() + } + + parent.removeChild(instance.$el) + }, instance.state.time) + + return instance +}