Skip to content

Commit

Permalink
v3.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulLeCam committed Nov 8, 2020
1 parent 116a8f9 commit 8ca7548
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 105 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v3.0.2 (2020-11-08)

Further fixes for panes support

## v3.0.1 (2020-11-07)

- Fixed `pane` prop support
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@react-leaflet/core",
"version": "1.0.1",
"version": "1.0.2",
"description": "React Leaflet core",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useLeafletContext } from './context'
import { LeafletElement, ElementHook } from './element'
import { useEventHandlers } from './events'
import { InteractiveLayerProps, useLayerLifecycle } from './layer'
import { withPane } from './pane'

export interface PathProps extends InteractiveLayerProps {
pathOptions?: PathOptions
Expand Down Expand Up @@ -34,7 +35,7 @@ export function createPathHook<
>(useElement: ElementHook<E, P>) {
return function usePath(props: P): ReturnType<ElementHook<E, P>> {
const context = useLeafletContext()
const elementRef = useElement(props, context)
const elementRef = useElement(withPane(props, context), context)

useEventHandlers(elementRef.current, props.eventHandlers)
useLayerLifecycle(elementRef.current, context)
Expand Down
4 changes: 2 additions & 2 deletions packages/react-leaflet/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-leaflet",
"version": "3.0.1",
"version": "3.0.2",
"description": "React components for Leaflet maps",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand Down Expand Up @@ -43,7 +43,7 @@
"umd/*"
],
"dependencies": {
"@react-leaflet/core": "^1.0.0"
"@react-leaflet/core": "^1.0.2"
},
"peerDependencies": {
"leaflet": "^1.7.1",
Expand Down
151 changes: 58 additions & 93 deletions packages/react-leaflet/src/Pane.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import {
LeafletContextInterface,
LeafletProvider,
addClassName,
removeClassName,
useLeafletContext,
} from '@react-leaflet/core'
import React, {
CSSProperties,
ReactNode,
useEffect,
useMemo,
useRef,
} from 'react'
import React, { CSSProperties, ReactNode, useEffect, useMemo } from 'react'
import { createPortal } from 'react-dom'

const DEFAULT_PANES = [
'mapPane',
Expand All @@ -22,14 +17,6 @@ const DEFAULT_PANES = [
'tooltipPane',
]

const PANE_STYLES: CSSProperties = {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
}

function omitPane(obj: Record<string, unknown>, pane: string) {
const { [pane]: _p, ...others } = obj
return others
Expand All @@ -43,93 +30,71 @@ export interface PaneProps {
style?: CSSProperties
}

export function Pane(props: PaneProps) {
const context = useLeafletContext()
const paneElementRef = useRef<HTMLElement | null>(null)
const propsRef = useRef<PaneProps>(props)
function createPane(
props: PaneProps,
context: LeafletContextInterface,
): HTMLElement {
const name = props.name

function applyStyles(paneElement: HTMLElement) {
if (props.className != null) {
addClassName(paneElement, props.className)
}
if (props.style != null) {
Object.keys(props.style).forEach((key) => {
// @ts-ignore
paneElement.style[key] = props.style[key]
})
}
if (DEFAULT_PANES.indexOf(name) !== -1) {
throw new Error(
`You must use a unique name for a pane that is not a default Leaflet pane: ${name}`,
)
}
if (context.map.getPane(name) != null) {
throw new Error(`A pane with this name already exists: ${name}`)
}

function createPane() {
const name = props.name
const parentPaneName = props.pane ?? context.pane
const parentPane = parentPaneName
? context.map.getPane(parentPaneName)
: undefined
const element = context.map.createPane(name, parentPane)

if (DEFAULT_PANES.indexOf(name) !== -1) {
throw new Error(
`You must use a unique name for a pane that is not a default Leaflet pane: ${name}`,
)
}
if (context.map.getPane(name) != null) {
throw new Error(`A pane with this name already exists: ${name}`)
}

const parentPane = context.pane
? context.map.getPane(context.pane)
: undefined
paneElementRef.current = context.map.createPane(name, parentPane)
applyStyles(paneElementRef.current)
if (props.className != null) {
addClassName(element, props.className)
}
if (props.style != null) {
Object.keys(props.style).forEach((key) => {
// @ts-ignore
element.style[key] = props.style[key]
})
}

function removePane(name: string) {
const pane = context.map.getPane(name)
pane?.remove?.()
return element
}

export function Pane(props: PaneProps) {
const context = useLeafletContext()
// eslint-disable-next-line react-hooks/exhaustive-deps
const paneElement = useMemo(() => createPane(props, context), [])
// eslint-disable-next-line react-hooks/exhaustive-deps
const newContext = useMemo(() => ({ ...context, pane: props.name }), [])

useEffect(() => {
return function removeCreatedPane() {
const pane = context.map.getPane(props.name)
pane?.remove?.()

// @ts-ignore map internals
if (context.map._panes != null) {
// @ts-ignore map internals
context.map._panes = omitPane(context.map._panes, name)
// @ts-ignore map internals
context.map._paneRenderers = omitPane(
if (context.map._panes != null) {
// @ts-ignore map internals
context.map._paneRenderers,
name,
)
}
}

useEffect(function handlePane() {
if (paneElementRef.current === null) {
createPane()
} else if (props !== propsRef.current) {
if (props.name === propsRef.current.name) {
// Remove the previous css class name from the pane if it has changed.
// setStyle() will take care of adding in the updated className
if (
propsRef.current.className &&
props.className !== propsRef.current.className
) {
removeClassName(paneElementRef.current, propsRef.current.className)
}
// Update the pane's DOM node style and class
applyStyles(paneElementRef.current)
} else {
removePane(propsRef.current.name)
createPane()
context.map._panes = omitPane(context.map._panes, props.name)
// @ts-ignore map internals
context.map._paneRenderers = omitPane(
// @ts-ignore map internals
context.map._paneRenderers,
props.name,
)
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

return function removeCreatedPane() {
removePane(props.name)
}
})

const newContext = useMemo(() => ({ ...context, pane: props.name }), [
context,
props.name,
])

return props.children ? (
<LeafletProvider value={newContext}>
<div style={PANE_STYLES}>{props.children}</div>
</LeafletProvider>
) : null
return props.children != null
? createPortal(
<LeafletProvider value={newContext}>{props.children}</LeafletProvider>,
paneElement,
)
: null
}
4 changes: 2 additions & 2 deletions packages/website/docs/api-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ The `name` prop must be unique to the pane and different from the [default Leafl
| Prop | Type | Required | Mutable | Behavior |
| ----------- | --------------- | -------- | ------- | -------------------------------------------- |
| `children` | `ReactNode` | No | **Yes** | [ParentComponent](#parentcomponent-behavior) |
| `className` | `string` | No | **Yes** |
| `className` | `string` | No | No |
| `name` | `string` | **Yes** | No |
| `pane` | `string` | No | No | [Pane](#pane-behavior) |
| `style` | `CSSProperties` | No | **Yes** |
| `style` | `CSSProperties` | No | No |
12 changes: 6 additions & 6 deletions packages/website/docs/example-panes.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ const inner = [

function BlinkingPane() {
const [render, setRender] = useState(true)
const timer = useRef()
const timerRef = useRef()
useEffect(() => {
timer.ref = setInterval(() => {
timerRef.current = setInterval(() => {
setRender((r) => !r)
}, 5000)
return () => {
clearInterval(timer.ref)
clearInterval(timerRef.current)
}
}, [])

return render ? (
<Pane name="cyan-rectangle" style={{ zIndex: 500 }}>
<Rectangle bounds={outer} color="cyan" />
<Rectangle bounds={outer} pathOptions={{ color: 'cyan' }} />
</Pane>
) : null
}
Expand All @@ -39,9 +39,9 @@ render(
/>
<BlinkingPane />
<Pane name="yellow-rectangle" style={{ zIndex: 499 }}>
<Rectangle bounds={inner} color="yellow" />
<Rectangle bounds={inner} pathOptions={{ color: 'yellow' }} />
<Pane name="purple-rectangle">
<Rectangle bounds={outer} color="purple" />
<Rectangle bounds={outer} pathOptions={{ color: 'purple' }} />
</Pane>
</Pane>
</MapContainer>,
Expand Down

0 comments on commit 8ca7548

Please sign in to comment.