import { useMapInternalContext } from '../utils/context/map-context.utils'; import { useCallback, useImperativeHandle, useRef } from 'react'; import type { RefObject } from 'react'; import YaMap from '../../bare'; import type { CameraPosition } from '../../bare'; import { promisify } from '../../utils/promisify.utils'; import type { Point, SetCameraPositionParams, Unsub } from '../utils/types'; import { MapEvent } from '../utils/types'; type ListenerAccumulator = Record>; export const useMapViewModel = () => { const { isConfigured, mapRef: contextMapRef } = useMapInternalContext(); const mapRef = useRef() as RefObject; const _eventListeners = useRef( {} as ListenerAccumulator ); const getCameraPosition = useCallback(async () => { return promisify(mapRef.current!.getCameraPosition, mapRef.current!); }, []); const setCameraPosition = useCallback((params: SetCameraPositionParams) => { mapRef.current!.setCenter( { ...params, }, params.zoom, params.azimuth ?? 0, params.tilt ?? 0, params.animationDuration ?? 0.5 ); }, []); const listenerTrigger = useCallback((event: MapEvent, e: unknown) => { !!_eventListeners.current?.[event] && Object.getOwnPropertySymbols(_eventListeners.current?.[event]).forEach( (key) => { _eventListeners.current?.[event]?.[key]?.(e); } ); }, []); const onCameraPositionChanged = useCallback( (e: CameraPosition) => { listenerTrigger(MapEvent.CAMERA_POSITION_CHANGED, e); }, [listenerTrigger] ); const onMapLongPress = useCallback( (e: Point) => { listenerTrigger(MapEvent.MAP_LONG_PRESS, e); }, [listenerTrigger] ); const onCameraPositionChange = useCallback(() => { listenerTrigger(MapEvent.CAMERA_POSITION_CHANGE_START, null); }, [listenerTrigger]); const addListener = useCallback( (event: MapEvent, cb: (d: T) => void): Unsub => { const eventKey = Symbol('Event key'); if (!_eventListeners.current[event]) { _eventListeners.current[event] = {}; } _eventListeners.current[event][eventKey] = cb; return () => { delete _eventListeners.current[event][eventKey]; }; }, [] ); useImperativeHandle(contextMapRef, () => ({ raw: mapRef, getCameraPosition, addListener, setCameraPosition, })); return { isVisible: isConfigured, mapRef, listeners: { onCameraPositionChanged, onMapLongPress, onCameraPositionChange, }, }; };