UNPKG

2.73 kBJavaScriptView Raw
1import { LeafletProvider, addClassName, useLeafletContext } from '@react-leaflet/core';
2import React, { forwardRef, useState, useEffect, useImperativeHandle, useMemo } from 'react';
3import { createPortal } from 'react-dom';
4const DEFAULT_PANES = [
5 'mapPane',
6 'markerPane',
7 'overlayPane',
8 'popupPane',
9 'shadowPane',
10 'tilePane',
11 'tooltipPane'
12];
13function omitPane(obj, pane) {
14 const { [pane]: _p , ...others } = obj;
15 return others;
16}
17function createPane(name, props, context) {
18 if (DEFAULT_PANES.indexOf(name) !== -1) {
19 throw new Error(`You must use a unique name for a pane that is not a default Leaflet pane: ${name}`);
20 }
21 if (context.map.getPane(name) != null) {
22 throw new Error(`A pane with this name already exists: ${name}`);
23 }
24 const parentPaneName = props.pane ?? context.pane;
25 const parentPane = parentPaneName ? context.map.getPane(parentPaneName) : undefined;
26 const element = context.map.createPane(name, parentPane);
27 if (props.className != null) {
28 addClassName(element, props.className);
29 }
30 if (props.style != null) {
31 Object.keys(props.style).forEach((key)=>{
32 // @ts-ignore
33 element.style[key] = props.style[key];
34 });
35 }
36 return element;
37}
38function PaneComponent(props, forwardedRef) {
39 const [paneName] = useState(props.name);
40 const [paneElement, setPaneElement] = useState(null);
41 useImperativeHandle(forwardedRef, ()=>paneElement, [
42 paneElement
43 ]);
44 const context = useLeafletContext();
45 // eslint-disable-next-line react-hooks/exhaustive-deps
46 const newContext = useMemo(()=>({
47 ...context,
48 pane: paneName
49 }), [
50 context
51 ]);
52 useEffect(()=>{
53 setPaneElement(createPane(paneName, props, context));
54 return function removeCreatedPane() {
55 const pane = context.map.getPane(paneName);
56 pane?.remove?.();
57 // @ts-ignore map internals
58 if (context.map._panes != null) {
59 // @ts-ignore map internals
60 context.map._panes = omitPane(context.map._panes, paneName);
61 // @ts-ignore map internals
62 context.map._paneRenderers = omitPane(// @ts-ignore map internals
63 context.map._paneRenderers, paneName);
64 }
65 };
66 // eslint-disable-next-line react-hooks/exhaustive-deps
67 }, []);
68 return props.children != null && paneElement != null ? /*#__PURE__*/ createPortal(/*#__PURE__*/ React.createElement(LeafletProvider, {
69 value: newContext
70 }, props.children), paneElement) : null;
71}
72export const Pane = /*#__PURE__*/ forwardRef(PaneComponent);