{"version":3,"file":"index.mjs","sources":[""],"sourcesContent":["import { onWindowResize } from \"@web3r/flowerkit/evt\";\r\nimport type { ReactElement, FC } from \"react\";\r\nimport {\r\n  useRef,\r\n  lazy,\r\n  Suspense,\r\n  useImperativeHandle,\r\n  useState,\r\n  useCallback,\r\n  useMemo,\r\n  useEffect,\r\n} from \"react\";\r\nimport type {\r\n  IMapState, IMapOptions, Clusterer, IMapBoundsOptions, IEvent, Placemark,\r\n} from \"yandex-maps\";\r\nimport { mapDefaults } from \"./config\";\r\nimport type {\r\n  IMap, IMapRef,\r\n  TAPI,\r\n  TCluster,\r\n  TLangs, TMapContext,\r\n  TMapInstance,\r\n  TPoint,\r\n} from \"./config/types\";\r\nimport { MapContext } from \"./context\";\r\nimport {\r\n  getUpdateBounds, getDefaultState, setComputedWidth, isClustersUpdated,\r\n} from \"./lib\";\r\nimport { getInitialClusters, getNormalizedClusters } from \"./lib/clusterer\";\r\nimport type { IComponentBaseProps } from \"../../types/components\";\r\nimport { useCN } from \"../../utils/react/useCN\";\r\nimport { useIO } from \"../../utils/react/useIO\";\r\nimport { useLocalisationLanguages } from \"../../utils/react/useLocalisationLanguages\";\r\nimport { useSSGRender } from \"../../utils/react/useSSGRender\";\r\nimport \"./style.pcss\";\r\n\r\nconst YandexMap = lazy(() => import(/* webpackChunkName: \"yaMap\" */\"./ui/Map\"));\r\n\r\ntype TNumberArrayLike = number[] | number[][] | null | undefined;\r\n\r\nconst getFlatNumberArray = (value: TNumberArrayLike): number[] | null => {\r\n  if (Array.isArray(value) && value.every((item) => typeof item === \"number\" && Number.isFinite(item))) {\r\n    return value as number[];\r\n  }\r\n  return null;\r\n};\r\n\r\nconst isEqualNumberArray = (first: TNumberArrayLike, second: TNumberArrayLike): boolean => {\r\n  const normalizedFirst = getFlatNumberArray(first);\r\n  const normalizedSecond = getFlatNumberArray(second);\r\n  if (!normalizedFirst || !normalizedSecond || normalizedFirst.length !== normalizedSecond.length) {\r\n    return false;\r\n  }\r\n  return normalizedFirst.every((value, index) => value === normalizedSecond[index]);\r\n};\r\n\r\n/**\r\n * Компонент карты. Служит оберткой над Yandex.Maps.\r\n\r\n * @returns {ReactElement}\r\n */\r\nconst Map: FC<IMap & IComponentBaseProps> = (props): ReactElement => {\r\n\r\n  const {\r\n    baseClass = mapDefaults.baseClass,\r\n    extraClasses = mapDefaults.extraClasses,\r\n    extraAttrs = mapDefaults.extraAttrs,\r\n    children = mapDefaults.children,\r\n    onAction = mapDefaults.onAction,\r\n    id = mapDefaults.id,\r\n    isAsync = mapDefaults.isAsync,\r\n    points = mapDefaults.points,\r\n    clusters = mapDefaults.clusters,\r\n    modules = mapDefaults.modules,\r\n    center = mapDefaults.center,\r\n    zoom = mapDefaults.zoom,\r\n    placeholderSlot = mapDefaults.placeholderSlot,\r\n    onError = mapDefaults.onError,\r\n    onReady = mapDefaults.onReady,\r\n    options = mapDefaults.options,\r\n    margin = mapDefaults.margin,\r\n    isDisabled = mapDefaults.isDisabled,\r\n    api = mapDefaults.api,\r\n    panelSlot = mapDefaults.panelSlot,\r\n    maxActivePoints = mapDefaults.maxActivePoints,\r\n    onMount = mapDefaults.onMount,\r\n    onUnmount = mapDefaults.onUnmount,\r\n    pointOptions = mapDefaults.pointOptions,\r\n    clusterOptions = mapDefaults.clusterOptions,\r\n    isAllPointsVisible = mapDefaults.isAllPointsVisible,\r\n    ref,\r\n  } = props || {};\r\n\r\n  // User clusters\r\n  const userClusters = useMemo(() => {\r\n    return getInitialClusters(clusters, points, clusterOptions, pointOptions);\r\n  }, [ clusters, points, clusterOptions, pointOptions ]);\r\n\r\n  // Classnames\r\n  const { getCN } = useCN(baseClass);\r\n\r\n  // Container ref\r\n  const containerRef = useRef<HTMLDivElement | null>(null);\r\n\r\n  // Instance ref\r\n  const instanceRef = useRef<TMapInstance>(null);\r\n\r\n  // Current balloon ref\r\n  const balloonRef = useRef<Placemark[\"balloon\"]>(null);\r\n\r\n  // Callback refs to avoid re-creating handlers\r\n  const onReadyRef = useRef(onReady);\r\n  const onErrorRef = useRef(onError);\r\n\r\n  // Update refs when props change\r\n  useEffect(() => {\r\n    onReadyRef.current = onReady;\r\n    onErrorRef.current = onError;\r\n  }, [ onReady, onError ]);\r\n\r\n  // IO\r\n  const { observer } = useIO({\r\n    callback: (entry: IntersectionObserverEntry[]) => {\r\n      if (entry) {\r\n        entry.forEach(({ isIntersecting }) => {\r\n          if (isIntersecting) {\r\n            setIsVisible(true);\r\n            setIsLoading(true);\r\n          }\r\n        });\r\n      }\r\n    },\r\n  });\r\n\r\n  // Panel state\r\n  const [ panelData, setPanelData ] = useState<TPoint | null>(null);\r\n\r\n  // Visibility state\r\n  const [ isVisible, setIsVisible ] = useState<boolean>(!isAsync);\r\n\r\n  // Disabled state\r\n  const [ isMapDisabled, setIsMapDisabled ] = useState<boolean>(!!isDisabled);\r\n\r\n  // Loading state\r\n  const [ isLoading, setIsLoading ] = useState<boolean>(false);\r\n\r\n  // Updating state\r\n  const [ isUpdating, setIsUpdating ] = useState<boolean>(false);\r\n\r\n  // Error state\r\n  const [ isError, setIsError ] = useState<boolean>(false);\r\n\r\n  // Current lang\r\n  const { lang } = useLocalisationLanguages({ isNormalize: true });\r\n\r\n  // Current query to API\r\n  const currentQuery = useMemo(() => {\r\n    return {\r\n      apikey: api?.key ?? \"\",\r\n      lang: lang as TLangs,\r\n    };\r\n  }, [ api, lang ]);\r\n\r\n  // Current map inner state\r\n  const [ currentState, setCurrentState ] = useState<IMapState>(() => getDefaultState({ zoom, center, margin }));\r\n  const prevStateRef = useRef<IMapState>(currentState);\r\n\r\n  // Current map inner options\r\n  const currentOptions = useMemo<IMapOptions>(() => {\r\n    return {\r\n      ...mapDefaults.options,\r\n      ...options,\r\n    };\r\n  }, [ options ]);\r\n\r\n  // Current map clusters\r\n  const [ currentClusters, setCurrentClusters ] = useState<TCluster[]>(userClusters);\r\n\r\n  // Refs on prev clusters state\r\n  const prevClusters = useRef<TCluster[]>(currentClusters);\r\n  const prevActivePoints = useRef<string[]>(currentClusters.flatMap((c) => c.points.filter((p) => p.state?.isActive)).map((p) => p.id));\r\n\r\n  // Log when clusters change and close previous balloon\r\n  useEffect(() => {\r\n    const activePoints = currentClusters.flatMap((c) => c.points.filter((p) => p.state?.isActive)).map((p) => p.id);\r\n\r\n    // Если активная метка изменилась, закроем старый балун асинхронно\r\n    const prevActivePointIds = prevActivePoints.current;\r\n    if (JSON.stringify(activePoints) !== JSON.stringify(prevActivePointIds) && balloonRef.current) {\r\n      (async () => {\r\n        try {\r\n          if (balloonRef.current?.isOpen?.()) {\r\n            await balloonRef.current.close();\r\n          }\r\n          // Очищаем ссылку после закрытия\r\n          balloonRef.current = null;\r\n        } catch (err) {\r\n          console.warn(\"[Map] Failed to close balloon:\", err);\r\n          balloonRef.current = null;\r\n        }\r\n      })();\r\n    }\r\n    prevActivePoints.current = activePoints;\r\n  }, [ currentClusters ]);\r\n\r\n  // State utils\r\n  const stateActions = useMemo(() => ({\r\n    /**\r\n     * Управляет активностью боковой панели.\r\n     * Используйте `null` для закрытия панели.\r\n     */\r\n    setPanelData,\r\n    /**\r\n     * Обновляет массив кластеров.\r\n     * Для коррекции границ карты требуется обновить критические параметры: уникальные id либо количество точек.\r\n     */\r\n    setClusters: (nextClusters: TCluster[] | ((prevClusters: TCluster[]) => TCluster[]), isShouldNormalize: boolean = true) => {\r\n      setCurrentClusters((prevClusters) => {\r\n        const computed = typeof nextClusters === \"function\" ? nextClusters(prevClusters) : nextClusters;\r\n        return isShouldNormalize ? getNormalizedClusters(computed, clusterOptions, pointOptions) : computed;\r\n      });\r\n    },\r\n    /**\r\n     * Обновляет флаг активности всей карты\r\n     */\r\n    setIsDisabled: setIsMapDisabled,\r\n    /**\r\n     * Обновляет состояние указанной точки.\r\n     */\r\n    setPointState: (idPoint: TPoint[\"id\"], state: Partial<TPoint[\"state\"]>) => {\r\n      if (typeof idPoint === \"string\" && idPoint.length) {\r\n        setCurrentClusters((prevClustersState) => {\r\n          let isFound = false;\r\n          const nextClustersState = prevClustersState.map((cluster) => {\r\n            const index = cluster.points.findIndex(({ id }) => id === idPoint);\r\n            if (index === -1) {\r\n              return cluster;\r\n            }\r\n            isFound = true;\r\n            return {\r\n              ...cluster,\r\n              points: cluster.points.map((point, pointIndex) => {\r\n                if (pointIndex !== index) {\r\n                  return point;\r\n                }\r\n                return {\r\n                  ...point,\r\n                  state: {\r\n                    ...point.state,\r\n                    ...(state || {}),\r\n                  },\r\n                };\r\n              }),\r\n            };\r\n          });\r\n          if (!isFound) {\r\n            console.error(`[Map] Can't find point with id \"${idPoint}\"`);\r\n          }\r\n          return nextClustersState;\r\n        });\r\n      } else {\r\n        console.error(\"[Map] Argument must be non-empty string\");\r\n      }\r\n    },\r\n  }), [ clusterOptions, pointOptions ]);\r\n\r\n  // Update handle\r\n  const handleUpdate = useCallback(() => {\r\n    const mapInstance = instanceRef.current;\r\n    if (!mapInstance) {\r\n      return;\r\n    }\r\n    const center = mapInstance.getCenter({\r\n      useMapMargin: true,\r\n    });\r\n    const zoom = mapInstance.getZoom();\r\n    const margin = mapInstance.margin.getMargin();\r\n    setCurrentState((prevState) => {\r\n      const nextCenter = getFlatNumberArray(center) ?? prevState.center;\r\n      const nextMargin = getFlatNumberArray(margin) ?? prevState.margin;\r\n      const isEqual = zoom === prevState.zoom\r\n        && isEqualNumberArray(nextCenter, prevState.center)\r\n        && isEqualNumberArray(nextMargin, prevState.margin);\r\n      if (isEqual) {\r\n        return prevState;\r\n      }\r\n      const newState = {\r\n        ...prevState,\r\n        center: nextCenter,\r\n        zoom,\r\n        margin: nextMargin,\r\n      };\r\n      console.debug(`[Map] Updating state (zoom from \"${prevState.zoom}\" to \"${newState.zoom}\", center from \"${prevState.center}\" to \"${newState.center}\", margin from \"${prevState.margin}\" to \"${newState.margin}\")`);\r\n      prevStateRef.current = prevState;\r\n      return newState;\r\n    });\r\n  }, []);\r\n\r\n  // Error handle\r\n  const handleError = useCallback((error: Error | string) => {\r\n    setIsLoading(false);\r\n    setIsError(true);\r\n    setIsUpdating(false);\r\n    console.error(\"[Map] Something is wrong\", error);\r\n    if (typeof onErrorRef.current === \"function\") {\r\n      onErrorRef.current({\r\n        instance: instanceRef.current,\r\n        containerRef,\r\n        error,\r\n      });\r\n    }\r\n  }, []);\r\n\r\n  // Ready handle\r\n  const handleReady = useCallback(async (instance: TAPI, clusters: Clusterer[]) => {\r\n    setIsLoading(false);\r\n    setIsError(false);\r\n    setIsUpdating(true);\r\n    const MapInstance = instanceRef.current;\r\n    if (MapInstance) {\r\n      MapInstance.options.set(\"customProps\", { isAllPointsVisible });\r\n      await getUpdateBounds(MapInstance)\r\n        .catch((err: Error | string) => {\r\n          console.warn(`[Maps] ${(err instanceof Error ? err.message : err.toString())}`);\r\n        })\r\n        .finally(() => {\r\n          setIsUpdating(false);\r\n          handleUpdate();\r\n          if (typeof onReadyRef.current === \"function\") {\r\n            onReadyRef.current({\r\n              clusters,\r\n              instance: MapInstance,\r\n              containerRef,\r\n              ymaps: instance,\r\n            });\r\n          }\r\n        });\r\n    } else {\r\n      handleError(new Error(\"Can't find map instance\"));\r\n    }\r\n  }, [ handleError, handleUpdate, isAllPointsVisible ]);\r\n\r\n  // Change ref\r\n  useImperativeHandle(ref, (): IMapRef => {\r\n    return {\r\n      el: containerRef.current,\r\n      ref: instanceRef,\r\n      utils: {\r\n        /**\r\n         * Обновляет карту для видимости всех точек\r\n         * @param options{IMapBoundsOptions}\r\n         * @returns {Promise<TMapInstance>}\r\n         */\r\n        getUpdateBounds: (options: IMapBoundsOptions): Promise<TMapInstance> => getUpdateBounds(instanceRef.current, options).then(() => {\r\n          handleUpdate();\r\n          return instanceRef.current;\r\n        }),\r\n      },\r\n      getData: () => ({\r\n        clusters: currentClusters,\r\n        prevClusters: prevClusters.current,\r\n      }),\r\n      stateActions,\r\n    };\r\n  }, [ currentClusters, handleUpdate, stateActions ]);\r\n\r\n  // Set IO\r\n  useEffect(() => {\r\n    if (observer && containerRef.current && isAsync) {\r\n      observer.observe(containerRef.current);\r\n      return () => observer.disconnect();\r\n    }\r\n  }, [ isAsync, observer ]);\r\n\r\n  useEffect(() => {\r\n    if (observer && isLoading && isAsync) {\r\n      observer.disconnect();\r\n    }\r\n  }, [ isAsync, isLoading, observer ]);\r\n\r\n  useEffect(() => {\r\n\r\n    setComputedWidth(containerRef.current);\r\n\r\n    const { removeListener } = onWindowResize(async () => {\r\n      const mapInstance = instanceRef.current;\r\n      if (!mapInstance) {\r\n        return;\r\n      }\r\n      setIsUpdating(true);\r\n      setComputedWidth(containerRef.current);\r\n      try {\r\n        await getUpdateBounds(mapInstance);\r\n        handleUpdate();\r\n      } catch (err) {\r\n        console.error(err);\r\n      } finally {\r\n        setIsUpdating(false);\r\n      }\r\n    });\r\n\r\n    if (typeof onMount === \"function\") {\r\n      onMount();\r\n    }\r\n\r\n    return () => {\r\n      removeListener();\r\n\r\n      if (typeof onUnmount === \"function\") {\r\n        onUnmount();\r\n      }\r\n    };\r\n  }, [ handleUpdate, onMount, onUnmount ]);\r\n\r\n  // update clusters & points from props\r\n  useEffect(() => {\r\n    if (userClusters !== prevClusters.current) {\r\n      setIsUpdating(true);\r\n      setCurrentClusters((prev) => {\r\n        console.debug(\"[Map] Update clusters from:\", prev, \"to:\", userClusters);\r\n        return userClusters;\r\n      });\r\n    }\r\n  }, [ userClusters ]);\r\n\r\n  // set bounds after clusters update from state\r\n  useEffect(() => {\r\n    const mapInstance = instanceRef.current;\r\n    const isChanged = isClustersUpdated(currentClusters, prevClusters.current);\r\n\r\n    if (!isChanged || !mapInstance) {\r\n      return;\r\n    }\r\n\r\n    const Objects = mapInstance.geoObjects;\r\n    let isDisposed = false;\r\n    let onObjectAdds: ((event: object | IEvent<unknown, unknown>) => void) | null = null;\r\n\r\n    const onFinally = () => {\r\n      if (isDisposed) {\r\n        return;\r\n      }\r\n      prevClusters.current = currentClusters;\r\n      setIsUpdating(false);\r\n    };\r\n\r\n    const updateBounds = async () => {\r\n      try {\r\n        await getUpdateBounds(mapInstance);\r\n        handleUpdate();\r\n      } catch (err) {\r\n        console.error(err);\r\n      } finally {\r\n        onFinally();\r\n      }\r\n    };\r\n\r\n    setIsUpdating(true);\r\n\r\n    if (currentClusters.some((cluster) => cluster.points.length)) {\r\n      if (Objects.getLength() === currentClusters.length) {\r\n        void updateBounds();\r\n      } else {\r\n        onObjectAdds = async (_event: object | IEvent<unknown, unknown>) => {\r\n          if (Objects.getLength() === currentClusters.length) {\r\n            if (onObjectAdds) {\r\n              Objects.events.remove(\"add\", onObjectAdds);\r\n            }\r\n            await updateBounds();\r\n          }\r\n        };\r\n        Objects.events.add(\"add\", onObjectAdds);\r\n      }\r\n    } else {\r\n      onFinally();\r\n    }\r\n\r\n    return () => {\r\n      isDisposed = true;\r\n      if (onObjectAdds) {\r\n        Objects.events.remove(\"add\", onObjectAdds);\r\n        onObjectAdds = null;\r\n      }\r\n    };\r\n  }, [ currentClusters, handleUpdate ]);\r\n\r\n  // update state\r\n  useEffect(() => {\r\n    const newState = getDefaultState({ center, zoom, margin });\r\n    const isChanged = prevStateRef.current.zoom !== newState.zoom\r\n      || !isEqualNumberArray(prevStateRef.current.center, newState.center)\r\n      || !isEqualNumberArray(prevStateRef.current.margin, newState.margin);\r\n    if (isChanged) {\r\n      setCurrentState((prevState) => {\r\n        return {\r\n          ...prevState,\r\n          ...newState,\r\n        };\r\n      });\r\n      prevStateRef.current = newState;\r\n    }\r\n  }, [ center, zoom, margin ]);\r\n\r\n  const className = getCN(\"\", {\r\n    isLoading,\r\n    isUpdating,\r\n    isError,\r\n    isDisabled: isMapDisabled,\r\n    isVisible,\r\n    isPanel: !!panelData,\r\n    ...extraClasses,\r\n  });\r\n\r\n  const ctx = useMemo<TMapContext>(() => ({\r\n    api, getCN, points, instanceRef, containerRef, balloonRef, center, zoom, modules, clusters, options, onAction, stateActions, panelSlot, panelData, maxActivePoints, currentClusters,\r\n  }), [\r\n    api,\r\n    balloonRef,\r\n    center,\r\n    clusters,\r\n    containerRef,\r\n    currentClusters,\r\n    getCN,\r\n    instanceRef,\r\n    maxActivePoints,\r\n    modules,\r\n    onAction,\r\n    options,\r\n    panelData,\r\n    panelSlot,\r\n    points,\r\n    stateActions,\r\n    zoom,\r\n  ]);\r\n\r\n  const SSGComponent = useSSGRender(\"data-js-yandex-map\", props);\r\n\r\n  if (SSGComponent) {\r\n    return SSGComponent;\r\n  }\r\n\r\n  return (\r\n    <MapContext value={ctx}>\r\n      <div id={id} ref={containerRef} className={className} {...extraAttrs}>\r\n        <div className={getCN(\"inner\")}>\r\n          {isVisible && (\r\n            <Suspense fallback={placeholderSlot}>\r\n              <YandexMap clusters={currentClusters} state={currentState} query={currentQuery} options={currentOptions} onReady={handleReady} onError={handleError}>\r\n                {children}\r\n              </YandexMap>\r\n            </Suspense>\r\n          )}\r\n        </div>\r\n      </div>\r\n    </MapContext>\r\n  );\r\n\r\n};\r\n\r\nexport type { IMap, IMapRef };\r\n\r\nexport {\r\n  Map,\r\n};\r\n"],"names":["YandexMap","lazy","getFlatNumberArray","value","Array","isArray","every","item","Number","isFinite","isEqualNumberArray","first","second","normalizedFirst","normalizedSecond","length","index","Map","props","baseClass","mapDefaults","extraClasses","extraAttrs","children","onAction","id","isAsync","points","clusters","modules","center","zoom","placeholderSlot","onError","onReady","options","margin","isDisabled","api","panelSlot","maxActivePoints","onMount","onUnmount","pointOptions","clusterOptions","isAllPointsVisible","ref","userClusters","useMemo","getInitialClusters","getCN","useCN","containerRef","useRef","instanceRef","balloonRef","onReadyRef","onErrorRef","useEffect","current","observer","useIO","callback","entry","forEach","isIntersecting","setIsVisible","setIsLoading","panelData","setPanelData","useState","isVisible","isMapDisabled","setIsMapDisabled","isLoading","isUpdating","setIsUpdating","isError","setIsError","lang","useLocalisationLanguages","isNormalize","currentQuery","apikey","key","currentState","setCurrentState","getDefaultState","prevStateRef","currentOptions","currentClusters","setCurrentClusters","prevClusters","prevActivePoints","flatMap","c","filter","p","state","isActive","map","activePoints","prevActivePointIds","JSON","stringify","isOpen","close","err","console","warn","stateActions","setClusters","nextClusters","isShouldNormalize","computed","getNormalizedClusters","setIsDisabled","setPointState","idPoint","prevClustersState","isFound","nextClustersState","cluster","findIndex","point","pointIndex","error","handleUpdate","useCallback","mapInstance","getCenter","useMapMargin","getZoom","getMargin","prevState","nextCenter","nextMargin","isEqual","newState","debug","handleError","instance","handleReady","async","MapInstance","set","getUpdateBounds","catch","Error","message","toString","finally","ymaps","useImperativeHandle","el","utils","then","getData","observe","disconnect","setComputedWidth","removeListener","onWindowResize","prev","isChanged","isClustersUpdated","Objects","geoObjects","isDisposed","onObjectAdds","onFinally","updateBounds","some","getLength","events","remove","add","className","isPanel","ctx","SSGComponent","useSSGRender","_jsx","MapContext","Suspense","fallback","query"],"mappings":"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"}