From a52022bc5a3521172644862abad5b1162e90cb72 Mon Sep 17 00:00:00 2001 From: epoll-j Date: Tue, 12 Nov 2024 17:05:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(dialog):=20dialog=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E5=AF=B9=E9=BD=90vue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit re #545 --- site/mobile/mobile.config.js | 2 +- src/dialog/Dialog.tsx | 349 ++++++++---------- src/dialog/_example/confirm.tsx | 59 +++ src/dialog/_example/feedback.jsx | 87 ----- src/dialog/_example/feedback.tsx | 74 ++++ src/dialog/_example/image-dialog.tsx | 63 ++++ src/dialog/_example/index.jsx | 63 ---- src/dialog/_example/index.tsx | 39 ++ src/dialog/_example/input.jsx | 69 ---- src/dialog/_example/input.tsx | 86 +++++ .../_example/{confirm.jsx => multi-state.tsx} | 106 +++--- src/dialog/_example/plugin.tsx | 26 ++ src/dialog/_example/style/index.less | 45 +-- src/dialog/defaultProps.ts | 16 + src/dialog/dialog.en-US.md | 71 ++++ src/dialog/dialog.md | 62 ++-- src/dialog/style/index.js | 2 +- src/dialog/type.ts | 60 ++- 18 files changed, 741 insertions(+), 538 deletions(-) create mode 100644 src/dialog/_example/confirm.tsx delete mode 100644 src/dialog/_example/feedback.jsx create mode 100644 src/dialog/_example/feedback.tsx create mode 100644 src/dialog/_example/image-dialog.tsx delete mode 100644 src/dialog/_example/index.jsx create mode 100644 src/dialog/_example/index.tsx delete mode 100644 src/dialog/_example/input.jsx create mode 100644 src/dialog/_example/input.tsx rename src/dialog/_example/{confirm.jsx => multi-state.tsx} (52%) create mode 100644 src/dialog/_example/plugin.tsx create mode 100644 src/dialog/defaultProps.ts create mode 100644 src/dialog/dialog.en-US.md diff --git a/site/mobile/mobile.config.js b/site/mobile/mobile.config.js index cb9a29f6..8907ea1d 100644 --- a/site/mobile/mobile.config.js +++ b/site/mobile/mobile.config.js @@ -135,7 +135,7 @@ export default { { title: 'Dialog 对话框', name: 'dialog', - component: () => import('tdesign-mobile-react/dialog/_example/index.jsx'), + component: () => import('tdesign-mobile-react/dialog/_example/index.tsx'), }, { title: 'Loading 加载中', diff --git a/src/dialog/Dialog.tsx b/src/dialog/Dialog.tsx index e3ed3288..ba105fcd 100644 --- a/src/dialog/Dialog.tsx +++ b/src/dialog/Dialog.tsx @@ -1,82 +1,92 @@ -import React, { CSSProperties, useCallback, useMemo, useState } from 'react'; -import { useSpring, animated } from '@react-spring/web'; -import ClassNames from 'classnames'; -import useUnmountedRef from 'ahooks/lib/useUnmountedRef'; -import Overlay from '../overlay'; -import { ButtonProps, TdButtonProps } from '../button'; -import { StyledProps, TNode } from '../common'; -import useConfig from '../_util/useConfig'; -import withStopPropagation, { PropagationEvent } from '../_util/withStopPropagation'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import get from 'lodash/get'; +import isString from 'lodash/isString'; +import { CloseIcon } from 'tdesign-icons-react'; +import classNames from 'classnames'; +import Popup from '../popup'; +import Button from '../button'; +import { StyledProps } from '../common'; +import { dialogDefaultProps } from './defaultProps'; import { TdDialogProps } from './type'; -import DialogActionBtn from './DialogActionBtn'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { usePrefixClass } from '../hooks/useClass'; +import parseTNode from '../_util/parseTNode'; export interface DialogProps extends TdDialogProps, StyledProps {} export const Dialog: React.FC = (props) => { const { className, - showOverlay = true, + showOverlay, destroyOnClose, onOverlayClick, - closeOnOverlayClick = true, - buttonLayout = 'horizontal', + overlayProps, + closeOnOverlayClick, + buttonLayout, onClose, visible, title, content, + children, actions, cancelBtn, confirmBtn, onCancel, onClosed, onConfirm, - preventScrollThrough = true, - zIndex = 1501, + preventScrollThrough, + zIndex, style, - } = props; - const { classPrefix } = useConfig(); - const unmountRef = useUnmountedRef(); - - const prefix = useMemo(() => `${classPrefix}-dialog`, [classPrefix]); - - const cls = useCallback((name?: string) => (name ? `${prefix}__${name}` : prefix), [prefix]); - - const btnLayout = useMemo(() => { - // 按钮超过两个,强制垂直布局 - if (actions && actions.length > 2) return 'vertical'; + width, + closeBtn, + middle, + top, + } = useDefaultProps(props, dialogDefaultProps); + + const dialogClass = usePrefixClass('dialog'); + const rootStyles = useMemo(() => ({ width: isString(width) ? width : `${width}px` }), [width]); + const isTextStyleBtn = useMemo( + () => [confirmBtn, cancelBtn, ...(actions || [])].some((item) => get(item, 'variant') === 'text'), + [actions, cancelBtn, confirmBtn], + ); + const footerClass = useMemo( + () => + classNames(`${dialogClass}__footer`, { + [`${dialogClass}__footer--column`]: buttonLayout === 'vertical', + [`${dialogClass}__footer--full`]: isTextStyleBtn && get(actions, 'length', 0) === 0, + }), + [actions, buttonLayout, dialogClass, isTextStyleBtn], + ); + const buttonClass = useMemo( + () => + classNames(`${dialogClass}__button`, { + [`${dialogClass}__button--${buttonLayout}`]: !isTextStyleBtn, + [`${dialogClass}__button--text`]: isTextStyleBtn, + }), + [buttonLayout, dialogClass, isTextStyleBtn], + ); - return buttonLayout; - }, [buttonLayout, actions]); + const calcBtn = (btn: any) => (isString(btn) ? { content: btn } : btn); + const actionsBtnProps = useMemo(() => actions?.map((item) => calcBtn(item)), [actions]); + const confirmBtnProps = useMemo( + () => ({ + theme: 'primary', + ...calcBtn(confirmBtn), + }), + [confirmBtn], + ); + const cancelBtnProps = useMemo( + () => ({ + theme: isTextStyleBtn ? 'default' : 'light', + ...calcBtn(cancelBtn), + }), + [cancelBtn, isTextStyleBtn], + ); const [active, setActive] = useState(visible); - - // 弹窗主体动画 - const dialogSpring = useSpring({ - scale: visible ? 1 : 0.8, - opacity: visible ? 1 : 0, - onStart: () => { - setActive(true); - }, - onRest: () => { - if (unmountRef.current) return; - setActive(visible); - - if (!visible && typeof onClosed === 'function') { - onClosed(); - } - }, - }); - - // 蒙层动画 - const maskSpring = useSpring({ - opacity: visible ? 1 : 0, - onStart: () => { - setActive(true); - }, - onRest: () => { - setActive(visible); - }, - }); + useEffect(() => { + setActive(visible); + }, [visible]); // 蒙层点击事件 const onOverlayClickHandle = useCallback( @@ -86,159 +96,114 @@ export const Dialog: React.FC = (props) => { } if (closeOnOverlayClick && typeof onClose === 'function') { + setActive(false); onClose({ trigger: 'overlay', e }); } }, [onOverlayClick, closeOnOverlayClick, onClose], ); - // 弹窗按钮 - const dialogActions = useMemo>(() => { - // 按钮类名 - const btnClassName = ClassNames(cls('btn'), cls(`${btnLayout}-btn`)); - const btnCommonProps = { - className: btnClassName, - }; - // 为外部传入的按钮添加类名 - if (actions && actions.length) - return actions.map((action) => { - if (React.isValidElement(action)) return React.cloneElement(action, { className: btnClassName } as unknown); - - return { - ...btnCommonProps, - ...action, - className: ClassNames((action as ButtonProps).className, btnClassName), - }; - }); - - const defaultActions: Array = [ - { - ...btnCommonProps, - content: '', - theme: 'default', - onClick: async (e) => { - if (typeof onCancel === 'function') { - await Promise.all([onCancel({ e })]); - } - - if (typeof onClose === 'function') { - onClose({ trigger: 'cancel', e }); - } - }, - }, - { - ...btnCommonProps, - content: '', - theme: 'primary', - onClick: async (e) => { - if (typeof onConfirm === 'function') { - await Promise.all([onConfirm({ e })]); - } - }, - }, - ]; - - if (cancelBtn) { - if (typeof cancelBtn === 'string') { - (defaultActions[0] as TdButtonProps).content = cancelBtn; - } else if (typeof cancelBtn === 'object') { - defaultActions[0] = { - ...(defaultActions[0] as ButtonProps), - ...cancelBtn, - }; - } else { - defaultActions[0] = cancelBtn; + const onCloseButtonClickHandle = useCallback( + (e) => { + if (typeof onClose === 'function') { + onClose({ trigger: 'close-btn', e }); } - } + setActive(false); + }, + [onClose], + ); - if (confirmBtn) { - if (typeof confirmBtn === 'string') { - (defaultActions[1] as TdButtonProps).content = confirmBtn; - } else if (typeof confirmBtn === 'object') { - defaultActions[1] = { - ...(defaultActions[1] as ButtonProps), - ...confirmBtn, - }; - } else { - defaultActions[1] = confirmBtn; + const onCancelButtonClickHandle = useCallback( + (e) => { + setActive(false); + if (typeof onClose === 'function') { + onClose({ trigger: 'cancel', e }); + } + if (typeof onCancel === 'function') { + onCancel({ e }); } - } - - const btns = defaultActions - .filter((btn) => { - if (typeof btn === 'object') return !!(btn as TdButtonProps).content || !!(btn as TdButtonProps).children; - - return !!btn; - }) - .map((action: ButtonProps | TNode) => { - if (React.isValidElement(action)) return React.cloneElement(action, { className: btnClassName } as unknown); - - return { - ...(action as ButtonProps), - className: ClassNames((action as ButtonProps).className, btnClassName), - }; - }); - - return btnLayout === 'vertical' ? btns.reverse() : btns; - }, [actions, btnLayout, cancelBtn, cls, confirmBtn, onCancel, onClose, onConfirm]); - - // Dialog Dom - const dialog = useMemo( - () => { - if (destroyOnClose && !active) return <>; - - return ( -
- - - -
- ); }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [active], + [onCancel, onClose], ); - const wrapStyle = useMemo( - () => ({ - zIndex, - position: 'fixed', - top: '50%', - left: '50%', - transform: 'translate(-50%,-50%)', - }), - [zIndex], + const onConfirmButtonClickHandle = useCallback( + (e) => { + setActive(false); + if (typeof onConfirm === 'function') { + onConfirm(e); + } + }, + [onConfirm], ); - const node = ( -
{ + const contentNode = parseTNode(children, null, content); + if (!contentNode) { + return null; + } + + return ( +
+
{contentNode}
+
+ ); + }; + + const renderActionsNode = () => { + const actionsNode = parseTNode(actions); + if (actionsNode && actionsBtnProps) { + return actionsBtnProps.map((item, index) => ( + + )); + } + }; + + const renderCancelButtonNode = () => { + const cancelButtonNode = parseTNode(cancelBtn); + if (!actions && cancelButtonNode) { + return ; + } + }; + + const renderConfirmButtonNode = () => { + const confirmButtonNode = parseTNode(confirmBtn); + if (!actions && confirmButtonNode) { + return ; + } + }; + + return ( + - {showOverlay ? ( - - - - ) : null} -
- {dialog} +
+ {parseTNode(top)} + {closeBtn && ( +
+ +
+ )} +
+ {title &&
{parseTNode(title)}
} + {renderContentNode()} +
+ {parseTNode(middle)} +
+ {renderActionsNode()} + {renderCancelButtonNode()} + {renderConfirmButtonNode()} +
-
+
); - - return withStopPropagation(preventScrollThrough ? [PropagationEvent.SCROLL] : [], node); }; export default Dialog; diff --git a/src/dialog/_example/confirm.tsx b/src/dialog/_example/confirm.tsx new file mode 100644 index 00000000..90748872 --- /dev/null +++ b/src/dialog/_example/confirm.tsx @@ -0,0 +1,59 @@ +import React, { useState } from 'react'; +import { Dialog, Button, DialogProps } from 'tdesign-mobile-react'; + +const ConfirmUsage = React.memo(() => { + const [alertProps, setAlertProps] = useState({ visible: false } as DialogProps); + + return ( +
+ {/* 普通调用 */} + +
+ + + { + setAlertProps({ visible: false }); + }} + onConfirm={() => { + setAlertProps({ visible: false }); + }} + /> +
+ ); +}); + +export default ConfirmUsage; diff --git a/src/dialog/_example/feedback.jsx b/src/dialog/_example/feedback.jsx deleted file mode 100644 index bf0b5efb..00000000 --- a/src/dialog/_example/feedback.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import React, { useState } from 'react'; -import { Dialog, Button } from 'tdesign-mobile-react'; - -const FeedbackUsage = React.memo(() => { - const [alertProps, setAlertProps] = useState({ visible: false }); - - return ( -
- {/* 普通调用 */} - - - - - - - - - { - setAlertProps({ visible: false }); - }} - onConfirm={() => { - setAlertProps({ visible: false }); - }} - /> -
- ); -}); - -export default FeedbackUsage; diff --git a/src/dialog/_example/feedback.tsx b/src/dialog/_example/feedback.tsx new file mode 100644 index 00000000..49f605b3 --- /dev/null +++ b/src/dialog/_example/feedback.tsx @@ -0,0 +1,74 @@ +import React, { useState } from 'react'; +import { Dialog, Button, DialogProps } from 'tdesign-mobile-react'; + +const Feedback = React.memo(() => { + const [alertProps, setAlertProps] = useState({ visible: false } as DialogProps); + + return ( +
+ +
+ +
+ + { + setAlertProps({ visible: false }); + }} + onConfirm={() => { + setAlertProps({ visible: false }); + }} + /> +
+ ); +}); + +export default Feedback; diff --git a/src/dialog/_example/image-dialog.tsx b/src/dialog/_example/image-dialog.tsx new file mode 100644 index 00000000..8be9e08b --- /dev/null +++ b/src/dialog/_example/image-dialog.tsx @@ -0,0 +1,63 @@ +import React, { useState } from 'react'; +import { Dialog, Button, DialogProps, Image } from 'tdesign-mobile-react'; + +const ImageUsage = React.memo(() => { + const [alertProps, setAlertProps] = useState({ visible: false } as DialogProps); + + return ( +
+ {/* 普通调用 */} + +
+ + + { + setAlertProps({ visible: false }); + }} + onConfirm={() => { + setAlertProps({ visible: false }); + }} + /> +
+ ); +}); + +export default ImageUsage; diff --git a/src/dialog/_example/index.jsx b/src/dialog/_example/index.jsx deleted file mode 100644 index 1a2c68a9..00000000 --- a/src/dialog/_example/index.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react'; -import { Dialog, Button } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; -import TDemoHeader from '../../../site/mobile/components/DemoHeader'; -import FeedbackUsage from './feedback'; -import ConfirmUsage from './confirm'; -import InputUsage from './input'; -import './style/index.less'; - -export default function Base() { - return ( - <> - - - - - - - - - - - -
- - -
-
- - ); -} diff --git a/src/dialog/_example/index.tsx b/src/dialog/_example/index.tsx new file mode 100644 index 00000000..c2144da1 --- /dev/null +++ b/src/dialog/_example/index.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import TDemoBlock from '../../../site/mobile/components/DemoBlock'; +import TDemoHeader from '../../../site/mobile/components/DemoHeader'; +import FeedbackUsage from './feedback'; +import ConfirmUsage from './confirm'; +import InputUsage from './input'; +import ImageUsage from './image-dialog'; +import MultiStateUsage from './multi-state'; +import PluginUsage from './plugin'; +import './style/index.less'; + +export default function Base() { + return ( +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/src/dialog/_example/input.jsx b/src/dialog/_example/input.jsx deleted file mode 100644 index de6fca2a..00000000 --- a/src/dialog/_example/input.jsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useState } from 'react'; -import { Dialog, Button } from 'tdesign-mobile-react'; - -const InputUsage = React.memo(() => { - const [visible, setVisible] = useState(false); - - return ( -
- - - - - } - destroyOnClose - onClose={() => { - setVisible(false); - }} - onConfirm={() => { - setVisible(false); - }} - /> -
- ); -}); - -export default InputUsage; diff --git a/src/dialog/_example/input.tsx b/src/dialog/_example/input.tsx new file mode 100644 index 00000000..e6169abe --- /dev/null +++ b/src/dialog/_example/input.tsx @@ -0,0 +1,86 @@ +import React, { useState } from 'react'; +import { Dialog, Button, DialogProps, Input } from 'tdesign-mobile-react'; + +const InputUsage = React.memo(() => { + const [alertProps, setAlertProps] = useState({ visible: false } as DialogProps); + + return ( +
+ {/* 普通调用 */} + +
+ + + { + setAlertProps({ visible: false }); + }} + onConfirm={() => { + setAlertProps({ visible: false }); + }} + /> +
+ ); +}); + +export default InputUsage; diff --git a/src/dialog/_example/confirm.jsx b/src/dialog/_example/multi-state.tsx similarity index 52% rename from src/dialog/_example/confirm.jsx rename to src/dialog/_example/multi-state.tsx index 42b3284b..34571294 100644 --- a/src/dialog/_example/confirm.jsx +++ b/src/dialog/_example/multi-state.tsx @@ -1,8 +1,19 @@ import React, { useState } from 'react'; -import { Dialog, Button } from 'tdesign-mobile-react'; +import { Dialog, Button, DialogProps } from 'tdesign-mobile-react'; -const ConfirmUsage = React.memo(() => { - const [alertProps, setAlertProps] = useState({ visible: false }); +const MultiStateUsage = React.memo(() => { + const [alertProps, setAlertProps] = useState({ visible: false } as DialogProps); + + const cancelBtn = { + content: '取消', + variant: 'text', + size: 'large', + }; + const confirmBtn = { + content: '确认', + variant: 'text', + size: 'large', + }; return (
@@ -10,100 +21,103 @@ const ConfirmUsage = React.memo(() => { - +
- +
- +
+
+ - { setAlertProps({ visible: false }); }} @@ -115,4 +129,4 @@ const ConfirmUsage = React.memo(() => { ); }); -export default ConfirmUsage; +export default MultiStateUsage; diff --git a/src/dialog/_example/plugin.tsx b/src/dialog/_example/plugin.tsx new file mode 100644 index 00000000..317b5423 --- /dev/null +++ b/src/dialog/_example/plugin.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Dialog, Button } from 'tdesign-mobile-react'; + +const PluginUsage = React.memo(() => ( +
+ +
+)); + +export default PluginUsage; diff --git a/src/dialog/_example/style/index.less b/src/dialog/_example/style/index.less index 931c6e75..b684143f 100644 --- a/src/dialog/_example/style/index.less +++ b/src/dialog/_example/style/index.less @@ -1,36 +1,19 @@ -.t-dialog__demo-wrap { - padding: 10px; - box-sizing: border-box; +.tdesign-mobile-demo { + background-color: #fff; - & > .t-button { - margin: 10px 0; + .btn-gap { + width: 100%; + height: 16px; } -} - -.t-dialog__demo-input { - margin: 0 auto; - padding: 12px; - width: 100%; - border: none; - border-radius: 4px; - background-color: #f3f3f3; - font-size: 16px; - line-height: 1; - display: block; - margin-top: 8px; - color: rgba(0, 0, 0, .9); - box-sizing: border-box; - - &::placeholder { - line-height: 24px; - color: rgba(0, 0, 0, .4); + .middle-container { + padding: 20px; + overflow: auto; + max-height: 100px; } } - -.t-dialog__demo-tips { - margin: 0 auto 16px; -} - -#app { - background-color: #fff; +.t-input { + margin-top: 16px; + --td-input-vertical-padding: 12px; + --td-bg-color-container: var(--td-bg-color-page, #f3f3f3); + border-radius: 6px; } \ No newline at end of file diff --git a/src/dialog/defaultProps.ts b/src/dialog/defaultProps.ts new file mode 100644 index 00000000..2a0a9ba6 --- /dev/null +++ b/src/dialog/defaultProps.ts @@ -0,0 +1,16 @@ +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +import { TdDialogProps } from './type'; + +export const dialogDefaultProps: TdDialogProps = { + buttonLayout: 'horizontal', + closeBtn: false, + closeOnOverlayClick: false, + confirmLoading: undefined, + destroyOnClose: false, + overlayProps: {}, + preventScrollThrough: true, + showOverlay: true, +}; diff --git a/src/dialog/dialog.en-US.md b/src/dialog/dialog.en-US.md new file mode 100644 index 00000000..36a89ce8 --- /dev/null +++ b/src/dialog/dialog.en-US.md @@ -0,0 +1,71 @@ +:: BASE_DOC :: + +## API + +### Dialog Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +actions | TNode | - | Typescript:`Array`,[Button API Documents](./button?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N +buttonLayout | String | horizontal | options: horizontal/vertical | N +cancelBtn | TNode | - | Typescript:`string \| ButtonProps \| TNode \| null`,[Button API Documents](./button?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N +closeBtn | Boolean | false | \- | N +closeOnOverlayClick | Boolean | false | \- | N +confirmBtn | TNode | - | Typescript:`string \| ButtonProps \| TNode \| null`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +confirmLoading | Boolean | undefined | confirm button loading status | N +content | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +destroyOnClose | Boolean | false | \- | N +middle | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +overlayProps | Object | {} | Typescript:`OverlayProps`,[Overlay API Documents](./overlay?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N +preventScrollThrough | Boolean | true | \- | N +showOverlay | Boolean | true | \- | N +title | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +top | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +visible | Boolean | - | \- | N +width | String / Number | - | \- | N +zIndex | Number | - | \- | N +onCancel | Function | | Typescript:`(context: { e: MouseEvent }) => void`
| N +onClose | Function | | Typescript:`(context: DialogCloseContext) => void`
[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts)。
`type DialogEventSource = 'cancel' \| 'overlay' \| 'close-btn'`

`interface DialogCloseContext { trigger: DialogEventSource; e: MouseEvent }`
| N +onClosed | Function | | Typescript:`() => void`
| N +onConfirm | Function | | Typescript:`(context: { e: MouseEvent }) => void`
| N +onOverlayClick | Function | | Typescript:`(context: { e: MouseEvent }) => void`
| N + +### DialogOptions + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | \- | N +style | Object | - | Typescript:`Styles`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +`Omit` | \- | - | extends `Omit` | N + +### DialogInstance + +name | params | return | description +-- | -- | -- | -- +destroy | \- | \- | required +hide | \- | \- | required +setConfirmLoading | `(loading: boolean)` | \- | required。set confirm button loading status +show | \- | \- | required +update | `(props: DialogOptions)` | \- | required + +### dialog 或 DialogPlugin + +name | params | default | description +-- | -- | -- | -- +options | \- | - | Typescript:`DialogOptions` + +插件返回值:`DialogInstance` + +### dialog.confirm 或 DialogPlugin.confirm + +name | params | default | description +-- | -- | -- | -- +options | \- | - | Typescript:`DialogOptions` + +### dialog.alert 或 DialogPlugin.alert + +name | params | default | description +-- | -- | -- | -- +options | Object | - | Typescript:`Omit` diff --git a/src/dialog/dialog.md b/src/dialog/dialog.md index 95843dbb..90a58a32 100644 --- a/src/dialog/dialog.md +++ b/src/dialog/dialog.md @@ -1,75 +1,71 @@ :: BASE_DOC :: ## API + ### Dialog Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -actions | TNode | - | 操作栏。TS 类型:`Array`,[Button API Documents](./button?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N +actions | TNode | - | 操作栏。TS 类型:`Array`,[Button API Documents](./button?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N buttonLayout | String | horizontal | 多按钮排列方式。可选项:horizontal/vertical | N -cancelBtn | TNode | '' | 取消按钮,可自定义。值为 null 则不显示取消按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制取消事件。TS 类型:`string | ButtonProps | TNode`,[Button API Documents](./button?tab=api)。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N -closeOnOverlayClick | Boolean | true | 点击蒙层时是否触发关闭事件 | N -confirmBtn | TNode | '' | 确认按钮。值为 null 则不显示确认按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制确认事件。TS 类型:`string | ButtonProps | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -content | TNode | - | 内容。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +cancelBtn | TNode | - | 取消按钮,可自定义。值为 null 则不显示取消按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制取消事件。TS 类型:`string \| ButtonProps \| TNode \| null`,[Button API Documents](./button?tab=api)。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N +closeBtn | Boolean | false | 多按钮排列方式。可选项:true/false | N +closeOnOverlayClick | Boolean | false | 点击蒙层时是否触发关闭事件 | N +confirmBtn | TNode | - | 确认按钮。值为 null 则不显示确认按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制确认事件。TS 类型:`string \| ButtonProps \| TNode \| null`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +confirmLoading | Boolean | undefined | 确认按钮加载状态 | N +content | TNode | - | 内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N destroyOnClose | Boolean | false | 是否在关闭弹框的时候销毁子元素 | N +middle | TNode | - | 中间自定义内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +overlayProps | Object | {} | 透传至 Overlay 组件。TS 类型:`OverlayProps`,[Overlay API Documents](./overlay?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts) | N preventScrollThrough | Boolean | true | 防止滚动穿透 | N showOverlay | Boolean | true | 是否显示遮罩层 | N -title | TNode | - | 标题。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -visible | Boolean | false | 控制对话框是否显示 | N +title | TNode | - | 标题。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +top | TNode | - | 顶部自定义内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +visible | Boolean | - | 控制对话框是否显示 | N +width | String / Number | - | 对话框宽度,示例:320, '500px', '80%' | N zIndex | Number | - | 对话框层级,Web 侧样式默认为 2500,移动端和小程序样式默认为 1500 | N onCancel | Function | | TS 类型:`(context: { e: MouseEvent }) => void`
如果“取消”按钮存在,则点击“取消”按钮时触发,同时触发关闭事件 | N -onClose | Function | | TS 类型:`(context: DialogCloseContext) => void`
关闭事件,点击 取消按钮 或 点击蒙层 时触发。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts)。
`type DialogEventSource = 'cancel' | 'overlay'`

`interface DialogCloseContext { trigger: DialogEventSource; e: MouseEvent }`
| N +onClose | Function | | TS 类型:`(context: DialogCloseContext) => void`
关闭事件,点击 取消按钮 或 点击蒙层 时触发。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/dialog/type.ts)。
`type DialogEventSource = 'cancel' \| 'overlay' \| 'close-btn'`

`interface DialogCloseContext { trigger: DialogEventSource; e: MouseEvent }`
| N onClosed | Function | | TS 类型:`() => void`
对话框消失动画效果结束后触发 | N onConfirm | Function | | TS 类型:`(context: { e: MouseEvent }) => void`
如果“确认”按钮存在,则点击“确认”按钮时触发 | N onOverlayClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void`
如果蒙层存在,点击蒙层时触发 | N ### DialogOptions -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 弹框类名,示例:'t-class-dialog-first t-class-dialog-second' | N style | Object | - | 弹框 style 属性,输入 [CSSStyleDeclaration.cssText](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText)。TS 类型:`Styles`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -`Omit` | - | - | 继承 `Omit` 中的全部 API | N +`Omit` | \- | - | 继承 `Omit` 中的全部属性 | N ### DialogInstance 名称 | 参数 | 返回值 | 描述 -- | -- | -- | -- -destroy | - | - | 销毁弹框 -hide | - | - | 隐藏弹框 -show | - | - | 显示弹框 -update | `(props: DialogOptions)` | - | 更新弹框内容 +destroy | \- | \- | 必需。销毁弹框 +hide | \- | \- | 必需。隐藏弹框 +setConfirmLoading | `(loading: boolean)` | \- | 必需。设置确认按钮加载状态 +show | \- | \- | 必需。显示弹框 +update | `(props: DialogOptions)` | \- | 必需。更新弹框内容 ### dialog 或 DialogPlugin -这是一个插件函数,参数形式为顺序参数(形如:(a, b, c)),而非对象参数(形如:({ a, b, c }))。顺序参数如下, - -参数名称 | 参数类型 | 参数默认值 | 参数说明 +参数名称 | 参数类型 | 参数默认值 | 参数描述 -- | -- | -- | -- -className | String | - | 类名 | N -style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -options | - | - | TS 类型:`DialogOptions` +options | \- | - | TS 类型:`DialogOptions` 插件返回值:`DialogInstance` ### dialog.confirm 或 DialogPlugin.confirm -这是一个插件函数,参数形式为顺序参数(形如:(a, b, c)),而非对象参数(形如:({ a, b, c }))。顺序参数如下, - -参数名称 | 参数类型 | 参数默认值 | 参数说明 +参数名称 | 参数类型 | 参数默认值 | 参数描述 -- | -- | -- | -- -className | String | - | 类名 | N -style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -options | - | - | TS 类型:`DialogOptions` +options | \- | - | TS 类型:`DialogOptions` ### dialog.alert 或 DialogPlugin.alert -这是一个插件函数,参数形式为顺序参数(形如:(a, b, c)),而非对象参数(形如:({ a, b, c }))。顺序参数如下, - -参数名称 | 参数类型 | 参数默认值 | 参数说明 +参数名称 | 参数类型 | 参数默认值 | 参数描述 -- | -- | -- | -- -className | String | - | 类名 | N -style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -options | Object | - | TS 类型:`Omit` +options | Object | - | TS 类型:`Omit` diff --git a/src/dialog/style/index.js b/src/dialog/style/index.js index 0f8b0ebd..49899d0a 100644 --- a/src/dialog/style/index.js +++ b/src/dialog/style/index.js @@ -1,2 +1,2 @@ /* eslint-disable import/no-relative-packages */ -import '../../_common/style/mobile/components/dialog/_index.less'; +import '../../_common/style/mobile/components/dialog/v2/_index.less'; diff --git a/src/dialog/type.ts b/src/dialog/type.ts index 49fdf07a..ba23bfd6 100644 --- a/src/dialog/type.ts +++ b/src/dialog/type.ts @@ -4,8 +4,8 @@ * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC * */ -import { TdButtonProps } from '../button'; import { ButtonProps } from '../button'; +import { OverlayProps } from '../overlay'; import { TNode, Styles } from '../common'; import { MouseEvent } from 'react'; @@ -13,7 +13,7 @@ export interface TdDialogProps { /** * 操作栏 */ - actions?: Array; + actions?: Array; /** * 多按钮排列方式 * @default horizontal @@ -21,19 +21,26 @@ export interface TdDialogProps { buttonLayout?: 'horizontal' | 'vertical'; /** * 取消按钮,可自定义。值为 null 则不显示取消按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制取消事件 - * @default '' */ - cancelBtn?: ButtonProps | TNode; + cancelBtn?: ButtonProps | TNode | null; + /** + * 多按钮排列方式。可选项:true/false + * @default false + */ + closeBtn?: boolean; /** * 点击蒙层时是否触发关闭事件 - * @default true + * @default false */ closeOnOverlayClick?: boolean; /** * 确认按钮。值为 null 则不显示确认按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制确认事件 - * @default '' */ - confirmBtn?: ButtonProps | TNode; + confirmBtn?: ButtonProps | TNode | null; + /** + * 确认按钮加载状态 + */ + confirmLoading?: boolean; /** * 内容 */ @@ -43,6 +50,15 @@ export interface TdDialogProps { * @default false */ destroyOnClose?: boolean; + /** + * 中间自定义内容 + */ + middle?: TNode; + /** + * 透传至 Overlay 组件 + * @default {} + */ + overlayProps?: OverlayProps; /** * 防止滚动穿透 * @default true @@ -57,11 +73,18 @@ export interface TdDialogProps { * 标题 */ title?: TNode; + /** + * 顶部自定义内容 + */ + top?: TNode; /** * 控制对话框是否显示 - * @default false */ visible?: boolean; + /** + * 对话框宽度,示例:320, '500px', '80%' + */ + width?: string | number; /** * 对话框层级,Web 侧样式默认为 2500,移动端和小程序样式默认为 1500 */ @@ -104,27 +127,34 @@ export interface DialogInstance { /** * 销毁弹框 */ - destroy?: () => void; + destroy: () => void; /** * 隐藏弹框 */ - hide?: () => void; + hide: () => void; + /** + * 设置确认按钮加载状态 + */ + setConfirmLoading: (loading: boolean) => void; /** * 显示弹框 */ - show?: () => void; + show: () => void; /** * 更新弹框内容 */ - update?: (props: DialogOptions) => void; + update: (props: DialogOptions) => void; } -export type DialogEventSource = 'cancel' | 'overlay'; +export type DialogEventSource = 'cancel' | 'overlay' | 'close-btn'; -export interface DialogCloseContext { trigger: DialogEventSource; e: MouseEvent }; +export interface DialogCloseContext { + trigger: DialogEventSource; + e: MouseEvent; +} export type DialogMethod = (options?: DialogOptions) => DialogInstance; export type DialogConfirmMethod = (options?: DialogOptions) => DialogInstance; -export type DialogAlertMethod = (options?: Omit) => DialogInstance; +export type DialogAlertMethod = (options?: Omit) => DialogInstance;