Archipelago — open-source initial import
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
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 }
|
||||
}
|
||||
Reference in New Issue
Block a user