Refactor GUI rendering and align RTA axis
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
let bound = false;
|
||||
|
||||
// Hält fokussierte Eingabefelder auch bei eingeblendeter Bildschirmtastatur sichtbar.
|
||||
export function bindOptionsViewportAssist(panel) {
|
||||
if (bound || !panel) return;
|
||||
bound = true;
|
||||
|
||||
const setKeyboardInset = () => {
|
||||
const viewport = window.visualViewport;
|
||||
if (!viewport) {
|
||||
panel.style.setProperty('--options-kb-inset', '0px');
|
||||
return;
|
||||
}
|
||||
const inset = Math.max(0, window.innerHeight - (viewport.height + viewport.offsetTop));
|
||||
panel.style.setProperty('--options-kb-inset', `${Math.round(inset)}px`);
|
||||
};
|
||||
|
||||
const revealFocusedField = (target) => {
|
||||
if (!target || !panel.contains(target)) return;
|
||||
const viewport = window.visualViewport;
|
||||
const panelRect = panel.getBoundingClientRect();
|
||||
const targetRect = target.getBoundingClientRect();
|
||||
const keyboardInset = viewport ? Math.max(0, window.innerHeight - (viewport.height + viewport.offsetTop)) : 0;
|
||||
const visibleTop = panelRect.top + 16;
|
||||
const visibleBottom = panelRect.bottom - keyboardInset - 16;
|
||||
if (targetRect.bottom > visibleBottom || targetRect.top < visibleTop) {
|
||||
const targetCenter = targetRect.top + targetRect.height / 2;
|
||||
const visibleCenter = visibleTop + (visibleBottom - visibleTop) / 2;
|
||||
panel.scrollTop += targetCenter - visibleCenter;
|
||||
}
|
||||
};
|
||||
|
||||
const onFocus = (event) => {
|
||||
const element = event.target;
|
||||
if (!(element instanceof HTMLElement)) return;
|
||||
const type = String(element.getAttribute('type') || '').toLowerCase();
|
||||
if (!['INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName)) return;
|
||||
if (type === 'checkbox' || type === 'range' || type === 'color') return;
|
||||
setKeyboardInset();
|
||||
requestAnimationFrame(() => revealFocusedField(element));
|
||||
setTimeout(() => revealFocusedField(element), 250);
|
||||
};
|
||||
|
||||
panel.addEventListener('focusin', onFocus);
|
||||
panel.addEventListener('focusout', () => {
|
||||
setTimeout(() => {
|
||||
const active = document.activeElement;
|
||||
if (!(active instanceof HTMLElement) || !panel.contains(active)) {
|
||||
panel.style.setProperty('--options-kb-inset', '0px');
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
|
||||
if (window.visualViewport) {
|
||||
window.visualViewport.addEventListener('resize', () => {
|
||||
setKeyboardInset();
|
||||
const active = document.activeElement;
|
||||
if (active instanceof HTMLElement && panel.contains(active)) {
|
||||
requestAnimationFrame(() => revealFocusedField(active));
|
||||
}
|
||||
});
|
||||
window.visualViewport.addEventListener('scroll', setKeyboardInset);
|
||||
}
|
||||
setKeyboardInset();
|
||||
}
|
||||
Reference in New Issue
Block a user