mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-06 16:13:52 +08:00
优化FaDrawer/FaModal遮罩层
This commit is contained in:
@@ -73,6 +73,9 @@ const emits = defineEmits<{
|
||||
'cancel': []
|
||||
}>()
|
||||
|
||||
const id = useId()
|
||||
provide('DrawerId', id)
|
||||
|
||||
const isOpen = ref(props.modelValue)
|
||||
|
||||
watch(() => props.modelValue, (newValue) => {
|
||||
@@ -106,14 +109,16 @@ function handleFocusOutside(e: Event) {
|
||||
}
|
||||
|
||||
function handleClickOutside(e: Event) {
|
||||
if (!props.closeOnClickOverlay) {
|
||||
if (!props.closeOnClickOverlay || (e.target as HTMLElement).dataset.drawerId !== id) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
function handleEscapeKeyDown(e: KeyboardEvent) {
|
||||
if (!props.closeOnPressEscape) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,12 +133,15 @@ function handleAnimationEnd() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Sheet :modal="props.overlay" :open="isOpen" @update:open="updateOpen">
|
||||
<Sheet :modal="false" :open="isOpen" @update:open="updateOpen">
|
||||
<SheetContent
|
||||
:closable="props.closable"
|
||||
:open="isOpen"
|
||||
:overlay="props.overlay"
|
||||
:overlay-blur="props.overlayBlur"
|
||||
class="w-full flex flex-col gap-0 p-0"
|
||||
:side="props.side"
|
||||
@open-auto-focus="handleFocusOutside"
|
||||
@close-auto-focus="handleFocusOutside"
|
||||
@focus-outside="handleFocusOutside"
|
||||
@pointer-down-outside="handleClickOutside"
|
||||
@@ -150,7 +158,7 @@ function handleAnimationEnd() {
|
||||
<SheetTitle :class="{ 'text-center': props.centered }">
|
||||
{{ title }}
|
||||
</SheetTitle>
|
||||
<SheetDescription v-if="!!description" :class="{ 'text-center': props.centered }">
|
||||
<SheetDescription class="empty:hidden" :class="{ 'text-center': props.centered }">
|
||||
{{ description }}
|
||||
</SheetDescription>
|
||||
</slot>
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
DialogContent,
|
||||
type DialogContentEmits,
|
||||
type DialogContentProps,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
@@ -15,8 +14,10 @@ import { type SheetVariants, sheetVariants } from '.'
|
||||
|
||||
interface SheetContentProps extends DialogContentProps {
|
||||
class?: HTMLAttributes['class']
|
||||
open?: boolean
|
||||
side?: SheetVariants['side']
|
||||
closable?: boolean
|
||||
overlay?: boolean
|
||||
overlayBlur?: boolean
|
||||
}
|
||||
|
||||
@@ -37,15 +38,31 @@ const delegatedProps = computed(() => {
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
|
||||
const id = inject('DrawerId')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogPortal>
|
||||
<DialogOverlay
|
||||
:class="cn('fixed inset-0 z-2000 data-[state=closed]:animate-out data-[state=open]:animate-in bg-black/50 data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0', {
|
||||
'backdrop-blur-sm': props.overlayBlur,
|
||||
})"
|
||||
/>
|
||||
<Transition
|
||||
v-bind="{
|
||||
enterActiveClass: 'ease-in-out duration-300',
|
||||
enterFromClass: 'opacity-0',
|
||||
enterToClass: 'opacity-100',
|
||||
leaveActiveClass: 'ease-in-out duration-300',
|
||||
leaveFromClass: 'opacity-100',
|
||||
leaveToClass: 'opacity-0',
|
||||
}"
|
||||
:appear="true"
|
||||
>
|
||||
<div
|
||||
v-if="props.open && props.overlay"
|
||||
:data-drawer-id="id"
|
||||
:class="cn('fixed inset-0 z-2000 data-[state=closed]:animate-out data-[state=open]:animate-in bg-black/50 data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0', {
|
||||
'backdrop-blur-sm': props.overlayBlur,
|
||||
})"
|
||||
/>
|
||||
</Transition>
|
||||
<DialogContent
|
||||
:class="cn(sheetVariants({ side }), props.class)"
|
||||
v-bind="{ ...forwarded, ...$attrs }"
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
DialogContent,
|
||||
type DialogContentEmits,
|
||||
type DialogContentProps,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
@@ -14,9 +13,11 @@ import { computed, type HTMLAttributes } from 'vue'
|
||||
|
||||
const props = defineProps<DialogContentProps & {
|
||||
class?: HTMLAttributes['class']
|
||||
open?: boolean
|
||||
maximize?: boolean
|
||||
maximizable?: boolean
|
||||
closable?: boolean
|
||||
overlay?: boolean
|
||||
overlayBlur?: boolean
|
||||
}>()
|
||||
const emits = defineEmits<DialogContentEmits & {
|
||||
@@ -41,15 +42,31 @@ const dialogContentRef = useTemplateRef('dialogContentRef')
|
||||
defineExpose({
|
||||
el: dialogContentRef,
|
||||
})
|
||||
|
||||
const id = inject('ModalId')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogPortal>
|
||||
<DialogOverlay
|
||||
:class="cn('fixed inset-0 z-2000 data-[state=closed]:animate-out data-[state=open]:animate-in bg-black/50 data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0', {
|
||||
'backdrop-blur-sm': props.overlayBlur,
|
||||
})"
|
||||
/>
|
||||
<Transition
|
||||
v-bind="{
|
||||
enterActiveClass: 'ease-in-out duration-300',
|
||||
enterFromClass: 'opacity-0',
|
||||
enterToClass: 'opacity-100',
|
||||
leaveActiveClass: 'ease-in-out duration-300',
|
||||
leaveFromClass: 'opacity-100',
|
||||
leaveToClass: 'opacity-0',
|
||||
}"
|
||||
:appear="true"
|
||||
>
|
||||
<div
|
||||
v-if="props.open && props.overlay"
|
||||
:data-modal-id="id"
|
||||
:class="cn('fixed inset-0 z-2000 data-[state=closed]:animate-out data-[state=open]:animate-in bg-black/50 data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0', {
|
||||
'backdrop-blur-sm': props.overlayBlur,
|
||||
})"
|
||||
/>
|
||||
</Transition>
|
||||
<DialogContent
|
||||
ref="dialogContentRef"
|
||||
v-bind="forwarded"
|
||||
|
||||
@@ -60,6 +60,9 @@ defineExpose({
|
||||
areaRef: dialogAreaRef,
|
||||
})
|
||||
|
||||
const id = useId()
|
||||
provide('ModalId', id)
|
||||
|
||||
const isOpen = ref(props.modelValue)
|
||||
const isMaximize = ref(props.maximize)
|
||||
|
||||
@@ -119,14 +122,16 @@ function handleFocusOutside(e: Event) {
|
||||
}
|
||||
|
||||
function handleClickOutside(e: Event) {
|
||||
if (!props.closeOnClickOverlay) {
|
||||
if (!props.closeOnClickOverlay || (e.target as HTMLElement).dataset.modalId !== id) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
function handleEscapeKeyDown(e: KeyboardEvent) {
|
||||
if (!props.closeOnPressEscape) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +151,12 @@ function handleAnimationEnd() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog :modal="props.overlay" :open="isOpen" @update:open="updateOpen">
|
||||
<Dialog :modal="false" :open="isOpen" @update:open="updateOpen">
|
||||
<DialogContent
|
||||
ref="dialogContentRef"
|
||||
:open="isOpen"
|
||||
:closable="props.closable"
|
||||
:overlay="props.overlay"
|
||||
:overlay-blur="props.overlayBlur"
|
||||
:maximize="isMaximize"
|
||||
:maximizable="props.maximizable"
|
||||
@@ -158,6 +165,7 @@ function handleAnimationEnd() {
|
||||
'md:top-1/2 md:-translate-y-1/2!': props.alignCenter,
|
||||
'duration-0': isDragging,
|
||||
})"
|
||||
@open-auto-focus="handleFocusOutside"
|
||||
@close-auto-focus="handleFocusOutside"
|
||||
@focus-outside="handleFocusOutside"
|
||||
@pointer-down-outside="handleClickOutside"
|
||||
@@ -193,7 +201,7 @@ function handleAnimationEnd() {
|
||||
/>
|
||||
{{ title }}
|
||||
</DialogTitle>
|
||||
<DialogDescription v-if="!!description" :class="{ 'text-center': props.center }">
|
||||
<DialogDescription class="empty:hidden" :class="{ 'text-center': props.center }">
|
||||
{{ description }}
|
||||
</DialogDescription>
|
||||
</slot>
|
||||
|
||||
Reference in New Issue
Block a user