69 lines
1.7 KiB
TypeScript
69 lines
1.7 KiB
TypeScript
import { ReactNode, useEffect, useRef } from 'react';
|
|
import * as L from 'leaflet';
|
|
import { useMap } from 'react-leaflet';
|
|
import { createRoot, Root } from 'react-dom/client';
|
|
|
|
interface Props {
|
|
position?: L.ControlPosition;
|
|
onClick: () => void;
|
|
active?: boolean;
|
|
title?: string;
|
|
children?: ReactNode;
|
|
}
|
|
|
|
export function CustomControl({ position = 'bottomright', onClick, active = false, title = '', children }: Props) {
|
|
const map = useMap();
|
|
const controlRef = useRef<L.Control>(null);
|
|
const rootRef = useRef<Root>(null);
|
|
|
|
useEffect(() => {
|
|
const ctrl = new L.Control({ position });
|
|
ctrl.onAdd = () => {
|
|
return L.DomUtil.create('div', 'leaflet-bar leaflet-control custom-control');
|
|
};
|
|
|
|
ctrl.addTo(map);
|
|
controlRef.current = ctrl;
|
|
|
|
// @ts-expect-error ctrl is a L.Control
|
|
const container = (ctrl as unknown)._container as HTMLElement;
|
|
rootRef.current = createRoot(container);
|
|
L.DomEvent.disableClickPropagation(container);
|
|
|
|
return () => {
|
|
if (rootRef.current) {
|
|
rootRef.current!.unmount();
|
|
rootRef.current = null;
|
|
}
|
|
ctrl.remove();
|
|
};
|
|
}, [map, position]);
|
|
|
|
useEffect(() => {
|
|
if (rootRef.current) {
|
|
rootRef.current.render(
|
|
<a
|
|
href={'#'}
|
|
title={title}
|
|
className={active ? 'active' : ''}
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
onClick();
|
|
}}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
padding: '4px'
|
|
}}
|
|
>
|
|
{children}
|
|
</a>
|
|
);
|
|
}
|
|
}, [onClick, active, title, children]);
|
|
|
|
return null;
|
|
}
|