react-leaflet-custom-corners-control
Version:
Creates a control wrapper around a React element with custom corners.
112 lines (97 loc) • 5.52 kB
Markdown
# react-leaflet-custom-control
[](https://npmjs.com/package/react-leaflet-custom-control)
[](https://npmjs.com/package/react-leaflet-custom-control)
[](https://github.com/chris-m92/react-leaflet-custom-control)
A React wrapper to create a custom control for [react-leaflet](https://github.com/PaulLeCam/react-leaflet) using ReactDOM's Portal capabilities
The current version of this package supports React Leaflet v3
[Code Sandbox Demo](https://codesandbox.io/s/n1xpv)
**NOTE**
||
|--|
|Version `^1.2.3` (which adds this note to the README) has updated peer dependencies for React v18. This may be a breaking change depending on your environment. If you are still running React v17 then install version 1.2.2.|
|Version `^1.4.0` now has a dependency on `react-leaflet@^4.2.1`. This allows for the `useMap()` hook. This also requires that this `Control` component **MUST** be a child of your `MapContainer`|
## Installation
```bash
#npm
npm install --save react-leaflet-custom-control
#yarn
yarn add react-leaflet-custom-control
```
## Usage
```jsx
import { MapContainer, TileLayer } from 'react-leaflet'
import Control from 'react-leaflet-custom-control'
import { Button } from '@mui/material'
import { Search as SearchIcon } from '@mui/icons-material'
import 'leaflet.css'
<MapContainer center={[35.77, -93.34]} zoom={5}>
<TileLayer
attribution="Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community"
className="basemap"
maxNativeZoom={19}
maxZoom={19}
subdomains={["clarity"]}
url="https://{s}.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
/>
<Control prepend position='topright'>
<Button color='inherit'>
<SearchIcon />
</Button>
</Control>
</MapContainer>
```
## Order Matters!
Because this uses `React.createPortal` which inherently appends the portal, DOM manipulation is used to append or prepend a container element to the portal target. Because of this, the order of your custom controls matter! The last `Control` element to be prepended to a control position will be at the very top while the last `Control` element to be appended to a control position will be at the very bottom. If mixing with default `React Leaflet` controls, they will be in between your custom controls.
### Weird Quirks
However, because of the way that the portal works and re-renders, multiple control elements will shift order after renders, so it's recommended to have a wrapping element be the child of the `Control` to prevent re-ordering each render
### Example
```jsx
import { MapContainer, TileLayer, ZoomControl } from 'react-leaflet'
import Control from 'react-leaflet-custom-control'
import { Button, Stack } from '@mui/material'
import {
Add as AddIcon,
Delete as DeleteIcon,
Search as SearchIcon
} from '@mui/icons-material'
import 'leaflet.css'
<MapContainer center={[35.77, -93.34]} zoom={5} zoomControl={false}>
<TileLayer
attribution="Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community"
className="basemap"
maxNativeZoom={19}
maxZoom={19}
subdomains={["clarity"]}
url="https://{s}.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
/>
{/* Search control is the very top right control */}
<Control prepend position='topright'>
<Button color='inherit'>
<SearchIcon />
</Button>
</Control>
<ZoomControl position='topright' />
{/* This control will be below the default zoom control. Note the wrapping Stack component */}
<Control position='topright'>
<Stack direction='column' spacing={2} >
<Button color='inherit'>
<AddIcon />
</Button>
<Button color='inherit'>
<DeleteIcon />
</Button>
</Stack>
</Control>
</MapContainer>
```
## Props
| Name | Type | Default | Description |
|----------------|----------------------------------------------------------------------|------------------|------------------------------------|
| position | [ControlOptions](https://leafletjs.com/reference-1.7.1.html#control) | **required** | The position of the control |
| children? | any | undefined | Child element to the control |
| ~~style?~~ | ~~`React.CSSProperties`~~ | ~~undefined~~ | ~~CSS Styles to override the control~~ |
| container? | `React.HTMLAttributes<HTMLDivElement>` | undefined | The target root container for the portal |
| prepend? | boolean | undefined | Whether the control should be prepended or appended to the position|
## Thanks
Huge thanks to @davetapley for contributing to `@1.3.0` and helping to work some of the issues.
Thanks to @samiamlabs for contributing to `@1.3.2` for fixing the infinite `div` issue.