diff --git a/packages/opendesign/src/components/index.ts b/packages/opendesign/src/components/index.ts index 049dff26ae80455ea23ef88c425f401088699bf1..a7c36024104e5d9eeb0d423cdb0d3326a50c7e88 100644 --- a/packages/opendesign/src/components/index.ts +++ b/packages/opendesign/src/components/index.ts @@ -33,6 +33,7 @@ export * from './dropdown'; export * from './dialog'; export * from './figure'; export * from './card'; +export * from './message'; export * from './intersection-observer'; export * from './resize-observer'; diff --git a/packages/opendesign/src/components/message/OMessage.vue b/packages/opendesign/src/components/message/OMessage.vue new file mode 100644 index 0000000000000000000000000000000000000000..b55cef66ebf9b6d4e35ae7a83332429c3a729ca8 --- /dev/null +++ b/packages/opendesign/src/components/message/OMessage.vue @@ -0,0 +1,42 @@ + + + diff --git a/packages/opendesign/src/components/message/OMessageList.vue b/packages/opendesign/src/components/message/OMessageList.vue new file mode 100644 index 0000000000000000000000000000000000000000..0b45998fa44dfa1313083207bbd92b423166344b --- /dev/null +++ b/packages/opendesign/src/components/message/OMessageList.vue @@ -0,0 +1,66 @@ + + + diff --git a/packages/opendesign/src/components/message/__demo__/IndexMessage.vue b/packages/opendesign/src/components/message/__demo__/IndexMessage.vue new file mode 100644 index 0000000000000000000000000000000000000000..e074ad3502d98830200b3c6865e3ac8b925c5c38 --- /dev/null +++ b/packages/opendesign/src/components/message/__demo__/IndexMessage.vue @@ -0,0 +1,10 @@ + + + diff --git a/packages/opendesign/src/components/message/__demo__/MessageBasic.vue b/packages/opendesign/src/components/message/__demo__/MessageBasic.vue new file mode 100644 index 0000000000000000000000000000000000000000..651c77c8254634685fca0ea25965cad848695178 --- /dev/null +++ b/packages/opendesign/src/components/message/__demo__/MessageBasic.vue @@ -0,0 +1,43 @@ + + + diff --git a/packages/opendesign/src/components/message/index.ts b/packages/opendesign/src/components/message/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..c5bf979732b2b7a6ce03c1776251b484ab57b69e --- /dev/null +++ b/packages/opendesign/src/components/message/index.ts @@ -0,0 +1,14 @@ +import type { App } from 'vue'; + +import _OMessage from './OMessage.vue'; +import useMessage from './use-message'; + +const OMessage = Object.assign(_OMessage, { + install(app: App) { + app.component(_OMessage.name, _OMessage); + }, +}); + +export * from './types'; + +export { OMessage, useMessage }; diff --git a/packages/opendesign/src/components/message/style/index.scss b/packages/opendesign/src/components/message/style/index.scss new file mode 100644 index 0000000000000000000000000000000000000000..370d2754650f6ea805ff25027d020c896cc96a56 --- /dev/null +++ b/packages/opendesign/src/components/message/style/index.scss @@ -0,0 +1,43 @@ +@use './var.scss'; + +.o-message { + display: flex; + align-items: center; + padding: var(--message-padding); + font-size: var(--message-text-size); + line-height: var(--message-text-height); + color: var(--message-color); + background-color: var(--message-bg-color); + border-radius: var(--message-radius); + border: 1px solid var(--message-bd-color); + width: fit-content; + transition: all var(--o-duration-m1) var(--o-easing-standard-out); +} + +.o-message + .o-message { + margin-top: 16px; +} + +.o-message-list { + position: fixed; + z-index: 1001; + left: 50%; + top: 32px; + transform: translateX(-50%); + display: flex; + flex-direction: column; + align-items: center; +} + +.fade-message-enter-from { + opacity: 0; +} + +.fade-message-enter-active, +.fade-message-leave-active { + transition: all var(--o-duration-m1) var(--o-easing-standard-out); +} + +.fade-message-leave-to { + opacity: 0; +} diff --git a/packages/opendesign/src/components/message/style/index.ts b/packages/opendesign/src/components/message/style/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..591b2fbd72dcd5e987362d645b561bd2fac42716 --- /dev/null +++ b/packages/opendesign/src/components/message/style/index.ts @@ -0,0 +1,2 @@ +import '../../style'; +import './index.scss'; diff --git a/packages/opendesign/src/components/message/style/var.scss b/packages/opendesign/src/components/message/style/var.scss new file mode 100644 index 0000000000000000000000000000000000000000..70cb1eeb861ff42b9e7a5507724680bd2474890e --- /dev/null +++ b/packages/opendesign/src/components/message/style/var.scss @@ -0,0 +1,29 @@ +.o-message { + --message-padding: 8px 16px; + --message-text-size: var(--o-font_size-text1); + --message-text-height: var(--o-line_height-text1); + + --message-color: var(--o-color-info1); + + --message-radius: var(--o-radius-control-m); +} + +.o-message-normal { + --message-bg-color: var(--o-color-control-light); + --message-bd-color: var(--o-color-control1); +} + +.o-message-success { + --message-bg-color: var(--o-color-success4-light); + --message-bd-color: var(--o-color-success1); +} + +.o-message-warning { + --message-bg-color: var(--o-color-warning4-light); + --message-bd-color: var(--o-color-warning1); +} + +.o-message-danger { + --message-bg-color: var(--o-color-danger4-light); + --message-bd-color: var(--o-color-danger1); +} diff --git a/packages/opendesign/src/components/message/types.ts b/packages/opendesign/src/components/message/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..6f7d7b190b24f3c9afbb9a8287903cc809240ab5 --- /dev/null +++ b/packages/opendesign/src/components/message/types.ts @@ -0,0 +1,26 @@ +import type { ExtractPropTypes, PropType } from 'vue'; +import { ColorT } from '../_shared/global'; + +export const messageProps = { + color: { + type: String as PropType, + default: 'normal', + }, + content: { + type: String, + default: '', + }, + duration: { + type: Number, + default: 3000, + }, + onClose: { + type: Function as PropType<() => void>, + }, +}; + +export type MessagePropsT = ExtractPropTypes; + +export type MessagePositionT = 'top' | 'bottom'; + +export type MessageParamsT = Partial; diff --git a/packages/opendesign/src/components/message/use-message.ts b/packages/opendesign/src/components/message/use-message.ts new file mode 100644 index 0000000000000000000000000000000000000000..4df6da19a1718eb1f4545073b8f423a0e35a9480 --- /dev/null +++ b/packages/opendesign/src/components/message/use-message.ts @@ -0,0 +1,108 @@ +import { createVNode, render } from 'vue'; +import { isString } from '../_shared/is'; +import { MessageParamsT } from './types'; +import OMessageList from './OMessageList.vue'; + +const DEFAULT_OPTIONS: MessageParamsT = { + color: 'normal', + position: 'top', + duration: 3000, +}; + +const instanceMap = new Map(); + +const normalizeOptions = (params: MessageParamsT) => { + const options: MessageParamsT = !params || isString(params) ? { content: params } : params; + + const normalized = { + ...DEFAULT_OPTIONS, + ...options, + }; + + return normalized; +}; + +const showMessage = (params: MessageParamsT) => { + const { position } = params; + + const instance = instanceMap.get(position); + if (!instance) { + let wrap: HTMLDivElement | null = document.createElement('div'); + + const vnode = createVNode(OMessageList, { + position: params.position, + onDestory: () => { + if (wrap) { + document.body.removeChild(wrap); + wrap = null; + } + instanceMap.set(position, undefined); + }, + }); + + render(vnode, wrap); + + const vm = vnode.component!; + vm.exposed?.add(params); + + instanceMap.set(position, vm); + + document.body.appendChild(wrap); + } else { + instance.exposed?.add(params); + } +}; + +const normal = (params: MessageParamsT): void => { + const options: MessageParamsT = normalizeOptions(params); + showMessage({ + ...options, + color: 'normal', + }); +}; + +const primary = (params: MessageParamsT): void => { + const options: MessageParamsT = normalizeOptions(params); + showMessage({ + ...options, + color: 'primary', + }); +}; + +const success = (params: MessageParamsT): void => { + const options: MessageParamsT = normalizeOptions(params); + showMessage({ + ...options, + color: 'success', + }); +}; + +const warning = (params: MessageParamsT): void => { + const options: MessageParamsT = normalizeOptions(params); + showMessage({ + ...options, + color: 'warning', + }); +}; + +const danger = (params: MessageParamsT): void => { + const options: MessageParamsT = normalizeOptions(params); + showMessage({ + ...options, + color: 'danger', + }); +}; + +const Message = { + normal, + primary, + success, + warning, + danger, +}; + +const useMessage = () => { + return Message; +}; + +export default useMessage; diff --git a/packages/portal/src/router.ts b/packages/portal/src/router.ts index f57e6dfadd7fd9fa23a8401f07a62d8eccb37a70..4848a27a4f82a518be22ee501fcb0d33a10a395b 100644 --- a/packages/portal/src/router.ts +++ b/packages/portal/src/router.ts @@ -68,6 +68,12 @@ export const routes = [ label: '下拉框', component: () => import('@components/select/__demo__/IndexSelect.vue'), }, + // { + // path: '/cascader', + // name: 'Cascader', + // label: '级联选择器', + // component: () => import('@components/cascader/__demo__/IndexCascader.vue'), + // }, { path: '/radio', name: 'Radio', @@ -164,6 +170,12 @@ export const routes = [ label: '卡片', component: () => import('@components/card/__demo__/IndexCard.vue'), }, + { + path: '/message', + name: 'Message', + label: '消息提示', + component: () => import('@components/message/__demo__/IndexMessage.vue'), + }, { path: '/resize-observer', name: 'ResizeObserver',