Files
uniapp-im-shop/TUIKit/utils/riseInput.ts
2025-12-30 23:28:59 +08:00

157 lines
4.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { isIOS } from '@tencentcloud/universal-api';
const ua = navigator.userAgent;
function getScrollTypeByPlatform() {
if (isIOS) {
if (/Safari\//.test(ua) || /IOS 11_[0-3]\D/.test(ua)) {
// Safari IOS 11.0-11.3 exclude`scrollTop`/`scrolIntoView` not working
return 0;
}
// IOS: use `scrollTop`
return 1;
}
// Android: use `scrollIntoView`
return 2;
}
function createKeyboardHeightObserver(callback: (height: number) => void) {
const initialViewportHeight = window.innerHeight;
let lastKeyboardHeight = 0;
if (window.visualViewport) {
const handleViewportChange = () => {
const currentViewportHeight = window.visualViewport!.height;
const keyboardHeight = initialViewportHeight - currentViewportHeight;
if (Math.abs(keyboardHeight - lastKeyboardHeight) > 10) {
lastKeyboardHeight = keyboardHeight;
callback(keyboardHeight > 0 ? keyboardHeight : 0);
}
};
window.visualViewport.addEventListener('resize', handleViewportChange);
return () => {
window.visualViewport?.removeEventListener('resize', handleViewportChange);
};
}
const handleWindowResize = () => {
const currentHeight = window.innerHeight;
const keyboardHeight = initialViewportHeight - currentHeight;
if (Math.abs(keyboardHeight - lastKeyboardHeight) > 10) {
lastKeyboardHeight = keyboardHeight;
callback(keyboardHeight > 0 ? keyboardHeight : 0);
}
};
window.addEventListener('resize', handleWindowResize);
return () => {
window.removeEventListener('resize', handleWindowResize);
};
}
function adjustPageHeight(keyboardHeight: number) {
const possibleContainers = [
document.getElementById('app'),
document.querySelector('.app'),
document.querySelector('[data-app]'),
document.body,
];
const container = possibleContainers.find(el => el !== null) as HTMLElement;
if (!container) return;
if (keyboardHeight > 0) {
container.style.paddingBottom = '';
container.style.transition = '';
const timer = setTimeout(() => {
const activeElement = document.activeElement as HTMLElement;
if (activeElement && activeElement.scrollIntoView) {
const elementRect = activeElement.getBoundingClientRect();
const currentViewportHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
if (elementRect.bottom > currentViewportHeight - 50) {
activeElement.scrollIntoView({
behavior: 'smooth',
block: 'end',
inline: 'nearest',
});
}
}
clearTimeout(timer);
}, 100);
} else {
container.style.paddingBottom = '';
const timer = setTimeout(() => {
container.style.transition = '';
clearTimeout(timer);
}, 250);
}
}
export default function riseInput(input: HTMLElement, target?: HTMLElement) {
const scrollType = getScrollTypeByPlatform();
let scrollTimer: ReturnType<typeof setTimeout>;
let keyboardObserver: (() => void) | null = null;
if (!target) {
// eslint-disable-next-line no-param-reassign
target = input;
}
const scrollIntoView = () => {
if (scrollType === 0) return;
if (scrollType === 1) {
document.body.scrollTop = document.body.scrollHeight;
} else {
target?.scrollIntoView(false);
}
};
if (isIOS) {
keyboardObserver = createKeyboardHeightObserver((keyboardHeight) => {
adjustPageHeight(keyboardHeight);
if (keyboardHeight > 0 && document.activeElement === input) {
const timer = setTimeout(() => {
input.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'nearest',
});
clearTimeout(timer);
}, 200);
}
});
}
input.addEventListener('focus', () => {
const timer = setTimeout(() => {
scrollIntoView();
clearTimeout(timer);
}, 300);
scrollTimer = setTimeout(scrollIntoView, 1000);
});
input.addEventListener('blur', () => {
clearTimeout(scrollTimer);
// Handle IOS issues about keyboard is hidden but page not refreshed
if (scrollType && isIOS) {
const timer = setTimeout(() => {
if (!keyboardObserver) {
document.body.scrollIntoView();
adjustPageHeight(0);
}
clearTimeout(timer);
}, 300);
}
});
return () => {
clearTimeout(scrollTimer);
keyboardObserver?.();
};
}