|
@@ -12,7 +12,6 @@ import {
|
|
|
DialogFooter,
|
|
|
DialogHeader,
|
|
|
DialogTitle,
|
|
|
- DialogTrigger,
|
|
|
VbenButton,
|
|
|
VbenIconButton,
|
|
|
VbenLoading,
|
|
@@ -21,8 +20,6 @@ import {
|
|
|
} from '@vben-core/shadcn-ui';
|
|
|
import { cn } from '@vben-core/shared';
|
|
|
|
|
|
-// import { useElementSize } from '@vueuse/core';
|
|
|
-
|
|
|
import { useModalDraggable } from './use-modal-draggable';
|
|
|
|
|
|
interface Props extends ModalProps {
|
|
@@ -42,15 +39,15 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
});
|
|
|
|
|
|
const contentRef = ref();
|
|
|
+const wrapperRef = ref<HTMLElement>();
|
|
|
const dialogRef = ref();
|
|
|
const headerRef = ref();
|
|
|
const footerRef = ref();
|
|
|
|
|
|
const { isMobile } = useIsMobile();
|
|
|
-// const { height: headerHeight } = useElementSize(headerRef);
|
|
|
-// const { height: footerHeight } = useElementSize(footerRef);
|
|
|
const state = props.modalApi?.useStore?.();
|
|
|
|
|
|
+const header = usePriorityValue('header', props, state);
|
|
|
const title = usePriorityValue('title', props, state);
|
|
|
const fullscreen = usePriorityValue('fullscreen', props, state);
|
|
|
const description = usePriorityValue('description', props, state);
|
|
@@ -68,9 +65,12 @@ const fullscreenButton = usePriorityValue('fullscreenButton', props, state);
|
|
|
const closeOnClickModal = usePriorityValue('closeOnClickModal', props, state);
|
|
|
const closeOnPressEscape = usePriorityValue('closeOnPressEscape', props, state);
|
|
|
|
|
|
-const shouldFullscreen = computed(() => fullscreen.value || isMobile.value);
|
|
|
+const shouldFullscreen = computed(
|
|
|
+ () => (fullscreen.value && header.value) || isMobile.value,
|
|
|
+);
|
|
|
+
|
|
|
const shouldDraggable = computed(
|
|
|
- () => draggable.value && !shouldFullscreen.value,
|
|
|
+ () => draggable.value && !shouldFullscreen.value && header.value,
|
|
|
);
|
|
|
|
|
|
const { dragging, transform } = useModalDraggable(
|
|
@@ -79,32 +79,29 @@ const { dragging, transform } = useModalDraggable(
|
|
|
shouldDraggable,
|
|
|
);
|
|
|
|
|
|
-// const loadingStyle = computed(() => {
|
|
|
-// // py-5 4px*5*2
|
|
|
-// const headerPadding = 40;
|
|
|
-// // p-2 4px*2*2
|
|
|
-// const footerPadding = 16;
|
|
|
-
|
|
|
-// return {
|
|
|
-// bottom: `${footerHeight.value + footerPadding}px`,
|
|
|
-// height: `calc(100% - ${footerHeight.value + headerHeight.value + headerPadding + footerPadding}px)`,
|
|
|
-// top: `${headerHeight.value + headerPadding}px`,
|
|
|
-// };
|
|
|
-// });
|
|
|
-
|
|
|
watch(
|
|
|
() => state?.value?.isOpen,
|
|
|
async (v) => {
|
|
|
if (v) {
|
|
|
await nextTick();
|
|
|
- if (contentRef.value) {
|
|
|
- const innerContentRef = contentRef.value.getContentRef();
|
|
|
- dialogRef.value = innerContentRef.$el;
|
|
|
-
|
|
|
- // reopen modal reassign value
|
|
|
- const { offsetX, offsetY } = transform;
|
|
|
- dialogRef.value.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
|
|
|
- }
|
|
|
+ if (!contentRef.value) return;
|
|
|
+ const innerContentRef = contentRef.value.getContentRef();
|
|
|
+ dialogRef.value = innerContentRef.$el;
|
|
|
+ // reopen modal reassign value
|
|
|
+ const { offsetX, offsetY } = transform;
|
|
|
+ dialogRef.value.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+);
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => showLoading.value,
|
|
|
+ (v) => {
|
|
|
+ if (v && wrapperRef.value) {
|
|
|
+ wrapperRef.value.scrollTo({
|
|
|
+ // behavior: 'smooth',
|
|
|
+ top: 0,
|
|
|
+ });
|
|
|
}
|
|
|
},
|
|
|
);
|
|
@@ -142,10 +139,6 @@ function pointerDownOutside(e: Event) {
|
|
|
:open="state?.isOpen"
|
|
|
@update:open="() => modalApi?.close()"
|
|
|
>
|
|
|
- <DialogTrigger v-if="$slots.trigger" as-child>
|
|
|
- <slot name="trigger"> </slot>
|
|
|
- </DialogTrigger>
|
|
|
-
|
|
|
<DialogContent
|
|
|
ref="contentRef"
|
|
|
:class="
|
|
@@ -170,8 +163,9 @@ function pointerDownOutside(e: Event) {
|
|
|
ref="headerRef"
|
|
|
:class="
|
|
|
cn(
|
|
|
- 'border-b px-6 py-5',
|
|
|
+ 'border-b px-5 py-4',
|
|
|
{
|
|
|
+ hidden: !header,
|
|
|
'cursor-move select-none': shouldDraggable,
|
|
|
},
|
|
|
props.headerClass,
|
|
@@ -182,12 +176,14 @@ function pointerDownOutside(e: Event) {
|
|
|
<slot name="title">
|
|
|
{{ title }}
|
|
|
|
|
|
- <VbenTooltip v-if="titleTooltip" side="right">
|
|
|
- <template #trigger>
|
|
|
- <Info class="inline-flex size-5 cursor-pointer pb-1" />
|
|
|
- </template>
|
|
|
- {{ titleTooltip }}
|
|
|
- </VbenTooltip>
|
|
|
+ <slot v-if="titleTooltip" name="titleTooltip">
|
|
|
+ <VbenTooltip side="right">
|
|
|
+ <template #trigger>
|
|
|
+ <Info class="inline-flex size-5 cursor-pointer pb-1" />
|
|
|
+ </template>
|
|
|
+ {{ titleTooltip }}
|
|
|
+ </VbenTooltip>
|
|
|
+ </slot>
|
|
|
</slot>
|
|
|
</DialogTitle>
|
|
|
<DialogDescription v-if="description">
|
|
@@ -201,13 +197,18 @@ function pointerDownOutside(e: Event) {
|
|
|
</VisuallyHidden>
|
|
|
</DialogHeader>
|
|
|
<div
|
|
|
+ ref="wrapperRef"
|
|
|
:class="
|
|
|
- cn('relative min-h-40 flex-1 p-3', contentClass, {
|
|
|
- 'overflow-y-auto': !showLoading,
|
|
|
+ cn('relative min-h-40 flex-1 overflow-y-auto p-3', contentClass, {
|
|
|
+ 'overflow-hidden': showLoading,
|
|
|
})
|
|
|
"
|
|
|
>
|
|
|
- <VbenLoading v-if="showLoading" class="size-full" spinning />
|
|
|
+ <VbenLoading
|
|
|
+ v-if="showLoading"
|
|
|
+ class="size-full h-auto min-h-full"
|
|
|
+ spinning
|
|
|
+ />
|
|
|
<slot></slot>
|
|
|
</div>
|
|
|
|