* fix(ui): update viewport height without visualViewport * fix(ui): initialize visual viewport state from helper --------- Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import React from 'react';
|
|
|
|
export interface VisualViewportState {
|
|
height: number;
|
|
keyboardHeight: number;
|
|
}
|
|
|
|
export const getVisualViewportState = (): VisualViewportState => {
|
|
if (typeof window === 'undefined') {
|
|
return { height: 0, keyboardHeight: 0 };
|
|
}
|
|
|
|
const height = window.visualViewport?.height ?? window.innerHeight;
|
|
const keyboardHeight = window.visualViewport
|
|
? Math.max(0, window.innerHeight - height)
|
|
: 0;
|
|
|
|
return { height, keyboardHeight };
|
|
};
|
|
|
|
export const useVisualViewport = (): VisualViewportState => {
|
|
const [state, setState] = React.useState<VisualViewportState>(getVisualViewportState);
|
|
|
|
const rafIdRef = React.useRef<number | null>(null);
|
|
|
|
React.useEffect(() => {
|
|
if (typeof window === 'undefined') return;
|
|
|
|
const visualViewport = window.visualViewport;
|
|
|
|
const handleChange = () => {
|
|
if (rafIdRef.current !== null) return;
|
|
rafIdRef.current = requestAnimationFrame(() => {
|
|
rafIdRef.current = null;
|
|
const nextState = getVisualViewportState();
|
|
setState((prev) => {
|
|
if (prev.height === nextState.height && prev.keyboardHeight === nextState.keyboardHeight) return prev;
|
|
return nextState;
|
|
});
|
|
});
|
|
};
|
|
|
|
if (visualViewport) {
|
|
visualViewport.addEventListener('resize', handleChange);
|
|
visualViewport.addEventListener('scroll', handleChange, { passive: true });
|
|
} else {
|
|
window.addEventListener('resize', handleChange);
|
|
}
|
|
handleChange();
|
|
|
|
return () => {
|
|
if (rafIdRef.current !== null) {
|
|
cancelAnimationFrame(rafIdRef.current);
|
|
}
|
|
if (visualViewport) {
|
|
visualViewport.removeEventListener('resize', handleChange);
|
|
visualViewport.removeEventListener('scroll', handleChange);
|
|
} else {
|
|
window.removeEventListener('resize', handleChange);
|
|
}
|
|
};
|
|
}, []);
|
|
|
|
return state;
|
|
};
|