This commit is contained in:
2026-01-28 22:37:27 +03:00
parent cbaa1cda9d
commit 53ca63ec91
64 changed files with 4375 additions and 2980 deletions

View File

@@ -1,72 +1,101 @@
<template>
<q-dialog v-model="modelValue" class="q-ma-none">
<q-dialog
v-model="modelValue"
class="q-ma-none"
>
<q-card
class="q-pa-none q-ma-none w100 no-scroll rounded-card"
style="max-height: calc(100vh - 48px);"
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-card-section class="row items-center q-pb-none">
<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="close" flat round dense v-close-popup />
</div>
</q-card-section>
<div>
<pn-shadow-scroll :height="scrollAreaHeight" :hideShadows="false">
<div>
<q-resize-observer @resize="onBodyResize"/>
<slot/>
<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="close" flat round dense v-close-popup />
</div>
</pn-shadow-scroll>
</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 pnShadowScroll from './pnShadowScroll.vue'
defineProps<{
title: string
}>()
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 scrollAreaHeight = 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
}
function onBodyResize (size: sizeParams) {
bodyHeight.value = size.height
}
async function updateScrollAreaHeight () {
const updateDimensions = async () => {
await nextTick(() => {
scrollAreaHeight.value = Math.min(
bodyHeight.value + 16,
window.innerHeight - headerHeight.value - 64
)
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(bodyHeight, updateScrollAreaHeight)
watch(headerHeight, updateScrollAreaHeight)
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>