mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 07:40:59 +00:00
4c0583845a
Selecting a place no longer spiderfies a city-sized cluster: the reveal only fans open bubbles of up to 12 stops, or stacks whose stops all share one coordinate, so a zoomed-out trip with hundreds of places stays usable (#2990). The selected pin now carries a white border inside a pulsing blue ring on both renderers (static under reduced motion), and the map measures the place card instead of assuming a fixed 320px, so the selection pans the pin above even a tall card on portrait tablets and eases it back out when the card grows over it later (#2991). Closes #2990 Closes #2991
43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
|
|
/**
|
|
* A callback ref that reports its element's rendered height whenever it changes, and 0
|
|
* once the element is gone. For a card floating over something that has to keep clear of
|
|
* it, the way the map keeps the selected pin above the place card (#2991).
|
|
*/
|
|
export function useReportedHeight(onHeight: ((height: number) => void) | undefined) {
|
|
const observer = useRef<ResizeObserver | null>(null);
|
|
const report = useRef(onHeight);
|
|
useLayoutEffect(() => {
|
|
report.current = onHeight;
|
|
}, [onHeight]);
|
|
|
|
const ref = useCallback((el: HTMLElement | null) => {
|
|
observer.current?.disconnect();
|
|
observer.current = null;
|
|
if (!el) {
|
|
report.current?.(0);
|
|
return;
|
|
}
|
|
const publish = () => report.current?.(el.offsetHeight);
|
|
publish();
|
|
if (typeof ResizeObserver !== 'undefined') {
|
|
observer.current = new ResizeObserver(publish);
|
|
observer.current.observe(el);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => () => observer.current?.disconnect(), []);
|
|
return ref;
|
|
}
|
|
|
|
/**
|
|
* The element's height as state, and `measure`, the callback ref that reads it: hand
|
|
* `measure` to the element as its `ref`.
|
|
*/
|
|
export function useMeasuredHeight() {
|
|
const [height, setHeight] = useState(0);
|
|
const measure = useReportedHeight(setHeight);
|
|
return { height, measure };
|
|
}
|