event form fix
This commit is contained in:
@@ -72,43 +72,22 @@ function fmt12(val) {
|
|||||||
function TimeInputMobile({ value, onChange }) {
|
function TimeInputMobile({ value, onChange }) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [inputVal, setInputVal] = useState(fmt12(value));
|
const [inputVal, setInputVal] = useState(fmt12(value));
|
||||||
const [keyboardOffset, setKeyboardOffset] = useState(0);
|
const [dropdownPos, setDropdownPos] = useState({ top: 0, left: 0 });
|
||||||
const [dropdownPos, setDropdownPos] = useState({ top: 0, bottom: 'auto', left: 0 });
|
|
||||||
const wrapRef = useRef(null);
|
const wrapRef = useRef(null);
|
||||||
const listRef = useRef(null);
|
const listRef = useRef(null);
|
||||||
|
|
||||||
useEffect(() => { setInputVal(fmt12(value)); }, [value]);
|
useEffect(() => { setInputVal(fmt12(value)); }, [value]);
|
||||||
|
|
||||||
// Detect keyboard height via Visual Viewport API
|
// Calculate dropdown position — always above the input.
|
||||||
useEffect(() => {
|
// getBoundingClientRect() is relative to the visual viewport on mobile Chrome,
|
||||||
const handleViewportChange = () => {
|
// so this correctly clears the keyboard regardless of its height.
|
||||||
if (window.visualViewport) {
|
|
||||||
const offset = window.innerHeight - window.visualViewport.height;
|
|
||||||
setKeyboardOffset(offset > 0 ? offset : 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (open) {
|
|
||||||
handleViewportChange();
|
|
||||||
window.visualViewport?.addEventListener('resize', handleViewportChange);
|
|
||||||
return () => window.visualViewport?.removeEventListener('resize', handleViewportChange);
|
|
||||||
} else {
|
|
||||||
setKeyboardOffset(0);
|
|
||||||
}
|
|
||||||
}, [open]);
|
|
||||||
|
|
||||||
// Calculate dropdown pixel position using getBoundingClientRect (required for position:fixed)
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open && wrapRef.current) {
|
if (open && wrapRef.current) {
|
||||||
const rect = wrapRef.current.getBoundingClientRect();
|
const rect = wrapRef.current.getBoundingClientRect();
|
||||||
const dropdownHeight = 5 * 40;
|
const dropdownHeight = 5 * 40;
|
||||||
const spaceBelow = window.innerHeight - rect.bottom - keyboardOffset;
|
setDropdownPos({ top: Math.max(0, rect.top - dropdownHeight), left: rect.left });
|
||||||
if (spaceBelow >= dropdownHeight) {
|
|
||||||
setDropdownPos({ top: rect.bottom, bottom: 'auto', left: rect.left });
|
|
||||||
} else {
|
|
||||||
setDropdownPos({ top: 'auto', bottom: window.innerHeight - rect.top + keyboardOffset, left: rect.left });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [open, keyboardOffset]);
|
}, [open]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open || !listRef.current) return;
|
if (!open || !listRef.current) return;
|
||||||
@@ -151,7 +130,6 @@ function TimeInputMobile({ value, onChange }) {
|
|||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
zIndex: 9999,
|
zIndex: 9999,
|
||||||
top: dropdownPos.top,
|
top: dropdownPos.top,
|
||||||
bottom: dropdownPos.bottom,
|
|
||||||
left: dropdownPos.left,
|
left: dropdownPos.left,
|
||||||
background: 'var(--surface)', border: '1px solid var(--border)',
|
background: 'var(--surface)', border: '1px solid var(--border)',
|
||||||
borderRadius: 8, boxShadow: '0 4px 20px rgba(0,0,0,0.2)',
|
borderRadius: 8, boxShadow: '0 4px 20px rgba(0,0,0,0.2)',
|
||||||
|
|||||||
Reference in New Issue
Block a user