Files
aviation/ui/src/components/CustomControl.tsx

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;
}