diff --git a/.gitmodules b/.gitmodules index 05391f031..eb70781dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "src/_common"] path = src/_common - url = git@github.com:Tencent/tdesign-common.git + url = git@github.com:Tencent/tdesign-common.git + diff --git a/examples/dialog/demos/attach.vue b/examples/dialog/demos/attach.vue index fda1cba6b..731f1f09c 100644 --- a/examples/dialog/demos/attach.vue +++ b/examples/dialog/demos/attach.vue @@ -1,16 +1,17 @@ - diff --git a/examples/dialog/dialog.md b/examples/dialog/dialog.md index a1ff8d838..55ffa0e17 100644 --- a/examples/dialog/dialog.md +++ b/examples/dialog/dialog.md @@ -20,6 +20,7 @@ header | String / Boolean / Slot / Function | true | 头部内容。值为 true mode | String | modal | 对话框类型,有三种:模态对话框、非模态对话框和普通对话框。弹出「模态对话框」时,只能操作对话框里面的内容,不能操作其他内容。弹出「非模态对话框」时,则可以操作页面内所有内容。「普通对话框」是指没有脱离文档流的对话框,可以在这个基础上开发更多的插件。可选项:modal/modeless/normal | N placement | String | top | 对话框位置,内置两种:垂直水平居中显示 和 靠近顶部(top:20%)显示。可选项:top/center | N preventScrollThrough | Boolean | true | 防止滚动穿透 | N +showInAttachedElement | Boolean | false | 仅在挂载元素中显示抽屉,默认在浏览器可视区域显示。父元素需要有定位属性,如:position: relative | N showOverlay | Boolean | true | 是否显示遮罩层 | N theme | String | default | 对话框风格。可选项:default/info/warning/danger/success | N top | String / Number | - | 用于弹框具体窗口顶部的距离,优先级大于 placement | N @@ -54,7 +55,7 @@ overlay-click | `(context: { e: MouseEvent })` | 如果蒙层存在,点击蒙 -- | -- | -- | -- | -- attach | String / Function | 'body' | 对话框挂载的节点。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body。TS 类型:`AttachNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N className | String | - | 弹框类名,示例:'t-class-dialog-first t-class-dialog-second' | N -style | String | - | 弹框 style 属性,输入 [CSSStyleDeclaration.cssText](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText) | 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-vue/blob/develop/src/common.ts) | N `Omit` | - | - | 继承 `Omit` 中的全部 API | N ### DialogInstance @@ -84,8 +85,6 @@ options | - | - | TS 类型:`DialogOptions` -- | -- | -- | -- options | - | - | TS 类型:`DialogOptions` -插件返回值:`DialogInstance` - ### DialogPlugin.alert 同时也支持 `this.$dialog.alert`。这是一个插件函数,参数形式为顺序参数(形如:(a, b, c)),而非对象参数(形如:({ a, b, c }))。顺序参数如下, @@ -93,5 +92,3 @@ options | - | - | TS 类型:`DialogOptions` 参数名称 | 参数类型 | 参数默认值 | 参数说明 -- | -- | -- | -- options | Object | - | TS 类型:`Omit` - -插件返回值:`DialogInstance` diff --git a/src/_common b/src/_common index dbfc06032..6e8ef080a 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit dbfc060325b95301692b5da272959ebd5311dfc2 +Subproject commit 6e8ef080a1ae6cc403913d029860cf5d3a9851aa diff --git a/src/dialog/dialog.tsx b/src/dialog/dialog.tsx index 49eeaabdf..ab823b492 100644 --- a/src/dialog/dialog.tsx +++ b/src/dialog/dialog.tsx @@ -71,7 +71,11 @@ export default mixins(ActionMixin, getConfigReceiverMixins('d const dialogClass = [`${name}`, `${name}--default`, `${name}--${this.placement}`, `${name}__modal-${this.theme}`]; if (['modeless', 'modal'].includes(this.mode)) { dialogClass.push(`${name}--fixed`); + if (this.isModal && this.showInAttachedElement) { + dialogClass.push(`${name}--absolute`); + } } + return dialogClass; }, dialogStyle(): Styles { @@ -101,11 +105,13 @@ export default mixins(ActionMixin, getConfigReceiverMixins('d visible(value) { if (value) { const { scrollWidth } = this; - if (scrollWidth > 0) { - const bodyCssText = `position: relative;width: calc(100% - ${scrollWidth}px);`; - document.body.style.cssText = bodyCssText; + if (this.isModal && !this.showInAttachedElement) { + if (scrollWidth > 0) { + const bodyCssText = `position: relative;width: calc(100% - ${scrollWidth}px);`; + document.body.style.cssText = bodyCssText; + } + addClass(document.body, lockClass); } - addClass(document.body, lockClass); } else { document.body.style.cssText = ''; removeClass(document.body, lockClass); @@ -342,7 +348,13 @@ export default mixins(ActionMixin, getConfigReceiverMixins('d const dialogView = this.renderDialog(); const view = [maskView, dialogView]; const ctxStyle: any = { zIndex: this.zIndex }; - const ctxClass = [`${name}__ctx`, { [`${prefix}-dialog__ctx--fixed`]: this.mode === 'modal' }]; + const ctxClass = [ + `${name}__ctx`, + { + [`${prefix}-dialog__ctx--fixed`]: this.mode === 'modal', + [`${prefix}-dialog__ctx--absolute`]: this.isModal && this.showInAttachedElement, + }, + ]; return ( , default: 'modal' as TdDialogProps['mode'], validator(val: TdDialogProps['mode']): boolean { + if (!val) return true; return ['modal', 'modeless', 'normal'].includes(val); }, }, @@ -74,6 +75,7 @@ export default { type: String as PropType, default: 'top' as TdDialogProps['placement'], validator(val: TdDialogProps['placement']): boolean { + if (!val) return true; return ['top', 'center'].includes(val); }, }, @@ -82,6 +84,8 @@ export default { type: Boolean, default: true, }, + /** 仅在挂载元素中显示抽屉,默认在浏览器可视区域显示。父元素需要有定位属性,如:position: relative */ + showInAttachedElement: Boolean, /** 是否显示遮罩层 */ showOverlay: { type: Boolean, @@ -92,6 +96,7 @@ export default { type: String as PropType, default: 'default' as TdDialogProps['theme'], validator(val: TdDialogProps['theme']): boolean { + if (!val) return true; return ['default', 'info', 'warning', 'danger', 'success'].includes(val); }, }, diff --git a/src/dialog/type.ts b/src/dialog/type.ts index 82e4993db..85548a491 100644 --- a/src/dialog/type.ts +++ b/src/dialog/type.ts @@ -5,7 +5,7 @@ * */ import { ButtonProps } from '../button'; -import { TNode, AttachNode } from '../common'; +import { TNode, Styles, AttachNode } from '../common'; export interface TdDialogProps { /** @@ -82,6 +82,11 @@ export interface TdDialogProps { * @default true */ preventScrollThrough?: boolean; + /** + * 仅在挂载元素中显示抽屉,默认在浏览器可视区域显示。父元素需要有定位属性,如:position: relative + * @default false + */ + showInAttachedElement?: boolean; /** * 是否显示遮罩层 * @default true @@ -156,9 +161,8 @@ export interface DialogOptions extends Omit { className?: string; /** * 弹框 style 属性,输入 [CSSStyleDeclaration.cssText](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText) - * @default '' */ - style?: string; + style?: string | Styles; } export interface DialogInstance { diff --git a/test/ssr/__snapshots__/ssr.test.js.snap b/test/ssr/__snapshots__/ssr.test.js.snap index 088138637..0e5c64087 100644 --- a/test/ssr/__snapshots__/ssr.test.js.snap +++ b/test/ssr/__snapshots__/ssr.test.js.snap @@ -3423,7 +3423,8 @@ exports[`ssr snapshot test renders ./examples/dialog/demos/async.vue correctly 1 `; exports[`ssr snapshot test renders ./examples/dialog/demos/attach.vue correctly 1`] = ` -
+
+
diff --git a/test/unit/dialog/__snapshots__/demo.test.js.snap b/test/unit/dialog/__snapshots__/demo.test.js.snap index 05c159c91..28686efe7 100644 --- a/test/unit/dialog/__snapshots__/demo.test.js.snap +++ b/test/unit/dialog/__snapshots__/demo.test.js.snap @@ -113,7 +113,9 @@ exports[`Dialog async demo works fine 1`] = ` `; exports[`Dialog attach demo works fine 1`] = ` -
+
+ + + + + `;