
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
{"version":3,"file":"index.modern.js","sources":["../src/hooks/useIsomorphicLayoutEffect.tsx","../src/hooks/useKakaoEvent.tsx","../src/util/kakaoMapApiLoader.ts","../src/components/Map.tsx","../src/hooks/useMap.tsx","../src/components/InfoWindow.tsx","../src/components/MarkerClusterer.tsx","../src/components/Marker.tsx","../src/components/MapMarker.tsx","../src/components/MapInfoWindow.tsx","../src/components/CustomOverlayMap.tsx","../src/components/MapTypeControl.tsx","../src/components/ZoomControl.tsx","../src/components/MapTypeId.tsx","../src/components/Circle.tsx","../src/components/Polyline.tsx","../src/components/Polygon.tsx","../src/components/Rectangle.tsx","../src/components/Ellipse.tsx","../src/components/AbstractOverlay.tsx","../src/components/Roadview.tsx","../src/hooks/useRoadview.tsx","../src/components/CustomOverlayRoadview.tsx","../src/components/RoadviewMarker.tsx","../src/components/RoadviewInfoWindow.tsx","../src/components/DrawingManager.tsx","../src/components/Toolbox.tsx","../src/components/StaticMap.tsx","../src/hooks/useInjectKakaoMapApi.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect } from \"react\"\n\nconst useIsomorphicLayoutEffect =\n typeof window !== \"undefined\" && typeof document !== \"undefined\"\n ? useLayoutEffect\n : useEffect\n\nexport default useIsomorphicLayoutEffect\n","import useIsomorphicLayoutEffect from \"./useIsomorphicLayoutEffect\"\n\nconst useKakaoEvent = <T extends kakao.maps.event.EventTarget>(\n /**\n * 이벤트 타겟\n */\n target: T | undefined,\n /**\n * event 타입\n */\n type: string,\n /**\n * 호출될 callback\n */\n callback: ((target: T, ...args: any[]) => void) | undefined\n) => {\n useIsomorphicLayoutEffect(() => {\n if (!target || !callback) return\n\n const wrapCallback = (...arg: any[]) => {\n if (arg === undefined) return callback(target)\n else return callback(target, ...arg)\n }\n\n kakao.maps.event.addListener(target, type, wrapCallback)\n\n return () => {\n kakao.maps.event.removeListener(target, type, wrapCallback)\n }\n }, [target, type, callback])\n}\n\nexport default useKakaoEvent\n","export type Libraries = (\"services\" | \"clusterer\" | \"drawing\")[]\n\nexport interface LoaderOptions {\n /**\n * script 객체 생성시 사용자 정의 id\n */\n id?: string\n /**\n * 발급 받은 Kakao 지도 Javscript API 키.\n *\n * @see [준비하기](https://apis.map.kakao.com/web/guide/#ready)\n */\n appkey: string\n /**\n * 사용하는 라이브러리 목록\n *\n * Kakao 지도 Javascript API 는 지도와 함께 사용할 수 있는 라이브러리 를 지원하고 있습니다.\n * 라이브러리는 javascript API와 관련되어 있지만 조금 특화된 기능을 묶어둔 것을 말합니다. 이 기능은 추가로 불러와서 사용할 수 있도록 되어있습니다.\n * 현재 사용할 수 있는 라이브러리는 다음과 같습니다.\n *\n * clusterer: 마커를 클러스터링 할 수 있는 클러스터러 라이브러리 입니다.\n * services: 장소 검색 과 주소-좌표 변환 을 할 수 있는 services 라이브러리 입니다.\n * drawing: 지도 위에 마커와 그래픽스 객체를 쉽게 그릴 수 있게 그리기 모드를 지원하는 drawing 라이브러리 입니다.\n * 라이브러리는 계속해서 추가될 예정입니다.\n */\n libraries?: Libraries\n /**\n * 사용자 정의 Kakao 지도 javascript 경로 지정\n *\n * @default \"//dapi.kakao.com/v2/maps/sdk.js\"\n */\n url?: string\n /**\n * 보안을 위한 nonce 값 설정\n */\n nonce?: string\n /**\n * 스크립트 로드 재시도 횟수\n */\n retries?: number\n}\n\nexport enum LoaderStatus {\n INITIALIZED,\n LOADING,\n SUCCESS,\n FAILURE,\n}\n\nconst DEFAULT_ID = \"__reactKakaoMapsSdkloaderId\"\n\n/**\n * Kakao Map Api Loader\n *\n * `new Loader(options).load()` 함수를 이용하여 Api를 비동기적으로 삽입할 수 있습니다.\n *\n * 해당 Loader를 이용시 `react-kakao-maps-sdk` 내부에서 injection 되는 이벤트를 감지하여 kakao map api 로딩 이후에 렌더링을 진행합니다.\n */\nexport class Loader {\n private static instance: Loader\n private static loadcheckcallbacks: ((e?: ErrorEvent) => void)[] = []\n\n public readonly id: string\n public readonly appkey: string\n public readonly url: string\n public readonly libraries: Libraries\n public readonly nonce: string | undefined\n public readonly retries: number\n\n private callbacks: ((e?: ErrorEvent) => void)[] = []\n private done = false\n private loading = false\n private errors: ErrorEvent[] = []\n private onerrorEvent: ErrorEvent | undefined\n\n constructor({\n appkey,\n id = DEFAULT_ID,\n libraries = [],\n nonce,\n retries = 3,\n url = \"//dapi.kakao.com/v2/maps/sdk.js\",\n }: LoaderOptions) {\n this.id = id\n this.appkey = appkey\n this.libraries = libraries\n this.nonce = nonce\n this.retries = retries\n this.url = url\n\n if (Loader.instance) {\n if (!Loader.equalOptions(this.options, Loader.instance.options)) {\n throw new Error(\n `Loader must not be called again with different options. ${JSON.stringify(\n this.options\n )} !== ${JSON.stringify(Loader.instance.options)}`\n )\n }\n\n return Loader.instance\n }\n Loader.instance = this\n }\n\n public get options() {\n return {\n appkey: this.appkey,\n id: this.id,\n libraries: this.libraries,\n nonce: this.nonce,\n retries: this.retries,\n url: this.url,\n }\n }\n\n public static isLoaded(): Promise<boolean> {\n return new Promise((resolve) => {\n if (!Loader.instance) {\n if (window.kakao && window.kakao.maps) {\n return window.kakao.maps.load(() => {\n resolve(true)\n })\n }\n return Loader.loadcheckcallbacks.push((e) => {\n resolve(!e)\n })\n }\n\n if (\n Loader.instance.status === LoaderStatus.FAILURE ||\n Loader.instance.status === LoaderStatus.INITIALIZED\n ) {\n return resolve(false)\n }\n\n if (Loader.instance.status === LoaderStatus.LOADING) {\n Loader.loadcheckcallbacks.push((e) => resolve(!e))\n }\n\n return resolve(true)\n })\n }\n\n public load(): Promise<typeof kakao> {\n return new Promise((resolve, reject) => {\n this.loadCallback((err?: ErrorEvent) => {\n if (!err) {\n resolve(window.kakao)\n } else {\n reject(err.error)\n }\n })\n })\n }\n\n public get status(): LoaderStatus {\n if (this.onerrorEvent) {\n return LoaderStatus.FAILURE\n }\n if (this.done) {\n return LoaderStatus.SUCCESS\n }\n if (this.loading) {\n return LoaderStatus.LOADING\n }\n return LoaderStatus.INITIALIZED\n }\n\n private get failed(): boolean {\n return this.done && !this.loading && this.errors.length >= this.retries + 1\n }\n\n private loadCallback(fn: (e?: ErrorEvent) => void): void {\n this.callbacks.push(fn)\n this.execute()\n }\n\n private resetIfRetryingFailed(): void {\n if (this.failed) {\n this.reset()\n }\n }\n\n private reset(): void {\n this.deleteScript()\n this.done = false\n this.loading = false\n this.errors = []\n this.onerrorEvent = undefined\n }\n\n private execute() {\n this.resetIfRetryingFailed()\n\n if (this.done) {\n this.callback()\n } else {\n if (window.kakao && window.kakao.maps) {\n console.warn(\n \"Kakao Maps이 이미 외부 요소에 의해 로딩되어 있습니다.\" +\n \"설정한 옵션과 일치 하지 않을 수 있으며, 이에 따른 예상치 동작이 발생할 수 있습니다.\"\n )\n this.callback()\n return\n }\n\n if (!this.loading) {\n this.loading = true\n this.setScript()\n }\n }\n }\n\n private setScript() {\n if (document.getElementById(this.id)) {\n this.callback()\n }\n\n const url = this.createUrl()\n const script = document.createElement(\"script\")\n\n script.id = this.id\n script.type = \"text/javascript\"\n script.src = url\n script.onerror = this.loadErrorCallback.bind(this)\n script.onload = this.callback.bind(this)\n script.defer = true\n script.async = true\n\n if (this.nonce) {\n script.nonce = this.nonce\n }\n\n document.head.appendChild(script)\n }\n\n private loadErrorCallback(\n event: Event | string,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): void {\n this.errors.push({\n event,\n source,\n // @ts-ignore\n lineno,\n // @ts-ignore\n colno,\n error,\n })\n\n if (this.errors.length <= this.retries) {\n const delay = this.errors.length * 2 ** this.errors.length\n\n console.log(`Failed to load Kakao Maps script, retrying in ${delay} ms.`)\n\n setTimeout(() => {\n this.deleteScript()\n this.setScript()\n }, delay)\n } else {\n this.onerrorEvent = this.errors[this.errors.length - 1]\n this.callback()\n }\n }\n\n public createUrl(): string {\n let url = this.url\n url += `?appkey=${this.appkey}`\n\n if (this.libraries.length) {\n url += `&libraries=${this.libraries.join(\",\")}`\n }\n\n url += `&autoload=false`\n\n return url\n }\n\n private deleteScript() {\n const script = document.getElementById(this.id)\n if (script) {\n script.remove()\n }\n }\n\n private callback() {\n kakao.maps.load(() => {\n this.done = true\n this.loading = false\n\n this.callbacks.forEach((cb) => {\n cb(this.onerrorEvent)\n })\n this.callbacks = []\n\n Loader.loadcheckcallbacks.forEach((cb) => {\n cb(this.onerrorEvent)\n })\n Loader.loadcheckcallbacks = []\n })\n }\n\n private static equalOptions(\n a: typeof Loader.prototype.options,\n b: typeof Loader.prototype.options\n ): boolean {\n if (a.appkey !== b.appkey) return false\n if (a.id !== b.id) return false\n\n if (a.libraries.length !== b.libraries.length) return false\n for (let i = 0; i < a.libraries.length; ++i) {\n if (a.libraries[i] !== b.libraries[i]) return false\n }\n if (a.nonce !== b.nonce) return false\n if (a.retries !== b.retries) return false\n if (a.url !== b.url) return false\n return true\n }\n}\n","import React, { useRef, useState, useImperativeHandle } from \"react\"\nimport useIsomorphicLayoutEffect from \"../hooks/useIsomorphicLayoutEffect\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport { PolymorphicComponentPropsWithOutRef } from \"../types\"\nimport { Loader } from \"../util/kakaoMapApiLoader\"\n\nexport const KakaoMapContext = React.createContext<kakao.maps.Map>(\n undefined as unknown as kakao.maps.Map\n)\n\nexport type MapProps = {\n /**\n * 중심으로 설정할 위치 입니다.\n */\n center:\n | {\n lat: number\n lng: number\n }\n | {\n x: number\n y: number\n }\n\n /**\n * 중심을 이동시킬때 Panto를 사용할지 정합니다.\n * @default false\n */\n isPanto?: boolean\n\n /**\n * 중심 좌표를 지정한 좌표 또는 영역으로 부드럽게 이동한다. 필요하면 확대 또는 축소도 수행한다.\n * 만약 이동할 거리가 지도 화면의 크기보다 클 경우 애니메이션 없이 이동한다.\n * padding 만큼 제외하고 영역을 계산하며, padding 을 지정하지 않으면 기본값으로 32가 사용된다.\n */\n padding?: number\n\n /**\n * 확대 수준 (기본값: 3)\n */\n level?: number\n\n /**\n * 최대 확대 수준\n */\n maxLevel?: number\n\n /**\n * 최소 확대 수준\n */\n minLevel?: number\n\n /**\n * 지도 종류 (기본값: 일반 지도)\n */\n mapTypeId?: kakao.maps.MapTypeId\n\n /**\n * 마우스 드래그, 휠, 모바일 터치를 이용한 시점 변경(이동, 확대, 축소) 가능 여부\n */\n draggable?: boolean\n\n /**\n * 마우스 휠이나 멀티터치로 지도 확대, 축소 기능을 막습니다. 상황에 따라 지도 확대, 축소 기능을 제어할 수 있습니다.\n */\n zoomable?: boolean\n\n /**\n * 마우스 휠, 모바일 터치를 이용한 확대 및 축소 가능 여부\n */\n scrollwheel?: boolean\n\n /**\n * 더블클릭 이벤트 및 더블클릭 확대 가능 여부\n */\n disableDoubleClick?: boolean\n\n /**\n * 더블클릭 확대 가능 여부\n */\n disableDoubleClickZoom?: boolean\n\n /**\n * 투영법 지정 (기본값: kakao.maps.ProjectionId.WCONG)\n */\n projectionId?: string\n\n /**\n * 지도 타일 애니메이션 설정 여부 (기본값: true)\n */\n tileAnimation?: boolean\n\n /**\n * 키보드의 방향키와 +, – 키로 지도 이동,확대,축소 가능 여부 (기본값: false)\n */\n keyboardShortcuts?:\n | boolean\n | {\n /**\n * 지도 이동 속도\n */\n speed: number\n }\n\n /**\n * map 생성 후 해당 객체를 전달하는 함수\n */\n onCreate?: (map: kakao.maps.Map) => void\n\n /**\n * 중심 좌표가 변경되면 발생한다.\n */\n onCenterChanged?: (target: kakao.maps.Map) => void\n\n /**\n * 확대 수준이 변경되기 직전 발생한다.\n */\n onZoomStart?: (target: kakao.maps.Map) => void\n\n /**\n * 확대 수준이 변경되면 발생한다.\n */\n onZoomChanged?: (target: kakao.maps.Map) => void\n\n /**\n * 지도 영역이 변경되면 발생한다.\n */\n onBoundsChanged?: (target: kakao.maps.Map) => void\n\n /**\n * 지도를 클릭하면 발생한다.\n */\n onClick?: (\n target: kakao.maps.Map,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 지도를 더블클릭하면 발생한다.\n */\n onDoubleClick?: (\n target: kakao.maps.Map,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 지도를 마우스 오른쪽 버튼으로 클릭하면 발생한다.\n */\n onRightClick?: (\n target: kakao.maps.Map,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 지도에서 마우스 커서를 이동하면 발생한다.\n */\n onMouseMove?: (\n target: kakao.maps.Map,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 드래그를 시작할 때 발생한다.\n */\n onDragStart?: (\n target: kakao.maps.Map,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 드래그를 하는 동안 발생한다.\n */\n onDrag?: (\n target: kakao.maps.Map,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 드래그가 끝날 때 발생한다.\n */\n onDragEnd?: (\n target: kakao.maps.Map,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 중심 좌표나 확대 수준이 변경되면 발생한다.\n * 단, 애니메이션 도중에는 발생하지 않는다.\n */\n onIdle?: (target: kakao.maps.Map) => void\n\n /**\n * 확대수준이 변경되거나 지도가 이동했을때 타일 이미지 로드가 모두 완료되면 발생한다.\n * 지도이동이 미세하기 일어나 타일 이미지 로드가 일어나지 않은경우 발생하지 않는다.\n */\n onTileLoaded?: (target: kakao.maps.Map) => void\n\n /**\n * 지도 기본 타일(일반지도, 스카이뷰, 하이브리드)이 변경되면 발생한다.\n */\n onMaptypeidChanged?: (target: kakao.maps.Map) => void\n\n children?: React.ReactNode | undefined\n}\n\ntype MapComponent = <T extends React.ElementType = \"div\">(\n props: PolymorphicComponentPropsWithOutRef<T, MapProps> &\n React.RefAttributes<kakao.maps.Map>\n) => React.ReactElement | null\n\n/**\n * 기본적인 Map 객체를 생성하는 Comeponent 입니다.\n * props로 받는 `on*` 이벤트는 해당 `kakao.maps.Map` 객체를 함께 인자로 전달 합니다.\n *\n * `ref`를 통해 `map` 객체에 직접 접근하여 사용 또는 onCreate 이벤트를 이용하여 접근이 가능합니다.\n *\n * > *주의 사항* `Map`, `RoadView` 컴포넌트에 한하여, ref 객체가 컴포넌트 마운트 시점에 바로 초기화가 안될 수 있습니다.\n * >\n * > 컴포넌트 마운트 시점에 `useEffect` 를 활용하여, 특정 로직을 수행하고 싶은 경우 `ref` 객체를 사용하는 것보다\n * > `onCreate` 이벤트와 `useState`를 함께 활용하여 제어하는 것을 추천 드립니다.\n */\nconst Map: MapComponent = React.forwardRef(\n <T extends React.ElementType = \"div\">(\n {\n id,\n as,\n children,\n center,\n isPanto = false,\n padding = 32,\n disableDoubleClick,\n disableDoubleClickZoom,\n draggable,\n zoomable,\n keyboardShortcuts,\n level,\n maxLevel,\n minLevel,\n mapTypeId,\n projectionId,\n scrollwheel,\n tileAnimation,\n onBoundsChanged,\n onCenterChanged,\n onClick,\n onDoubleClick,\n onDrag,\n onDragEnd,\n onDragStart,\n onIdle,\n onMaptypeidChanged,\n onMouseMove,\n onRightClick,\n onTileLoaded,\n onZoomChanged,\n onZoomStart,\n onCreate,\n ...props\n }: PolymorphicComponentPropsWithOutRef<T, MapProps>,\n ref: React.ForwardedRef<kakao.maps.Map>\n ) => {\n const Container = as || \"div\"\n const [isLoaded, setIsLoaded] = useState(false)\n const [map, setMap] = useState<kakao.maps.Map>()\n const container = useRef<HTMLDivElement>(null)\n\n useIsomorphicLayoutEffect(() => {\n Loader.isLoaded().then(setIsLoaded)\n }, [])\n\n useIsomorphicLayoutEffect(() => {\n if (!isLoaded) return\n\n const MapContainer = container.current\n\n if (!MapContainer) {\n return\n }\n\n const initalMapCenter =\n \"lat\" in center\n ? new kakao.maps.LatLng(center.lat, center.lng)\n : new kakao.maps.Coords(center.x, center.y)\n\n const kakaoMap = new kakao.maps.Map(MapContainer, {\n center: initalMapCenter,\n disableDoubleClick: disableDoubleClick,\n disableDoubleClickZoom: disableDoubleClickZoom,\n draggable: draggable,\n keyboardShortcuts: keyboardShortcuts,\n level: level,\n mapTypeId: mapTypeId,\n projectionId: projectionId,\n scrollwheel: scrollwheel,\n tileAnimation: tileAnimation,\n })\n\n setMap(kakaoMap)\n\n return () => {\n MapContainer.innerHTML = \"\"\n }\n }, [\n isLoaded,\n disableDoubleClick,\n disableDoubleClickZoom,\n mapTypeId,\n tileAnimation,\n ])\n\n useImperativeHandle(ref, () => map!, [map])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || !onCreate) return\n onCreate(map)\n }, [map, onCreate])\n\n // center position 변경시 map center 변경\n useIsomorphicLayoutEffect(() => {\n if (!map) return\n\n let prevCenter = map.getCenter()\n if (prevCenter instanceof kakao.maps.Coords) {\n prevCenter = prevCenter.toLatLng()\n }\n\n const centerPosition =\n \"lat\" in center\n ? new kakao.maps.LatLng(center.lat, center.lng)\n : new kakao.maps.Coords(center.x, center.y)\n\n if (\n (centerPosition instanceof kakao.maps.LatLng &&\n centerPosition.equals(prevCenter)) ||\n (centerPosition instanceof kakao.maps.Coords &&\n centerPosition.toLatLng().equals(prevCenter))\n ) {\n return\n }\n\n if (isPanto) {\n map.panTo(centerPosition, padding)\n } else {\n map.setCenter(centerPosition)\n }\n // @ts-ignore\n }, [map, center.lat, center.lng, center.x, center.y])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || typeof draggable === \"undefined\") return\n map.setDraggable(draggable)\n }, [map, draggable])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || typeof zoomable === \"undefined\") return\n map.setZoomable(zoomable)\n }, [map, zoomable])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || !keyboardShortcuts || typeof keyboardShortcuts !== \"boolean\")\n return\n map.setKeyboardShortcuts(keyboardShortcuts)\n }, [map, keyboardShortcuts])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || !level) return\n map.setLevel(level)\n }, [map, level])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || !mapTypeId) return\n map.setMapTypeId(mapTypeId)\n }, [map, mapTypeId])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || !projectionId) return\n map.setProjectionId(projectionId)\n }, [map, projectionId])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || !maxLevel) return\n map.setMaxLevel(maxLevel)\n }, [map, maxLevel])\n\n useIsomorphicLayoutEffect(() => {\n if (!map || !minLevel) return\n map.setMinLevel(minLevel)\n }, [map, minLevel])\n\n useKakaoEvent(map, \"bounds_changed\", onBoundsChanged)\n useKakaoEvent(map, \"center_changed\", onCenterChanged)\n useKakaoEvent(map, \"click\", onClick)\n useKakaoEvent(map, \"dblclick\", onDoubleClick)\n useKakaoEvent(map, \"drag\", onDrag)\n useKakaoEvent(map, \"dragstart\", onDragStart)\n useKakaoEvent(map, \"dragend\", onDragEnd)\n useKakaoEvent(map, \"idle\", onIdle)\n useKakaoEvent(map, \"maptypeid_changed\", onMaptypeidChanged)\n useKakaoEvent(map, \"mousemove\", onMouseMove)\n useKakaoEvent(map, \"rightclick\", onRightClick)\n useKakaoEvent(map, \"tilesloaded\", onTileLoaded)\n useKakaoEvent(map, \"zoom_changed\", onZoomChanged)\n useKakaoEvent(map, \"zoom_start\", onZoomStart)\n\n return (\n <>\n <Container\n id={id || \"react-kakao-maps-sdk-map-container\"}\n {...props}\n ref={container}\n />\n {map && (\n <KakaoMapContext.Provider value={map}>\n {children}\n </KakaoMapContext.Provider>\n )}\n </>\n )\n }\n)\n\nexport default Map\n","import { useContext } from \"react\"\nimport { KakaoMapContext } from \"../components/Map\"\n\n/**\n * kakao map 객체를 가져오는 hook 입니다.\n * Map 객체 내부가 아니라면 Error를 발생 시킵니다.\n */\nconst useMap = (componentName?: string) => {\n const kakaoMap = useContext(KakaoMapContext)\n if (!kakaoMap) {\n throw new Error(\n `${\n componentName ? componentName + \" Component\" : \"useMap\"\n } must exist inside Map Component!`\n )\n }\n\n return kakaoMap\n}\n\nexport default useMap\n","import React, {\n useLayoutEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n} from \"react\"\nimport ReactDom from \"react-dom\"\n\ninterface InfoWindowProps {\n map: kakao.maps.Map | kakao.maps.Roadview\n position: kakao.maps.LatLng | kakao.maps.Viewpoint\n marker?: kakao.maps.Marker\n /**\n * 인포윈도우를 열 때 지도가 자동으로 패닝하지 않을지의 여부\n * @default false\n */\n disableAutoPan?: boolean\n\n /**\n * 삭제 가능한 인포윈도우\n */\n removable?: boolean\n\n /**\n * 인포윈도우 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 로드뷰에 올라있는 인포윈도우의 높이 값(m 단위)\n */\n altitude?: number\n\n /**\n * 로드뷰 상에서 인포윈도우의 가시반경(m 단위), 두 지점 사이의 거리가 지정한 값보다 멀어지면 인포윈도우는 보이지 않게 된다\n */\n range?: number\n\n /**\n * 인포윈도우 객체 생성후 해당 객체를 반환하는 함수\n */\n onCreate?: (infoWindow: kakao.maps.InfoWindow) => void\n}\n\nconst InfoWindow = React.forwardRef<\n kakao.maps.InfoWindow,\n React.PropsWithChildren<InfoWindowProps>\n>(\n (\n {\n map,\n position,\n marker,\n children,\n altitude,\n disableAutoPan,\n range,\n removable,\n zIndex,\n onCreate,\n },\n ref\n ) => {\n const container = useRef(document.createElement(\"div\"))\n\n const infoWindow = useMemo(() => {\n const kakaoInfoWindow = new kakao.maps.InfoWindow({\n altitude: altitude,\n disableAutoPan: disableAutoPan,\n range: range,\n removable: removable,\n zIndex: zIndex,\n content: container.current,\n position: position,\n })\n container.current.style.display = \"none\"\n return kakaoInfoWindow\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [disableAutoPan, removable])\n\n useImperativeHandle(ref, () => infoWindow, [infoWindow])\n\n useLayoutEffect(() => {\n infoWindow.open(map, marker)\n return () => {\n infoWindow.close()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [map, marker])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(infoWindow)\n }, [infoWindow, onCreate])\n\n useLayoutEffect(() => {\n if (!infoWindow) return\n infoWindow.setPosition(position)\n }, [infoWindow, position])\n\n useLayoutEffect(() => {\n if (!infoWindow || !altitude) return\n infoWindow.setAltitude(altitude)\n }, [infoWindow, altitude])\n\n useLayoutEffect(() => {\n if (!infoWindow || !range) return\n infoWindow.setRange(range)\n }, [infoWindow, range])\n\n useLayoutEffect(() => {\n if (!infoWindow || !zIndex) return\n infoWindow.setZIndex(zIndex)\n }, [infoWindow, zIndex])\n\n return (\n container.current.parentElement &&\n ReactDom.createPortal(children, container.current.parentElement)\n )\n }\n)\n\nexport default InfoWindow\n","import React, { useLayoutEffect, useImperativeHandle, useMemo } from \"react\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport useMap from \"../hooks/useMap\"\n\nexport const KakaoMapMarkerClustererContext =\n React.createContext<kakao.maps.MarkerClusterer>(\n undefined as unknown as kakao.maps.MarkerClusterer\n )\n\nexport interface MarkerClustererProps {\n /**\n * 클러스터의 격자 크기. 화면 픽셀 단위이며 해당 격자 영역 안에 마커가 포함되면 클러스터에 포함시킨다\n * @default 60\n */\n gridSize?: number\n /**\n * 마커들의 좌표 평균을 클러스터 좌표 설정 여부\n * @default false\n */\n averageCenter?: boolean\n /**\n * 클러스터링 할 지도의 최소 레벨 값. 지정한 숫자에 해당하는 레벨 미만에서는 클러스터링 하지 않는다\n * @default 0\n */\n minLevel?: number\n /**\n * 클러스터링 할 최소 마커 수\n * @default 2\n */\n minClusterSize?: number\n /**\n * 클러스터의 스타일. 여러개를 선언하면 calculator 로 구분된 사이즈 구간마다 서로 다른 스타일을 적용시킬 수 있다\n */\n styles?: React.CSSProperties[] | object[]\n /**\n * 클러스터에 표시할 문자열 또는 문자열 생성 함수.\n * @default \"클러스터에 포함된 숫자\"\n */\n texts?: string[] | ((size: number) => string)\n /**\n * 클러스터 크기를 구분하는 값을 가진 배열 또는 구분값 생성함수\n * @default [10, 100, 1000, 10000]\n */\n calculator?: number[] | ((size: number) => number[])\n /**\n * 클러스터 클릭 시 지도 확대 여부. true로 설정하면 클러스터 클릭 시 확대 되지 않는다\n * @default false\n */\n disableClickZoom?: boolean\n /**\n * 클러스터 클릭 가능 여부 지정 옵션. false일 경우 클러스터의 clusterclick, clusterdblclick, clusterrightclick 이벤트가 발생하지 않으며, 커서가 변경되지 않는다.\n * @default true\n */\n clickable?: boolean\n /**\n * 클러스터에 마우스 over/out 가능 여부 지정 옵션. false일 경우 클러스터의 clusterover, clusterout 이벤트가 발생하지 않는다.\n * @default true\n */\n hoverable?: boolean\n\n /**\n * 클러스터 마커를 클릭 했을 때 발생한다.\n * 이벤트 핸들러 함수 인자로는 Cluster 객체가 넘어온다.\n * 클러스터 마커 클릭 시 지도가 줌인 되는 경우 원하는 Cluster 객체를 얻지 못할 수도 있다.\n * 때문에 MarkerClusterer 를 생성할 때 disableClickZoom 옵션을 true로 설정하여\n * 클러스터 마커를 클릭했을 때 지도가 줌인되지 않도록 설정 후 사용한다.\n */\n onClusterclick?: (\n target: kakao.maps.MarkerClusterer,\n cluster: kakao.maps.Cluster\n ) => void\n /**\n * 클러스터 마커를 마우스 오버 했을 때 발생한다\n * 이벤트 핸들러 함수 인자로는 마우스 오버한 Cluster 객체가 넘어온다.\n */\n onClusterover?: (\n target: kakao.maps.MarkerClusterer,\n cluster: kakao.maps.Cluster\n ) => void\n /**\n * 클러스터 마커를 마우스 아웃 했을 때 발생한다\n * 이벤트 핸들러 함수 인자로는 마우스 아웃된 Cluster 객체가 넘어온다.\n */\n onClusterout?: (\n target: kakao.maps.MarkerClusterer,\n cluster: kakao.maps.Cluster\n ) => void\n /**\n * 클러스터 마커를 더블클릭 했을 때 발생한다\n * 이벤트 핸들러 함수 인자로는 더블클릭한 Cluster 객체가 넘어온다.\n * MarkerClusterer 를 생성할 때 disableClickZoom 옵션을 true로 설정해야만 이벤트가 발생한다.\n */\n onClusterdblclick?: (\n target: kakao.maps.MarkerClusterer,\n cluster: kakao.maps.Cluster\n ) => void\n /**\n * 클러스터 마커를 오른쪽 클릭 했을 때 발생한다\n * 이벤트 핸들러 함수 인자로는 오른쪽 클릭한 Cluster 객체가 넘어온다.\n */\n onClusterrightclick?: (\n target: kakao.maps.MarkerClusterer,\n cluster: kakao.maps.Cluster\n ) => void\n /**\n * 클러스터링이 완료됐을 때 발생한다.\n * 이벤트 핸들러 함수 인자로는 생성된 Cluster 객체 전체가 배열로 넘어온다.\n */\n onClustered?: (\n target: kakao.maps.MarkerClusterer,\n clusters: kakao.maps.Cluster[]\n ) => void\n /**\n * MarkerClusterer 생성 후 해당 객체를 전달하는 함수\n */\n onCreate?: (target: kakao.maps.MarkerClusterer) => void\n}\n\nconst MarkerClusterer = React.forwardRef<\n kakao.maps.MarkerClusterer,\n React.PropsWithChildren<MarkerClustererProps>\n>(\n (\n {\n children,\n averageCenter,\n calculator,\n clickable,\n disableClickZoom,\n gridSize,\n hoverable,\n minClusterSize,\n minLevel,\n styles,\n texts,\n onClusterclick,\n onClusterdblclick,\n onClustered,\n onClusterout,\n onClusterover,\n onClusterrightclick,\n onCreate,\n },\n ref\n ) => {\n const map = useMap(`MarkerClusterer`)\n const markerCluster = useMemo(() => {\n if (!window.kakao.maps.MarkerClusterer) {\n console.warn(\n \"clusterer 라이브러리를 별도 로드 해야 사용 가능합니다. `https://apis.map.kakao.com/web/guide/#loadlibrary`\"\n )\n return\n }\n return new kakao.maps.MarkerClusterer({\n averageCenter,\n calculator,\n clickable,\n disableClickZoom,\n gridSize,\n hoverable,\n minClusterSize,\n minLevel,\n styles,\n texts,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useImperativeHandle(ref, () => markerCluster!, [markerCluster])\n\n useLayoutEffect(() => {\n markerCluster?.setMap(map)\n }, [map, markerCluster])\n\n useLayoutEffect(() => {\n if (markerCluster && onCreate) onCreate(markerCluster)\n }, [markerCluster, onCreate])\n\n useLayoutEffect(() => {\n if (markerCluster && gridSize) {\n markerCluster.setGridSize(gridSize)\n markerCluster.redraw()\n }\n }, [markerCluster, gridSize])\n\n useLayoutEffect(() => {\n if (markerCluster && minClusterSize) {\n markerCluster.setMinClusterSize(minClusterSize)\n markerCluster.redraw()\n }\n }, [markerCluster, minClusterSize])\n\n useLayoutEffect(() => {\n if (markerCluster && typeof averageCenter !== \"undefined\") {\n markerCluster.setAverageCenter(averageCenter)\n markerCluster.redraw()\n }\n }, [markerCluster, averageCenter])\n\n useLayoutEffect(() => {\n if (markerCluster && minLevel) {\n markerCluster.setMinLevel(minLevel)\n markerCluster.redraw()\n }\n }, [markerCluster, minLevel])\n\n useLayoutEffect(() => {\n if (markerCluster && texts) {\n markerCluster.setTexts(texts)\n markerCluster.redraw()\n }\n }, [markerCluster, texts])\n\n useLayoutEffect(() => {\n if (markerCluster && calculator) {\n markerCluster.setCalculator(calculator)\n markerCluster.redraw()\n }\n }, [markerCluster, calculator])\n\n useLayoutEffect(() => {\n if (markerCluster && styles) {\n markerCluster.setStyles(styles)\n markerCluster.redraw()\n }\n }, [markerCluster, styles])\n\n useKakaoEvent(markerCluster, \"clusterclick\", onClusterclick)\n useKakaoEvent(markerCluster, \"clusterover\", onClusterover)\n useKakaoEvent(markerCluster, \"clusterout\", onClusterout)\n useKakaoEvent(markerCluster, \"clusterdblclick\", onClusterdblclick)\n useKakaoEvent(markerCluster, \"clusterrightclick\", onClusterrightclick)\n useKakaoEvent(markerCluster, \"clustered\", onClustered)\n\n if (!markerCluster) {\n return null\n }\n\n return (\n <KakaoMapMarkerClustererContext.Provider value={markerCluster}>\n {children}\n </KakaoMapMarkerClustererContext.Provider>\n )\n }\n)\n\nexport default MarkerClusterer\n","import React, {\n useContext,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n} from \"react\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport InfoWindow from \"./InfoWindow\"\nimport { KakaoMapMarkerClustererContext } from \"./MarkerClusterer\"\n\ninterface MarkerProps {\n map: kakao.maps.Map | kakao.maps.Roadview\n position: kakao.maps.LatLng | kakao.maps.Viewpoint\n\n /**\n * marker 생성 후 marker 객체를 전달하는 callback\n */\n onCreate?: (marker: kakao.maps.Marker) => void\n\n /**\n * click 이벤트 핸들러\n */\n onClick?: (marker: kakao.maps.Marker) => void\n\n /**\n * mouseover 이벤트 핸들러\n */\n onMouseOver?: (marker: kakao.maps.Marker) => void\n\n /**\n * mouseout 이벤트 핸들러\n */\n onMouseOut?: (marker: kakao.maps.Marker) => void\n\n /**\n * dragstart 이벤트 핸들러\n */\n onDragStart?: (marker: kakao.maps.Marker) => void\n\n /**\n * dragend 이벤트 핸들러\n */\n onDragEnd?: (marker: kakao.maps.Marker) => void\n\n /**\n * 마커의 이미지\n */\n image?: kakao.maps.MarkerImage\n\n /**\n * 마커 엘리먼트의 타이틀 속성 값 (툴팁)\n */\n title?: string\n\n /**\n * 드래그 가능한 마커, 로드뷰에 올릴 경우에는 유효하지 않다.\n */\n draggable?: boolean\n\n /**\n * 클릭 가능한 마커\n */\n clickable?: boolean\n\n /**\n * 마커 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 마커 투명도 (0-1)\n */\n opacity?: number\n\n /**\n * 로드뷰에 올라있는 마커의 높이 값(m 단위)\n */\n altitude?: number\n\n /**\n * 로드뷰 상에서 마커의 가시반경(m 단위), 두 지점 사이의 거리가 지정한 값보다 멀어지면 마커는 로드뷰에서 보이지 않게 된다.\n */\n range?: number\n\n /**\n * InfoWindow 옵션\n */\n infoWindowOptions?: {\n /**\n * 인포윈도우를 열 때 지도가 자동으로 패닝하지 않을지의 여부 (기본값: false)\n */\n disableAutoPan?: boolean\n\n /**\n * 삭제 가능한 인포윈도우\n */\n removable?: boolean\n\n /**\n * 인포윈도우 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 로드뷰에 올라있는 인포윈도우의 높이 값(m 단위)\n */\n altitude?: number\n\n /**\n * 로드뷰 상에서 인포윈도우의 가시반경(m 단위), 두 지점 사이의 거리가 지정한 값보다 멀어지면 인포윈도우는 보이지 않게 된다\n */\n range?: number\n }\n}\n\nconst Marker = React.forwardRef<\n kakao.maps.Marker,\n React.PropsWithChildren<MarkerProps>\n>(\n (\n {\n map,\n position,\n children,\n altitude,\n clickable,\n draggable,\n image,\n infoWindowOptions,\n onCreate,\n onClick,\n onDragEnd,\n onDragStart,\n onMouseOut,\n onMouseOver,\n opacity,\n range,\n title,\n zIndex,\n },\n ref\n ) => {\n const markerCluster = useContext(KakaoMapMarkerClustererContext)\n\n // Marker 객체는 단 한번만 생성 되도록 함\n const marker = useMemo(() => {\n const kakaoMarker = new kakao.maps.Marker({\n altitude,\n clickable,\n draggable,\n image,\n opacity,\n range,\n title,\n zIndex,\n position,\n })\n\n return kakaoMarker\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useImperativeHandle(ref, () => marker, [marker])\n\n useLayoutEffect(() => {\n if (markerCluster) {\n markerCluster.addMarker(marker)\n } else {\n marker.setMap(map)\n }\n\n return () => {\n if (markerCluster) {\n markerCluster.removeMarker(marker)\n } else {\n marker.setMap(null)\n }\n }\n }, [map, markerCluster, marker])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(marker)\n }, [marker, onCreate])\n\n useKakaoEvent(marker, \"click\", onClick)\n useKakaoEvent(marker, \"dragstart\", onDragStart)\n useKakaoEvent(marker, \"dragend\", onDragEnd)\n useKakaoEvent(marker, \"mouseout\", onMouseOut)\n useKakaoEvent(marker, \"mouseover\", onMouseOver)\n\n // position이 변경되면 객체를 갱신한다.\n useLayoutEffect(() => {\n if (!map || !marker || !position) return\n\n marker.setPosition(position)\n }, [map, marker, position])\n\n // image 객체가 존재하면 이미지를 로드한다\n useLayoutEffect(() => {\n if (!map || !marker || !image) return\n\n marker.setImage(image)\n }, [map, marker, image])\n\n // altitude 값이 있으면 높이를 조정한다\n useLayoutEffect(() => {\n if (!map || !marker || !altitude) return\n\n marker.setAltitude(altitude)\n }, [map, marker, altitude])\n\n // clickable 값이 있으면 클릭이 가능하도록 한다.\n useLayoutEffect(() => {\n if (!map || !marker || typeof clickable === \"undefined\") return\n\n marker.setClickable(clickable)\n }, [map, marker, clickable])\n\n // draggable 값이 있으면 드래그가 가능하도록 한다.\n useLayoutEffect(() => {\n if (!map || !marker || typeof draggable === \"undefined\") return\n\n marker.setDraggable(draggable)\n }, [map, marker, draggable])\n\n // opacity 값이 있으면 투명도를 조절한다.\n useLayoutEffect(() => {\n if (!map || !marker || !opacity) return\n\n marker.setOpacity(opacity)\n }, [map, marker, opacity])\n\n // range 값이 있으면 마커의 가시반경을 조절한다.\n useLayoutEffect(() => {\n if (!map || !marker || !range) return\n\n marker.setRange(range)\n }, [map, marker, range])\n\n // title 값이 있으면 마커의 제목을 조절한다.\n useLayoutEffect(() => {\n if (!map || !marker || !title) return\n\n marker.setTitle(title)\n }, [map, marker, title])\n\n // zIndex 값이 있으면 마커의 zindex를 조절한다.\n useLayoutEffect(() => {\n if (!map || !marker || !zIndex) return\n\n marker.setZIndex(zIndex)\n }, [map, marker, zIndex])\n\n if (children)\n return (\n <InfoWindow\n position={position}\n map={map}\n marker={marker}\n altitude={infoWindowOptions?.altitude}\n disableAutoPan={infoWindowOptions?.disableAutoPan}\n range={infoWindowOptions?.range}\n removable={infoWindowOptions?.removable}\n zIndex={infoWindowOptions?.zIndex}\n >\n {children}\n </InfoWindow>\n )\n\n return null\n }\n)\n\nexport default Marker\n","import React, { useMemo } from \"react\"\nimport useMap from \"../hooks/useMap\"\nimport Marker from \"./Marker\"\n\nexport interface MapMarkerProps {\n /**\n * 표시 위치\n */\n position:\n | {\n lat: number\n lng: number\n }\n | {\n x: number\n y: number\n }\n\n image?: {\n /**\n * 표시 이미지 src\n */\n src: string\n\n /**\n * 표시 이미지 크기\n */\n size: {\n width: number\n height: number\n }\n\n options?: {\n /**\n * 마커 이미지의 alt 속성값을 정의한다.\n */\n alt?: string\n\n /**\n * 마커의 클릭 또는 마우스오버 가능한 영역을 표현하는 좌표값\n */\n coords?: string\n\n /**\n * 마커의 좌표에 일치시킬 이미지 안의 좌표 (기본값: 이미지의 가운데 아래)\n */\n offset?: { x: number; y: number }\n\n /**\n * 마커의 클릭 또는 마우스오버 가능한 영역의 모양\n */\n shape?: \"default\" | \"rect\" | \"circle\" | \"poly\"\n\n /**\n * 스프라이트 이미지 중 사용할 영역의 좌상단 좌표\n */\n spriteOrigin?: { x: number; y: number }\n\n /**\n * 스프라이트 이미지의 전체 크기\n */\n spriteSize?: { width: number; height: number }\n }\n }\n\n /**\n * click 이벤트 핸들러\n */\n onClick?: (marker: kakao.maps.Marker) => void\n\n /**\n * mouseover 이벤트 핸들러\n */\n onMouseOver?: (marker: kakao.maps.Marker) => void\n\n /**\n * mouseout 이벤트 핸들러\n */\n onMouseOut?: (marker: kakao.maps.Marker) => void\n\n /**\n * dragstart 이벤트 핸들러\n */\n onDragStart?: (marker: kakao.maps.Marker) => void\n\n /**\n * dragend 이벤트 핸들러\n */\n onDragEnd?: (marker: kakao.maps.Marker) => void\n\n /**\n * Maker 생성 이벤트 핸들러\n */\n onCreate?: (maker: kakao.maps.Marker) => void\n\n /**\n * 마커 엘리먼트의 타이틀 속성 값 (툴팁)\n */\n title?: string\n\n /**\n * 드래그 가능한 마커, 로드뷰에 올릴 경우에는 유효하지 않다.\n */\n draggable?: boolean\n\n /**\n * 클릭 가능한 마커\n */\n clickable?: boolean\n\n /**\n * 마커 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 마커 투명도 (0-1)\n */\n opacity?: number\n\n /**\n * InfoWindow 옵션\n */\n infoWindowOptions?: {\n /**\n * 인포윈도우를 열 때 지도가 자동으로 패닝하지 않을지의 여부 (기본값: false)\n */\n disableAutoPan?: boolean\n\n /**\n * 삭제 가능한 인포윈도우\n */\n removable?: boolean\n\n /**\n * 인포윈도우 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n }\n}\n\n/**\n * Map에서 Marker를 생성할 때 사용 합니다.\n * `onCreate` 이벤트를 통해 생성 후 `maker` 객체에 직접 접근하여 초기 설정이 가능합니다.\n */\nconst MapMarker = React.forwardRef<\n kakao.maps.Marker,\n React.PropsWithChildren<MapMarkerProps>\n>(\n (\n {\n image,\n position,\n children,\n clickable,\n draggable,\n infoWindowOptions,\n onClick,\n onDragEnd,\n onDragStart,\n onMouseOut,\n onMouseOver,\n onCreate,\n opacity,\n title,\n zIndex,\n },\n ref\n ) => {\n const map = useMap(`MapMarker`)\n\n const markerImage = useMemo(() => {\n return (\n image &&\n new kakao.maps.MarkerImage(\n image.src,\n new kakao.maps.Size(image.size.width, image.size.height),\n {\n alt: image.options?.alt,\n coords: image.options?.coords,\n offset:\n image.options?.offset &&\n new kakao.maps.Point(\n image.options?.offset.x,\n image.options?.offset.y\n ),\n shape: image.options?.shape,\n spriteOrigin:\n image.options?.spriteOrigin &&\n new kakao.maps.Point(\n image.options?.spriteOrigin.x,\n image.options?.spriteOrigin.y\n ),\n spriteSize:\n image.options?.spriteSize &&\n new kakao.maps.Size(\n image.options?.spriteSize.width,\n image.options?.spriteSize.height\n ),\n }\n )\n )\n }, [image])\n\n const markerPosition = useMemo(() => {\n if (\"lat\" in position) {\n return new kakao.maps.LatLng(position.lat, position.lng)\n }\n return new kakao.maps.Coords(position.x, position.y).toLatLng()\n\n // @ts-ignore\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [position.lat, position.lng, position.x, position.y])\n\n return (\n <Marker\n map={map}\n position={markerPosition}\n image={markerImage}\n clickable={clickable}\n draggable={draggable}\n infoWindowOptions={infoWindowOptions}\n onClick={onClick}\n onDragEnd={onDragEnd}\n onDragStart={onDragStart}\n onMouseOut={onMouseOut}\n onMouseOver={onMouseOver}\n onCreate={onCreate}\n opacity={opacity}\n title={title}\n zIndex={zIndex}\n ref={ref}\n >\n {children}\n </Marker>\n )\n }\n)\n\nexport default MapMarker\n","import React, { useMemo } from \"react\"\nimport InfoWindow from \"./InfoWindow\"\nimport useMap from \"../hooks/useMap\"\n\nexport interface MapInfoWindowProps {\n /**\n * Contianer id에 대해서 지정합니다.\n */\n id?: string\n\n /**\n * Contianer className에 대해서 지정합니다.\n */\n className?: string\n\n /**\n * Contianer style에 대해서 지정합니다.\n */\n style?: React.CSSProperties\n\n /**\n * 인포윈도가 표시될 위치\n */\n position: {\n lat: number\n lng: number\n }\n /**\n * 인포윈도우를 열 때 지도가 자동으로 패닝하지 않을지의 여부 (기본값: false)\n */\n disableAutoPan?: boolean\n\n /**\n * 삭제 가능한 인포윈도우\n */\n removable?: boolean\n\n /**\n * 인포윈도우 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 인포윈도우 객체 생성후 해당 객체를 반환하는 함수\n */\n onCreate?: (infoWindow: kakao.maps.InfoWindow) => void\n}\n\n/**\n * Map 컴포넌트에서 InfoWindow를 그릴 때 사용됩니다.\n * `onCreate` 이벤트를 통해 생성 후 `infoWindow` 객체에 직접 접근하여 초기 설정이 가능합니다.\n */\nconst MapInfoWindow = React.forwardRef<\n kakao.maps.InfoWindow,\n React.PropsWithChildren<MapInfoWindowProps>\n>(\n (\n { position, children, disableAutoPan, removable, zIndex, onCreate },\n ref\n ) => {\n const map = useMap(`MapInfoWindow`)\n const infoPosition = useMemo(() => {\n return new kakao.maps.LatLng(position.lat, position.lng)\n }, [position.lat, position.lng])\n\n return (\n <InfoWindow\n disableAutoPan={disableAutoPan}\n removable={removable}\n zIndex={zIndex}\n map={map}\n position={infoPosition}\n onCreate={onCreate}\n ref={ref}\n >\n {children}\n </InfoWindow>\n )\n }\n)\n\nexport default MapInfoWindow\n","import React, {\n useContext,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n} from \"react\"\nimport ReactDOM from \"react-dom\"\nimport useMap from \"../hooks/useMap\"\nimport { KakaoMapMarkerClustererContext } from \"./MarkerClusterer\"\n\nexport interface CustomOverlayMapProps {\n /**\n * 커스텀 오버레이의 좌표\n */\n position: {\n lat: number\n lng: number\n }\n /**\n * true 로 설정하면 컨텐츠 영역을 클릭했을 경우 지도 이벤트를 막아준다.\n */\n clickable?: boolean\n\n /**\n * 컨텐츠의 x축 위치. 0_1 사이의 값을 가진다. 기본값은 0.5\n */\n xAnchor?: number\n\n /**\n * 컨텐츠의 y축 위치. 0_1 사이의 값을 가진다. 기본값은 0.5\n */\n yAnchor?: number\n\n /**\n * 커스텀 오버레이의 z-index\n */\n zIndex?: number\n\n /**\n * 커스텀 오버레이를 생성 후 해당 객체를 가지고 callback 함수를 실행 시켜줌\n */\n onCreate?: (customOverlay: kakao.maps.CustomOverlay) => void\n}\n\n/**\n * Map에 CustomOverlay를 올릴 때 사용하는 컴포넌트 입니다.\n * `onCreate` 이벤트 또는 `ref` 객체를 통해서 `CustomOverlay` 객체에 직접 접근 및 초기 설정 작업을 지정할 수 있습니다.\n */\nconst CustomOverlayMap = React.forwardRef<\n kakao.maps.CustomOverlay,\n React.PropsWithChildren<CustomOverlayMapProps>\n>(\n (\n { position, children, clickable, xAnchor, yAnchor, zIndex, onCreate },\n ref\n ) => {\n const markerCluster = useContext(KakaoMapMarkerClustererContext)\n\n const map = useMap(`CustomOverlayMap`)\n const container = useRef(document.createElement(\"div\"))\n\n const overlayPosition = useMemo(() => {\n return new kakao.maps.LatLng(position.lat, position.lng)\n }, [position.lat, position.lng])\n\n const overlay = useMemo(() => {\n const KakaoCustomOverlay = new kakao.maps.CustomOverlay({\n clickable: clickable,\n xAnchor: xAnchor,\n yAnchor: yAnchor,\n zIndex: zIndex,\n position: overlayPosition,\n content: container.current,\n })\n container.current.style.display = \"none\"\n\n return KakaoCustomOverlay\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [clickable, xAnchor, yAnchor])\n\n useImperativeHandle(ref, () => overlay, [overlay])\n\n useLayoutEffect(() => {\n if (!map) return\n\n if (markerCluster) {\n markerCluster.addMarker(overlay)\n } else {\n overlay.setMap(map)\n }\n\n return () => {\n if (markerCluster) {\n markerCluster.removeMarker(overlay)\n } else {\n overlay.setMap(null)\n }\n }\n }, [map, markerCluster, overlay])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(overlay)\n }, [overlay, onCreate])\n\n useLayoutEffect(() => {\n overlay.setPosition(overlayPosition)\n }, [overlay, overlayPosition])\n\n useLayoutEffect(() => {\n if (!zIndex) return\n overlay.setZIndex(zIndex)\n }, [overlay, zIndex])\n\n return (\n container.current.parentElement &&\n ReactDOM.createPortal(children, container.current.parentElement)\n )\n }\n)\n\nexport default CustomOverlayMap\n","import React, { useImperativeHandle, useLayoutEffect, useMemo } from \"react\"\nimport useMap from \"../hooks/useMap\"\n\nexport interface MapTypeControlProps {\n /**\n * MapTypeControl의 Position를 정의 한다.\n */\n position?: kakao.maps.ControlPosition\n}\n\n/**\n * 일반 지도/하이브리드 간 지도 타입 전환 컨트롤을 생성한다.\n * 현재는 일반 지도/하이브리드 간 전환 컨트롤만 지원되며 다른 지도 타입을 제어하는 컨트롤이 필요할 경우에는 직접 구현해야 한다.\n */\nconst MapTypeControl = React.forwardRef<\n kakao.maps.MapTypeControl,\n MapTypeControlProps\n>(({ position = kakao.maps.ControlPosition.TOPRIGHT }, ref) => {\n const map = useMap(`MapTypeControl`)\n\n const mapTypeControl = useMemo(() => {\n return new kakao.maps.MapTypeControl()\n }, [])\n\n useImperativeHandle(ref, () => mapTypeControl, [mapTypeControl])\n\n useLayoutEffect(() => {\n map.addControl(mapTypeControl, position)\n\n return () => {\n map.removeControl(mapTypeControl)\n }\n }, [map, mapTypeControl, position])\n\n return null\n})\n\nexport default MapTypeControl\n","import React, { useEffect, useImperativeHandle, useMemo } from \"react\"\nimport useMap from \"../hooks/useMap\"\n\nexport interface ZoomControlProps {\n /**\n * ZoomControl의 Position를 정의 한다.\n */\n position?: kakao.maps.ControlPosition\n}\n\n/**\n * 확대·축소 컨트롤을 생성한다.\n */\nconst ZoomControl = React.forwardRef<kakao.maps.ZoomControl, ZoomControlProps>(\n ({ position = kakao.maps.ControlPosition.RIGHT }, ref) => {\n const map = useMap(`ZoomControl`)\n\n const ZoomControl = useMemo(() => {\n return new kakao.maps.ZoomControl()\n }, [])\n\n useImperativeHandle(ref, () => ZoomControl, [ZoomControl])\n\n useEffect(() => {\n map.addControl(ZoomControl, position)\n\n return () => {\n map.removeControl(ZoomControl)\n }\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [map, position])\n\n return null\n }\n)\n\nexport default ZoomControl\n","import React, { useEffect } from \"react\"\nimport useMap from \"../hooks/useMap\"\n\nexport interface MapTypeIdProps {\n /**\n * MapTypeId를 정의 한다.\n */\n type: kakao.maps.MapTypeId\n}\n\n/**\n * 추가적으로 보이고 싶은 지도 타입을 추가 할 때 사용한다.\n */\nconst MapTypeId: React.FC<MapTypeIdProps> = ({ type }) => {\n const map = useMap(`MapTypeId`)\n\n useEffect(() => {\n map.addOverlayMapTypeId(type)\n\n return () => {\n map.removeOverlayMapTypeId(type)\n }\n }, [map, type])\n\n return null\n}\n\nexport default MapTypeId\n","import React, { useImperativeHandle, useLayoutEffect, useMemo } from \"react\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport useMap from \"../hooks/useMap\"\n\nexport interface CircleProps {\n /**\n * 중심 좌표를 지정합니다.\n */\n center: {\n lat: number\n lng: number\n }\n /**\n * 원의 반지름 크기를 지정합니다 (미터 단위).\n */\n radius: number\n\n /**\n * #xxxxxx 형태의 채움 색 (기본값: ‘#F10000’)\n */\n fillColor?: string\n /**\n * 채움 불투명도 (0-1) (기본값: 0)\n */\n fillOpacity?: number\n /**\n * 픽셀 단위의 선 두께 (기본값: 3)\n */\n strokeWeight?: number\n /**\n * #xxxxxx 형태의 선 색 (기본값: ‘#F10000’)\n */\n strokeColor?: string\n /**\n * 선 불투명도 (0-1) (기본값: 0.6)\n */\n strokeOpacity?: number\n /**\n * 선 스타일 (기본값: ‘solid’)\n */\n strokeStyle?: kakao.maps.StrokeStyles\n /**\n * 원의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 원에 마우스 커서를 올리면 발생한다.\n */\n onMouseover?: (\n target: kakao.maps.Circle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 커서가 원에서 벗어나면 발생한다.\n */\n onMouseout?: (\n target: kakao.maps.Circle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 원에서 마우스를 움직이면 발생한다.\n */\n onMousemove?: (\n target: kakao.maps.Circle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 원에서 마우스 버튼을 누르면 발생한다.\n */\n onMousedown?: (\n target: kakao.maps.Circle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 원을 클릭하면 발생한다.\n */\n onClick?: (\n target: kakao.maps.Circle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 객체 생성시 호출 됩니다.\n */\n onCreate?: (target: kakao.maps.Circle) => void\n}\n\n/**\n * Map 상에 원을 그립니다.\n */\nconst Circle = React.forwardRef<kakao.maps.Circle, CircleProps>(\n (\n {\n center,\n radius,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n onMouseover,\n onMouseout,\n onMousemove,\n onMousedown,\n onClick,\n onCreate,\n },\n ref\n ) => {\n const map = useMap(`Circle`)\n\n const circleCenter = useMemo(() => {\n return new kakao.maps.LatLng(center.lat, center.lng)\n }, [center.lat, center.lng])\n\n const circle = useMemo(() => {\n return new kakao.maps.Circle({\n center: circleCenter,\n radius,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useImperativeHandle(ref, () => circle, [circle])\n\n useLayoutEffect(() => {\n circle.setMap(map)\n return () => {\n circle.setMap(null)\n }\n }, [map, circle])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(circle)\n }, [circle, onCreate])\n\n useLayoutEffect(() => {\n if (circle) circle.setPosition(circleCenter)\n }, [circle, circleCenter])\n\n useLayoutEffect(() => {\n circle.setRadius(radius)\n }, [circle, radius])\n\n useLayoutEffect(() => {\n if (!zIndex) return\n circle.setZIndex(zIndex)\n }, [circle, zIndex])\n\n useLayoutEffect(() => {\n circle.setOptions({\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n })\n }, [\n circle,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n ])\n\n useKakaoEvent(circle, \"mouseover\", onMouseover)\n useKakaoEvent(circle, \"mouseout\", onMouseout)\n useKakaoEvent(circle, \"mousemove\", onMousemove)\n useKakaoEvent(circle, \"mousedown\", onMousedown)\n useKakaoEvent(circle, \"click\", onClick)\n\n return null\n }\n)\n\nexport default Circle\n","import React, { useImperativeHandle, useLayoutEffect, useMemo } from \"react\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport useMap from \"../hooks/useMap\"\n\ninterface LatLng {\n lat: number\n lng: number\n}\n\nexport interface PolylineProps {\n path: LatLng[] | LatLng[][]\n /**\n * 화살표 여부\n */\n endArrow?: boolean\n /**\n * 픽셀 단위의 선 두께 (기본값: 3)\n */\n strokeWeight?: number\n /**\n * #xxxxxx 형태의 선 색 (기본값: ‘#F10000’)\n */\n strokeColor?: string\n /**\n * 선 불투명도 (0-1) (기본값: 0.6)\n */\n strokeOpacity?: number\n /**\n * 선 스타일 (기본값: ‘solid’)\n */\n strokeStyle?: kakao.maps.StrokeStyles\n /**\n * 선의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 마우스 커서를 올리면 발생한다.\n */\n onMouseover?: (\n target: kakao.maps.Polyline,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 커서가 벗어나면 발생한다.\n */\n onMouseout?: (\n target: kakao.maps.Polyline,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스를 움직이면 발생한다.\n */\n onMousemove?: (\n target: kakao.maps.Polyline,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 버튼을 누르면 발생한다.\n */\n onMousedown?: (\n target: kakao.maps.Polyline,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 클릭하면 발생한다.\n */\n onClick?: (\n target: kakao.maps.Polyline,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 객체 생성시 호출 됩니다.\n */\n onCreate?: (target: kakao.maps.Polyline) => void\n}\n\n/**\n * Map 상에 폴리라인을 그립니다.\n */\nconst Polyline = React.forwardRef<kakao.maps.Polyline, PolylineProps>(\n (\n {\n path,\n endArrow,\n onClick,\n onMousedown,\n onMousemove,\n onMouseout,\n onMouseover,\n onCreate,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n },\n ref\n ) => {\n const map = useMap(`Polyline`)\n\n const polyLinePath = useMemo(() => {\n if ((path as LatLng[]).every((v) => v instanceof Array)) {\n return (path as LatLng[][]).map((v) => {\n return v.map((p) => new kakao.maps.LatLng(p.lat, p.lng))\n })\n }\n return (path as LatLng[]).map((v) => {\n return new kakao.maps.LatLng(v.lat, v.lng)\n })\n }, [path])\n\n const polyline = useMemo(() => {\n return new kakao.maps.Polyline({\n path: polyLinePath,\n endArrow,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useImperativeHandle(ref, () => polyline, [polyline])\n\n useLayoutEffect(() => {\n polyline.setMap(map)\n return () => polyline.setMap(null)\n }, [map, polyline])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(polyline)\n }, [polyline, onCreate])\n\n useLayoutEffect(() => {\n polyline.setOptions({\n endArrow,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n })\n }, [\n polyline,\n endArrow,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n ])\n\n useLayoutEffect(() => {\n polyline.setPath(polyLinePath)\n }, [polyline, polyLinePath])\n\n useLayoutEffect(() => {\n if (zIndex) polyline.setZIndex(zIndex)\n }, [polyline, zIndex])\n\n useKakaoEvent(polyline, \"mouseover\", onMouseover)\n useKakaoEvent(polyline, \"mouseout\", onMouseout)\n useKakaoEvent(polyline, \"mousemove\", onMousemove)\n useKakaoEvent(polyline, \"mousedown\", onMousedown)\n useKakaoEvent(polyline, \"click\", onClick)\n\n return null\n }\n)\n\nexport default Polyline\n","import React, { useLayoutEffect, useImperativeHandle, useMemo } from \"react\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport useMap from \"../hooks/useMap\"\n\ninterface LatLng {\n lat: number\n lng: number\n}\n\nexport interface PolygonProps {\n path: LatLng[] | LatLng[][]\n /**\n * #xxxxxx 형태의 채움 색 (기본값: ‘#F10000’)\n */\n fillColor?: string\n /**\n * 채움 불투명도 (0-1) (기본값: 0)\n */\n fillOpacity?: number\n /**\n * 픽셀 단위의 선 두께 (기본값: 3)\n */\n strokeWeight?: number\n /**\n * #xxxxxx 형태의 선 색 (기본값: ‘#F10000’)\n */\n strokeColor?: string\n /**\n * 선 불투명도 (0-1) (기본값: 0.6)\n */\n strokeOpacity?: number\n /**\n * 선 스타일 (기본값: ‘solid’)\n */\n strokeStyle?: kakao.maps.StrokeStyles\n /**\n * 선의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 마우스 커서를 올리면 발생한다.\n */\n onMouseover?: (\n target: kakao.maps.Polygon,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 커서가 벗어나면 발생한다.\n */\n onMouseout?: (\n target: kakao.maps.Polygon,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스를 움직이면 발생한다.\n */\n onMousemove?: (\n target: kakao.maps.Polygon,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 버튼을 누르면 발생한다.\n */\n onMousedown?: (\n target: kakao.maps.Polygon,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 클릭하면 발생한다.\n */\n onClick?: (\n target: kakao.maps.Polygon,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 객체 생성시 호출 됩니다.\n */\n onCreate?: (target: kakao.maps.Polygon) => void\n}\n\n/**\n * Map 상에 다각형을 그립니다.\n */\nconst Polygon = React.forwardRef<kakao.maps.Polygon, PolygonProps>(\n (\n {\n path,\n onClick,\n onMousedown,\n onMousemove,\n onMouseout,\n onMouseover,\n onCreate,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n fillColor,\n fillOpacity,\n zIndex,\n },\n ref\n ) => {\n const map = useMap(`Polygon`)\n\n const polygonPath = useMemo(() => {\n if ((path as LatLng[]).every((v) => v instanceof Array)) {\n return (path as LatLng[][]).map((v) => {\n return v.map((p) => new kakao.maps.LatLng(p.lat, p.lng))\n })\n }\n return (path as LatLng[]).map((v) => {\n return new kakao.maps.LatLng(v.lat, v.lng)\n })\n }, [path])\n\n const polygon = useMemo(() => {\n return new kakao.maps.Polygon({\n path: polygonPath,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useImperativeHandle(ref, () => polygon, [polygon])\n\n useLayoutEffect(() => {\n polygon.setMap(map)\n return () => polygon.setMap(null)\n }, [map, polygon])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(polygon)\n }, [polygon, onCreate])\n\n useLayoutEffect(() => {\n polygon.setOptions({\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n })\n }, [\n polygon,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n ])\n\n useLayoutEffect(() => {\n polygon.setPath(polygonPath)\n }, [polygon, polygonPath])\n\n useLayoutEffect(() => {\n if (zIndex) polygon.setZIndex(zIndex)\n }, [polygon, zIndex])\n\n useKakaoEvent(polygon, \"mouseover\", onMouseover)\n useKakaoEvent(polygon, \"mouseout\", onMouseout)\n useKakaoEvent(polygon, \"mousemove\", onMousemove)\n useKakaoEvent(polygon, \"mousedown\", onMousedown)\n useKakaoEvent(polygon, \"click\", onClick)\n\n return null\n }\n)\n\nexport default Polygon\n","import React, { useImperativeHandle, useLayoutEffect, useMemo } from \"react\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport useMap from \"../hooks/useMap\"\n\ninterface LatLng {\n lat: number\n lng: number\n}\n\nexport interface RectangleProps {\n bounds: {\n sw: LatLng\n ne: LatLng\n }\n /**\n * #xxxxxx 형태의 채움 색 (기본값: ‘#F10000’)\n */\n fillColor?: string\n /**\n * 채움 불투명도 (0-1) (기본값: 0)\n */\n fillOpacity?: number\n /**\n * 픽셀 단위의 선 두께 (기본값: 3)\n */\n strokeWeight?: number\n /**\n * #xxxxxx 형태의 선 색 (기본값: ‘#F10000’)\n */\n strokeColor?: string\n /**\n * 선 불투명도 (0-1) (기본값: 0.6)\n */\n strokeOpacity?: number\n /**\n * 선 스타일 (기본값: ‘solid’)\n */\n strokeStyle?: kakao.maps.StrokeStyles\n /**\n * 선의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 마우스 커서를 올리면 발생한다.\n */\n onMouseover?: (\n target: kakao.maps.Rectangle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 커서가 벗어나면 발생한다.\n */\n onMouseout?: (\n target: kakao.maps.Rectangle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스를 움직이면 발생한다.\n */\n onMousemove?: (\n target: kakao.maps.Rectangle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 버튼을 누르면 발생한다.\n */\n onMousedown?: (\n target: kakao.maps.Rectangle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 클릭하면 발생한다.\n */\n onClick?: (\n target: kakao.maps.Rectangle,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 객체 생성시 호출 됩니다.\n */\n onCreate?: (target: kakao.maps.Rectangle) => void\n}\n\n/**\n * Map 상에 사각형을 그립니다.\n */\nconst Rectangle = React.forwardRef<kakao.maps.Rectangle, RectangleProps>(\n (\n {\n bounds,\n onClick,\n onMousedown,\n onMousemove,\n onMouseout,\n onMouseover,\n onCreate,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n fillColor,\n fillOpacity,\n zIndex,\n },\n ref\n ) => {\n const map = useMap(`Rectangle`)\n\n const rectangleBounds = useMemo(() => {\n return new kakao.maps.LatLngBounds(\n new kakao.maps.LatLng(bounds.sw.lat, bounds.sw.lng),\n new kakao.maps.LatLng(bounds.ne.lat, bounds.ne.lng)\n )\n }, [bounds])\n\n const rectangle = useMemo(() => {\n return new kakao.maps.Rectangle({\n bounds: rectangleBounds,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useImperativeHandle(ref, () => rectangle, [rectangle])\n\n useLayoutEffect(() => {\n rectangle.setMap(map)\n return () => rectangle.setMap(null)\n }, [map, rectangle])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(rectangle)\n }, [rectangle, onCreate])\n\n useLayoutEffect(() => {\n rectangle.setOptions({\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n })\n }, [\n rectangle,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n ])\n\n useLayoutEffect(() => {\n rectangle.setBounds(rectangleBounds)\n }, [rectangle, rectangleBounds])\n\n useLayoutEffect(() => {\n if (zIndex) rectangle.setZIndex(zIndex)\n }, [rectangle, zIndex])\n\n useKakaoEvent(rectangle, \"mouseover\", onMouseover)\n useKakaoEvent(rectangle, \"mouseout\", onMouseout)\n useKakaoEvent(rectangle, \"mousemove\", onMousemove)\n useKakaoEvent(rectangle, \"mousedown\", onMousedown)\n useKakaoEvent(rectangle, \"click\", onClick)\n\n return null\n }\n)\n\nexport default Rectangle\n","import React, { useImperativeHandle, useLayoutEffect, useMemo } from \"react\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport useMap from \"../hooks/useMap\"\n\nexport interface EllipseProps {\n /**\n * 중심 좌표를 지정합니다.\n */\n center: {\n lat: number\n lng: number\n }\n /**\n * 미터 단위의 x축 반지름\n */\n rx: number\n\n /**\n * 미터 단위의 y축 반지름\n */\n ry: number\n\n /**\n * #xxxxxx 형태의 채움 색 (기본값: ‘#F10000’)\n */\n fillColor?: string\n\n /**\n * 채움 불투명도 (0-1) (기본값: 0)\n */\n fillOpacity?: number\n\n /**\n * 픽셀 단위의 선 두께 (기본값: 3)\n */\n strokeWeight?: number\n\n /**\n * #xxxxxx 형태의 선 색 (기본값: ‘#F10000’)\n */\n strokeColor?: string\n\n /**\n * 선 불투명도 (0-1) (기본값: 0.6)\n */\n strokeOpacity?: number\n\n /**\n * 선 스타일 (기본값: ‘solid’)\n */\n strokeStyle?: kakao.maps.StrokeStyles\n\n /**\n * 타원의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 타원에 마우스 커서를 올리면 발생한다.\n */\n onMouseover?: (\n target: kakao.maps.Ellipse,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 마우스 커서가 타원에서 벗어나면 발생한다.\n */\n onMouseout?: (\n target: kakao.maps.Ellipse,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 타원에서 마우스를 움직이면 발생한다.\n */\n onMousemove?: (\n target: kakao.maps.Ellipse,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 타원에서 마우스 버튼을 누르면 발생한다.\n */\n onMousedown?: (\n target: kakao.maps.Ellipse,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n /**\n * 타원을 클릭하면 발생한다.\n */\n onClick?: (\n target: kakao.maps.Ellipse,\n mouseEvent: kakao.maps.event.MouseEvent\n ) => void\n\n /**\n * 객체 생성시 호출 됩니다.\n */\n onCreate?: (target: kakao.maps.Ellipse) => void\n}\n\n/**\n * Map 상에 타원을 그립니다.\n */\nconst Ellipse = React.forwardRef<kakao.maps.Ellipse, EllipseProps>(\n (\n {\n center,\n rx,\n ry,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n onMouseover,\n onMouseout,\n onMousemove,\n onMousedown,\n onClick,\n onCreate,\n },\n ref\n ) => {\n const map = useMap(`Ellipse`)\n\n const ellipseCenter = useMemo(() => {\n return new kakao.maps.LatLng(center.lat, center.lng)\n }, [center.lat, center.lng])\n\n const ellipse = useMemo(() => {\n return new kakao.maps.Ellipse({\n center: ellipseCenter,\n rx,\n ry,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n zIndex,\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useImperativeHandle(ref, () => ellipse, [ellipse])\n\n useLayoutEffect(() => {\n ellipse.setMap(map)\n\n return () => {\n ellipse.setMap(null)\n }\n }, [map, ellipse])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(ellipse)\n }, [ellipse, onCreate])\n\n useLayoutEffect(() => {\n if (ellipse) ellipse.setPosition(ellipseCenter)\n }, [ellipse, ellipseCenter])\n\n useLayoutEffect(() => {\n ellipse.setRadius(rx, ry)\n }, [ellipse, rx, ry])\n\n useLayoutEffect(() => {\n if (!zIndex) return\n ellipse.setZIndex(zIndex)\n }, [ellipse, zIndex])\n\n useLayoutEffect(() => {\n ellipse.setOptions({\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n })\n }, [\n ellipse,\n fillColor,\n fillOpacity,\n strokeColor,\n strokeOpacity,\n strokeStyle,\n strokeWeight,\n ])\n\n useKakaoEvent(ellipse, \"mouseover\", onMouseover)\n useKakaoEvent(ellipse, \"mouseout\", onMouseout)\n useKakaoEvent(ellipse, \"mousemove\", onMousemove)\n useKakaoEvent(ellipse, \"mousedown\", onMousedown)\n useKakaoEvent(ellipse, \"click\", onClick)\n\n return null\n }\n)\n\nexport default Ellipse\n","import React, { useImperativeHandle, useLayoutEffect, useMemo } from \"react\"\nimport useMap from \"../hooks/useMap\"\n\nexport interface AbstractOverlayProps {\n /**\n * AbstractOverlay에서 필요한 `onAdd` 함수를 구현 합니다.\n * 위치를 재조정할 필요가 있을 때 호출된다.\n * 이 함수 내에서 엘리먼트의 위치를 잡아주어야 한다.\n *\n * 이때 arrow 함수가 아닌 일반 funtion으로 하여 this 바인딩이 되도록 하여 AbstractOverlay를 상속 받은 객체에 접근하여 필요 기능을 정의 합니다.\n * ```tsx\n * const panel = (this as kakao.maps.AbstractOverlay).getPanels().overlayLayer\n * panel.appendChild(node.current)\n * ```\n */\n draw: () => void\n /**\n * 지도에 올릴 때 호출된다.\n * setMap(map) 을 실행하면 이 함수가 실행된다.\n * 이 함수 내에서 생성된 `DOM` 객체를 MapPanels에 자식 노드로 넣어주도록 한다.\n *\n * ```tsx\n * var projection = this.getProjection()\n * var point = projection.pointFromCoords(positionLatlng)\n * var width = node.current.offsetWidth\n * var height = node.current.offsetHeight\n *\n * console.log(point, width, height)\n *\n * node.current.style.left = point.x - width / 2 + \"px\"\n * node.current.style.top = point.y - height / 2 + \"px\"\n * ```\n */\n onAdd: () => void\n\n /**\n * 지도에서 제거할 때 호출된다.\n * setMap(null) 을 실행하면 이 함수가 실행된다.\n * 이 함수 내에서 MapPanels에 자식 노드로 넣어준 엘리먼트를 제거하도록 한다.\n *\n * ```tsx\n * this.node.parentNode.removeChild(this.node);\n * ```\n */\n onRemove: () => void\n\n /**\n * 생성된 kakao.maps.AbstractOverlay 객체를 받을 수 있는 CallBack 함수 입니다.\n */\n onCreate?: (target: kakao.maps.AbstractOverlay) => void\n}\n\n/**\n * `API` 사용자가 직접 정의할 수 있는 오버레이.\n * AbstractOverlay를 상속 받아 사용할 객체를 생성하고 prototype을 연결해 준다.\n * 온전히 동작하는 오버레이를 만들고자 한다면 3가지 인터페이스 메소드( onAdd, draw, onRemove )를 구현해야 한다.\n *\n * 해당 Component 내부에서 `ReactAbstractOveraly` class를 만들어 `onAdd`, `draw`, `onRemove` 를 연결한 후 React Life Cycle에 맞춰 `setMap` 를 자동으로 호출 합니다.\n *\n * *경고* `draw`, `onAdd`, `onRemove` 의 경우 반드시 익명함수가 **아닌** 형태로 만들어서 전달해야 합니다.\n * `this.~` 를 통한 접근이 가능하니 해당 부분을 이용해서 구현 해주세요!\n *\n * ### Example Code\n *\n * ```jsx live\n * function () {\n * const TooltipMarker = ({\n * position,\n * }) => {\n * const node = useRef(document.createElement(\"div\"))\n *\n * const positionLatlng = useMemo(() => {\n * return new kakao.maps.LatLng(position.lat, position.lng)\n * }, [position.lat, position.lng])\n *\n * function onAdd() {\n * const panel = this.getPanels()\n * .overlayLayer\n * panel.appendChild(node.current)\n * }\n *\n * function onRemove() {\n * node.current.parentNode.removeChild(node.current)\n * }\n *\n * function draw() {\n * var projection = this.getProjection()\n * var point = projection.pointFromCoords(positionLatlng)\n * var width = node.current.offsetWidth\n * var height = node.current.offsetHeight\n *\n * console.log(point, width, height)\n *\n * node.current.style.left = point.x - width / 2 + \"px\"\n * node.current.style.top = point.y - height / 2 + \"px\"\n * }\n *\n * useEffect(() => {\n * node.current.style.position = \"absolute\"\n * node.current.style.whiteSpace = \"nowrap\"\n * }, [])\n *\n * return (\n * <>\n * <AbstractOverlay onAdd={onAdd} onRemove={onRemove} draw={draw} />\n * {ReactDOM.createPortal(\n * <div\n * style={{\n * color: \"#000\",\n * backgroundColor: \"#fff\",\n * padding: \"5px\",\n * borderRadius: \"15px\",\n * }}\n * >\n * Hello Marker!\n * </div>,\n * node.current\n * )}\n * </>\n * )\n * }\n *\n * return (\n * <>\n * <Map // 지도를 표시할 Container\n * center={{\n * // 지도의 중심좌표\n * lat: 37.54699,\n * lng: 127.09598,\n * }}\n * style={{\n * // 지도의 크기\n * width: \"100%\",\n * height: \"450px\",\n * }}\n * level={3} // 지도의 확대 레벨\n * >\n * <TooltipMarker\n * position={{\n * lat: 37.54699,\n * lng: 127.09598,\n * }}\n * />\n * </Map>\n * </>\n * )\n *}\n * ```\n */\nconst AbstractOverlay = React.forwardRef<\n kakao.maps.AbstractOverlay,\n AbstractOverlayProps\n>(({ draw, onAdd, onRemove, onCreate }, ref) => {\n const map = useMap()\n\n const reactAbstractOverlay = useMemo(() => {\n class ReactAbstractOveraly extends kakao.maps.AbstractOverlay {\n constructor(draw: () => void, onAdd: () => void, onRemove: () => void) {\n super()\n this.draw = draw\n this.onAdd = onAdd\n this.onRemove = onRemove\n }\n }\n const overlay = new ReactAbstractOveraly(draw, onAdd, onRemove)\n return overlay\n }, [draw, onAdd, onRemove])\n\n useImperativeHandle(ref, () => reactAbstractOverlay, [reactAbstractOverlay])\n\n useLayoutEffect(() => {\n reactAbstractOverlay.setMap(map)\n\n return () => {\n reactAbstractOverlay.setMap(null)\n }\n }, [map, reactAbstractOverlay])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(reactAbstractOverlay)\n }, [reactAbstractOverlay, onCreate])\n\n return null\n})\n\nexport default AbstractOverlay\n","import React, { useImperativeHandle, useRef, useState } from \"react\"\nimport useIsomorphicLayoutEffect from \"../hooks/useIsomorphicLayoutEffect\"\nimport useKakaoEvent from \"../hooks/useKakaoEvent\"\nimport {\n PolymorphicComponentProps,\n PolymorphicComponentPropsWithOutRef,\n} from \"../types\"\nimport { Loader } from \"../util/kakaoMapApiLoader\"\n\nexport const KakaoRoadviewContext = React.createContext<kakao.maps.Roadview>(\n undefined as unknown as kakao.maps.Roadview\n)\n\nexport interface RoadviewProps {\n /**\n * 중심으로 설정할 위치 입니다.\n * 해당 lat와 lng에 해당하는 radius범위 안에서 가장가까운 Roadview을 선택합니다.\n * 만약 없다면 lat, lng로 설정 됩니다.\n */\n position: {\n lat: number\n lng: number\n radius: number\n }\n\n /**\n * 로드뷰 시작 지역의 고유 아이디 값.\n */\n panoId?: number\n\n /**\n * panoId가 유효하지 않을 경우 지도좌표를 기반으로 데이터를 요청할 수평 좌표값.\n */\n panoX?: number\n\n /**\n * panoId가 유효하지 않을 경우 지도좌표를 기반으로 데이터를 요청할 수직 좌표값.\n */\n panoY?: number\n\n /**\n * 로드뷰 처음 실행시에 바라봐야 할 수평 각. 0이 정북방향. (0_360)\n */\n pan?: number\n\n /**\n * 로드뷰 처음 실행시에 바라봐야 할 수직 각.(-90_90)\n */\n tilt?: number\n\n /**\n * 로드뷰 줌 초기값.(-3_3)\n */\n zoom?: number\n\n /**\n * 로드뷰 생성후 해당 객체를 전달하는 callback.\n */\n onCreate?: (roadview: kakao.maps.Roadview) => void\n\n /**\n * 로드뷰가 초기화를 끝내면 발생한다.\n */\n onInit?: (target: kakao.maps.Roadview) => void\n\n /**\n * 파노라마 ID가 바뀌면 발생한다.\n */\n onPanoidChange?: (target: kakao.maps.Roadview) => void\n\n /**\n * 시점이 바뀌면 발생한다.\n */\n onViewpointChange?: (target: kakao.maps.Roadview) => void\n\n /**\n * 지도 좌표가 바뀌면 발생한다.\n */\n onPositionChanged?: (target: kakao.maps.Roadview) => void\n\n /**\n * getNearestPanoId 동작 실패시 호출 합니다.\n */\n onErrorGetNearestPanoId?: (target: kakao.maps.Roadview) => void\n}\n\ntype RoadviewComponent = <T extends React.ElementType = \"div\">(\n props: PolymorphicComponentPropsWithOutRef<T, RoadviewProps> &\n React.RefAttributes<kakao.maps.Roadview>\n) => React.ReactElement | null\n\n/**\n * Roadview를 Roadview를 생성하는 컴포넌트 입니다.\n * props로 받는 `on*` 이벤트는 해당 `kakao.maps.Map` 객체를 반환 합니다.\n * `onCreate` 이벤트를 통해 생성 후 `Roadview` 객체에 직접 접근하여 초기 설정이 가능합니다.\n */\nconst Roadview: RoadviewComponent = React.forwardRef(\n <T extends React.ElementType = \"div\">(\n {\n id,\n as,\n children,\n position,\n pan,\n panoId,\n panoX,\n panoY,\n tilt,\n zoom,\n onCreate,\n onInit,\n onPanoidChange,\n onPositionChanged,\n onViewpointChange,\n onErrorGetNearestPanoId,\n ...props\n }: PolymorphicComponentProps<T, React.PropsWithChildren<RoadviewProps>>,\n ref: React.ForwardedRef<kakao.maps.Roadview>\n ) => {\n const Container = as || \"div\"\n const [isLoaded, setIsLoaded] = useState(false)\n const [isLoading, setIsLoading] = useState(true)\n const [roadview, setRoadview] = useState<kakao.maps.Roadview>()\n const container = useRef<HTMLDivElement>(null)\n\n useIsomorphicLayoutEffect(() => {\n Loader.isLoaded().then(setIsLoaded)\n }, [])\n\n useIsomorphicLayoutEffect(() => {\n if (!isLoaded) return\n\n const RoadviewContainer = container.current\n\n if (!RoadviewContainer) return\n\n const kakaoRoadview = new kakao.maps.Roadview(RoadviewContainer, {\n pan: pan,\n panoId: panoId,\n panoX: panoX,\n panoY: panoY,\n tilt: tilt,\n zoom: zoom,\n })\n\n setRoadview(kakaoRoadview)\n\n return () => {\n RoadviewContainer.innerHTML = \"\"\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isLoaded, panoX, panoY, zoom])\n\n useImperativeHandle(ref, () => roadview!, [roadview])\n\n useIsomorphicLayoutEffect(() => {\n if (!roadview || !onCreate) return\n onCreate(roadview)\n }, [roadview, onCreate])\n\n useIsomorphicLayoutEffect(() => {\n if (\n !roadview ||\n panoId ||\n (roadview.getPosition().getLat() === position.lat &&\n roadview.getPosition().getLng() === position.lng)\n )\n return\n\n const newPostion = new kakao.maps.LatLng(position.lat, position.lng)\n\n new kakao.maps.RoadviewClient().getNearestPanoId(\n newPostion,\n position.radius,\n (panoId) => {\n if (panoId === null && onErrorGetNearestPanoId) {\n onErrorGetNearestPanoId(roadview)\n } else {\n roadview.setPanoId(panoId, newPostion)\n }\n }\n )\n }, [\n roadview,\n panoId,\n position.lat,\n position.lng,\n position.radius,\n onErrorGetNearestPanoId,\n ])\n\n useIsomorphicLayoutEffect(() => {\n if (\n !roadview ||\n !panoId ||\n panoId === roadview.getPanoId() ||\n (roadview.getPosition().getLat() === position.lat &&\n roadview.getPosition().getLng() === position.lng)\n )\n return\n\n const newPostion = new kakao.maps.LatLng(position.lat, position.lng)\n roadview.setPanoId(panoId, newPostion)\n }, [roadview, panoId, position.lat, position.lng])\n\n useIsomorphicLayoutEffect(() => {\n if (!roadview) return\n\n const prevViewpoint = roadview.getViewpoint()\n\n if (prevViewpoint.pan === pan && prevViewpoint.tilt === tilt) return\n\n if (pan) prevViewpoint.pan = pan\n if (tilt) prevViewpoint.tilt = tilt\n roadview.setViewpoint(prevViewpoint)\n }, [roadview, pan, tilt])\n\n useKakaoEvent(roadview, \"init\", (target) => {\n setIsLoading(false)\n if (onInit) onInit(target)\n })\n useKakaoEvent(roadview, \"panoid_changed\", onPanoidChange)\n useKakaoEvent(roadview, \"viewpoint_changed\", onViewpointChange)\n useKakaoEvent(roadview, \"position_changed\", onPositionChanged)\n\n return (\n <>\n <Container\n ref={container}\n id={id || \"react-kakao-maps-sdk-roadview-container\"}\n {...props}\n />\n {roadview && !isLoading && (\n <KakaoRoadviewContext.Provider value={roadview}>\n {children}\n </KakaoRoadviewContext.Provider>\n )}\n </>\n )\n }\n)\n\nexport default Roadview\n","import { useContext } from \"react\"\nimport { KakaoRoadviewContext } from \"../components/Roadview\"\n\n/**\n * kakao roadview 객체를 가져오는 hook 입니다.\n * Roadview 객체 내부가 아니라면 Error를 발생 시킵니다.\n */\nconst useRoadview = (componentName?: string) => {\n const kakaoRoadview = useContext(KakaoRoadviewContext)\n if (!kakaoRoadview) {\n throw new Error(\n `${\n componentName ? componentName + \" Component\" : \"useRoadview\"\n } must exist inside Roadview Component!`\n )\n }\n\n return kakaoRoadview\n}\n\nexport default useRoadview\n","import React, {\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n} from \"react\"\nimport ReactDOM from \"react-dom\"\nimport useRoadview from \"../hooks/useRoadview\"\n\nexport interface CustomOverlayRoadviewProps {\n /**\n * 커스텀 오버레이의 좌표\n */\n position:\n | {\n lat: number\n lng: number\n }\n | {\n /**\n * 가로 각도, 0부터 360 사이의 값으로 북쪽부터 시계방향으로 대응한다.\n */\n pan: number\n /**\n * 세로 각도, -90부터 90 사이의 값으로 위쪽부터 아래쪽으로 대응한다.\n */\n tilt: number\n /**\n * 확대 수준, -3부터 3 사이의 정수이다.\n */\n zoom?: number\n /**\n * 특정 위치의 로드뷰 고유의 아이디 값\n */\n panoId?: number\n }\n /**\n * true 로 설정하면 컨텐츠 영역을 클릭했을 경우 지도 이벤트를 막아준다.\n */\n clickable?: boolean\n\n /**\n * 컨텐츠의 x축 위치. 0_1 사이의 값을 가진다. 기본값은 0.5\n */\n xAnchor?: number\n\n /**\n * 컨텐츠의 y축 위치. 0_1 사이의 값을 가진다. 기본값은 0.5\n */\n yAnchor?: number\n\n /**\n * 커스텀 오버레이의 z-index\n */\n zIndex?: number\n\n /**\n * 로드뷰상에서 커스텀 오버레이의 높이(위치)를 지정한다.\n * 단위는 m(미터)이며 현재 로드뷰의 바닥 높이를 기준으로 떨어져있는 높이를 말한다.\n */\n altitude?: number\n\n /**\n * 커스텀 오버레이의 가시반경을 설정한다.\n * 로드뷰의 위치와 커스텀 오버레이의 위치 사이의 거리가 가시반경 이내일 경우에만 로드뷰상에 노출된다.\n * 단위는 m(미터)이며 기본값은 500m이다.\n */\n range?: number\n\n /**\n * 커스텀 오버레이를 생성 후 해당 객체를 가지고 callback 함수를 실행 시켜줌\n */\n onCreate?: (customOverlay: kakao.maps.CustomOverlay) => void\n}\n\n/**\n * Roadview에 CustomOverlay를 올릴 때 사용하는 컴포넌트 입니다.\n * `onCreate` 이벤트 또는 `ref` 객체를 통해서 `CustomOverlay` 객체에 직접 접근 및 초기 설정 작업을 지정할 수 있습니다.\n */\nconst CustomOverlayRoadview = React.forwardRef<\n kakao.maps.CustomOverlay,\n React.PropsWithChildren<CustomOverlayRoadviewProps>\n>(\n (\n {\n position,\n children,\n clickable,\n xAnchor,\n yAnchor,\n zIndex,\n altitude,\n range,\n onCreate,\n },\n ref\n ) => {\n const roadview = useRoadview(`CustomOverlayRoadview`)\n const container = useRef(document.createElement(\"div\"))\n\n const overlayPosition = useMemo(() => {\n if (\"lat\" in position) {\n return new kakao.maps.LatLng(position.lat, position.lng)\n }\n return new kakao.maps.Viewpoint(\n position.pan,\n position.tilt,\n position.zoom,\n position.panoId\n )\n /* eslint-disable react-hooks/exhaustive-deps */\n }, [\n // @ts-ignore\n position.lat,\n // @ts-ignore\n position.lng,\n // @ts-ignore\n position.pan,\n // @ts-ignore\n position.tilt,\n // @ts-ignore\n position.zoom,\n // @ts-ignore\n position.panoId,\n ])\n /* eslint-enable react-hooks/exhaustive-deps */\n\n const overlay = useMemo(() => {\n const KakaoCustomOverlay = new kakao.maps.CustomOverlay({\n clickable: clickable,\n xAnchor: xAnchor,\n yAnchor: yAnchor,\n zIndex: zIndex,\n position: overlayPosition,\n content: container.current,\n })\n container.current.style.display = \"none\"\n return KakaoCustomOverlay\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [clickable, xAnchor, yAnchor])\n\n useImperativeHandle(ref, () => overlay, [overlay])\n\n useLayoutEffect(() => {\n if (!roadview) return\n\n overlay.setMap(roadview)\n\n return () => {\n overlay.setMap(null)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overlay, roadview])\n\n useLayoutEffect(() => {\n if (onCreate) onCreate(overlay)\n }, [overlay, onCreate])\n\n useLayoutEffect(() => {\n overlay.setPosition(overlayPosition)\n }, [overlay, overlayPosition])\n\n useLayoutEffect(() => {\n if (!zIndex) return\n overlay.setZIndex(zIndex)\n }, [overlay, zIndex])\n\n useLayoutEffect(() => {\n if (!altitude) return\n overlay.setAltitude(altitude)\n }, [overlay, altitude])\n\n useLayoutEffect(() => {\n if (!range) return\n overlay.setRange(range)\n }, [overlay, range])\n\n return (\n container.current.parentElement &&\n ReactDOM.createPortal(children, container.current.parentElement)\n )\n }\n)\n\nexport default CustomOverlayRoadview\n","import React, { useMemo } from \"react\"\nimport useRoadview from \"../hooks/useRoadview\"\nimport Marker from \"./Marker\"\n\nexport interface RoadviewMarkerProps {\n /**\n * 표시 위치\n */\n position:\n | {\n lat: number\n lng: number\n }\n | {\n x: number\n y: number\n }\n | {\n /**\n * 가로 각도, 0부터 360 사이의 값으로 북쪽부터 시계방향으로 대응한다.\n */\n pan: number\n /**\n * 세로 각도, -90부터 90 사이의 값으로 위쪽부터 아래쪽으로 대응한다.\n */\n tilt: number\n /**\n * 확대 수준, -3부터 3 사이의 정수이다.\n */\n zoom?: number\n /**\n * 특정 위치의 로드뷰 고유의 아이디 값\n */\n panoId?: number\n }\n\n image?: {\n /**\n * 표시 이미지 src\n */\n src: string\n\n /**\n * 표시 이미지 크기\n */\n size: {\n width: number\n height: number\n }\n\n options?: {\n /**\n * 마커 이미지의 alt 속성값을 정의한다.\n */\n alt?: string\n\n /**\n * 마커의 클릭 또는 마우스오버 가능한 영역을 표현하는 좌표값\n */\n coords?: string\n\n /**\n * 마커의 좌표에 일치시킬 이미지 안의 좌표 (기본값: 이미지의 가운데 아래)\n */\n offset?: { x: number; y: number }\n\n /**\n * 마커의 클릭 또는 마우스오버 가능한 영역의 모양\n */\n shape?: \"default\" | \"rect\" | \"circle\" | \"poly\"\n\n /**\n * 스프라이트 이미지 중 사용할 영역의 좌상단 좌표\n */\n spriteOrigin?: { x: number; y: number }\n\n /**\n * 스프라이트 이미지의 전체 크기\n */\n spriteSize?: { width: number; height: number }\n }\n }\n\n /**\n * click 이벤트 핸들러\n */\n onClick?: (marker: kakao.maps.Marker) => void\n\n /**\n * mouseover 이벤트 핸들러\n */\n onMouseOver?: (marker: kakao.maps.Marker) => void\n\n /**\n * mouseout 이벤트 핸들러\n */\n onMouseOut?: (marker: kakao.maps.Marker) => void\n\n /**\n * dragstart 이벤트 핸들러\n */\n onDragStart?: (marker: kakao.maps.Marker) => void\n\n /**\n * dragend 이벤트 핸들러\n */\n onDragEnd?: (marker: kakao.maps.Marker) => void\n\n /**\n * Maker 생성 이벤트 핸들러\n */\n onCreate?: (maker: kakao.maps.Marker) => void\n\n /**\n * 마커 엘리먼트의 타이틀 속성 값 (툴팁)\n */\n title?: string\n\n /**\n * 클릭 가능한 마커\n */\n clickable?: boolean\n\n /**\n * 마커 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 마커 투명도 (0-1)\n */\n opacity?: number\n\n /**\n * 로드뷰에 올라있는 마커의 높이 값(m 단위)\n */\n altitude?: number\n\n /**\n * 로드뷰 상에서 마커의 가시반경(m 단위), 두 지점 사이의 거리가 지정한 값보다 멀어지면 마커는 로드뷰에서 보이지 않게 된다.\n */\n range?: number\n\n /**\n * InfoWindow 옵션\n */\n infoWindowOptions?: {\n /**\n * 인포윈도우를 열 때 지도가 자동으로 패닝하지 않을지의 여부 (기본값: false)\n */\n disableAutoPan?: boolean\n\n /**\n * 삭제 가능한 인포윈도우\n */\n removable?: boolean\n\n /**\n * 인포윈도우 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n }\n}\n\n/**\n * Map에서 Marker를 생성할 때 사용 합니다.\n * `onCreate` 이벤트를 통해 생성 후 `maker` 객체에 직접 접근하여 초기 설정이 가능합니다.\n */\nconst RoadviewMarker = React.forwardRef<\n kakao.maps.Marker,\n React.PropsWithChildren<RoadviewMarkerProps>\n>(\n (\n {\n image,\n position,\n children,\n altitude,\n clickable,\n infoWindowOptions,\n onClick,\n onDragEnd,\n onDragStart,\n onMouseOut,\n onMouseOver,\n onCreate,\n opacity,\n range,\n title,\n zIndex,\n },\n ref\n ) => {\n const roadview = useRoadview(`RoadviewMarker`)\n\n const markerImage = useMemo(() => {\n return (\n image &&\n new kakao.maps.MarkerImage(\n image.src,\n new kakao.maps.Size(image.size.width, image.size.height),\n {\n alt: image.options?.alt,\n coords: image.options?.coords,\n offset:\n image.options?.offset &&\n new kakao.maps.Point(\n image.options?.offset.x,\n image.options?.offset.y\n ),\n shape: image.options?.shape,\n spriteOrigin:\n image.options?.spriteOrigin &&\n new kakao.maps.Point(\n image.options?.spriteOrigin.x,\n image.options?.spriteOrigin.y\n ),\n spriteSize:\n image.options?.spriteSize &&\n new kakao.maps.Size(\n image.options?.spriteSize.width,\n image.options?.spriteSize.height\n ),\n }\n )\n )\n }, [image])\n\n const markerPosition = useMemo(() => {\n if (\"lat\" in position) {\n return new kakao.maps.LatLng(position.lat, position.lng)\n }\n if (\"x\" in position) {\n return new kakao.maps.Coords(position.x, position.y).toLatLng()\n }\n return new kakao.maps.Viewpoint(\n position.pan,\n position.tilt,\n position.zoom,\n position.panoId\n )\n\n /* eslint-disable react-hooks/exhaustive-deps */\n }, [\n // @ts-ignore\n position.lat,\n // @ts-ignore\n position.lng,\n // @ts-ignore\n position.x,\n // @ts-ignore\n position.y,\n // @ts-ignore\n position.pan,\n // @ts-ignore\n position.tilt,\n // @ts-ignore\n position.zoom,\n // @ts-ignore\n position?.panoId,\n ])\n /* eslint-enable react-hooks/exhaustive-deps */\n\n return (\n <Marker\n map={roadview}\n position={markerPosition}\n image={markerImage}\n altitude={altitude}\n clickable={clickable}\n infoWindowOptions={infoWindowOptions}\n onClick={onClick}\n onDragEnd={onDragEnd}\n onDragStart={onDragStart}\n onMouseOut={onMouseOut}\n onMouseOver={onMouseOver}\n onCreate={onCreate}\n opacity={opacity}\n range={range}\n title={title}\n zIndex={zIndex}\n ref={ref}\n >\n {children}\n </Marker>\n )\n }\n)\n\nexport default RoadviewMarker\n","import React, { useMemo } from \"react\"\nimport InfoWindow from \"./InfoWindow\"\nimport useRoadview from \"../hooks/useRoadview\"\n\nexport interface RoadviewInfoWindowProps {\n /**\n * 인포윈도가 표시될 위치\n */\n position:\n | {\n lat: number\n lng: number\n }\n | {\n /**\n * 가로 각도, 0부터 360 사이의 값으로 북쪽부터 시계방향으로 대응한다.\n */\n pan: number\n /**\n * 세로 각도, -90부터 90 사이의 값으로 위쪽부터 아래쪽으로 대응한다.\n */\n tilt: number\n /**\n * 확대 수준, -3부터 3 사이의 정수이다.\n */\n zoom?: number\n /**\n * 특정 위치의 로드뷰 고유의 아이디 값\n */\n panoId?: number\n }\n\n /**\n * 인포윈도우를 열 때 지도가 자동으로 패닝하지 않을지의 여부 (기본값: false)\n */\n disableAutoPan?: boolean\n\n /**\n * 삭제 가능한 인포윈도우\n */\n removable?: boolean\n\n /**\n * 인포윈도우 엘리먼트의 z-index 속성 값\n */\n zIndex?: number\n\n /**\n * 로드뷰에 올라있는 인포윈도우의 높이 값(m 단위)\n */\n altitude?: number\n\n /**\n * 로드뷰 상에서 인포윈도우의 가시반경(m 단위), 두 지점 사이의 거리가 지정한 값보다 멀어지면 인포윈도우는 보이지 않게 된다\n */\n range?: number\n\n /**\n * 인포윈도우 객체 생성후 해당 객체를 반환하는 함수\n */\n onCreate?: (infoWindow: kakao.maps.InfoWindow) => void\n}\n\n/**\n * Map 컴포넌트에서 InfoWindow를 그릴 때 사용됩니다.\n * `onCreate` 이벤트를 통해 생성 후 `infoWindow` 객체에 직접 접근하여 초기 설정이 가능합니다.\n */\nconst RoadviewInfoWindow = React.forwardRef<\n kakao.maps.InfoWindow,\n React.PropsWithChildren<RoadviewInfoWindowProps>\n>(\n (\n {\n position,\n children,\n altitude,\n disableAutoPan,\n range,\n removable,\n zIndex,\n onCreate,\n },\n ref\n ) => {\n const roadview = useRoadview(`RoadviewInfoWindow`)\n const infoPosition = useMemo(() => {\n if (\"lat\" in position) {\n return new kakao.maps.LatLng(position.lat, position.lng)\n }\n return new kakao.maps.Viewpoint(\n position.pan,\n position.tilt,\n position.zoom,\n position.panoId\n )\n /* eslint-disable react-hooks/exhaustive-deps */\n }, [\n // @ts-ignore\n position.lat,\n // @ts-ignore\n position.lng,\n // @ts-ignore\n position.pan,\n // @ts-ignore\n position.tilt,\n // @ts-ignore\n position.zoom,\n // @ts-ignore\n position.panoId,\n ])\n /* eslint-enable react-hooks/exhaustive-deps */\n\n return (\n <InfoWindow\n altitude={altitude}\n disableAutoPan={disableAutoPan}\n range={range}\n removable={removable}\n zIndex={zIndex}\n map={roadview}\n position={infoPosition}\n onCreate={onCreate}\n ref={ref}\n >\n {children}\n </InfoWindow>\n )\n }\n)\n\nexport default RoadviewInfoWindow\n","import React, {\n ReactNode,\n Ref,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n} from \"react\"\nimport useMap from \"../hooks/useMap\"\n\nexport const DrawingManagerContext =\n React.createContext<kakao.maps.drawing.DrawingManager>(\n undefined as unknown as kakao.maps.drawing.DrawingManager\n )\n\nexport type DrawingManagerProps<\n T extends kakao.maps.drawing.OverlayType = kakao.maps.drawing.OverlayType\n> = Partial<kakao.maps.drawing.OverlayOptions> &\n Pick<kakao.maps.drawing.OverlayOptions, `${T}Options`> & {\n /**\n * 마우스 오버 시 가이드 툴팁 표시 여부. ‘draw’, ‘drag’, ‘edit’ 3가지를 지정할 수 있다 (기본값: 모두 표시 안함)\n * 예를들어 [‘draw’]로 설정하면 객체를 그릴때 가이드 툴팁이 표시된다\n */\n guideTooltip?: Array<\"draw\" | \"drag\" | \"edit\">\n /**\n * 사용할 그리기 요소 지정한다 (기본값: 모든 그리기 요소)\n */\n drawingMode?: Array<T>\n\n /**\n * 그리기 요소를 선택하면 발생한다.\n */\n onSelect?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>,\n event: kakao.maps.drawing.MouseEvent\n ) => void\n\n /**\n * 그리기를 시작하면 발생한다.\n */\n onDrawstart?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>,\n event: kakao.maps.drawing.MouseEvent\n ) => void\n\n /**\n * 그리기 시작 후, 마우스를 이동하면 발생한다.\n */\n onDraw?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>,\n event: kakao.maps.drawing.MouseEvent\n ) => void\n\n /**\n * 그리기를 시작하면 발생한다.\n */\n onDrawend?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>,\n event: kakao.maps.drawing.MouseEvent\n ) => void\n\n /**\n * 다음 단계 그리기를 하면 발생한다. (Polyline, Polygon, Arrow 한정)\n */\n onDrawnext?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>,\n event: kakao.maps.drawing.MouseEvent\n ) => void\n\n /**\n * 그리기를 취소하면 발생한다.\n */\n onCancle?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>,\n event: kakao.maps.drawing.MouseEvent\n ) => void\n\n /**\n * 그리기 요소를 삭제하면 발생한다.\n */\n onRemove?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>,\n event: kakao.maps.drawing.MouseEvent\n ) => void\n\n /**\n * 그리기 요소들의 상태가 변경되면 발생한다.\n * 각 요소의 생성/수정/이동/삭제 동작과 undo 또는 redo 함수 호출이 이에 해당한다.\n */\n onStateChanged?: (\n drawingManager: kakao.maps.drawing.DrawingManager<T>\n ) => void\n\n /**\n * 객체 생성후 해당 이벤트가 발생합니다.\n */\n onCreate?: (drawingManager: kakao.maps.drawing.DrawingManager<T>) => void\n\n /**\n * Toolbox에 대해서 추가할 때 사용합니다.\n */\n children?: ReactNode\n }\n\nfunction useDrawingManagerEvent<T extends kakao.maps.drawing.OverlayType>(\n target: kakao.maps.drawing.DrawingManager<T> | undefined,\n type:\n | \"drawstart\"\n | \"draw\"\n | \"drawend\"\n | \"drawnext\"\n | \"select\"\n | \"cancel\"\n | \"remove\"\n | \"state_changed\",\n callback:\n | ((target: kakao.maps.drawing.DrawingManager<T>, ...args: any) => void)\n | undefined\n) {\n useLayoutEffect(() => {\n if (!target || !callback) return\n\n const wrapCallback = (...arg: any[]) => {\n if (arg === undefined) return callback(target)\n else return callback(target, ...arg)\n }\n\n // @ts-ignore\n target.addListener(type, wrapCallback)\n }, [callback, target, type])\n}\n\n/**\n * 그리기 관리자 객체를 생성하는 컴포넌트 입니다.\n *\n * 초기 생성자에 필요한 Props는 최초 렌더링에만 반영을 하고 이후에는 값이 변경되더라도 적용되지 않습니다.\n *\n * > `on~` 시리즈를 제외한 props는 초기 렌더링 이후 작동 안함\n *\n * DrawingManager는 이전 Map, Marker, CustomOverlay와 달리 Props를 통해 제어를 하는 것이 아닌 직접 DrawingManager 객체를 이용하여 제어를 해야 합니다.\n *\n * 이를 위해 ref 객체를 통해 `DrawingManager` 객체를 접근 할 수 있으며, 이를 활용하여 여러 이벤트 처리 및 제어가 가능합니다.\n *\n * TypeScript 사용자를 위한 `Generic`이 적용되어 있으므로, `ref` 객체에 대한 typing 및 `drawingMode`에 대해 확실하게 정의해야 합니다.\n *\n * ```tsx\n * const Main = () => {\n * const managerRef = useRef<kakao.maps.drawing.DrawingManager<\n * kakao.maps.drawing.OverlayType.POLYLINE\n * >>(null);\n *\n * function selectOverlay(type: string) {\n * const manager = managerRef.current;\n * manager.cancel();\n * manager.select(kakao.maps.drawing.OverlayType.POLYLINE);\n * }\n *\n * return (\n * <>\n * <Map\n * center={{\n * // 지도의 중심좌표\n * lat: 33.450701,\n * lng: 126.570667,\n * }}\n * style={{\n * width: \"100%\",\n * height: \"450px\",\n * }}\n * level={3} // 지도의 확대 레벨\n * >\n * <DrawingManager\n * ref={managerRef}\n * drawingMode={[\n * kakao.maps.drawing.OverlayType.POLYLINE,\n * ]}\n * guideTooltip={['draw', 'drag', 'edit']}\n * polylineOptions={{\n * draggable: true,\n * removable: true,\n * editable: true\n * }}\n * />\n * </Map>\n * <button onClick={(e) => {\n * selectOverlay('POLYLINE')\n * }}>선</button>\n * </>\n * )\n * }\n * ```\n *\n * > JavaScript 코드 버전\n *\n * ```jsx live\n * function() {\n * const Main = () => {\n * const managerRef = useRef(null);\n *\n * function selectOverlay() {\n * const manager = managerRef.current;\n * manager.cancel();\n * manager.select(kakao.maps.drawing.OverlayType.POLYLINE);\n * }\n *\n * return (\n * <>\n * <Map\n * center={{\n * // 지도의 중심좌표\n * lat: 33.450701,\n * lng: 126.570667,\n * }}\n * style={{\n * width: \"100%\",\n * height: \"450px\",\n * }}\n * level={3} // 지도의 확대 레벨\n * >\n * <DrawingManager\n * ref={managerRef}\n * drawingMode={[\n * kakao.maps.drawing.OverlayType.POLYLINE,\n * ]}\n * guideTooltip={['draw', 'drag', 'edit']}\n * polylineOptions={{\n * draggable: true,\n * removable: true,\n * editable: true\n * }}\n * />\n * </Map>\n * <button onClick={selectOverlay}>선</button>\n * </>\n * )\n * }\n * return (<Main />)\n * }\n * ```\n */\nconst DrawingManager = React.forwardRef(function <\n T extends kakao.maps.drawing.OverlayType\n>(\n {\n arrowOptions,\n circleOptions,\n ellipseOptions,\n markerOptions,\n polygonOptions,\n polylineOptions,\n rectangleOptions,\n drawingMode,\n guideTooltip,\n onSelect,\n onDrawstart,\n onDraw,\n onDrawend,\n onDrawnext,\n onCancle,\n onRemove,\n onStateChanged,\n onCreate,\n children,\n }: DrawingManagerProps<T>,\n ref: Ref<kakao.maps.drawing.DrawingManager<T>>\n) {\n const map = useMap(\"Toolbox\")\n\n const drawingManager = useMemo(\n () => {\n if (!window.kakao.maps.drawing) {\n console.warn(\n \"drawing 라이브러리를 별도 로드 해야 사용 가능합니다. `https://apis.map.kakao.com/web/guide/#loadlibrary`\"\n )\n return\n }\n\n return new kakao.maps.drawing.DrawingManager({\n // @ts-ignore\n map,\n drawingMode,\n guideTooltip,\n arrowOptions,\n circleOptions,\n ellipseOptions,\n markerOptions,\n polygonOptions,\n polylineOptions,\n rectangleOptions,\n })\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n )\n useImperativeHandle(ref, () => drawingManager!, [drawingManager])\n\n useLayoutEffect(() => {\n drawingManager && onCreate && onCreate(drawingManager)\n }, [drawingManager, onCreate])\n\n useDrawingManagerEvent(drawingManager, \"select\", onSelect)\n useDrawingManagerEvent(drawingManager, \"drawstart\", onDrawstart)\n useDrawingManagerEvent(drawingManager, \"draw\", onDraw)\n useDrawingManagerEvent(drawingManager, \"drawend\", onDrawend)\n useDrawingManagerEvent(drawingManager, \"drawnext\", onDrawnext)\n useDrawingManagerEvent(drawingManager, \"cancel\", onCancle)\n useDrawingManagerEvent(drawingManager, \"remove\", onRemove)\n useDrawingManagerEvent(drawingManager, \"state_changed\", onStateChanged)\n\n if (!drawingManager) return null\n\n return (\n <DrawingManagerContext.Provider value={drawingManager}>\n {children}\n </DrawingManagerContext.Provider>\n )\n}) as unknown as <\n T extends kakao.maps.drawing.OverlayType = kakao.maps.drawing.OverlayType\n>(\n _props: DrawingManagerProps<T> &\n React.RefAttributes<kakao.maps.drawing.DrawingManager<T>>\n) => null\n\nexport default DrawingManager\n","import React, {\n Ref,\n useContext,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n} from \"react\"\nimport useMap from \"../hooks/useMap\"\nimport { DrawingManagerContext } from \"./DrawingManager\"\n\nexport type ToolboxProps = {\n /**\n * Toolbox의 Position를 정의 한다.\n */\n position?: kakao.maps.ControlPosition\n}\n\n/**\n * 그리기 툴박스를 생성합니다.\n *\n * 해당 컴포넌트는 반드시 `DrawingManager` 컴포넌트의 자식으로 존재해야 합니다.\n */\nconst Toolbox = React.forwardRef(function (\n { position }: ToolboxProps,\n ref: Ref<kakao.maps.drawing.Toolbox>\n) {\n position = position || kakao.maps.ControlPosition.TOP\n\n const map = useMap(\"Toolbox\")\n const drawingmanager = useContext(DrawingManagerContext)\n\n if (!drawingmanager) {\n throw new Error(\"Toolbox must exist inside DrawingManager Component!`\")\n }\n\n const toolbox = useMemo(\n () =>\n new kakao.maps.drawing.Toolbox({\n drawingManager: drawingmanager,\n }),\n [drawingmanager]\n )\n useImperativeHandle(ref, () => toolbox, [toolbox])\n\n useLayoutEffect(() => {\n const element = toolbox.getElement()\n map.addControl(element, position!)\n return () => {\n map.removeControl(element)\n }\n }, [map, toolbox, position])\n\n return null\n})\n\nexport default Toolbox\n","import React, { useRef, useState, useImperativeHandle } from \"react\"\nimport useIsomorphicLayoutEffect from \"../hooks/useIsomorphicLayoutEffect\"\n\nexport interface StaticMapProps {\n /**\n * MapContinaer의 id에 대해서 지정합니다.\n */\n id?: string\n\n /**\n * MapContainer의 className에 대해서 지정합니다.\n */\n className?: string\n\n /**\n * MapContainer의 style에 대해서 지정합니다.\n */\n style?: React.CSSProperties\n\n /**\n * 중심으로 설정할 위치 입니다.\n */\n center: {\n lat: number\n lng: number\n }\n\n /**\n * 확대 수준\n * @default 3\n */\n level?: number\n\n /**\n * 지도 종류 (기본값: 일반 지도)\n */\n mapTypeId?: kakao.maps.MapTypeId\n\n /**\n * 이미지 지도에 표시할 마커 또는 마커 배열\n */\n marker:\n | boolean\n | {\n /**\n * 마커 tooltip에 표시될 내용\n */\n text?: string\n /**\n * 마커 포지션\n */\n position?: {\n lat: number\n lng: number\n }\n }\n | Array<{\n /**\n * 마커 tooltip에 표시될 내용\n */\n text?: string\n /**\n * 마커 포지션\n */\n position: {\n lat: number\n lng: number\n }\n }>\n /**\n * StaticMap 생성 이벤트 핸들러\n */\n onCreate?: (maker: kakao.maps.StaticMap) => void\n}\n\nconst StaticMap = React.forwardRef<kakao.maps.StaticMap, StaticMapProps>(\n (\n {\n id = \"react-kakao-maps-sdk-staticmap-container\",\n style,\n className,\n center,\n marker,\n level,\n mapTypeId,\n onCreate,\n },\n ref\n ) => {\n const [map, setMap] = useState<kakao.maps.StaticMap>()\n const container = useRef<HTMLDivElement>(null)\n\n useIsomorphicLayoutEffect(() => {\n if (!window.kakao) {\n console.warn(\n \"kakao map javascript api를 먼저 불러와야 합니다. `https://apis.map.kakao.com/web/guide`\"\n )\n return\n }\n\n const mapContainer = container.current\n if (!mapContainer) return\n\n kakao.maps.load(() => {\n const _marker = (() => {\n if (Array.isArray(marker)) {\n return marker.map((mk) => {\n return {\n ...mk,\n position: new kakao.maps.LatLng(\n mk.position.lat,\n mk.position.lng\n ),\n }\n })\n }\n if (typeof marker === \"object\") {\n if (!!marker.position) {\n return {\n ...marker,\n position: new kakao.maps.LatLng(\n marker.position.lat,\n marker.position.lng\n ),\n }\n }\n return marker as { text: string }\n }\n return marker\n })()\n const kakaoStaticMap = new kakao.maps.StaticMap(mapContainer, {\n center: new kakao.maps.LatLng(center.lat, center.lng),\n level,\n mapTypeId,\n marker: _marker,\n })\n\n setMap(kakaoStaticMap)\n })\n }, [JSON.stringify(marker)])\n\n useImperativeHandle(ref, () => map!, [map])\n\n useIsomorphicLayoutEffect(() => {\n if (map) map.setCenter(new kakao.maps.LatLng(center.lat, center.lng))\n }, [map, center.lat, center.lng])\n\n useIsomorphicLayoutEffect(() => {\n if (map && level) map.setLevel(level)\n }, [map, level])\n\n useIsomorphicLayoutEffect(() => {\n if (map && mapTypeId) map.setMapTypeId(mapTypeId)\n }, [map, mapTypeId])\n\n useIsomorphicLayoutEffect(() => {\n if (map && onCreate) onCreate(map)\n }, [map, onCreate])\n\n return (\n <div id={id} style={style} className={className} ref={container}></div>\n )\n }\n)\n\nexport default StaticMap\n","import { useEffect, useMemo, useState } from \"react\"\nimport { Loader, LoaderOptions } from \"../util/kakaoMapApiLoader\"\n\n/**\n * Kakao Map Api를 injection 합니다.\n *\n * 해당 hook은 cleanup 시점에도 Kakao Map Api를 제거 하지 않고, 동일한 hook를 여러 위치에서 호출 하더라도 최초 한번만 injection 됩니다.\n */\nconst useInjectKakaoMapApi = (options: LoaderOptions) => {\n const [state, setState] = useState<{\n loading: boolean\n error: ErrorEvent | undefined\n }>({\n loading: true,\n error: undefined,\n })\n\n const loader = useMemo(\n () => new Loader(options),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(options)]\n )\n\n useEffect(() => {\n loader\n .load()\n .then(() =>\n setState({\n loading: false,\n error: undefined,\n })\n )\n .catch((error) =>\n setState({\n loading: false,\n error: error,\n })\n )\n }, [loader])\n\n return state\n}\n\nexport default useInjectKakaoMapApi\n"],"names":["useIsomorphicLayoutEffect","window","document","useLayoutEffect","useEffect","useKakaoEvent","target","type","callback","wrapCallback","arg","undefined","kakao","maps","event","addListener","removeListener","LoaderStatus","Loader","constructor","appkey","id","libraries","nonce","retries","url","this","callbacks","done","loading","errors","onerrorEvent","instance","equalOptions","options","Error","JSON","stringify","static","Promise","resolve","status","FAILURE","INITIALIZED","LOADING","loadcheckcallbacks","push","e","load","reject","loadCallback","err","error","SUCCESS","failed","length","fn","execute","resetIfRetryingFailed","reset","deleteScript","console","warn","setScript","getElementById","createUrl","script","createElement","src","onerror","loadErrorCallback","bind","onload","defer","async","head","appendChild","source","lineno","colno","delay","log","setTimeout","join","remove","forEach","cb","a","b","i","KakaoMapContext","React","createContext","Map","forwardRef","ref","as","children","center","isPanto","padding","disableDoubleClick","disableDoubleClickZoom","draggable","zoomable","keyboardShortcuts","level","maxLevel","minLevel","mapTypeId","projectionId","scrollwheel","tileAnimation","onBoundsChanged","onCenterChanged","onClick","onDoubleClick","onDrag","onDragEnd","onDragStart","onIdle","onMaptypeidChanged","onMouseMove","onRightClick","onTileLoaded","onZoomChanged","onZoomStart","onCreate","props","_objectWithoutPropertiesLoose","_ref","_excluded","Container","isLoaded","setIsLoaded","useState","map","setMap","container","useRef","then","MapContainer","current","initalMapCenter","LatLng","lat","lng","Coords","x","y","kakaoMap","innerHTML","useImperativeHandle","prevCenter","getCenter","toLatLng","centerPosition","equals","panTo","setCenter","setDraggable","setZoomable","setKeyboardShortcuts","setLevel","setMapTypeId","setProjectionId","setMaxLevel","setMinLevel","Fragment","Provider","value","useMap","componentName","useContext","InfoWindow","position","marker","altitude","disableAutoPan","range","removable","zIndex","infoWindow","useMemo","kakaoInfoWindow","content","style","display","open","close","setPosition","setAltitude","setRange","setZIndex","parentElement","ReactDom","createPortal","KakaoMapMarkerClustererContext","MarkerClusterer","averageCenter","calculator","clickable","disableClickZoom","gridSize","hoverable","minClusterSize","styles","texts","onClusterclick","onClusterdblclick","onClustered","onClusterout","onClusterover","onClusterrightclick","markerCluster","setGridSize","redraw","setMinClusterSize","setAverageCenter","setTexts","setCalculator","setStyles","Marker","image","infoWindowOptions","onMouseOut","onMouseOver","opacity","title","addMarker","removeMarker","setImage","setClickable","setOpacity","setTitle","MapMarker","markerImage","MarkerImage","Size","size","width","height","alt","_image$options","coords","_image$options2","offset","_image$options3","Point","_image$options4","_image$options5","shape","_image$options6","spriteOrigin","_image$options8","_image$options9","spriteSize","_image$options10","_image$options11","_image$options12","markerPosition","MapInfoWindow","infoPosition","CustomOverlayMap","xAnchor","yAnchor","overlayPosition","overlay","KakaoCustomOverlay","CustomOverlay","ReactDOM","MapTypeControl","ControlPosition","TOPRIGHT","mapTypeControl","addControl","removeControl","ZoomControl","RIGHT","MapTypeId","addOverlayMapTypeId","removeOverlayMapTypeId","Circle","radius","fillColor","fillOpacity","strokeColor","strokeOpacity","strokeStyle","strokeWeight","onMouseover","onMouseout","onMousemove","onMousedown","circleCenter","circle","setRadius","setOptions","Polyline","path","endArrow","polyLinePath","every","v","Array","p","polyline","setPath","Polygon","polygonPath","polygon","Rectangle","bounds","rectangleBounds","LatLngBounds","sw","ne","rectangle","setBounds","Ellipse","rx","ry","ellipseCenter","ellipse","AbstractOverlay","draw","onAdd","onRemove","reactAbstractOverlay","ReactAbstractOveraly","super","KakaoRoadviewContext","Roadview","pan","panoId","panoX","panoY","tilt","zoom","onInit","onPanoidChange","onPositionChanged","onViewpointChange","onErrorGetNearestPanoId","isLoading","setIsLoading","roadview","setRoadview","RoadviewContainer","kakaoRoadview","getPosition","getLat","getLng","newPostion","RoadviewClient","getNearestPanoId","setPanoId","getPanoId","prevViewpoint","getViewpoint","setViewpoint","_extends","useRoadview","CustomOverlayRoadview","Viewpoint","RoadviewMarker","_image$options7","RoadviewInfoWindow","DrawingManagerContext","useDrawingManagerEvent","DrawingManager","arrowOptions","circleOptions","ellipseOptions","markerOptions","polygonOptions","polylineOptions","rectangleOptions","drawingMode","guideTooltip","onSelect","onDrawstart","onDraw","onDrawend","onDrawnext","onCancle","onStateChanged","drawingManager","drawing","Toolbox","TOP","drawingmanager","toolbox","element","getElement","StaticMap","className","mapContainer","_marker","isArray","mk","kakaoStaticMap","useInjectKakaoMapApi","state","setState","loader","catch"],"mappings":"ufAEA,MAAMA,EACc,oBAAXC,QAA8C,oBAAbC,SACpCC,EACAC,ECHAC,EAAgB,CAIpBC,EAIAC,EAIAC,KAEAR,EAA0B,KACxB,IAAKM,IAAWE,EAAU,OAE1B,MAAMC,EAAe,IAAIC,SACXC,IAARD,EAA0BF,EAASF,GAC3BE,EAASF,KAAWI,GAKlC,OAFAE,MAAMC,KAAKC,MAAMC,YAAYT,EAAQC,EAAME,GAEpC,KACLG,MAAMC,KAAKC,MAAME,eAAeV,EAAQC,EAAME,EAA9C,CACD,EACA,CAACH,EAAQC,EAAMC,GAbO,EC0BfS,IAAAA,GAAZ,SAAYA,GACVA,EAAAA,EAAA,YAAA,GAAA,cACAA,EAAAA,EAAA,QAAA,GAAA,UACAA,EAAAA,EAAA,QAAA,GAAA,UACAA,EAAAA,EAAA,QAAA,GAAA,SAJF,CAAA,CAAYA,IAAAA,EAKX,CAAA,UAWYC,EAiBXC,aAAYC,OACVA,EADUC,GAEVA,EA5Be,8BA0BLC,UAGVA,EAAY,GAHFC,MAIVA,EAJUC,QAKVA,EAAU,EALAC,IAMVA,EAAM,oCASN,GARcC,KApBAL,QAoBA,EAAAK,KAnBAN,YAmBA,EAAAM,KAlBAD,SAkBA,EAAAC,KAjBAJ,eAiBA,EAAAI,KAhBAH,WAgBA,EAAAG,KAfAF,aAeA,EAAAE,KAbRC,UAA0C,GAC1CC,KAAAA,MAAO,EACPC,KAAAA,SAAU,OACVC,OAAuB,GAUfJ,KATRK,kBASQ,EACdL,KAAKL,GAAKA,EACVK,KAAKN,OAASA,EACdM,KAAKJ,UAAYA,EACjBI,KAAKH,MAAQA,EACbG,KAAKF,QAAUA,EACfE,KAAKD,IAAMA,EAEPP,EAAOc,SAAU,CACnB,IAAKd,EAAOe,aAAaP,KAAKQ,QAAShB,EAAOc,SAASE,SACrD,MAAUC,IAAAA,MACmD,2DAAAC,KAAKC,UAC9DX,KAAKQ,gBACEE,KAAKC,UAAUnB,EAAOc,SAASE,YAI5C,OAAOhB,EAAOc,QACf,CACDd,EAAOc,SAAWN,IACnB,CAEUQ,cACT,MAAO,CACLd,OAAQM,KAAKN,OACbC,GAAIK,KAAKL,GACTC,UAAWI,KAAKJ,UAChBC,MAAOG,KAAKH,MACZC,QAASE,KAAKF,QACdC,IAAKC,KAAKD,IAEb,CAEqBa,kBACpB,OAAWC,IAAAA,QAASC,GACbtB,EAAOc,SAYVd,EAAOc,SAASS,SAAWxB,EAAayB,SACxCxB,EAAOc,SAASS,SAAWxB,EAAa0B,YAEjCH,GAAQ,IAGbtB,EAAOc,SAASS,SAAWxB,EAAa2B,SAC1C1B,EAAO2B,mBAAmBC,KAAMC,GAAMP,GAASO,IAG1CP,GAAQ,IArBTvC,OAAOW,OAASX,OAAOW,MAAMC,KACxBZ,OAAOW,MAAMC,KAAKmC,KAAK,KAC5BR,GAAQ,EACT,GAEItB,EAAO2B,mBAAmBC,KAAMC,IACrCP,GAASO,EAAF,GAiBd,CAEMC,OACL,WAAWT,QAAQ,CAACC,EAASS,KAC3BvB,KAAKwB,aAAcC,IACZA,EAGHF,EAAOE,EAAIC,OAFXZ,EAAQvC,OAAOW,MAGhB,EALH,EAQH,CAEU6B,aACT,OAAIf,KAAKK,aACAd,EAAayB,QAElBhB,KAAKE,KACAX,EAAaoC,QAElB3B,KAAKG,QACAZ,EAAa2B,QAEf3B,EAAa0B,WACrB,CAEWW,aACV,OAAO5B,KAAKE,OAASF,KAAKG,SAAWH,KAAKI,OAAOyB,QAAU7B,KAAKF,QAAU,CAC3E,CAEO0B,aAAaM,GACnB9B,KAAKC,UAAUmB,KAAKU,GACpB9B,KAAK+B,SACN,CAEOC,wBACFhC,KAAK4B,QACP5B,KAAKiC,OAER,CAEOA,QACNjC,KAAKkC,eACLlC,KAAKE,MAAO,EACZF,KAAKG,SAAU,EACfH,KAAKI,OAAS,GACdJ,KAAKK,kBAAepB,CACrB,CAEO8C,UAGN,GAFA/B,KAAKgC,wBAEDhC,KAAKE,KACPF,KAAKlB,eACA,CACL,GAAIP,OAAOW,OAASX,OAAOW,MAAMC,KAM/B,OALAgD,QAAQC,KACN,6FAGFpC,KAAKlB,WAIFkB,KAAKG,UACRH,KAAKG,SAAU,EACfH,KAAKqC,YAER,CACF,CAEOA,YACF7D,SAAS8D,eAAetC,KAAKL,KAC/BK,KAAKlB,WAGP,MAAMiB,EAAMC,KAAKuC,YACXC,EAAShE,SAASiE,cAAc,UAEtCD,EAAO7C,GAAKK,KAAKL,GACjB6C,EAAO3D,KAAO,kBACd2D,EAAOE,IAAM3C,EACbyC,EAAOG,QAAU3C,KAAK4C,kBAAkBC,KAAK7C,MAC7CwC,EAAOM,OAAS9C,KAAKlB,SAAS+D,KAAK7C,MACnCwC,EAAOO,OAAQ,EACfP,EAAOQ,OAAQ,EAEXhD,KAAKH,QACP2C,EAAO3C,MAAQG,KAAKH,OAGtBrB,SAASyE,KAAKC,YAAYV,EAC3B,CAEOI,kBACNxD,EACA+D,EACAC,EACAC,EACA3B,GAYA,GAVA1B,KAAKI,OAAOgB,KAAK,CACfhC,QACA+D,SAEAC,SAEAC,QACA3B,UAGE1B,KAAKI,OAAOyB,QAAU7B,KAAKF,QAAS,CACtC,MAAMwD,EAAQtD,KAAKI,OAAOyB,OAAS,GAAK7B,KAAKI,OAAOyB,OAEpDM,QAAQoB,qDAAqDD,SAE7DE,WAAW,KACTxD,KAAKkC,eACLlC,KAAKqC,WACN,EAAEiB,EACJ,MACCtD,KAAKK,aAAeL,KAAKI,OAAOJ,KAAKI,OAAOyB,OAAS,GACrD7B,KAAKlB,UAER,CAEMyD,YACL,IAAIxC,EAAMC,KAAKD,IASf,OARAA,GAAkB,WAAAC,KAAKN,SAEnBM,KAAKJ,UAAUiC,SACjB9B,GAAqB,cAAAC,KAAKJ,UAAU6D,KAAK,QAG3C1D,qBAEOA,CACR,CAEOmC,eACN,MAAMM,EAAShE,SAAS8D,eAAetC,KAAKL,IACxC6C,GACFA,EAAOkB,QAEV,CAEO5E,WACNI,MAAMC,KAAKmC,KAAK,KACdtB,KAAKE,MAAO,EACZF,KAAKG,SAAU,EAEfH,KAAKC,UAAU0D,QAASC,IACtBA,EAAG5D,KAAKK,aAAN,GAEJL,KAAKC,UAAY,GAEjBT,EAAO2B,mBAAmBwC,QAASC,IACjCA,EAAG5D,KAAKK,aACT,GACDb,EAAO2B,mBAAqB,EAC7B,EACF,CAE0BP,oBACzBiD,EACAC,GAEA,GAAID,EAAEnE,SAAWoE,EAAEpE,OAAQ,OAAO,EAClC,GAAImE,EAAElE,KAAOmE,EAAEnE,GAAI,OAAA,EAEnB,GAAIkE,EAAEjE,UAAUiC,SAAWiC,EAAElE,UAAUiC,OAAQ,OAAO,EACtD,IAAK,IAAIkC,EAAI,EAAGA,EAAIF,EAAEjE,UAAUiC,SAAUkC,EACxC,GAAIF,EAAEjE,UAAUmE,KAAOD,EAAElE,UAAUmE,GAAI,OACxC,EACD,OAAIF,EAAEhE,QAAUiE,EAAEjE,OACdgE,EAAE/D,UAAYgE,EAAEhE,SAChB+D,EAAE9D,MAAQ+D,EAAE/D,GAEjB,EAtQUP,EACIc,cADJd,EAAAA,EAEI2B,mBAAmD,mcCtDvD6C,EAAkBC,EAAMC,mBACnCjF,GAsNIkF,EAAoBF,EAAMG,WAC9B,CAqCEC,EAAAA,KACE,IArCF1E,GACEA,EADF2E,GAEEA,EAFFC,SAGEA,EAHFC,OAIEA,EAJFC,QAKEA,GAAU,EALZC,QAMEA,EAAU,GANZC,mBAOEA,EAPFC,uBAQEA,EARFC,UASEA,EATFC,SAUEA,EAVFC,kBAWEA,EAXFC,MAYEA,EAZFC,SAaEA,EAbFC,SAcEA,EAdFC,UAeEA,EAfFC,aAgBEA,EAhBFC,YAiBEA,EAjBFC,cAkBEA,EAlBFC,gBAmBEA,EAnBFC,gBAoBEA,EApBFC,QAqBEA,EArBFC,cAsBEA,EAtBFC,OAuBEA,EAvBFC,UAwBEA,EAxBFC,YAyBEA,EAzBFC,OA0BEA,EA1BFC,mBA2BEA,EA3BFC,YA4BEA,EA5BFC,aA6BEA,EA7BFC,aA8BEA,EA9BFC,cA+BEA,EA/BFC,YAgCEA,EAhCFC,SAiCEA,GACGC,EAAAA,EAILC,EAAAC,EAAAC,GAAA,MAAMC,EAAYpC,GAAM,OACjBqC,EAAUC,GAAeC,GAAS,IAClCC,EAAKC,GAAUF,IAChBG,EAAYC,EAAuB,MA4IzC,OA1IA3I,EAA0B,KACxBkB,EAAOmH,WAAWO,KAAKN,EAAvB,EACC,IAEHtI,EAA0B,KACxB,IAAKqI,EAAU,OAEf,MAAMQ,EAAeH,EAAUI,QAE/B,IAAKD,EACH,OAGF,MAAME,EACJ,QAAS7C,EACL,IAAItF,MAAMC,KAAKmI,OAAO9C,EAAO+C,IAAK/C,EAAOgD,KACzC,IAAItI,MAAMC,KAAKsI,OAAOjD,EAAOkD,EAAGlD,EAAOmD,GAEvCC,EAAW,IAAI1I,MAAMC,KAAKgF,IAAIgD,EAAc,CAChD3C,OAAQ6C,EACR1C,mBAAoBA,EACpBC,uBAAwBA,EACxBC,UAAWA,EACXE,kBAAmBA,EACnBC,MAAOA,EACPG,UAAWA,EACXC,aAAcA,EACdC,YAAaA,EACbC,cAAeA,IAKjB,OAFAyB,EAAOa,GAEA,KACLT,EAAaU,UAAY,EAC1B,CAAA,EACA,CACDlB,EACAhC,EACAC,EACAO,EACAG,IAGFwC,EAAoBzD,EAAK,IAAMyC,EAAM,CAACA,IAEtCxI,EAA0B,KACnBwI,GAAQT,GACbA,EAASS,EAAD,EACP,CAACA,EAAKT,IAGT/H,EAA0B,KACxB,IAAKwI,EAAK,OAEV,IAAIiB,EAAajB,EAAIkB,YACjBD,aAAsB7I,MAAMC,KAAKsI,SACnCM,EAAaA,EAAWE,YAG1B,MAAMC,EACJ,QAAS1D,EACL,IAAItF,MAAMC,KAAKmI,OAAO9C,EAAO+C,IAAK/C,EAAOgD,KACzC,IAAItI,MAAMC,KAAKsI,OAAOjD,EAAOkD,EAAGlD,EAAOmD,GAG1CO,aAA0BhJ,MAAMC,KAAKmI,QACpCY,EAAeC,OAAOJ,IACvBG,aAA0BhJ,MAAMC,KAAKsI,QACpCS,EAAeD,WAAWE,OAAOJ,KAKjCtD,EACFqC,EAAIsB,MAAMF,EAAgBxD,GAE1BoC,EAAIuB,UAAUH,GACf,EAEA,CAACpB,EAAKtC,EAAO+C,IAAK/C,EAAOgD,IAAKhD,EAAOkD,EAAGlD,EAAOmD,IAElDrJ,EAA0B,KACnBwI,QAA4B,IAAdjC,GACnBiC,EAAIwB,aAAazD,EAAjB,EACC,CAACiC,EAAKjC,IAETvG,EAA0B,KACnBwI,QAA2B,IAAbhC,GACnBgC,EAAIyB,YAAYzD,EAAhB,EACC,CAACgC,EAAKhC,IAETxG,EAA0B,KACnBwI,GAAQ/B,GAAkD,kBAAtBA,GAEzC+B,EAAI0B,qBAAqBzD,EAAzB,EACC,CAAC+B,EAAK/B,IAETzG,EAA0B,KACnBwI,GAAQ9B,GACb8B,EAAI2B,SAASzD,EAAb,EACC,CAAC8B,EAAK9B,IAET1G,EAA0B,KACnBwI,GAAQ3B,GACb2B,EAAI4B,aAAavD,EAAjB,EACC,CAAC2B,EAAK3B,IAET7G,EAA0B,KACnBwI,GAAQ1B,GACb0B,EAAI6B,gBAAgBvD,EACrB,EAAE,CAAC0B,EAAK1B,IAET9G,EAA0B,KACnBwI,GAAQ7B,GACb6B,EAAI8B,YAAY3D,EAAhB,EACC,CAAC6B,EAAK7B,IAET3G,EAA0B,KACnBwI,GAAQ5B,GACb4B,EAAI+B,YAAY3D,EAAhB,EACC,CAAC4B,EAAK5B,IAETvG,EAAcmI,EAAK,iBAAkBvB,GACrC5G,EAAcmI,EAAK,iBAAkBtB,GACrC7G,EAAcmI,EAAK,QAASrB,GAC5B9G,EAAcmI,EAAK,WAAYpB,GAC/B/G,EAAcmI,EAAK,OAAQnB,GAC3BhH,EAAcmI,EAAK,YAAajB,GAChClH,EAAcmI,EAAK,UAAWlB,GAC9BjH,EAAcmI,EAAK,OAAQhB,GAC3BnH,EAAcmI,EAAK,oBAAqBf,GACxCpH,EAAcmI,EAAK,YAAad,GAChCrH,EAAcmI,EAAK,aAAcb,GACjCtH,EAAcmI,EAAK,cAAeZ,GAClCvH,EAAcmI,EAAK,eAAgBX,GACnCxH,EAAcmI,EAAK,aAAcV,GAG/BnC,EAAAxB,cAAAwB,EAAA6E,SAAA,KACE7E,EAAAxB,cAACiE,EACC/G,EAAAA,CAAAA,GAAIA,GAAM,sCACN2G,EACJjC,CAAAA,IAAK2C,KAENF,GACC7C,EAAAxB,cAACuB,EAAgB+E,SAAS,CAAAC,MAAOlC,GAC9BvC,GARP,GC9YA0E,EAAUC,IACd,MAAMtB,EAAWuB,EAAWnF,GAC5B,IAAK4D,EACH,MAAUnH,IAAAA,OAENyI,EAAgBA,EAAgB,aAAe,UAA/C,qCAKN,OAAOtB,GC2BHwB,EAAanF,EAAMG,WAIvB,EAEI0C,MACAuC,WACAC,SACA/E,WACAgF,WACAC,iBACAC,QACAC,YACAC,SACAtD,YAEFhC,KAEA,MAAM2C,EAAYC,EAAOzI,SAASiE,cAAc,QAE1CmH,EAAaC,EAAQ,KACzB,MAAMC,EAAkB,IAAI5K,MAAMC,KAAKiK,WAAW,CAChDG,SAAUA,EACVC,eAAgBA,EAChBC,MAAOA,EACPC,UAAWA,EACXC,OAAQA,EACRI,QAAS/C,EAAUI,QACnBiC,SAAUA,IAGZ,OADArC,EAAUI,QAAQ4C,MAAMC,QAAU,OAC3BH,GAEN,CAACN,EAAgBE,IAoCpB,OAlCA5B,EAAoBzD,EAAK,IAAMuF,EAAY,CAACA,IAE5CnL,EAAgB,KACdmL,EAAWM,KAAKpD,EAAKwC,GACd,KACLM,EAAWO,OAAX,GAGD,CAACrD,EAAKwC,IAET7K,EAAgB,KACV4H,GAAUA,EAASuD,EACxB,EAAE,CAACA,EAAYvD,IAEhB5H,EAAgB,KACTmL,GACLA,EAAWQ,YAAYf,EAAvB,EACC,CAACO,EAAYP,IAEhB5K,EAAgB,KACTmL,GAAeL,GACpBK,EAAWS,YAAYd,EAAvB,EACC,CAACK,EAAYL,IAEhB9K,EAAgB,KACTmL,GAAeH,GACpBG,EAAWU,SAASb,EAApB,EACC,CAACG,EAAYH,IAEhBhL,EAAgB,KACTmL,GAAeD,GACpBC,EAAWW,UAAUZ,EACtB,EAAE,CAACC,EAAYD,IAGd3C,EAAUI,QAAQoD,eAClBC,EAASC,aAAanG,EAAUyC,EAAUI,QAAQoD,cAAlD,GChHOG,EACX1G,EAAMC,mBACJjF,GAgHE2L,EAAkB3G,EAAMG,WAI5B,EAEIG,WACAsG,gBACAC,aACAC,YACAC,mBACAC,WACAC,YACAC,iBACAjG,WACAkG,SACAC,QACAC,iBACAC,oBACAC,cACAC,eACAC,gBACAC,sBACAtF,YAEFhC,KAEA,MAAMyC,EAAMmC,EAAO,mBACb2C,EAAgB/B,EAAQ,KAC5B,GAAKtL,OAAOW,MAAMC,KAAKyL,gBAMvB,OAAW1L,IAAAA,MAAMC,KAAKyL,gBAAgB,CACpCC,gBACAC,aACAC,YACAC,mBACAC,WACAC,YACAC,iBACAjG,WACAkG,SACAC,UAfAlJ,QAAQC,KACN,0FAIG,EAaN,IAoEH,OAlEA0F,EAAoBzD,EAAK,IAAMuH,EAAgB,CAACA,IAEhDnN,EAAgB,KACD,MAAbmN,GAAAA,EAAe7E,OAAOD,EACvB,EAAE,CAACA,EAAK8E,IAETnN,EAAgB,KACVmN,GAAiBvF,GAAUA,EAASuF,EACzC,EAAE,CAACA,EAAevF,IAEnB5H,EAAgB,KACVmN,GAAiBX,IACnBW,EAAcC,YAAYZ,GAC1BW,EAAcE,SACf,EACA,CAACF,EAAeX,IAEnBxM,EAAgB,KACVmN,GAAiBT,IACnBS,EAAcG,kBAAkBZ,GAChCS,EAAcE,SACf,EACA,CAACF,EAAeT,IAEnB1M,EAAgB,KACVmN,QAA0C,IAAlBf,IAC1Be,EAAcI,iBAAiBnB,GAC/Be,EAAcE,SACf,EACA,CAACF,EAAef,IAEnBpM,EAAgB,KACVmN,GAAiB1G,IACnB0G,EAAc/C,YAAY3D,GAC1B0G,EAAcE,SACf,EACA,CAACF,EAAe1G,IAEnBzG,EAAgB,KACVmN,GAAiBP,IACnBO,EAAcK,SAASZ,GACvBO,EAAcE,SACf,EACA,CAACF,EAAeP,IAEnB5M,EAAgB,KACVmN,GAAiBd,IACnBc,EAAcM,cAAcpB,GAC5Bc,EAAcE,SACf,EACA,CAACF,EAAed,IAEnBrM,EAAgB,KACVmN,GAAiBR,IACnBQ,EAAcO,UAAUf,GACxBQ,EAAcE,SACf,EACA,CAACF,EAAeR,IAEnBzM,EAAciN,EAAe,eAAgBN,GAC7C3M,EAAciN,EAAe,cAAeF,GAC5C/M,EAAciN,EAAe,aAAcH,GAC3C9M,EAAciN,EAAe,kBAAmBL,GAChD5M,EAAciN,EAAe,oBAAqBD,GAClDhN,EAAciN,EAAe,YAAaJ,GAErCI,EAKH3H,EAAAxB,cAACkI,EAA+B5B,SAAQ,CAACC,MAAO4C,GAC7CrH,GAJJ,IAGC,GC5HA6H,EAASnI,EAAMG,WAInB,EAEI0C,MACAuC,WACA9E,WACAgF,WACAwB,YACAlG,YACAwH,QACAC,oBACAjG,WACAZ,UACAG,YACAC,cACA0G,aACAC,cACAC,UACAhD,QACAiD,QACA/C,UAEFtF,KAEA,MAAMuH,EAAgBzC,EAAWwB,GAG3BrB,EAASO,EAAQ,IACD,IAAI3K,MAAMC,KAAKiN,OAAO,CACxC7C,WACAwB,YACAlG,YACAwH,QACAI,UACAhD,QACAiD,QACA/C,SACAN,aAKD,IA6FH,OA3FAvB,EAAoBzD,EAAK,IAAMiF,EAAQ,CAACA,IAExC7K,EAAgB,KACVmN,EACFA,EAAce,UAAUrD,GAExBA,EAAOvC,OAAOD,GAGT,KACD8E,EACFA,EAAcgB,aAAatD,GAE3BA,EAAOvC,OAAO,KACf,GAEF,CAACD,EAAK8E,EAAetC,IAExB7K,EAAgB,KACV4H,GAAUA,EAASiD,EACxB,EAAE,CAACA,EAAQjD,IAEZ1H,EAAc2K,EAAQ,QAAS7D,GAC/B9G,EAAc2K,EAAQ,YAAazD,GACnClH,EAAc2K,EAAQ,UAAW1D,GACjCjH,EAAc2K,EAAQ,WAAYiD,GAClC5N,EAAc2K,EAAQ,YAAakD,GAGnC/N,EAAgB,KACTqI,GAAQwC,GAAWD,GAExBC,EAAOc,YAAYf,EACpB,EAAE,CAACvC,EAAKwC,EAAQD,IAGjB5K,EAAgB,KACTqI,GAAQwC,GAAW+C,GAExB/C,EAAOuD,SAASR,IACf,CAACvF,EAAKwC,EAAQ+C,IAGjB5N,EAAgB,KACTqI,GAAQwC,GAAWC,GAExBD,EAAOe,YAAYd,EACpB,EAAE,CAACzC,EAAKwC,EAAQC,IAGjB9K,EAAgB,KACTqI,GAAQwC,QAA+B,IAAdyB,GAE9BzB,EAAOwD,aAAa/B,EACrB,EAAE,CAACjE,EAAKwC,EAAQyB,IAGjBtM,EAAgB,KACTqI,GAAQwC,QAA+B,IAAdzE,GAE9ByE,EAAOhB,aAAazD,EAApB,EACC,CAACiC,EAAKwC,EAAQzE,IAGjBpG,EAAgB,KACTqI,GAAQwC,GAAWmD,GAExBnD,EAAOyD,WAAWN,IACjB,CAAC3F,EAAKwC,EAAQmD,IAGjBhO,EAAgB,KACTqI,GAAQwC,GAAWG,GAExBH,EAAOgB,SAASb,EAAhB,EACC,CAAC3C,EAAKwC,EAAQG,IAGjBhL,EAAgB,KACTqI,GAAQwC,GAAWoD,GAExBpD,EAAO0D,SAASN,IACf,CAAC5F,EAAKwC,EAAQoD,IAGjBjO,EAAgB,KACTqI,GAAQwC,GAAWK,GAExBL,EAAOiB,UAAUZ,EAClB,EAAE,CAAC7C,EAAKwC,EAAQK,IAEbpF,EAEAN,gBAACmF,EAAU,CACTC,SAAUA,EACVvC,IAAKA,EACLwC,OAAQA,EACRC,SAAQ,MAAE+C,OAAF,EAAEA,EAAmB/C,SAC7BC,eAAc,MAAE8C,OAAF,EAAEA,EAAmB9C,eACnCC,YAAO6C,SAAAA,EAAmB7C,MAC1BC,UAAW4C,MAAAA,OAAAA,EAAAA,EAAmB5C,UAC9BC,OAAQ2C,MAAAA,OAAAA,EAAAA,EAAmB3C,QAE1BpF,GAKR,OC7HG0I,EAAYhJ,EAAMG,WAItB,EAEIiI,QACAhD,WACA9E,WACAwG,YACAlG,YACAyH,oBACA7G,UACAG,YACAC,cACA0G,aACAC,cACAnG,WACAoG,UACAC,QACA/C,UAEFtF,KAEA,MAAMyC,EAAMmC,EAAO,aAEbiE,EAAcrD,EAAQ,iCAC1B,OACEwC,GACA,IAAInN,MAAMC,KAAKgO,YACbd,EAAM3J,IACN,IAAIxD,MAAMC,KAAKiO,KAAKf,EAAMgB,KAAKC,MAAOjB,EAAMgB,KAAKE,QACjD,CACEC,IAAG,OAAEnB,EAAAA,EAAM7L,cAAR,EAAEiN,EAAeD,IACpBE,OAAQ,SAAArB,EAAM7L,cAAN,EAAAmN,EAAeD,OACvBE,QACiBA,OAAfC,EAAAxB,EAAM7L,cAASoN,EAAAA,EAAAA,SACf,IAAI1O,MAAMC,KAAK2O,MAAf,OACEzB,EAAAA,EAAM7L,cADR,EACEuN,EAAeH,OAAOlG,EACtB,OAAA2E,EAAAA,EAAM7L,cAAN,EAAAwN,EAAeJ,OAAOjG,GAE1BsG,MAAK,SAAE5B,EAAM7L,cAAR,EAAE0N,EAAeD,MACtBE,cACiBA,SAAf9B,EAAM7L,cAAS2N,EAAAA,EAAAA,eACf,IAAIjP,MAAMC,KAAK2O,MACb,OADFM,EACE/B,EAAM7L,cAAN,EAAA4N,EAAeD,aAAazG,SAD9B2G,EAEEhC,EAAM7L,gBAAN6N,EAAeF,aAAaxG,GAEhC2G,mBACEC,EAAAlC,EAAM7L,kBAAS8N,aACf,IAAIpP,MAAMC,KAAKiO,KACb,SAAAf,EAAM7L,cAAN,EAAAgO,EAAeF,WAAWhB,aAC1BjB,EAAAA,EAAM7L,gBAANiO,EAAeH,WAAWf,SAvBlC,EA4BD,CAAClB,IAEEqC,EAAiB7E,EAAQ,IACzB,QAASR,EACAnK,IAAAA,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,KAE3CtI,IAAAA,MAAMC,KAAKsI,OAAO4B,EAAS3B,EAAG2B,EAAS1B,GAAGM,WAIpD,CAACoB,EAAS9B,IAAK8B,EAAS7B,IAAK6B,EAAS3B,EAAG2B,EAAS1B,IAErD,OACE1D,EAAAxB,cAAC2J,EAAM,CACLtF,IAAKA,EACLuC,SAAUqF,EACVrC,MAAOa,EACPnC,UAAWA,EACXlG,UAAWA,EACXyH,kBAAmBA,EACnB7G,QAASA,EACTG,UAAWA,EACXC,YAAaA,EACb0G,WAAYA,EACZC,YAAaA,EACbnG,SAAUA,EACVoG,QAASA,EACTC,MAAOA,EACP/C,OAAQA,EACRtF,IAAKA,GAEJE,EAlBH,GCnKAoK,EAAgB1K,EAAMG,WAI1B,EACIiF,WAAU9E,WAAUiF,iBAAgBE,YAAWC,SAAQtD,YACzDhC,KAEA,MAAMyC,EAAMmC,EAAO,iBACb2F,EAAe/E,EAAQ,IAChB3K,IAAAA,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,KACnD,CAAC6B,EAAS9B,IAAK8B,EAAS7B,MAE3B,OACEvD,EAAAxB,cAAC2G,EAAU,CACTI,eAAgBA,EAChBE,UAAWA,EACXC,OAAQA,EACR7C,IAAKA,EACLuC,SAAUuF,EACVvI,SAAUA,EACVhC,IAAKA,GAEJE,EATH,GCjBAsK,EAAmB5K,EAAMG,WAI7B,EACIiF,WAAU9E,WAAUwG,YAAW+D,UAASC,UAASpF,SAAQtD,YAC3DhC,KAEA,MAAMuH,EAAgBzC,EAAWwB,GAE3B7D,EAAMmC,EAAO,oBACbjC,EAAYC,EAAOzI,SAASiE,cAAc,QAE1CuM,EAAkBnF,EAAQ,QACnB3K,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,KACnD,CAAC6B,EAAS9B,IAAK8B,EAAS7B,MAErByH,EAAUpF,EAAQ,KACtB,MAAMqF,EAAqB,IAAIhQ,MAAMC,KAAKgQ,cAAc,CACtDpE,UAAWA,EACX+D,QAASA,EACTC,QAASA,EACTpF,OAAQA,EACRN,SAAU2F,EACVjF,QAAS/C,EAAUI,UAIrB,OAFAJ,EAAUI,QAAQ4C,MAAMC,QAAU,OAE3BiF,GAEN,CAACnE,EAAW+D,EAASC,IAmCxB,OAjCAjH,EAAoBzD,EAAK,IAAM4K,EAAS,CAACA,IAEzCxQ,EAAgB,KACd,GAAKqI,EAQL,OANI8E,EACFA,EAAce,UAAUsC,GAExBA,EAAQlI,OAAOD,GAGV,KACD8E,EACFA,EAAcgB,aAAaqC,GAE3BA,EAAQlI,OAAO,KAChB,CACF,EACA,CAACD,EAAK8E,EAAeqD,IAExBxQ,EAAgB,KACV4H,GAAUA,EAAS4I,IACtB,CAACA,EAAS5I,IAEb5H,EAAgB,KACdwQ,EAAQ7E,YAAY4E,EAApB,EACC,CAACC,EAASD,IAEbvQ,EAAgB,KACTkL,GACLsF,EAAQ1E,UAAUZ,EACnB,EAAE,CAACsF,EAAStF,IAGX3C,EAAUI,QAAQoD,eAClB4E,EAAS1E,aAAanG,EAAUyC,EAAUI,QAAQoD,cAAlD,GCtGA6E,EAAiBpL,EAAMG,WAG3B,EAAGiF,SAAAA,EAAWnK,MAAMC,KAAKmQ,gBAAgBC,UAAYlL,KACrD,MAAMyC,EAAMmC,EAAO,kBAEbuG,EAAiB3F,EAAQ,IACtB,IAAI3K,MAAMC,KAAKkQ,eACrB,IAYH,OAVAvH,EAAoBzD,EAAK,IAAMmL,EAAgB,CAACA,IAEhD/Q,EAAgB,KACdqI,EAAI2I,WAAWD,EAAgBnG,GAExB,KACLvC,EAAI4I,cAAcF,EAAlB,GAED,CAAC1I,EAAK0I,EAAgBnG,IAElB,OCrBHsG,EAAc1L,EAAMG,WACxB,EAAGiF,SAAAA,EAAWnK,MAAMC,KAAKmQ,gBAAgBM,OAASvL,KAChD,MAAMyC,EAAMmC,EAAO,eAEb0G,EAAc9F,EAAQ,IACf3K,IAAAA,MAAMC,KAAKwQ,YACrB,IAcH,OAZA7H,EAAoBzD,EAAK,IAAMsL,EAAa,CAACA,IAE7CjR,EAAU,KACRoI,EAAI2I,WAAWE,EAAatG,GAErB,KACLvC,EAAI4I,cAAcC,EACnB,GAGA,CAAC7I,EAAKuC,IAGV,OCrBGwG,EAAsC,EAAGhR,WAC7C,MAAMiI,EAAMmC,EAAO,aAUnB,OARAvK,EAAU,KACRoI,EAAIgJ,oBAAoBjR,GAEjB,KACLiI,EAAIiJ,uBAAuBlR,KAE5B,CAACiI,EAAKjI,IAGV,MCkEKmR,EAAS/L,EAAMG,WACnB,EAEII,SACAyL,SACAC,YACAC,cACAC,cACAC,gBACAC,cACAC,eACA5G,SACA6G,cACAC,aACAC,cACAC,cACAlL,UACAY,YAEFhC,KAEA,MAAMyC,EAAMmC,EAAO,UAEb2H,EAAe/G,EAAQ,IAChB3K,IAAAA,MAAMC,KAAKmI,OAAO9C,EAAO+C,IAAK/C,EAAOgD,KAC/C,CAAChD,EAAO+C,IAAK/C,EAAOgD,MAEjBqJ,EAAShH,EAAQ,IACV3K,IAAAA,MAAMC,KAAK6Q,OAAO,CAC3BxL,OAAQoM,EACRX,SACAC,YACAC,cACAC,cACAC,gBACAC,cACAC,eACA5G,WAGD,IAqDH,OAnDA7B,EAAoBzD,EAAK,IAAMwM,EAAQ,CAACA,IAExCpS,EAAgB,KACdoS,EAAO9J,OAAOD,GACP,KACL+J,EAAO9J,OAAO,KACf,GACA,CAACD,EAAK+J,IAETpS,EAAgB,KACV4H,GAAUA,EAASwK,EACxB,EAAE,CAACA,EAAQxK,IAEZ5H,EAAgB,KACVoS,GAAQA,EAAOzG,YAAYwG,EAChC,EAAE,CAACC,EAAQD,IAEZnS,EAAgB,KACdoS,EAAOC,UAAUb,IAChB,CAACY,EAAQZ,IAEZxR,EAAgB,KACTkL,GACLkH,EAAOtG,UAAUZ,EAAjB,EACC,CAACkH,EAAQlH,IAEZlL,EAAgB,KACdoS,EAAOE,WAAW,CAChBb,YACAC,cACAC,cACAC,gBACAC,cACAC,kBAED,CACDM,EACAX,EACAC,EACAC,EACAC,EACAC,EACAC,IAGF5R,EAAckS,EAAQ,YAAaL,GACnC7R,EAAckS,EAAQ,WAAYJ,GAClC9R,EAAckS,EAAQ,YAAaH,GACnC/R,EAAckS,EAAQ,YAAaF,GACnChS,EAAckS,EAAQ,QAASpL,GAGhC,OCzGGuL,EAAW/M,EAAMG,WACrB,EAEI6M,OACAC,WACAzL,UACAkL,cACAD,cACAD,aACAD,cACAnK,WACA+J,cACAC,gBACAC,cACAC,eACA5G,UAEFtF,KAEA,MAAMyC,EAAMmC,EAAO,YAEbkI,EAAetH,EAAQ,IACtBoH,EAAkBG,MAAOC,GAAMA,aAAaC,OACvCL,EAAoBnK,IAAKuK,GACxBA,EAAEvK,IAAKyK,GAAM,IAAIrS,MAAMC,KAAKmI,OAAOiK,EAAEhK,IAAKgK,EAAE/J,OAG/CyJ,EAAkBnK,IAAKuK,GAClBnS,IAAAA,MAAMC,KAAKmI,OAAO+J,EAAE9J,IAAK8J,EAAE7J,MAEvC,CAACyJ,IAEEO,EAAW3H,EAAQ,QACZ3K,MAAMC,KAAK6R,SAAS,CAC7BC,KAAME,EACND,WACAd,cACAC,gBACAC,cACAC,eACA5G,WAGD,IA4CH,OA1CA7B,EAAoBzD,EAAK,IAAMmN,EAAU,CAACA,IAE1C/S,EAAgB,KACd+S,EAASzK,OAAOD,GACT,IAAM0K,EAASzK,OAAO,OAC5B,CAACD,EAAK0K,IAET/S,EAAgB,KACV4H,GAAUA,EAASmL,EAAD,EACrB,CAACA,EAAUnL,IAEd5H,EAAgB,KACd+S,EAAST,WAAW,CAClBG,WACAd,cACAC,gBACAC,cACAC,gBAEH,EAAE,CACDiB,EACAN,EACAd,EACAC,EACAC,EACAC,IAGF9R,EAAgB,KACd+S,EAASC,QAAQN,EAAjB,EACC,CAACK,EAAUL,IAEd1S,EAAgB,KACVkL,GAAQ6H,EAASjH,UAAUZ,EAAnB,EACX,CAAC6H,EAAU7H,IAEdhL,EAAc6S,EAAU,YAAahB,GACrC7R,EAAc6S,EAAU,WAAYf,GACpC9R,EAAc6S,EAAU,YAAad,GACrC/R,EAAc6S,EAAU,YAAab,GACrChS,EAAc6S,EAAU,QAAS/L,GAE1B,OCnFLiM,EAAUzN,EAAMG,WACpB,EAEI6M,OACAxL,UACAkL,cACAD,cACAD,aACAD,cACAnK,WACA+J,cACAC,gBACAC,cACAC,eACAL,YACAC,cACAxG,UAEFtF,KAEA,MAAMyC,EAAMmC,EAAO,WAEb0I,EAAc9H,EAAQ,IACrBoH,EAAkBG,MAAOC,GAAMA,aAAaC,OACvCL,EAAoBnK,IAAKuK,GACxBA,EAAEvK,IAAKyK,GAAM,IAAIrS,MAAMC,KAAKmI,OAAOiK,EAAEhK,IAAKgK,EAAE/J,OAG/CyJ,EAAkBnK,IAAKuK,OAClBnS,MAAMC,KAAKmI,OAAO+J,EAAE9J,IAAK8J,EAAE7J,MAEvC,CAACyJ,IAEEW,EAAU/H,EAAQ,IACf,IAAI3K,MAAMC,KAAKuS,QAAQ,CAC5BT,KAAMU,EACNzB,YACAC,cACAC,cACAC,gBACAC,cACAC,eACA5G,WAGD,IA8CH,OA5CA7B,EAAoBzD,EAAK,IAAMuN,EAAS,CAACA,IAEzCnT,EAAgB,KACdmT,EAAQ7K,OAAOD,GACR,IAAM8K,EAAQ7K,OAAO,OAC3B,CAACD,EAAK8K,IAETnT,EAAgB,KACV4H,GAAUA,EAASuL,EACxB,EAAE,CAACA,EAASvL,IAEb5H,EAAgB,KACdmT,EAAQb,WAAW,CACjBb,YACAC,cACAC,cACAC,gBACAC,cACAC,gBAEH,EAAE,CACDqB,EACA1B,EACAC,EACAC,EACAC,EACAC,EACAC,IAGF9R,EAAgB,KACdmT,EAAQH,QAAQE,EACjB,EAAE,CAACC,EAASD,IAEblT,EAAgB,KACVkL,GAAQiI,EAAQrH,UAAUZ,IAC7B,CAACiI,EAASjI,IAEbhL,EAAciT,EAAS,YAAapB,GACpC7R,EAAciT,EAAS,WAAYnB,GACnC9R,EAAciT,EAAS,YAAalB,GACpC/R,EAAciT,EAAS,YAAajB,GACpChS,EAAciT,EAAS,QAASnM,GAEzB,OCxFLoM,EAAY5N,EAAMG,WACtB,EAEI0N,SACArM,UACAkL,cACAD,cACAD,aACAD,cACAnK,WACA+J,cACAC,gBACAC,cACAC,eACAL,YACAC,cACAxG,UAEFtF,KAEA,MAAMyC,EAAMmC,EAAO,aAEb8I,EAAkBlI,EAAQ,QACnB3K,MAAMC,KAAK6S,aACpB,IAAI9S,MAAMC,KAAKmI,OAAOwK,EAAOG,GAAG1K,IAAKuK,EAAOG,GAAGzK,KAC/C,IAAItI,MAAMC,KAAKmI,OAAOwK,EAAOI,GAAG3K,IAAKuK,EAAOI,GAAG1K,MAEhD,CAACsK,IAEEK,EAAYtI,EAAQ,IACb3K,IAAAA,MAAMC,KAAK0S,UAAU,CAC9BC,OAAQC,EACR7B,YACAC,cACAC,cACAC,gBACAC,cACAC,eACA5G,WAGD,IA8CH,OA5CA7B,EAAoBzD,EAAK,IAAM8N,EAAW,CAACA,IAE3C1T,EAAgB,KACd0T,EAAUpL,OAAOD,GACV,IAAMqL,EAAUpL,OAAO,OAC7B,CAACD,EAAKqL,IAET1T,EAAgB,KACV4H,GAAUA,EAAS8L,EACxB,EAAE,CAACA,EAAW9L,IAEf5H,EAAgB,KACd0T,EAAUpB,WAAW,CACnBb,YACAC,cACAC,cACAC,gBACAC,cACAC,gBANF,EAQC,CACD4B,EACAjC,EACAC,EACAC,EACAC,EACAC,EACAC,IAGF9R,EAAgB,KACd0T,EAAUC,UAAUL,EAApB,EACC,CAACI,EAAWJ,IAEftT,EAAgB,KACVkL,GAAQwI,EAAU5H,UAAUZ,EAApB,EACX,CAACwI,EAAWxI,IAEfhL,EAAcwT,EAAW,YAAa3B,GACtC7R,EAAcwT,EAAW,WAAY1B,GACrC9R,EAAcwT,EAAW,YAAazB,GACtC/R,EAAcwT,EAAW,YAAaxB,GACtChS,EAAcwT,EAAW,QAAS1M,GAGnC,OCzEG4M,EAAUpO,EAAMG,WACpB,EAEII,SACA8N,KACAC,KACArC,YACAC,cACAC,cACAC,gBACAC,cACAC,eACA5G,SACA6G,cACAC,aACAC,cACAC,cACAlL,UACAY,YAEFhC,KAEA,MAAMyC,EAAMmC,EAAO,WAEbuJ,EAAgB3I,EAAQ,IACrB,IAAI3K,MAAMC,KAAKmI,OAAO9C,EAAO+C,IAAK/C,EAAOgD,KAC/C,CAAChD,EAAO+C,IAAK/C,EAAOgD,MAEjBiL,EAAU5I,EAAQ,QACX3K,MAAMC,KAAKkT,QAAQ,CAC5B7N,OAAQgO,EACRF,KACAC,KACArC,YACAC,cACAC,cACAC,gBACAC,cACAC,eACA5G,WAGD,IAsDH,OApDA7B,EAAoBzD,EAAK,IAAMoO,EAAS,CAACA,IAEzChU,EAAgB,KACdgU,EAAQ1L,OAAOD,GAER,KACL2L,EAAQ1L,OAAO,KAChB,GACA,CAACD,EAAK2L,IAEThU,EAAgB,KACV4H,GAAUA,EAASoM,EAAD,EACrB,CAACA,EAASpM,IAEb5H,EAAgB,KACVgU,GAASA,EAAQrI,YAAYoI,EAApB,EACZ,CAACC,EAASD,IAEb/T,EAAgB,KACdgU,EAAQ3B,UAAUwB,EAAIC,EACvB,EAAE,CAACE,EAASH,EAAIC,IAEjB9T,EAAgB,KACTkL,GACL8I,EAAQlI,UAAUZ,EAAlB,EACC,CAAC8I,EAAS9I,IAEblL,EAAgB,KACdgU,EAAQ1B,WAAW,CACjBb,YACAC,cACAC,cACAC,gBACAC,cACAC,gBANF,EAQC,CACDkC,EACAvC,EACAC,EACAC,EACAC,EACAC,EACAC,IAGF5R,EAAc8T,EAAS,YAAajC,GACpC7R,EAAc8T,EAAS,WAAYhC,GACnC9R,EAAc8T,EAAS,YAAa/B,GACpC/R,EAAc8T,EAAS,YAAa9B,GACpChS,EAAc8T,EAAS,QAAShN,GAEzB,OCjDLiN,EAAkBzO,EAAMG,WAG5B,EAAGuO,OAAMC,QAAOC,WAAUxM,YAAYhC,KACtC,MAAMyC,EAAMmC,IAEN6J,EAAuBjJ,EAAQ,KACnC,MAAMkJ,UAA6B7T,MAAMC,KAAKuT,gBAC5CjT,YAAYkT,EAAkBC,EAAmBC,GAC/CG,QACAhT,KAAK2S,KAAOA,EACZ3S,KAAK4S,MAAQA,EACb5S,KAAK6S,SAAWA,CACjB,EAGH,OADgB,IAAIE,EAAqBJ,EAAMC,EAAOC,EAC/C5D,EACN,CAAC0D,EAAMC,EAAOC,IAgBjB,OAdA/K,EAAoBzD,EAAK,IAAMyO,EAAsB,CAACA,IAEtDrU,EAAgB,KACdqU,EAAqB/L,OAAOD,GAErB,KACLgM,EAAqB/L,OAAO,QAE7B,CAACD,EAAKgM,IAETrU,EAAgB,KACV4H,GAAUA,EAASyM,IACtB,CAACA,EAAsBzM,IAG3B,OCvLDI,EAAA,CAAA,KAAA,KAAA,WAAA,WAAA,MAAA,SAAA,QAAA,QAAA,OAAA,OAAA,WAAA,SAAA,iBAAA,oBAAA,oBAAA,2BASawM,EAAuBhP,EAAMC,mBACxCjF,GAsFIiU,EAA8BjP,EAAMG,WACxC,CAAAoC,EAoBEnC,SAnBA1E,GACEA,EADF2E,GAEEA,EAFFC,SAGEA,EAHF8E,SAIEA,EAJF8J,IAKEA,EALFC,OAMEA,EANFC,MAOEA,EAPFC,MAQEA,EARFC,KASEA,EATFC,KAUEA,EAVFnN,SAWEA,EAXFoN,OAYEA,EAZFC,eAaEA,EAbFC,kBAcEA,EAdFC,kBAeEA,EAfFC,wBAgBEA,GAIArN,EAHGF,EAGHC,EAAAC,EAAAC,GACF,MAAMC,EAAYpC,GAAM,OACjBqC,EAAUC,GAAeC,GAAS,IAClCiN,EAAWC,GAAgBlN,GAAS,IACpCmN,EAAUC,GAAepN,IAC1BG,EAAYC,EAAuB,MAsGzC,OApGA3I,EAA0B,KACxBkB,EAAOmH,WAAWO,KAAKN,EACxB,EAAE,IAEHtI,EAA0B,KACxB,IAAKqI,EAAU,OAEf,MAAMuN,EAAoBlN,EAAUI,QAEpC,IAAK8M,EAAmB,OAExB,MAAMC,EAAgB,IAAIjV,MAAMC,KAAK+T,SAASgB,EAAmB,CAC/Df,IAAKA,EACLC,OAAQA,EACRC,MAAOA,EACPC,MAAOA,EACPC,KAAMA,EACNC,KAAMA,IAKR,OAFAS,EAAYE,GAEL,KACLD,EAAkBrM,UAAY,GAC/B,EAEA,CAAClB,EAAU0M,EAAOC,EAAOE,IAE5B1L,EAAoBzD,EAAK,IAAM2P,EAAW,CAACA,IAE3C1V,EAA0B,KACnB0V,GAAa3N,GAClBA,EAAS2N,EAAD,EACP,CAACA,EAAU3N,IAEd/H,EAA0B,KACxB,IACG0V,GACDZ,GACCY,EAASI,cAAcC,WAAahL,EAAS9B,KAC5CyM,EAASI,cAAcE,WAAajL,EAAS7B,IAE/C,OAEF,MAAM+M,EAAa,IAAIrV,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,MAEhE,IAAItI,MAAMC,KAAKqV,gBAAiBC,iBAC9BF,EACAlL,EAAS4G,OACRmD,IACgB,OAAXA,GAAmBS,EACrBA,EAAwBG,GAExBA,EAASU,UAAUtB,EAAQmB,EAC5B,EAGN,EAAE,CACDP,EACAZ,EACA/J,EAAS9B,IACT8B,EAAS7B,IACT6B,EAAS4G,OACT4D,IAGFvV,EAA0B,KACxB,IACG0V,IACAZ,GACDA,IAAWY,EAASW,aACnBX,EAASI,cAAcC,WAAahL,EAAS9B,KAC5CyM,EAASI,cAAcE,WAAajL,EAAS7B,IAE/C,OAEF,MAAM+M,EAAa,IAAIrV,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,KAChEwM,EAASU,UAAUtB,EAAQmB,EAA3B,EACC,CAACP,EAAUZ,EAAQ/J,EAAS9B,IAAK8B,EAAS7B,MAE7ClJ,EAA0B,KACxB,IAAK0V,EAAU,OAEf,MAAMY,EAAgBZ,EAASa,eAE3BD,EAAczB,MAAQA,GAAOyB,EAAcrB,OAASA,IAEpDJ,IAAKyB,EAAczB,IAAMA,GACzBI,IAAMqB,EAAcrB,KAAOA,GAC/BS,EAASc,aAAaF,KACrB,CAACZ,EAAUb,EAAKI,IAEnB5U,EAAcqV,EAAU,OAASpV,IAC/BmV,GAAa,GACTN,GAAQA,EAAO7U,EAAD,GAEpBD,EAAcqV,EAAU,iBAAkBN,GAC1C/U,EAAcqV,EAAU,oBAAqBJ,GAC7CjV,EAAcqV,EAAU,mBAAoBL,GAG1C1P,EAAAxB,cAAAwB,EAAA6E,SAAA,KACE7E,EAAAxB,cAACiE,EAADqO,EAAA,CACE1Q,IAAK2C,EACLrH,GAAIA,GAAM,2CACN2G,IAEL0N,IAAaF,GACZ7P,EAAAxB,cAACwQ,EAAqBlK,UAASC,MAAOgL,GACnCzP,GARP,GC3NAyQ,EAAe9L,IACnB,MAAMiL,EAAgBhL,EAAW8J,GACjC,IAAKkB,EACH,MAAU1T,IAAAA,OAENyI,EAAgBA,EAAgB,aAAe,eAA/C,0CAKN,OAAOiL,GC8DHc,EAAwBhR,EAAMG,WAIlC,EAEIiF,WACA9E,WACAwG,YACA+D,UACAC,UACApF,SACAJ,WACAE,QACApD,YAEFhC,KAEA,MAAM2P,EAAWgB,EAAY,yBACvBhO,EAAYC,EAAOzI,SAASiE,cAAc,QAE1CuM,EAAkBnF,EAAQ,IAC1B,QAASR,EACAnK,IAAAA,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,KAE3CtI,IAAAA,MAAMC,KAAK+V,UACpB7L,EAAS8J,IACT9J,EAASkK,KACTlK,EAASmK,KACTnK,EAAS+J,QAGV,CAED/J,EAAS9B,IAET8B,EAAS7B,IAET6B,EAAS8J,IAET9J,EAASkK,KAETlK,EAASmK,KAETnK,EAAS+J,SAILnE,EAAUpF,EAAQ,KACtB,MAAMqF,EAAqB,IAAIhQ,MAAMC,KAAKgQ,cAAc,CACtDpE,UAAWA,EACX+D,QAASA,EACTC,QAASA,EACTpF,OAAQA,EACRN,SAAU2F,EACVjF,QAAS/C,EAAUI,UAGrB,OADAJ,EAAUI,QAAQ4C,MAAMC,QAAU,OAC3BiF,GAEN,CAACnE,EAAW+D,EAASC,IAsCxB,OApCAjH,EAAoBzD,EAAK,IAAM4K,EAAS,CAACA,IAEzCxQ,EAAgB,KACd,GAAKuV,EAIL,OAFA/E,EAAQlI,OAAOiN,GAER,KACL/E,EAAQlI,OAAO,KAAf,CACD,EAEA,CAACkI,EAAS+E,IAEbvV,EAAgB,KACV4H,GAAUA,EAAS4I,EAAD,EACrB,CAACA,EAAS5I,IAEb5H,EAAgB,KACdwQ,EAAQ7E,YAAY4E,IACnB,CAACC,EAASD,IAEbvQ,EAAgB,KACTkL,GACLsF,EAAQ1E,UAAUZ,IACjB,CAACsF,EAAStF,IAEblL,EAAgB,KACT8K,GACL0F,EAAQ5E,YAAYd,IACnB,CAAC0F,EAAS1F,IAEb9K,EAAgB,KACTgL,GACLwF,EAAQ3E,SAASb,IAChB,CAACwF,EAASxF,IAGXzC,EAAUI,QAAQoD,eAClB4E,EAAS1E,aAAanG,EAAUyC,EAAUI,QAAQoD,cAAlD,GCXA2K,EAAiBlR,EAAMG,WAI3B,EAEIiI,QACAhD,WACA9E,WACAgF,WACAwB,YACAuB,oBACA7G,UACAG,YACAC,cACA0G,aACAC,cACAnG,WACAoG,UACAhD,QACAiD,QACA/C,UAEFtF,KAEA,MAAM2P,EAAWgB,EAAY,kBAEvB9H,EAAcrD,EAAQ,KAAK,IAAA4D,EAAAE,EAAAE,EAAAE,EAAAC,EAAAE,EAAAkH,EAAAhH,EAAAC,EAAAE,EAAAC,EAAAC,EAC/B,OACEpC,GACA,IAAInN,MAAMC,KAAKgO,YACbd,EAAM3J,IACN,IAAIxD,MAAMC,KAAKiO,KAAKf,EAAMgB,KAAKC,MAAOjB,EAAMgB,KAAKE,QACjD,CACEC,IAAG,OAAEnB,EAAAA,EAAM7L,cAAR,EAAEiN,EAAeD,IACpBE,OAAM,SAAErB,EAAM7L,cAAR,EAAEmN,EAAeD,OACvBE,QACE,OAAAC,EAAAxB,EAAM7L,cAAN,EAAAqN,EAAeD,SACf,IAAI1O,MAAMC,KAAK2O,MACb,OAAAzB,EAAAA,EAAM7L,cAAN,EAAAuN,EAAeH,OAAOlG,EACtB,OAAA2E,EAAAA,EAAM7L,cAAN,EAAAwN,EAAeJ,OAAOjG,GAE1BsG,MAAK,SAAE5B,EAAM7L,cAAR,EAAE0N,EAAeD,MACtBE,cACE,OAAAiH,EAAA/I,EAAM7L,cAAN,EAAA4U,EAAejH,eACf,IAAIjP,MAAMC,KAAK2O,MACb,OAAAzB,EAAAA,EAAM7L,cAAN,EAAA4N,EAAeD,aAAazG,EAC5B,OAAA2E,EAAAA,EAAM7L,cAAN,EAAA6N,EAAeF,aAAaxG,GAEhC2G,YACiBA,OAAfjC,EAAAA,EAAM7L,cAAS8N,EAAAA,EAAAA,aACf,IAAIpP,MAAMC,KAAKiO,KAAf,SACEf,EAAM7L,cADR,EACEgO,EAAeF,WAAWhB,MAD5B,OAAAmB,EAEEpC,EAAM7L,cAFR,EAEEiO,EAAeH,WAAWf,SAvBlC,EA4BD,CAAClB,IAEEqC,EAAiB7E,EAAQ,IACzB,QAASR,EACJ,IAAInK,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,KAElD,MAAO6B,EACEnK,IAAAA,MAAMC,KAAKsI,OAAO4B,EAAS3B,EAAG2B,EAAS1B,GAAGM,WAEhD,IAAI/I,MAAMC,KAAK+V,UACpB7L,EAAS8J,IACT9J,EAASkK,KACTlK,EAASmK,KACTnK,EAAS+J,QAIV,CAED/J,EAAS9B,IAET8B,EAAS7B,IAET6B,EAAS3B,EAET2B,EAAS1B,EAET0B,EAAS8J,IAET9J,EAASkK,KAETlK,EAASmK,KAETnK,MAAAA,OAAAA,EAAAA,EAAU+J,SAIZ,OACEnP,EAAAxB,cAAC2J,EAAM,CACLtF,IAAKkN,EACL3K,SAAUqF,EACVrC,MAAOa,EACP3D,SAAUA,EACVwB,UAAWA,EACXuB,kBAAmBA,EACnB7G,QAASA,EACTG,UAAWA,EACXC,YAAaA,EACb0G,WAAYA,EACZC,YAAaA,EACbnG,SAAUA,EACVoG,QAASA,EACThD,MAAOA,EACPiD,MAAOA,EACP/C,OAAQA,EACRtF,IAAKA,GAEJE,EAnBH,GCrMA8Q,EAAqBpR,EAAMG,WAI/B,EAEIiF,WACA9E,WACAgF,WACAC,iBACAC,QACAC,YACAC,SACAtD,YAEFhC,KAEA,MAAM2P,EAAWgB,EAAY,sBACvBpG,EAAe/E,EAAQ,IACvB,QAASR,MACAnK,MAAMC,KAAKmI,OAAO+B,EAAS9B,IAAK8B,EAAS7B,SAE3CtI,MAAMC,KAAK+V,UACpB7L,EAAS8J,IACT9J,EAASkK,KACTlK,EAASmK,KACTnK,EAAS+J,QAGV,CAED/J,EAAS9B,IAET8B,EAAS7B,IAET6B,EAAS8J,IAET9J,EAASkK,KAETlK,EAASmK,KAETnK,EAAS+J,SAIX,OACEnP,EAACxB,cAAA2G,GACCG,SAAUA,EACVC,eAAgBA,EAChBC,MAAOA,EACPC,UAAWA,EACXC,OAAQA,EACR7C,IAAKkN,EACL3K,SAAUuF,EACVvI,SAAUA,EACVhC,IAAKA,GAEJE,EAXH,GCxGO+Q,EACXrR,EAAMC,mBACJjF,GA4FJ,SAASsW,EACP3W,EACAC,EASAC,GAIAL,EAAgB,KACTG,GAAWE,GAQhBF,EAAOS,YAAYR,EANE,IAAIG,SACXC,IAARD,EAA0BF,EAASF,GAC3BE,EAASF,KAAWI,KAKjC,CAACF,EAAUF,EAAQC,GACvB,CA8GK2W,MAAAA,EAAiBvR,EAAMG,WAAW,UAGtCqR,aACEA,EADFC,cAEEA,EAFFC,eAGEA,EAHFC,cAIEA,EAJFC,eAKEA,EALFC,gBAMEA,EANFC,iBAOEA,EAPFC,YAQEA,EARFC,aASEA,EATFC,SAUEA,EAVFC,YAWEA,EAXFC,OAYEA,EAZFC,UAaEA,EAbFC,WAcEA,EAdFC,SAeEA,EAfF1D,SAgBEA,EAhBF2D,eAiBEA,EAjBFnQ,SAkBEA,EAlBF9B,SAmBEA,GAEFF,GAEA,MAAMyC,EAAMmC,EAAO,WAEbwN,EAAiB5M,EACrB,KACE,GAAKtL,OAAOW,MAAMC,KAAKuX,QAOvB,WAAWxX,MAAMC,KAAKuX,QAAQlB,eAAe,CAE3C1O,MACAkP,cACAC,eACAR,eACAC,gBACAC,iBACAC,gBACAC,iBACAC,kBACAC,qBAjBA5T,QAAQC,KACN,wFAKG,EAeT,IAiBF,OAfA0F,EAAoBzD,EAAK,IAAMoS,EAAiB,CAACA,IAEjDhY,EAAgB,KACdgY,GAAkBpQ,GAAYA,EAASoQ,IACtC,CAACA,EAAgBpQ,IAEpBkP,EAAuBkB,EAAgB,SAAUP,GACjDX,EAAuBkB,EAAgB,YAAaN,GACpDZ,EAAuBkB,EAAgB,OAAQL,GAC/Cb,EAAuBkB,EAAgB,UAAWJ,GAClDd,EAAuBkB,EAAgB,WAAYH,GACnDf,EAAuBkB,EAAgB,SAAUF,GACjDhB,EAAuBkB,EAAgB,SAAU5D,GACjD0C,EAAuBkB,EAAgB,gBAAiBD,GAEnDC,EAGHxS,EAAAxB,cAAC6S,EAAsBvM,SAAQ,CAACC,MAAOyN,GACpClS,OAGN,GCrSKoS,EAAU1S,EAAMG,WAAW,UAC/BiF,SAAEA,GACFhF,GAEAgF,EAAWA,GAAYnK,MAAMC,KAAKmQ,gBAAgBsH,IAElD,MAAM9P,EAAMmC,EAAO,WACb4N,EAAiB1N,EAAWmM,GAElC,IAAKuB,EACH,MAAM,IAAIpW,MAAM,wDAGlB,MAAMqW,EAAUjN,EACd,IACE,IAAI3K,MAAMC,KAAKuX,QAAQC,QAAQ,CAC7BF,eAAgBI,IAEpB,CAACA,IAYH,OAVA/O,EAAoBzD,EAAK,IAAMyS,EAAS,CAACA,IAEzCrY,EAAgB,KACd,MAAMsY,EAAUD,EAAQE,aAExB,OADAlQ,EAAI2I,WAAWsH,EAAS1N,GACjB,KACLvC,EAAI4I,cAAcqH,EAAlB,CACD,EACA,CAACjQ,EAAKgQ,EAASzN,IAGnB,IAAA,GCsBK4N,EAAYhT,EAAMG,WACtB,EAEIzE,GAAAA,EAAK,2CACLqK,QACAkN,YACA1S,SACA8E,SACAtE,QACAG,YACAkB,YAEFhC,KAEA,MAAOyC,EAAKC,GAAUF,IAChBG,EAAYC,EAAuB,MAqEzC,OAnEA3I,EAA0B,KACxB,IAAKC,OAAOW,MAIV,YAHAiD,QAAQC,KACN,iFAKJ,MAAM+U,EAAenQ,EAAUI,QAC1B+P,GAELjY,MAAMC,KAAKmC,KAAK,KACd,MAAM8V,EACA9F,MAAM+F,QAAQ/N,GACTA,EAAOxC,IAAKwQ,QAEZA,EADL,CAEEjO,SAAU,IAAInK,MAAMC,KAAKmI,OACvBgQ,EAAGjO,SAAS9B,IACZ+P,EAAGjO,SAAS7B,QAKE,iBAAX8B,GACHA,EAAOD,SACX0L,EAAA,CAAA,EACKzL,EADL,CAEED,SAAU,IAAInK,MAAMC,KAAKmI,OACvBgC,EAAOD,SAAS9B,IAChB+B,EAAOD,SAAS7B,OAMjB8B,EAEHiO,EAAiB,IAAIrY,MAAMC,KAAK8X,UAAUE,EAAc,CAC5D3S,OAAQ,IAAItF,MAAMC,KAAKmI,OAAO9C,EAAO+C,IAAK/C,EAAOgD,KACjDxC,QACAG,YACAmE,OAAQ8N,IAGVrQ,EAAOwQ,IAlCT,EAoCC,CAAC7W,KAAKC,UAAU2I,KAEnBxB,EAAoBzD,EAAK,IAAMyC,EAAM,CAACA,IAEtCxI,EAA0B,KACpBwI,GAAKA,EAAIuB,UAAU,IAAInJ,MAAMC,KAAKmI,OAAO9C,EAAO+C,IAAK/C,EAAOgD,KACjE,EAAE,CAACV,EAAKtC,EAAO+C,IAAK/C,EAAOgD,MAE5BlJ,EAA0B,KACpBwI,GAAO9B,GAAO8B,EAAI2B,SAASzD,EAAb,EACjB,CAAC8B,EAAK9B,IAET1G,EAA0B,KACpBwI,GAAO3B,GAAW2B,EAAI4B,aAAavD,IACtC,CAAC2B,EAAK3B,IAET7G,EAA0B,KACpBwI,GAAOT,GAAUA,EAASS,EAAD,EAC5B,CAACA,EAAKT,IAGPpC,EAAKxB,cAAA,MAAA,CAAA9C,GAAIA,EAAIqK,MAAOA,EAAOkN,UAAWA,EAAW7S,IAAK2C,GAAtD,GCxJAwQ,EAAwBhX,IAC5B,MAAOiX,EAAOC,GAAY7Q,EAGvB,CACD1G,SAAS,EACTuB,WAAOzC,IAGH0Y,EAAS9N,EACb,IAAM,IAAIrK,EAAOgB,GAEjB,CAACE,KAAKC,UAAUH,KAoBlB,OAjBA9B,EAAU,KACRiZ,EACGrW,OACA4F,KAAK,IACJwQ,EAAS,CACPvX,SAAS,EACTuB,WAAOzC,KAGV2Y,MAAOlW,GACNgW,EAAS,CACPvX,SAAS,EACTuB,MAAOA,IAXb,EAcC,CAACiW,IAEGF"}