mirror of
https://github.com/maputnik/editor.git
synced 2026-02-05 20:20:02 +00:00
More componenet migration
This commit is contained in:
@@ -10,6 +10,7 @@ import IconMissing from './IconMissing'
|
||||
type IconLayerProps = {
|
||||
type: string
|
||||
style?: object
|
||||
className?: string
|
||||
};
|
||||
|
||||
export default class IconLayer extends React.Component<IconLayerProps> {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import lodash from 'lodash';
|
||||
|
||||
@@ -8,20 +7,13 @@ import LayerListItem from './LayerListItem'
|
||||
import ModalAdd from './ModalAdd'
|
||||
|
||||
import {SortableContainer} from 'react-sortable-hoc';
|
||||
import { LayerSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||
|
||||
const layerListPropTypes = {
|
||||
layers: PropTypes.array.isRequired,
|
||||
selectedLayerIndex: PropTypes.number.isRequired,
|
||||
onLayersChange: PropTypes.func.isRequired,
|
||||
onLayerSelect: PropTypes.func,
|
||||
sources: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
function layerPrefix(name) {
|
||||
function layerPrefix(name: string) {
|
||||
return name.replace(' ', '-').replace('_', '-').split('-')[0]
|
||||
}
|
||||
|
||||
function findClosestCommonPrefix(layers, idx) {
|
||||
function findClosestCommonPrefix(layers: LayerSpecification[], idx: number) {
|
||||
const currentLayerPrefix = layerPrefix(layers[idx].id)
|
||||
let closestIdx = idx
|
||||
for (let i = idx; i > 0; i--) {
|
||||
@@ -37,14 +29,34 @@ function findClosestCommonPrefix(layers, idx) {
|
||||
|
||||
let UID = 0;
|
||||
|
||||
type LayerListContainerProps = {
|
||||
layers: LayerSpecification[]
|
||||
selectedLayerIndex: number
|
||||
onLayersChange(...args: unknown[]): unknown
|
||||
onLayerSelect(...args: unknown[]): unknown
|
||||
onLayerDestroy?(...args: unknown[]): unknown
|
||||
onLayerCopy(...args: unknown[]): unknown
|
||||
onLayerVisibilityToggle(...args: unknown[]): unknown
|
||||
sources: object
|
||||
errors: any[]
|
||||
};
|
||||
|
||||
type LayerListContainerState = {
|
||||
collapsedGroups: {[ket: string]: boolean}
|
||||
areAllGroupsExpanded: boolean
|
||||
keys: {[key: string]: number}
|
||||
isOpen: {[key: string]: boolean}
|
||||
};
|
||||
|
||||
// List of collapsible layer editors
|
||||
class LayerListContainer extends React.Component {
|
||||
static propTypes = {...layerListPropTypes}
|
||||
class LayerListContainer extends React.Component<LayerListContainerProps, LayerListContainerState> {
|
||||
static defaultProps = {
|
||||
onLayerSelect: () => {},
|
||||
}
|
||||
selectedItemRef: React.RefObject<any>;
|
||||
scrollContainerRef: React.RefObject<HTMLElement>;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: LayerListContainerProps) {
|
||||
super(props);
|
||||
this.selectedItemRef = React.createRef();
|
||||
this.scrollContainerRef = React.createRef();
|
||||
@@ -60,7 +72,7 @@ class LayerListContainer extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
toggleModal(modalName) {
|
||||
toggleModal(modalName: string) {
|
||||
this.setState({
|
||||
keys: {
|
||||
...this.state.keys,
|
||||
@@ -74,9 +86,9 @@ class LayerListContainer extends React.Component {
|
||||
}
|
||||
|
||||
toggleLayers = () => {
|
||||
let idx=0
|
||||
let idx = 0
|
||||
|
||||
let newGroups=[]
|
||||
let newGroups: {[key:string]: boolean} = {}
|
||||
|
||||
this.groupedLayers().forEach(layers => {
|
||||
const groupPrefix = layerPrefix(layers[0].id)
|
||||
@@ -87,7 +99,7 @@ class LayerListContainer extends React.Component {
|
||||
newGroups[lookupKey] = this.state.areAllGroupsExpanded
|
||||
}
|
||||
|
||||
layers.forEach((layer) => {
|
||||
layers.forEach((_layer) => {
|
||||
idx += 1
|
||||
})
|
||||
});
|
||||
@@ -98,7 +110,7 @@ class LayerListContainer extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
groupedLayers() {
|
||||
groupedLayers(): (LayerSpecification & {key: string})[][] {
|
||||
const groups = []
|
||||
const layerIdCount = new Map();
|
||||
|
||||
@@ -122,7 +134,7 @@ class LayerListContainer extends React.Component {
|
||||
return groups
|
||||
}
|
||||
|
||||
toggleLayerGroup(groupPrefix, idx) {
|
||||
toggleLayerGroup(groupPrefix: string, idx: number) {
|
||||
const lookupKey = [groupPrefix, idx].join('-')
|
||||
const newGroups = { ...this.state.collapsedGroups }
|
||||
if(lookupKey in this.state.collapsedGroups) {
|
||||
@@ -135,12 +147,12 @@ class LayerListContainer extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
isCollapsed(groupPrefix, idx) {
|
||||
isCollapsed(groupPrefix: string, idx: number) {
|
||||
const collapsed = this.state.collapsedGroups[[groupPrefix, idx].join('-')]
|
||||
return collapsed === undefined ? true : collapsed
|
||||
}
|
||||
|
||||
shouldComponentUpdate (nextProps, nextState) {
|
||||
shouldComponentUpdate (nextProps: LayerListContainerProps, nextState: LayerListContainerState) {
|
||||
// Always update on state change
|
||||
if (this.state !== nextState) {
|
||||
return true;
|
||||
@@ -148,8 +160,8 @@ class LayerListContainer extends React.Component {
|
||||
|
||||
// This component tree only requires id and visibility from the layers
|
||||
// objects
|
||||
function getRequiredProps (layer) {
|
||||
const out = {
|
||||
function getRequiredProps(layer: LayerSpecification) {
|
||||
const out: {id: string, layout?: { visibility: any}} = {
|
||||
id: layer.id,
|
||||
};
|
||||
|
||||
@@ -165,10 +177,10 @@ class LayerListContainer extends React.Component {
|
||||
this.props.layers.map(getRequiredProps),
|
||||
);
|
||||
|
||||
function withoutLayers (props) {
|
||||
function withoutLayers(props: LayerListContainerProps) {
|
||||
const out = {
|
||||
...props
|
||||
};
|
||||
} as LayerListContainerProps & { layers?: any };
|
||||
delete out['layers'];
|
||||
return out;
|
||||
}
|
||||
@@ -184,7 +196,7 @@ class LayerListContainer extends React.Component {
|
||||
return propsChanged;
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
componentDidUpdate (prevProps: LayerListContainerProps) {
|
||||
if (prevProps.selectedLayerIndex !== this.props.selectedLayerIndex) {
|
||||
const selectedItemNode = this.selectedItemRef.current;
|
||||
if (selectedItemNode && selectedItemNode.node) {
|
||||
@@ -207,7 +219,7 @@ class LayerListContainer extends React.Component {
|
||||
|
||||
render() {
|
||||
|
||||
const listItems = []
|
||||
const listItems: JSX.Element[] = []
|
||||
let idx = 0
|
||||
const layersByGroup = this.groupedLayers();
|
||||
layersByGroup.forEach(layers => {
|
||||
@@ -235,7 +247,7 @@ class LayerListContainer extends React.Component {
|
||||
);
|
||||
});
|
||||
|
||||
const additionalProps = {};
|
||||
const additionalProps: {ref?: React.RefObject<any>} = {};
|
||||
if (idx === this.props.selectedLayerIndex) {
|
||||
additionalProps.ref = this.selectedItemRef;
|
||||
}
|
||||
@@ -255,7 +267,7 @@ class LayerListContainer extends React.Component {
|
||||
visibility={(layer.layout || {}).visibility}
|
||||
isSelected={idx === this.props.selectedLayerIndex}
|
||||
onLayerSelect={this.props.onLayerSelect}
|
||||
onLayerDestroy={this.props.onLayerDestroy.bind(this)}
|
||||
onLayerDestroy={this.props.onLayerDestroy?.bind(this)}
|
||||
onLayerCopy={this.props.onLayerCopy.bind(this)}
|
||||
onLayerVisibilityToggle={this.props.onLayerVisibilityToggle.bind(this)}
|
||||
{...additionalProps}
|
||||
@@ -316,11 +328,13 @@ class LayerListContainer extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const LayerListContainerSortable = SortableContainer((props) => <LayerListContainer {...props} />)
|
||||
const LayerListContainerSortable = SortableContainer((props: LayerListContainerProps) => <LayerListContainer {...props} />)
|
||||
|
||||
export default class LayerList extends React.Component {
|
||||
static propTypes = {...layerListPropTypes}
|
||||
type LayerListProps = LayerListContainerProps & {
|
||||
onMoveLayer(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
export default class LayerList extends React.Component<LayerListProps> {
|
||||
render() {
|
||||
return <LayerListContainerSortable
|
||||
{...this.props}
|
||||
@@ -8,7 +8,12 @@ import IconLayer from './IconLayer'
|
||||
import {SortableElement, SortableHandle} from 'react-sortable-hoc'
|
||||
|
||||
|
||||
const DraggableLabel = SortableHandle((props) => {
|
||||
type DraggableLabelProps = {
|
||||
layerId: string
|
||||
layerType: string
|
||||
};
|
||||
|
||||
const DraggableLabel = SortableHandle((props: DraggableLabelProps) => {
|
||||
return <div className="maputnik-layer-list-item-handle">
|
||||
<IconLayer
|
||||
className="layer-handle__icon"
|
||||
@@ -20,15 +25,15 @@ const DraggableLabel = SortableHandle((props) => {
|
||||
</div>
|
||||
});
|
||||
|
||||
class IconAction extends React.Component {
|
||||
static propTypes = {
|
||||
action: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
wdKey: PropTypes.string,
|
||||
classBlockName: PropTypes.string,
|
||||
classBlockModifier: PropTypes.string,
|
||||
}
|
||||
type IconActionProps = {
|
||||
action: string
|
||||
onClick(...args: unknown[]): unknown
|
||||
wdKey?: string
|
||||
classBlockName?: string
|
||||
classBlockModifier?: string
|
||||
};
|
||||
|
||||
class IconAction extends React.Component<IconActionProps> {
|
||||
renderIcon() {
|
||||
switch(this.props.action) {
|
||||
case 'duplicate': return <MdContentCopy />
|
||||
@@ -51,7 +56,7 @@ class IconAction extends React.Component {
|
||||
}
|
||||
|
||||
return <button
|
||||
tabIndex="-1"
|
||||
tabIndex={-1}
|
||||
title={this.props.action}
|
||||
className={`maputnik-layer-list-icon-action ${classAdditions}`}
|
||||
data-wd-key={this.props.wdKey}
|
||||
@@ -63,21 +68,21 @@ class IconAction extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
class LayerListItem extends React.Component {
|
||||
static propTypes = {
|
||||
layerIndex: PropTypes.number.isRequired,
|
||||
layerId: PropTypes.string.isRequired,
|
||||
layerType: PropTypes.string.isRequired,
|
||||
isSelected: PropTypes.bool,
|
||||
visibility: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
|
||||
onLayerSelect: PropTypes.func.isRequired,
|
||||
onLayerCopy: PropTypes.func,
|
||||
onLayerDestroy: PropTypes.func,
|
||||
onLayerVisibilityToggle: PropTypes.func,
|
||||
}
|
||||
type LayerListItemProps = {
|
||||
id?: string
|
||||
layerIndex: number
|
||||
layerId: string
|
||||
layerType: string
|
||||
isSelected?: boolean
|
||||
visibility?: string
|
||||
className?: string
|
||||
onLayerSelect(...args: unknown[]): unknown
|
||||
onLayerCopy?(...args: unknown[]): unknown
|
||||
onLayerDestroy?(...args: unknown[]): unknown
|
||||
onLayerVisibilityToggle?(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
class LayerListItem extends React.Component<LayerListItemProps> {
|
||||
static defaultProps = {
|
||||
isSelected: false,
|
||||
visibility: 'visible',
|
||||
@@ -102,12 +107,12 @@ class LayerListItem extends React.Component {
|
||||
return <li
|
||||
id={this.props.id}
|
||||
key={this.props.layerId}
|
||||
onClick={e => this.props.onLayerSelect(this.props.layerIndex)}
|
||||
onClick={_e => this.props.onLayerSelect(this.props.layerIndex)}
|
||||
data-wd-key={"layer-list-item:"+this.props.layerId}
|
||||
className={classnames({
|
||||
"maputnik-layer-list-item": true,
|
||||
"maputnik-layer-list-item-selected": this.props.isSelected,
|
||||
[this.props.className]: true,
|
||||
[this.props.className!]: true,
|
||||
})}>
|
||||
<DraggableLabel {...this.props} />
|
||||
<span style={{flexGrow: 1}} />
|
||||
@@ -115,25 +120,25 @@ class LayerListItem extends React.Component {
|
||||
wdKey={"layer-list-item:"+this.props.layerId+":delete"}
|
||||
action={'delete'}
|
||||
classBlockName="delete"
|
||||
onClick={e => this.props.onLayerDestroy(this.props.layerIndex)}
|
||||
onClick={_e => this.props.onLayerDestroy!(this.props.layerIndex)}
|
||||
/>
|
||||
<IconAction
|
||||
wdKey={"layer-list-item:"+this.props.layerId+":copy"}
|
||||
action={'duplicate'}
|
||||
classBlockName="duplicate"
|
||||
onClick={e => this.props.onLayerCopy(this.props.layerIndex)}
|
||||
onClick={_e => this.props.onLayerCopy!(this.props.layerIndex)}
|
||||
/>
|
||||
<IconAction
|
||||
wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"}
|
||||
action={visibilityAction}
|
||||
classBlockName="visibility"
|
||||
classBlockModifier={visibilityAction}
|
||||
onClick={e => this.props.onLayerVisibilityToggle(this.props.layerIndex)}
|
||||
onClick={_e => this.props.onLayerVisibilityToggle!(this.props.layerIndex)}
|
||||
/>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
|
||||
const LayerListItemSortable = SortableElement((props) => <LayerListItem {...props} />);
|
||||
const LayerListItemSortable = SortableElement((props: LayerListItemProps) => <LayerListItem {...props} />);
|
||||
|
||||
export default LayerListItemSortable;
|
||||
Reference in New Issue
Block a user