import { useYMaps } from "@pbe/react-yandex-maps"; import type { FC, ReactNode, PropsWithChildren, } from "react"; import { memo, useContext, useEffect, useMemo, useRef, } from "react"; import type { Clusterer } from "yandex-maps"; import { MapClusterer } from "./MapClusterer"; import type { TMapModulesProps } from "./MapModules"; import { MapModules } from "./MapModules"; import { MapPanel } from "./MapPanel"; import { MapPlacemark } from "./MapPlacemark"; import { mapDefaults } from "../config"; import type { IMap, TCluster, TMapContext, TPoint, } from "../config/types"; import { MapContext } from "../context"; import { getActivePointsCount } from "../lib/clusterer"; export type TMapItemsProps = Pick & PropsWithChildren<{ onReady?: (clusters: Clusterer[]) => void; }>; const MemoModules = memo((props: TMapModulesProps): ReactNode => ); MemoModules.displayName = "MapModules"; const hasPointPaneData = (point: TPoint): boolean => { return !!(point?.meta?.pane?.title || point?.meta?.pane?.description); }; /** * Внутренний компонент содержимого карт * @returns {ReactNode} */ const MapItems: FC = ({ children, clusters = [], onReady, }: TMapItemsProps): ReactNode => { const { panelSlot, modules, api, } = useContext(MapContext); const ymaps = useYMaps(api?.load ?? mapDefaults.api!.load); const clustersRef = useRef([]); const activePointsCountRef = useRef(getActivePointsCount(clusters)); const isPanelEnabled = useMemo(() => { if (panelSlot) { return true; } return clusters.some((cluster) => cluster.points.some((point) => hasPointPaneData(point))); }, [ panelSlot, clusters ]); useEffect(() => { clustersRef.current = []; activePointsCountRef.current = getActivePointsCount(clusters); }, [ clusters ]); const onClusterersReady = (instance: Clusterer) => { clustersRef.current.push(instance); if (clustersRef.current.length === clusters?.length && typeof onReady === "function") { onReady(clustersRef.current); } }; return ymaps && ( <> {clusters.map((cluster: TCluster, index) => { const { id, points } = cluster; const clusterKey = `clusterer_${id}_${points.map((point) => `${point.id}_${point.coords.join("_")}`).join("|")}_${index}`; return ( {points.map((props: TPoint, index) => { const pointKey = `placemark_${id}_${props.id}_${props.coords.join("_")}_${index}`; return ( ); })} ); })} {isPanelEnabled && {panelSlot}} {children} ); }; export { MapItems, };