Files
archy/aiui/packages/app/src/composables/useVisualViewport.ts
T

65 lines
2.1 KiB
TypeScript

import { ref, onMounted, onUnmounted } from 'vue'
/**
* Tracks the visual viewport to detect mobile keyboard open/close.
* Uses the VisualViewport API to compute keyboard height as the difference
* between window.innerHeight and visualViewport.height.
*
* When the keyboard opens, viewportHeight shrinks to the visible area above
* the keyboard. Bind your container's height to viewportHeight to make the
* layout resize instead of the browser pushing content offscreen.
*/
export function useVisualViewport() {
const keyboardHeight = ref(0)
const isKeyboardOpen = ref(false)
const viewportHeight = ref(typeof window !== 'undefined' ? window.innerHeight : 0)
// Store the initial full height so we can compute keyboard offset
let fullHeight = typeof window !== 'undefined' ? window.innerHeight : 0
let debounceTimer: ReturnType<typeof setTimeout> | null = null
function onViewportChangeRaw() {
if (debounceTimer) clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => {
const vv = window.visualViewport
if (!vv) return
const kbHeight = Math.max(0, fullHeight - vv.height)
keyboardHeight.value = kbHeight
isKeyboardOpen.value = kbHeight > 100
viewportHeight.value = vv.height
}, 50)
}
function onWindowResize() {
// Update full height when orientation changes or browser chrome resizes
const vv = window.visualViewport
if (vv && !isKeyboardOpen.value) {
fullHeight = vv.height
viewportHeight.value = vv.height
}
}
onMounted(() => {
const vv = window.visualViewport
if (vv) {
fullHeight = vv.height
viewportHeight.value = vv.height
vv.addEventListener('resize', onViewportChangeRaw)
vv.addEventListener('scroll', onViewportChangeRaw)
}
window.addEventListener('resize', onWindowResize)
})
onUnmounted(() => {
const vv = window.visualViewport
if (vv) {
vv.removeEventListener('resize', onViewportChangeRaw)
vv.removeEventListener('scroll', onViewportChangeRaw)
}
window.removeEventListener('resize', onWindowResize)
})
return { keyboardHeight, isKeyboardOpen, viewportHeight }
}