Remove legacy context API (#1258)

## Summary
- replace `childContextTypes` usage with `IconContext` providers
- drop `prop-types` imports

## Testing
- `npm run lint`
- `npm run build`


------
https://chatgpt.com/codex/tasks/task_e_6868431f6ecc83318393a5d079ca736e
This commit is contained in:
Bart Louwers
2025-07-04 23:49:11 +02:00
committed by GitHub
parent e58b92b0cd
commit 4b977fd33e
4 changed files with 104 additions and 128 deletions
+1
View File
@@ -13,6 +13,7 @@
- Upgrade OpenLayers from v6 to v10 - Upgrade OpenLayers from v6 to v10
- When loading a style into localStorage that causes a QuotaExceededError, purge localStorage and retry - When loading a style into localStorage that causes a QuotaExceededError, purge localStorage and retry
- Remove react-autobind dependency - Remove react-autobind dependency
- Remove usage of legacy `childContextTypes` API
- _...Add new stuff here..._ - _...Add new stuff here..._
### 🐞 Bug fixes ### 🐞 Bug fixes
+19 -26
View File
@@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import ScrollContainer from './ScrollContainer' import ScrollContainer from './ScrollContainer'
import { WithTranslation, withTranslation } from 'react-i18next'; import { WithTranslation, withTranslation } from 'react-i18next';
import { IconContext } from 'react-icons';
type AppLayoutInternalProps = { type AppLayoutInternalProps = {
toolbar: React.ReactElement toolbar: React.ReactElement
@@ -13,38 +13,31 @@ type AppLayoutInternalProps = {
} & WithTranslation; } & WithTranslation;
class AppLayoutInternal extends React.Component<AppLayoutInternalProps> { class AppLayoutInternal extends React.Component<AppLayoutInternalProps> {
static childContextTypes = {
reactIconBase: PropTypes.object
}
getChildContext() {
return {
reactIconBase: { size: 14 }
}
}
render() { render() {
document.body.dir = this.props.i18n.dir(); document.body.dir = this.props.i18n.dir();
return <div className="maputnik-layout"> return <IconContext.Provider value={{size: '14px'}}>
{this.props.toolbar} <div className="maputnik-layout">
<div className="maputnik-layout-main"> {this.props.toolbar}
<div className="maputnik-layout-list"> <div className="maputnik-layout-main">
{this.props.layerList} <div className="maputnik-layout-list">
{this.props.layerList}
</div>
<div className="maputnik-layout-drawer">
<ScrollContainer>
{this.props.layerEditor}
</ScrollContainer>
</div>
{this.props.map}
</div> </div>
<div className="maputnik-layout-drawer"> {this.props.bottom && <div className="maputnik-layout-bottom">
<ScrollContainer> {this.props.bottom}
{this.props.layerEditor}
</ScrollContainer>
</div> </div>
{this.props.map} }
{this.props.modals}
</div> </div>
{this.props.bottom && <div className="maputnik-layout-bottom"> </IconContext.Provider>
{this.props.bottom}
</div>
}
{this.props.modals}
</div>
} }
} }
+49 -59
View File
@@ -1,8 +1,8 @@
import React, {type JSX} from 'react' import React, {type JSX} from 'react'
import PropTypes from 'prop-types'
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton' import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'
import {Accordion} from 'react-accessible-accordion'; import {Accordion} from 'react-accessible-accordion';
import {MdMoreVert} from 'react-icons/md' import {MdMoreVert} from 'react-icons/md'
import { IconContext } from 'react-icons'
import {BackgroundLayerSpecification, LayerSpecification, SourceSpecification} from 'maplibre-gl'; import {BackgroundLayerSpecification, LayerSpecification, SourceSpecification} from 'maplibre-gl';
import FieldJson from './FieldJson' import FieldJson from './FieldJson'
@@ -86,10 +86,6 @@ class LayerEditorInternal extends React.Component<LayerEditorInternalProps, Laye
onLayerDestroyed: () => {}, onLayerDestroyed: () => {},
} }
static childContextTypes = {
reactIconBase: PropTypes.object
}
constructor(props: LayerEditorInternalProps) { constructor(props: LayerEditorInternalProps) {
super(props) super(props)
@@ -116,14 +112,6 @@ class LayerEditorInternal extends React.Component<LayerEditorInternalProps, Laye
}; };
} }
getChildContext () {
return {
reactIconBase: {
size: 14,
color: '#8e8e8e',
}
}
}
changeProperty(group: keyof LayerSpecification | null, property: string, newValue: any) { changeProperty(group: keyof LayerSpecification | null, property: string, newValue: any) {
this.props.onLayerChanged( this.props.onLayerChanged(
@@ -311,53 +299,55 @@ class LayerEditorInternal extends React.Component<LayerEditorInternalProps, Laye
items[id].handler(); items[id].handler();
} }
return <section className="maputnik-layer-editor" return <IconContext.Provider value={{size: '14px', color: '#8e8e8e'}}>
role="main" <section className="maputnik-layer-editor"
aria-label={t("Layer editor")} role="main"
> aria-label={t("Layer editor")}
<header>
<div className="layer-header">
<h2 className="layer-header__title">
{t("Layer: {{layerId}}", { layerId: formatLayerId(this.props.layer.id) })}
</h2>
<div className="layer-header__info">
<Wrapper
className='more-menu'
onSelection={handleSelection}
closeOnSelection={false}
>
<Button
id="skip-target-layer-editor"
data-wd-key="skip-target-layer-editor"
className='more-menu__button'
title={"Layer options"}>
<MdMoreVert className="more-menu__button__svg" />
</Button>
<Menu>
<ul className="more-menu__menu">
{Object.keys(items).map((id) => {
const item = items[id];
return <li key={id}>
<MenuItem value={id} className='more-menu__menu__item'>
{item.text}
</MenuItem>
</li>
})}
</ul>
</Menu>
</Wrapper>
</div>
</div>
</header>
<Accordion
allowMultipleExpanded={true}
allowZeroExpanded={true}
preExpanded={groupIds}
> >
{groups} <header>
</Accordion> <div className="layer-header">
</section> <h2 className="layer-header__title">
{t("Layer: {{layerId}}", { layerId: formatLayerId(this.props.layer.id) })}
</h2>
<div className="layer-header__info">
<Wrapper
className='more-menu'
onSelection={handleSelection}
closeOnSelection={false}
>
<Button
id="skip-target-layer-editor"
data-wd-key="skip-target-layer-editor"
className='more-menu__button'
title={"Layer options"}>
<MdMoreVert className="more-menu__button__svg" />
</Button>
<Menu>
<ul className="more-menu__menu">
{Object.keys(items).map((id) => {
const item = items[id];
return <li key={id}>
<MenuItem value={id} className='more-menu__menu__item'>
{item.text}
</MenuItem>
</li>
})}
</ul>
</Menu>
</Wrapper>
</div>
</div>
</header>
<Accordion
allowMultipleExpanded={true}
allowZeroExpanded={true}
preExpanded={groupIds}
>
{groups}
</Accordion>
</section>
</IconContext.Provider>
} }
} }
+35 -43
View File
@@ -1,8 +1,8 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import {MdContentCopy, MdVisibility, MdVisibilityOff, MdDelete} from 'react-icons/md' import {MdContentCopy, MdVisibility, MdVisibilityOff, MdDelete} from 'react-icons/md'
import { IconContext } from 'react-icons'
import IconLayer from './IconLayer' import IconLayer from './IconLayer'
import {SortableElement, SortableHandle} from 'react-sortable-hoc' import {SortableElement, SortableHandle} from 'react-sortable-hoc'
@@ -91,51 +91,43 @@ class LayerListItem extends React.Component<LayerListItemProps> {
onLayerVisibilityToggle: () => {}, onLayerVisibilityToggle: () => {},
} }
static childContextTypes = {
reactIconBase: PropTypes.object
}
getChildContext() {
return {
reactIconBase: { size: 14 }
}
}
render() { render() {
const visibilityAction = this.props.visibility === 'visible' ? 'show' : 'hide'; const visibilityAction = this.props.visibility === 'visible' ? 'show' : 'hide';
return <li return <IconContext.Provider value={{size: '14px'}}>
id={this.props.id} <li
key={this.props.layerId} id={this.props.id}
onClick={_e => this.props.onLayerSelect(this.props.layerIndex)} key={this.props.layerId}
data-wd-key={"layer-list-item:"+this.props.layerId} onClick={_e => this.props.onLayerSelect(this.props.layerIndex)}
className={classnames({ data-wd-key={"layer-list-item:"+this.props.layerId}
"maputnik-layer-list-item": true, className={classnames({
"maputnik-layer-list-item-selected": this.props.isSelected, "maputnik-layer-list-item": true,
[this.props.className!]: true, "maputnik-layer-list-item-selected": this.props.isSelected,
})}> [this.props.className!]: true,
<DraggableLabel {...this.props} /> })}>
<span style={{flexGrow: 1}} /> <DraggableLabel {...this.props} />
<IconAction <span style={{flexGrow: 1}} />
wdKey={"layer-list-item:"+this.props.layerId+":delete"} <IconAction
action={'delete'} wdKey={"layer-list-item:"+this.props.layerId+":delete"}
classBlockName="delete" action={'delete'}
onClick={_e => this.props.onLayerDestroy!(this.props.layerIndex)} classBlockName="delete"
/> onClick={_e => this.props.onLayerDestroy!(this.props.layerIndex)}
<IconAction />
wdKey={"layer-list-item:"+this.props.layerId+":copy"} <IconAction
action={'duplicate'} wdKey={"layer-list-item:"+this.props.layerId+":copy"}
classBlockName="duplicate" action={'duplicate'}
onClick={_e => this.props.onLayerCopy!(this.props.layerIndex)} classBlockName="duplicate"
/> onClick={_e => this.props.onLayerCopy!(this.props.layerIndex)}
<IconAction />
wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"} <IconAction
action={visibilityAction} wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"}
classBlockName="visibility" action={visibilityAction}
classBlockModifier={visibilityAction} classBlockName="visibility"
onClick={_e => this.props.onLayerVisibilityToggle!(this.props.layerIndex)} classBlockModifier={visibilityAction}
/> onClick={_e => this.props.onLayerVisibilityToggle!(this.props.layerIndex)}
</li> />
</li>
</IconContext.Provider>
} }
} }