UNPKG

react-leaflet-custom-corners-control

Version:

Creates a control wrapper around a React element with custom corners.

112 lines (97 loc) 5.52 kB
# react-leaflet-custom-control [![npm](https://img.shields.io/npm/v/react-leaflet-custom-control.svg)](https://npmjs.com/package/react-leaflet-custom-control) [![npm](https://img.shields.io/npm/dt/react-leaflet-custom-control.svg)](https://npmjs.com/package/react-leaflet-custom-control) [![license](https://img.shields.io/github/license/chris-m92/react-leaflet-custom-control.svg)](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.