()
@@ -94,6 +100,7 @@ export default defineComponent({
mask,
maskClosable,
closeOnEsc,
+ draggable,
sentinelStartRef,
sentinelEndRef,
)
@@ -105,8 +112,25 @@ export default defineComponent({
animatedVisible,
modalTransformOrigin,
)
+ const resetDraggableRef = ref<() => void>(() => {})
- onMounted(() => watchVisibleChange(props, wrapperRef, sentinelStartRef, mask))
+ onMounted(() => watchVisibleChange(props, wrapperRef, sentinelStartRef, mask, resetDraggableRef))
+
+ const stopWatch = watch(
+ () => draggable,
+ draggable => {
+ if (draggable) {
+ const { reset } = useDraggable(modalRef, { handle: headerRef, free: true })
+ resetDraggableRef.value = reset
+ }
+ },
+ { immediate: true },
+ )
+
+ onUnmounted(() => {
+ stopWatch()
+ resetDraggableRef.value = () => {}
+ })
return () => {
const prefixCls = mergedPrefixCls.value
@@ -141,6 +165,7 @@ export default defineComponent({
<ɵHeader
+ ref={headerRef}
v-slots={slots}
closable={closable.value}
closeIcon={closeIcon.value}
@@ -177,12 +202,13 @@ function useConfig(props: ModalProps, config: ModalConfig) {
const closable = computed(() => props.closable ?? config.closable)
const closeIcon = computed(() => props.closeIcon ?? config.closeIcon)
const closeOnEsc = computed(() => props.closeOnEsc ?? config.closeOnEsc)
+ const draggable = computed(() => props.draggable)
const mask = computed(() => props.mask ?? config.mask)
const maskClosable = computed(() => props.maskClosable ?? config.maskClosable)
const width = computed(() => convertCssPixel(props.width ?? config.width))
const zIndex = computed(() => props.zIndex ?? config.zIndex)
- return { centered, closable, closeIcon, closeOnEsc, width, mask, maskClosable, zIndex }
+ return { centered, closable, closeIcon, closeOnEsc, draggable, width, mask, maskClosable, zIndex }
}
function watchVisibleChange(
@@ -190,8 +216,10 @@ function watchVisibleChange(
wrapperRef: Ref,
sentinelStartRef: Ref,
mask: ComputedRef,
+ resetDraggableRef: Ref<() => void>,
) {
let lastOutSideActiveElement: HTMLElement | null = null
+
watch(
() => props.visible,
visible => {
@@ -202,6 +230,7 @@ function watchVisibleChange(
lastOutSideActiveElement = activeElement as HTMLElement
sentinelStartRef.value?.focus()
}
+ resetDraggableRef.value?.()
} else {
if (mask.value) {
lastOutSideActiveElement?.focus?.()
@@ -218,6 +247,7 @@ function useEvent(
mask: ComputedRef,
maskClosable: ComputedRef,
closeOnEsc: ComputedRef,
+ draggable: ComputedRef,
sentinelStartRef: Ref,
sentinelEndRef: Ref,
) {
@@ -232,7 +262,7 @@ function useEvent(
}
const onWrapperClick = (evt: MouseEvent) => {
- if (evt.target === evt.currentTarget && !mouseDown && mask.value && maskClosable.value) {
+ if (evt.target === evt.currentTarget && (!mouseDown || draggable.value) && mask.value && maskClosable.value) {
close(evt)
}
}
diff --git a/packages/components/modal/src/types.ts b/packages/components/modal/src/types.ts
index 5e8b96425..9b334ec70 100644
--- a/packages/components/modal/src/types.ts
+++ b/packages/components/modal/src/types.ts
@@ -54,6 +54,7 @@ export const modalProps = {
width: IxPropTypes.oneOfType([String, Number]),
wrapperClassName: IxPropTypes.string,
zIndex: IxPropTypes.number,
+ draggable: { type: Boolean, default: false },
// events
'onUpdate:visible': IxPropTypes.emit<(visible: boolean) => void>(),