Skip to content

Commit

Permalink
fix(dialog): fix cancelBtn and confirmBtn slot not work
Browse files Browse the repository at this point in the history
  • Loading branch information
liweijie0812 committed Dec 3, 2024
1 parent eaaef59 commit b9d0231
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 47 deletions.
29 changes: 28 additions & 1 deletion src/dialog/__test__/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,34 @@ describe('dialog', () => {
expect(onClose).toHaveBeenCalledWith({ e: expect.any(MouseEvent), trigger: 'overlay' });
});
});

describe('slots', () => {
it(':confirmBtn', async () => {
const visible = true;
const confirmBtn = 'confirm';
const wrapper = mount(Dialog, {
props: {
visible,
},
slots: {
confirmBtn: `<button class="slot-confirm-btn">${confirmBtn}</button>`,
},
});
expect(wrapper.find('.slot-confirm-btn').text()).toBe(confirmBtn);
});
it(':cancelBtn', async () => {
const visible = true;
const cancelBtn = 'cancel';
const wrapper = mount(Dialog, {
props: {
visible,
},
slots: {
cancelBtn: `<button class="slot-cancel-btn">${cancelBtn}</button>`,
},
});
expect(wrapper.find('.slot-cancel-btn').text()).toBe(cancelBtn);
});
});
describe('event', () => {
it(':cancel && confirm && close', async () => {
const visible = true;
Expand Down
16 changes: 7 additions & 9 deletions src/dialog/dialog.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
name | type | default | description | required
-- | -- | -- | -- | --
actions | Array / Slot / Function | - | Typescript:`Array<ButtonProps>`[Button API Documents](./button?tab=api)[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts) | N
buttonLayout | String | horizontal | optionshorizontal/vertical | N
buttonLayout | String | horizontal | options: horizontal/vertical | N
cancelBtn | String / Object / Slot / Function | - | Typescript:`string \| ButtonProps \| TNode \| null`[Button API Documents](./button?tab=api)[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts) | N
closeOnOverlayClick | Boolean | undefined | \- | N
closeBtn | Boolean | false | \- | N
closeOnOverlayClick | Boolean | false | \- | N
confirmBtn | String / Object / Slot / Function | - | Typescript:`string \| ButtonProps \| TNode \| null`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
content | String / Slot / Function | - | Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
destroyOnClose | Boolean | false | \- | N
overlayProps | Object | {} | \- | N
overlayProps | Object | {} | Typescript:`OverlayProps`[Overlay API Documents](./overlay?tab=api)[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts) | N
preventScrollThrough | Boolean | true | \- | N
showOverlay | Boolean | true | \- | N
title | String / Slot / Function | - | Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
Expand All @@ -32,6 +33,7 @@ name | params | description
-- | -- | --
cancel | `(context: { e: MouseEvent })` | \-
close | `(context: DialogCloseContext)` | [see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts)。<br/>`type DialogEventSource = 'cancel' \| 'overlay'`<br/><br/>`interface DialogCloseContext { trigger: DialogEventSource; e: MouseEvent }`<br/>
closed | \- | \-
confirm | `(context: { e: MouseEvent })` | \-
overlay-click | `(context: { e: MouseEvent })` | \-

Expand Down Expand Up @@ -70,8 +72,6 @@ name | params | default | description
-- | -- | -- | --
options | \- | - | Typescript:`DialogOptions`

插件返回值:`DialogInstance`

### DialogPlugin.alert

同时也支持 `this.$dialog.alert`
Expand All @@ -80,10 +80,8 @@ name | params | default | description
-- | -- | -- | --
options | Object | - | Typescript:`Omit<DialogOptions, 'cancelBtn'>`

插件返回值:`DialogInstance`


### CSS Variables

The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
Expand All @@ -97,4 +95,4 @@ Name | Default Value | Description
--td-dialog-title-color | @font-gray-1 | -
--td-dialog-title-font-size | 18px | -
--td-dialog-title-line-height | 26px | -
--td-dialog-width | 311px | -
--td-dialog-width | 311px | -
26 changes: 12 additions & 14 deletions src/dialog/dialog.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
:: BASE_DOC ::

## API

### Dialog Props

名称 | 类型 | 默认值 | 说明 | 必传
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
actions | Array / Slot / Function | - | 操作栏。TS 类型:`Array<ButtonProps>`[Button API Documents](./button?tab=api)[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts) | N
buttonLayout | String | horizontal | 多按钮排列方式。可选项:horizontal/vertical | N
cancelBtn | String / Object / Slot / Function | - | 取消按钮,可自定义。值为 null 则不显示取消按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制取消事件。TS 类型:`string \| ButtonProps \| TNode \| null`[Button API Documents](./button?tab=api)[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts) | N
closeBtn | Boolean | false | 多按钮排列方式。可选项:true/false | N
closeOnOverlayClick | Boolean | undefined | 点击蒙层时是否触发关闭事件 | N
closeOnOverlayClick | Boolean | false | 点击蒙层时是否触发关闭事件 | N
confirmBtn | String / Object / Slot / Function | - | 确认按钮。值为 null 则不显示确认按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制确认事件。TS 类型:`string \| ButtonProps \| TNode \| null`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
content | String / Slot / Function | - | 内容。TS 类型:`string \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
destroyOnClose | Boolean | false | 是否在关闭弹框的时候销毁子元素 | N
overlayProps | Object | {} | 透传至 Overlay 组件 | N
overlayProps | Object | {} | 透传至 Overlay 组件。TS 类型:`OverlayProps`[Overlay API Documents](./overlay?tab=api)[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts) | N
preventScrollThrough | Boolean | true | 防止滚动穿透 | N
showOverlay | Boolean | true | 是否显示遮罩层 | N
title | String / Slot / Function | - | 标题。TS 类型:`string \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
Expand All @@ -22,7 +23,7 @@ width | String / Number | - | 对话框宽度,示例:320, '500px', '80%' | N
zIndex | Number | - | 对话框层级,Web 侧样式默认为 2500,移动端和小程序样式默认为 1500 | N
onCancel | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>如果“取消”按钮存在,则点击“取消”按钮时触发,同时触发关闭事件 | N
onClose | Function | | TS 类型:`(context: DialogCloseContext) => void`<br/>关闭事件,点击 取消按钮 或 点击蒙层 时触发。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts)。<br/>`type DialogEventSource = 'cancel' \| 'overlay'`<br/><br/>`interface DialogCloseContext { trigger: DialogEventSource; e: MouseEvent }`<br/> | N
onClosed | Function | | TS 类型:`() => void`<br/>组件关闭且动画结束后执行。 | N
onClosed | Function | | TS 类型:`() => void`<br/>对话框消失动画效果结束后触发 | N
onConfirm | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>如果“确认”按钮存在,则点击“确认”按钮时触发 | N
onOverlayClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>如果蒙层存在,点击蒙层时触发 | N

Expand All @@ -32,12 +33,13 @@ onOverlayClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void
-- | -- | --
cancel | `(context: { e: MouseEvent })` | 如果“取消”按钮存在,则点击“取消”按钮时触发,同时触发关闭事件
close | `(context: DialogCloseContext)` | 关闭事件,点击 取消按钮 或 点击蒙层 时触发。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/dialog/type.ts)。<br/>`type DialogEventSource = 'cancel' \| 'overlay'`<br/><br/>`interface DialogCloseContext { trigger: DialogEventSource; e: MouseEvent }`<br/>
closed | \- | 对话框消失动画效果结束后触发
confirm | `(context: { e: MouseEvent })` | 如果“确认”按钮存在,则点击“确认”按钮时触发
overlay-click | `(context: { e: MouseEvent })` | 如果蒙层存在,点击蒙层时触发

### DialogOptions

名称 | 类型 | 默认值 | 说明 | 必传
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
className | String | - | 弹框类名,示例:'t-class-dialog-first t-class-dialog-second' | N
style | String / Object | - | 弹框 style 属性,输入 [CSSStyleDeclaration.cssText](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText)。TS 类型:`string \| Styles`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
Expand All @@ -56,7 +58,7 @@ update | `(props: DialogOptions)` | \- | 必需。更新弹框内容

同时也支持 `this.$dialog`

参数名称 | 参数类型 | 参数默认值 | 参数说明
参数名称 | 参数类型 | 参数默认值 | 参数描述
-- | -- | -- | --
options | \- | - | TS 类型:`DialogOptions`

Expand All @@ -66,24 +68,20 @@ options | \- | - | TS 类型:`DialogOptions`

同时也支持 `this.$dialog.confirm`

参数名称 | 参数类型 | 参数默认值 | 参数说明
参数名称 | 参数类型 | 参数默认值 | 参数描述
-- | -- | -- | --
options | \- | - | TS 类型:`DialogOptions`

插件返回值:`DialogInstance`

### DialogPlugin.alert

同时也支持 `this.$dialog.alert`

参数名称 | 参数类型 | 参数默认值 | 参数说明
参数名称 | 参数类型 | 参数默认值 | 参数描述
-- | -- | -- | --
options | Object | - | TS 类型:`Omit<DialogOptions, 'cancelBtn'>`

插件返回值:`DialogInstance`


### CSS Variables

组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
Expand All @@ -97,4 +95,4 @@ options | Object | - | TS 类型:`Omit<DialogOptions, 'cancelBtn'>`
--td-dialog-title-color | @font-gray-1 | -
--td-dialog-title-font-size | 18px | -
--td-dialog-title-line-height | 26px | -
--td-dialog-width | 311px | -
--td-dialog-width | 311px | -
58 changes: 38 additions & 20 deletions src/dialog/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import { CloseIcon } from 'tdesign-icons-vue-next';
import { computed, defineComponent } from 'vue';
import get from 'lodash/get';
import isString from 'lodash/isString';
import isObject from 'lodash/isObject';

import TButton, { ButtonProps } from '../button';
import TPopup from '../popup';
import config from '../config';
import props from './props';
import { useTNodeJSX, useContent } from '../hooks/tnode';
import { usePrefixClass } from '../hooks/useClass';
import { TdDialogProps } from './type';

const { prefix } = config;

export default defineComponent({
name: `${prefix}-dialog`,
components: { TPopup, TButton, CloseIcon },
props,
emits: ['update:visible', 'confirm', 'overlay-click', 'cancel', 'close', 'closed'],
setup(props, context) {
Expand Down Expand Up @@ -77,20 +78,31 @@ export default defineComponent({
context.emit('overlay-click', { e });
};

const calcBtn = (btn: any) => (isString(btn) ? { content: btn } : btn);
const confirmBtnProps = computed(() => ({
const calcBtn = (btn: TdDialogProps['cancelBtn'] | TdDialogProps['confirmBtn']) => {
if (isString(btn)) {
return { content: btn };
}

if (isObject(btn)) {
return btn;
}

return {};
};

const confirmBtnProps = computed<ButtonProps>(() => ({
theme: 'primary',
...calcBtn(props.confirmBtn),
}));

const cancelBtnProps = computed<ButtonProps>(() => ({
theme: isTextStyleBtn.value ? 'default' : 'light',
...calcBtn(props.cancelBtn),
}));

const actionsBtnProps = computed(() => props.actions?.map((item) => calcBtn(item)));

return () => {
const { visible, showOverlay, overlayProps, preventScrollThrough, destroyOnClose, zIndex, closeBtn, actions } =
props;
const renderTitleNode = () => {
const titleNode = renderTNodeJSX('title');
if (!titleNode) {
Expand All @@ -114,43 +126,49 @@ export default defineComponent({
const actionsNode = renderTNodeJSX('actions');
if (actionsNode && actionsBtnProps.value) {
return actionsBtnProps.value.map((item, index) => (
<t-button key={index} {...item} class={buttonClass.value} onClick={handleCancel} />
<TButton key={index} {...item} class={buttonClass.value} onClick={handleCancel} />
));
}
return null;
};
const renderCancelBtnNode = () => {
const cancelBtnNode = renderTNodeJSX('cancelBtn');
if (!actions && cancelBtnNode) {
return <t-button {...cancelBtnProps.value} class={buttonClass.value} onClick={handleCancel} />;
if (!props.actions && cancelBtnNode) {
if (context.slots.cancelBtn) {
return cancelBtnNode;
}
return <TButton {...cancelBtnProps.value} class={buttonClass.value} onClick={handleCancel} />;
}
return null;
};

const renderConfirmBntNode = () => {
const confirmBtnNode = renderTNodeJSX('confirmBtn');
if (!actions && confirmBtnNode) {
return <t-button {...confirmBtnProps.value} class={buttonClass.value} onClick={handleConfirm} />;
if (!props.actions && confirmBtnNode) {
if (context.slots.confirmBtn) {
return confirmBtnNode;
}
return <TButton {...confirmBtnProps.value} class={buttonClass.value} onClick={handleConfirm} />;
}
return null;
};
return (
<t-popup
visible={visible}
<TPopup
visible={props.visible}
placement="center"
show-overlay={showOverlay}
overlay-props={overlayProps}
prevent-scroll-through={preventScrollThrough}
destroy-on-close={destroyOnClose}
z-index={zIndex}
show-overlay={props.showOverlay}
overlay-props={props.overlayProps}
prevent-scroll-through={props.preventScrollThrough}
destroy-on-close={props.destroyOnClose}
z-index={props.zIndex}
onClose={handleOverlayClick}
onClosed={handleClosed}
>
<div class={`${dialogClass.value} ${context.attrs.class || ''}`} style={rootStyles.value}>
{renderTNodeJSX('top')}
{closeBtn && (
{props.closeBtn && (
<div class={`${dialogClass.value}__close-btn`}>
<close-icon onClick={handleClose} />
<CloseIcon onClick={handleClose} />
</div>
)}
<div class={`${dialogClass.value}__content`}>
Expand All @@ -164,7 +182,7 @@ export default defineComponent({
{renderConfirmBntNode()}
</div>
</div>
</t-popup>
</TPopup>
);
};
},
Expand Down
2 changes: 1 addition & 1 deletion src/dialog/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default {
onCancel: Function as PropType<TdDialogProps['onCancel']>,
/** 关闭事件,点击 取消按钮 或 点击蒙层 时触发 */
onClose: Function as PropType<TdDialogProps['onClose']>,
/** 组件关闭且动画结束后执行 */
/** 对话框消失动画效果结束后触发 */
onClosed: Function as PropType<TdDialogProps['onClosed']>,
/** 如果“确认”按钮存在,则点击“确认”按钮时触发 */
onConfirm: Function as PropType<TdDialogProps['onConfirm']>,
Expand Down
10 changes: 8 additions & 2 deletions src/dialog/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* */

import { ButtonProps } from '../button';
import { OverlayProps } from '../overlay';
import { TNode, Styles } from '../common';

export interface TdDialogProps {
Expand All @@ -21,6 +22,11 @@ export interface TdDialogProps {
* 取消按钮,可自定义。值为 null 则不显示取消按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。使用 TNode 自定义按钮时,需自行控制取消事件
*/
cancelBtn?: string | ButtonProps | TNode | null;
/**
* 多按钮排列方式。可选项:true/false
* @default false
*/
closeBtn?: boolean;
/**
* 点击蒙层时是否触发关闭事件
*/
Expand All @@ -42,7 +48,7 @@ export interface TdDialogProps {
* 透传至 Overlay 组件
* @default {}
*/
overlayProps?: object;
overlayProps?: OverlayProps;
/**
* 防止滚动穿透
* @default true
Expand Down Expand Up @@ -78,7 +84,7 @@ export interface TdDialogProps {
*/
onClose?: (context: DialogCloseContext) => void;
/**
* 组件关闭且动画结束后执行
* 对话框消失动画效果结束后触发
*/
onClosed?: () => void;
/**
Expand Down

0 comments on commit b9d0231

Please sign in to comment.