react-naver-maps
Version:
React Navermaps API integration for modern development.
1 lines • 14.1 kB
Source Map (JSON)
{"version":3,"sources":["../src/naver-map.tsx"],"sourcesContent":["import pick from 'lodash.pick';\nimport upperfirst from 'lodash.upperfirst';\nimport { forwardRef, useImperativeHandle, useLayoutEffect, useRef, useState } from 'react';\nimport type { ReactNode } from 'react';\n\nimport { useContainerContext } from './contexts/container';\nimport { EventTargetContext } from './contexts/event-target';\nimport { NaverMapContext } from './contexts/naver-map';\nimport { HandleEvents } from './helpers/event';\nimport { usePrevious } from './hooks/use-previous';\nimport { useNavermaps } from './use-navermaps';\n\ntype MapPaddingOptions = {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n};\n\ntype MapOptions = {\n background?: string;\n baseTileOpacity?: number;\n /**\n * @type naver.maps.Bounds | naver.maps.BoundsLiteral | null\n */\n bounds?: naver.maps.Bounds | naver.maps.BoundsLiteral | null;\n /**\n * @type naver.maps.Coord | naver.maps.CoordLiteral\n */\n center?: naver.maps.Coord | naver.maps.CoordLiteral;\n disableDoubleClickZoom?: boolean;\n disableDoubleTapZoom?: boolean;\n disableKineticPan?: boolean;\n disableTwoFingerTapZoom?: boolean;\n draggable?: boolean;\n keyboardShortcuts?: boolean;\n logoControl?: boolean;\n logoControlOptions?: naver.maps.LogoControlOptions;\n mapDataControl?: boolean;\n mapDataControlOptions?: naver.maps.MapDataControlOptions;\n mapTypeControl?: boolean;\n mapTypeControlOptions?: naver.maps.MapTypeControlOptions;\n mapTypeId?: string;\n mapTypes?: naver.maps.MapTypeRegistry;\n maxBounds?: naver.maps.Bounds | naver.maps.BoundsLiteral | null;\n maxZoom?: number;\n minZoom?: number;\n padding?: MapPaddingOptions;\n pinchZoom?: boolean;\n resizeOrigin?: naver.maps.Position;\n scaleControl?: boolean;\n scaleControlOptions?: naver.maps.ScaleControlOptions;\n scrollWheel?: boolean;\n size?: naver.maps.Size | naver.maps.SizeLiteral;\n overlayZoomEffect?: string | null;\n tileSpare?: number;\n tileTransition?: boolean;\n zoom?: number;\n zoomControl?: boolean;\n zoomControlOptions?: naver.maps.ZoomControlOptions;\n zoomOrigin?: naver.maps.Coord | naver.maps.CoordLiteral | null;\n blankTileImage?: string | null;\n\n // special.\n centerPoint?: naver.maps.Point | naver.maps.PointLiteral;\n};\n\ntype Uncontrolled = {\n /**\n * Uncontrolled prop of mapTypeId\n */\n defaultMapTypeId?: MapOptions['mapTypeId'];\n /**\n * Uncontrolled prop of size\n * @type naver.maps.Coord | naver.maps.CoordLiteral\n */\n defaultSize?: MapOptions['size'];\n /**\n * Uncontrolled prop of bounds\n * @type naver.maps.Bounds | naver.maps.BoundsLiteral | null\n */\n defaultBounds?: MapOptions['bounds'];\n /**\n * Uncontrolled prop of center\n * @type naver.maps.Coord | naver.maps.CoordLiteral\n */\n defaultCenter?: MapOptions['center'];\n /**\n * Uncontrolled prop of zoom\n */\n defaultZoom?: MapOptions['zoom'];\n /**\n * Uncontrolled prop of centerPoint\n * @type naver.maps.Point | naver.maps.PointLiteral\n */\n defaultCenterPoint?: MapOptions['centerPoint'];\n};\n\ntype MapEventCallbacks = {\n onMapTypeIdChanged?: (value: string) => void;\n onMapTypeChanged?: (value: naver.maps.MapType) => void;\n onSizeChanged?: (value: naver.maps.Size) => void;\n onBoundsChanged?: (value: naver.maps.Bounds) => void;\n onCenterChanged?: (value: naver.maps.Coord) => void;\n onCenterPointChanged?: (value: naver.maps.Point) => void;\n onZoomChanged?: (value: number) => void;\n};\n\nconst basicMapOptionKeys: Array<keyof MapOptions> = [\n 'background',\n 'baseTileOpacity',\n // 'bounds',\n // 'center',\n 'disableDoubleClickZoom',\n 'disableDoubleTapZoom',\n 'disableKineticPan',\n 'disableTwoFingerTapZoom',\n 'draggable',\n 'keyboardShortcuts',\n 'logoControl',\n 'logoControlOptions',\n 'mapDataControl',\n 'mapDataControlOptions',\n 'mapTypeControl',\n 'mapTypeControlOptions',\n // 'mapTypeId',\n 'mapTypes',\n 'maxBounds',\n 'maxZoom',\n 'minZoom',\n 'padding',\n 'pinchZoom',\n 'resizeOrigin',\n 'scaleControl',\n 'scaleControlOptions',\n 'scrollWheel',\n // 'size',\n 'overlayZoomEffect',\n 'tileSpare',\n 'tileTransition',\n // 'zoom',\n 'zoomControl',\n 'zoomControlOptions',\n 'zoomOrigin',\n 'blankTileImage',\n];\n\nconst kvoKeys = [\n 'mapTypeId',\n 'size',\n 'bounds',\n 'center',\n 'zoom',\n 'centerPoint',\n] as const;\n\nconst kvoEvents = [\n ...kvoKeys.map(key => `${key}_changed`),\n 'mapType_changed', // special. https://navermaps.github.io/maps.js.ncp/docs/naver.maps.Map.html#event:mapType_changed__anchor\n];\nconst uiEvents = [\n 'mousedown',\n 'mouseup',\n 'click',\n 'dblclick',\n 'rightclick',\n 'mouseover',\n 'mouseout',\n 'mousemove',\n 'dragstart',\n 'drag',\n 'dragend',\n 'touchstart',\n 'touchmove',\n 'touchend',\n 'pinchstart',\n 'pinch',\n 'pinchend',\n 'tap',\n 'longtap',\n 'twofingertap',\n 'doubletap',\n] as const;\nconst mapOnlyEvents = [\n 'addLayer',\n 'idle',\n 'init',\n 'keydown',\n 'keyup',\n 'panning',\n 'projection_changed',\n 'removeLayer',\n 'resize',\n 'tilesloaded',\n 'zooming',\n] as const;\nconst events = [...uiEvents, ...kvoEvents, ...mapOnlyEvents];\n\n// type FunctionTypeChildren = (nmap: naver.maps.Map) => React.ReactNode;\n\nconst defaultOptionKeyMap = {\n mapTypeId: 'defaultMapTypeId',\n size: 'defaultSize',\n bounds: 'defaultBounds',\n center: 'defaultCenter',\n zoom: 'defaultZoom',\n centerPoint: 'defaultCenterPoint',\n} as const;\n\nexport type Props = Uncontrolled & {\n /**\n * Map 관련 components\n */\n children?: ReactNode;\n} & MapOptions & MapEventCallbacks;\n\nexport const NaverMap = forwardRef<naver.maps.Map | null, Props>(function NaverMap(props, ref) {\n const navermaps = useNavermaps();\n const { element: mapDiv } = useContainerContext();\n const [nmap, setNmap] = useState<naver.maps.Map>();\n const nmapRef = useRef<naver.maps.Map>();\n\n // https://github.com/facebook/react/issues/20090\n useLayoutEffect(() => {\n if (!mapDiv) {\n throw new Error('react-naver-maps: MapDiv is not found. Did you correctly wrap with `MapDiv`?');\n }\n\n const basicMapOptions = pick(props, basicMapOptionKeys);\n const kvos = kvoKeys.reduce((acc, key) => {\n // default kvo\n if (props[defaultOptionKeyMap[key]]) {\n return {\n ...acc,\n [key]: props[defaultOptionKeyMap[key]],\n };\n }\n\n // kvo\n if (props[key]) {\n return {\n ...acc,\n [key]: props[key],\n };\n }\n\n return acc;\n }, {});\n\n const _nmap = new navermaps.Map(mapDiv, { ...basicMapOptions, ...kvos });\n setNmap(_nmap);\n // for ref hack\n nmapRef.current = _nmap;\n\n return () => {\n _nmap.destroy();\n };\n }, []);\n\n const uncontrolledOmittedProps = (Object.keys(props) as Array<keyof Props>).reduce((acc, key) => {\n // kvo key가 defaultKvo key와 함께 있을 경우 무시한다.\n if (key in defaultOptionKeyMap && props[defaultOptionKeyMap[key as keyof typeof defaultOptionKeyMap]]) {\n return acc;\n }\n\n return {\n ...acc,\n [key]: props[key],\n };\n }, {}) as Props;\n\n // nmap 이 layoutEffect에서 생성되므로 항상 Map이 존재한다.\n useImperativeHandle<naver.maps.Map | undefined, naver.maps.Map | undefined>(ref, () => nmapRef.current);\n\n return (\n <>{nmap && <NaverMapCore {...uncontrolledOmittedProps} nmap={nmap} />}</>\n );\n});\n\nfunction NaverMapCore({ nmap, children, ...mapProps }: Props & { nmap: naver.maps.Map }) {\n const basicMapOptions = pick(mapProps, basicMapOptionKeys);\n const {\n mapTypeId,\n size,\n bounds,\n center,\n centerPoint,\n zoom,\n } = mapProps;\n\n const prevKVOs = usePrevious({\n mapTypeId,\n size,\n bounds,\n center,\n centerPoint,\n zoom,\n }, [\n mapTypeId,\n size,\n bounds,\n center,\n centerPoint,\n zoom,\n ]);\n\n function getDirtyKVOs(keys: Array<typeof kvoKeys[number]>): Pick<Props, typeof kvoKeys[number]> {\n return keys.reduce((acc, key) => {\n const currentValue = nmap[`get${upperfirst(key)}` as keyof naver.maps.Map]();\n const propValue = mapProps[key];\n\n if (!propValue || prevKVOs && prevKVOs[key] === propValue) {\n return acc;\n }\n\n const isEqual = typeof currentValue.equals === 'function' ? currentValue.equals(propValue) : currentValue === propValue;\n\n if (isEqual) {\n return acc;\n }\n\n return {\n ...acc,\n [key]: propValue,\n };\n }, {} as Pick<Props, typeof kvoKeys[number]>);\n }\n\n useLayoutEffect(() => {\n nmap.setOptions(basicMapOptions);\n }, [Object.values(basicMapOptions)]);\n\n useLayoutEffect(() => {\n const updated = getDirtyKVOs(['size']).size;\n if (updated) {\n nmap.setSize(updated);\n }\n }, [size]);\n\n useLayoutEffect(() => {\n const updated = getDirtyKVOs(['mapTypeId']).mapTypeId;\n if (updated) {\n nmap.setMapTypeId(updated);\n }\n }, [mapTypeId]);\n\n useLayoutEffect(() => {\n const dirties = getDirtyKVOs(['bounds', 'center', 'centerPoint', 'zoom']);\n\n if (dirties.bounds) {\n // TODO\n nmap.fitBounds(dirties.bounds);\n\n // Ignore rest kvos\n return;\n }\n\n if (dirties.center && dirties.zoom) {\n\n nmap.morph(dirties.center, dirties.zoom);\n\n // Ignore rest kvos\n return;\n }\n\n if (dirties.centerPoint) {\n nmap.setCenterPoint(dirties.centerPoint);\n }\n\n if (dirties.center) {\n // TODO\n nmap.panTo(dirties.center, {});\n }\n\n if (dirties.zoom) {\n nmap.setZoom(dirties.zoom);\n }\n }, [bounds, center, centerPoint, zoom]);\n\n return (\n <NaverMapContext.Provider value={nmap}>\n <EventTargetContext.Provider value={nmap}>\n <>\n <HandleEvents\n events={events}\n listeners={mapProps as any}\n />\n {children}\n </>\n </EventTargetContext.Provider>\n </NaverMapContext.Provider>\n );\n}\n"],"mappings":"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","names":["NaverMap"]}