diff --git a/src/components/AppLayout.jsx b/src/components/AppLayout.tsx similarity index 73% rename from src/components/AppLayout.jsx rename to src/components/AppLayout.tsx index 99b669ea5..90392ab92 100644 --- a/src/components/AppLayout.jsx +++ b/src/components/AppLayout.tsx @@ -2,16 +2,16 @@ import React from 'react' import PropTypes from 'prop-types' import ScrollContainer from './ScrollContainer' -class AppLayout extends React.Component { - static propTypes = { - toolbar: PropTypes.element.isRequired, - layerList: PropTypes.element.isRequired, - layerEditor: PropTypes.element, - map: PropTypes.element.isRequired, - bottom: PropTypes.element, - modals: PropTypes.node, - } +type AppLayoutProps = { + toolbar: React.ReactElement + layerList: React.ReactElement + layerEditor?: React.ReactElement + map: React.ReactElement + bottom?: React.ReactElement + modals?: React.ReactNode +}; +class AppLayout extends React.Component { static childContextTypes = { reactIconBase: PropTypes.object } diff --git a/src/components/AppMessagePanel.jsx b/src/components/AppMessagePanel.tsx similarity index 62% rename from src/components/AppMessagePanel.jsx rename to src/components/AppMessagePanel.tsx index 3f69343c2..90948000e 100644 --- a/src/components/AppMessagePanel.jsx +++ b/src/components/AppMessagePanel.tsx @@ -1,29 +1,28 @@ import React from 'react' -import PropTypes from 'prop-types' import {formatLayerId} from '../util/format'; +import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec'; -export default class AppMessagePanel extends React.Component { - static propTypes = { - errors: PropTypes.array, - infos: PropTypes.array, - mapStyle: PropTypes.object, - onLayerSelect: PropTypes.func, - currentLayer: PropTypes.object, - selectedLayerIndex: PropTypes.number, - } +type AppMessagePanelProps = { + errors?: unknown[] + infos?: unknown[] + mapStyle?: StyleSpecification + onLayerSelect?(...args: unknown[]): unknown + currentLayer?: object + selectedLayerIndex?: number +}; +export default class AppMessagePanel extends React.Component { static defaultProps = { onLayerSelect: () => {}, } render() { const {selectedLayerIndex} = this.props; - const errors = this.props.errors.map((error, idx) => { + const errors = this.props.errors?.map((error: any, idx) => { let content; if (error.parsed && error.parsed.type === "layer") { const {parsed} = error; - const {mapStyle, currentLayer} = this.props; - const layerId = mapStyle.layers[parsed.data.index].id; + const layerId = this.props.mapStyle?.layers[parsed.data.index].id; content = ( <> Layer {formatLayerId(layerId)}: {parsed.data.message} @@ -32,7 +31,7 @@ export default class AppMessagePanel extends React.Component {  —  @@ -49,7 +48,7 @@ export default class AppMessagePanel extends React.Component {

}) - const infos = this.props.infos.map((m, i) => { + const infos = this.props.infos?.map((m, i) => { return

{m}

}) diff --git a/src/components/AppToolbar.jsx b/src/components/AppToolbar.tsx similarity index 77% rename from src/components/AppToolbar.jsx rename to src/components/AppToolbar.tsx index 13d62caef..97e4ac793 100644 --- a/src/components/AppToolbar.jsx +++ b/src/components/AppToolbar.tsx @@ -1,5 +1,4 @@ import React from 'react' -import PropTypes from 'prop-types' import classnames from 'classnames' import {detect} from 'detect-browser'; @@ -9,27 +8,28 @@ import pkgJson from '../../package.json' // This is required because of , there isn't another way to detect support that I'm aware of. const browser = detect(); -const colorAccessibilityFiltersEnabled = ['chrome', 'firefox'].indexOf(browser.name) > -1; +const colorAccessibilityFiltersEnabled = ['chrome', 'firefox'].indexOf(browser!.name) > -1; -class IconText extends React.Component { - static propTypes = { - children: PropTypes.node, - } +type IconTextProps = { + children?: React.ReactNode +}; + +class IconText extends React.Component { render() { return {this.props.children} } } -class ToolbarLink extends React.Component { - static propTypes = { - className: PropTypes.string, - children: PropTypes.node, - href: PropTypes.string, - onToggleModal: PropTypes.func, - } +type ToolbarLinkProps = { + className?: string + children?: React.ReactNode + href?: string + onToggleModal?(...args: unknown[]): unknown +}; +class ToolbarLink extends React.Component { render() { return { render() { return { render() { return
{ render() { return @@ -246,7 +246,7 @@ export default class AppToolbar extends React.Component { className="maputnik-select" data-wd-key="maputnik-select" onChange={(e) => this.handleSelection(e.target.value)} - value={currentView.id} + value={currentView?.id} > {views.filter(v => v.group === "general").map((item) => { return ( diff --git a/src/components/MapMaplibreGlLayerPopup.jsx b/src/components/MapMaplibreGlLayerPopup.tsx similarity index 83% rename from src/components/MapMaplibreGlLayerPopup.jsx rename to src/components/MapMaplibreGlLayerPopup.tsx index d378ab6fe..e7e49b3b0 100644 --- a/src/components/MapMaplibreGlLayerPopup.jsx +++ b/src/components/MapMaplibreGlLayerPopup.tsx @@ -1,18 +1,16 @@ import React from 'react' -import PropTypes from 'prop-types' import IconLayer from './IconLayer' -import {latest} from '@maplibre/maplibre-gl-style-spec' -function groupFeaturesBySourceLayer(features) { - const sources = {} +function groupFeaturesBySourceLayer(features: any[]) { + const sources = {} as any - let returnedFeatures = {}; + let returnedFeatures = {} as any; features.forEach(feature => { if(returnedFeatures.hasOwnProperty(feature.layer.id)) { returnedFeatures[feature.layer.id]++ - const featureObject = sources[feature.layer['source-layer']].find(f => f.layer.id === feature.layer.id) + const featureObject = sources[feature.layer['source-layer']].find((f: any) => f.layer.id === feature.layer.id) featureObject.counter = returnedFeatures[feature.layer.id] } else { @@ -26,14 +24,14 @@ function groupFeaturesBySourceLayer(features) { return sources } -class FeatureLayerPopup extends React.Component { - static propTypes = { - onLayerSelect: PropTypes.func.isRequired, - features: PropTypes.array, - zoom: PropTypes.number, - } +type FeatureLayerPopupProps = { + onLayerSelect(...args: unknown[]): unknown + features: any[] + zoom?: number +}; - _getFeatureColor(feature, zoom) { +class FeatureLayerPopup extends React.Component { + _getFeatureColor(feature: any, _zoom?: number) { // Guard because openlayers won't have this if (!feature.layer.paint) { return; @@ -57,7 +55,6 @@ class FeatureLayerPopup extends React.Component { } if(propName) { - const propertySpec = latest["paint_"+feature.layer.type][propName]; let color = feature.layer.paint[propName]; return String(color); } @@ -78,7 +75,7 @@ class FeatureLayerPopup extends React.Component { const sources = groupFeaturesBySourceLayer(this.props.features) const items = Object.keys(sources).map(vectorLayerId => { - const layers = sources[vectorLayerId].map((feature, idx) => { + const layers = sources[vectorLayerId].map((feature: any, idx: number) => { const featureColor = this._getFeatureColor(feature, this.props.zoom); return
{ static defaultProps = { onMapLoaded: () => {}, onDataChange: () => {}, onLayerSelect: () => {}, } + updateStyle: any; + map: any; + container: HTMLDivElement | null = null; + overlay: Overlay | undefined; + popupContainer: HTMLElement | null = null; - constructor(props) { + constructor(props: MapOpenLayersProps) { super(props); this.state = { - zoom: 0, - rotation: 0, - cursor: [], + zoom: "0", + rotation: "0", + cursor: [] as string[], center: [], }; this.updateStyle = throttle(this._updateStyle.bind(this), 200); } - _updateStyle(newMapStyle) { + _updateStyle(newMapStyle: StyleSpecification) { if(!this.map) return; // See @@ -60,7 +72,7 @@ export default class MapOpenLayers extends React.Component { apply(this.map, newMapStyle); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: MapOpenLayersProps) { if (this.props.mapStyle !== prevProps.mapStyle) { this.updateStyle( this.props.replaceAccessTokens(this.props.mapStyle) @@ -70,7 +82,7 @@ export default class MapOpenLayers extends React.Component { componentDidMount() { this.overlay = new Overlay({ - element: this.popupContainer, + element: this.popupContainer!, autoPan: true, autoPanAnimation: { duration: 250 @@ -78,7 +90,7 @@ export default class MapOpenLayers extends React.Component { }); const map = new Map({ - target: this.container, + target: this.container!, overlays: [this.overlay], view: new View({ zoom: 1, @@ -98,7 +110,7 @@ export default class MapOpenLayers extends React.Component { const onMoveEnd = () => { const zoom = map.getView().getZoom(); - const center = toLonLat(map.getView().getCenter()); + const center = toLonLat(map.getView().getCenter()!); this.props.onChange({ zoom, @@ -112,15 +124,15 @@ export default class MapOpenLayers extends React.Component { onMoveEnd(); map.on('moveend', onMoveEnd); - map.on('postrender', (evt) => { - const center = toLonLat(map.getView().getCenter()); + map.on('postrender', (_e) => { + const center = toLonLat(map.getView().getCenter()!); this.setState({ center: [ center[0].toFixed(2), center[1].toFixed(2), ], rotation: map.getView().getRotation().toFixed(2), - zoom: map.getView().getZoom().toFixed(2) + zoom: map.getView().getZoom()!.toFixed(2) }); }); @@ -132,9 +144,9 @@ export default class MapOpenLayers extends React.Component { ); } - closeOverlay = (e) => { + closeOverlay = (e: any) => { e.target.blur(); - this.overlay.setPosition(undefined); + this.overlay!.setPosition(undefined); } render() { diff --git a/src/util/format.js b/src/util/format.js deleted file mode 100644 index 44e494d66..000000000 --- a/src/util/format.js +++ /dev/null @@ -1,3 +0,0 @@ -export function formatLayerId (id) { - return id === "" ? "[empty_string]" : `'${id}'`; -} diff --git a/src/util/format.ts b/src/util/format.ts new file mode 100644 index 000000000..4d84da606 --- /dev/null +++ b/src/util/format.ts @@ -0,0 +1,3 @@ +export function formatLayerId (id: string | undefined) { + return id === "" ? "[empty_string]" : `'${id}'`; +}