Files
tgCrewAdmin/src/components/pnSimpleScrollDialog.vue

104 lines
2.7 KiB
Vue

<template>
<q-dialog
v-model="modelValue"
class="q-ma-none"
>
<q-card
class="q-pa-none q-ma-none w100 q-pb-md no-scroll rounded-card no-wrap overflow-hidden"
ref="cardRef"
style="
max-height: calc(100vh - 48px - 2 * max(var(--tg-content-safe-area-inset-top) + var(--tg-safe-area-inset-top), var(--tg-safe-area-inset-bottom)));
width: calc(100vw - 32px);
"
>
<q-resize-observer @resize="onResizeCard" />
<q-card-section class="row items-center q-pb-none" ref="cardHeaderRef">
<div class="flex no-wrap items-center w100">
<q-resize-observer @resize="onHeaderResize"/>
<span class="text-bold">
{{ $t(title)}}
</span>
<q-space/>
<q-btn
icon="mdi-close"
dense flat round
v-close-popup
/>
</div>
</q-card-section>
<div
ref="cardBodyRef"
class="q-px-none q-ma-none"
>
<pn-shadow-scroll
:height="bodyHeight"
>
<div ref="cardBodyInnerRef" class="q-pa-none q-ma-none">
<q-resize-observer @resize="updateDimensions" />
<slot/>
</div>
</pn-shadow-scroll>
</div>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { ref, watch, nextTick } from 'vue'
import { useSlots } from 'vue'
const modelValue = defineModel<boolean>({
required: true
})
defineProps<{
title: string
}>()
const slots = useSlots()
const cardBodyInnerRef = ref<HTMLElement | null>(null)
const headerHeight = ref(0)
const bodyInnerHeight = ref(0)
const bodyHeight = ref(0)
const cardHeight = ref(0)
interface sizeParams {
height: number,
width: number
}
function onResizeCard (size :sizeParams) {
cardHeight.value = size.width
}
function onHeaderResize (size: sizeParams) {
headerHeight.value = size.height
}
const updateDimensions = async () => {
await nextTick(() => {
bodyInnerHeight.value = cardBodyInnerRef.value?.offsetHeight || 0
const maxH = cardMaxHeight()
const availableForBody = maxH - headerHeight.value - 32 // 16 - md-padding + 16px - shadow-block
bodyHeight.value = Math.min(bodyInnerHeight.value + 32, availableForBody)
})
}
watch(() => slots.body?.(), updateDimensions, { flush: 'post' })
watch(modelValue, updateDimensions)
const cardRef = ref()
function cardMaxHeight () {
const el = cardRef.value?.$el
if (el) {
const computedStyle = window.getComputedStyle(el)
return parseFloat(computedStyle.maxHeight)
}
return 0
}
</script>