From 12def857719267bf64259131f8d3f5b7d187465d Mon Sep 17 00:00:00 2001 From: HarelM Date: Fri, 22 Dec 2023 00:16:13 +0200 Subject: [PATCH] More migration of components --- package-lock.json | 7 + package.json | 1 + src/components/FieldCheckbox.jsx | 20 --- src/components/FieldCheckbox.tsx | 18 +++ src/components/FieldDynamicArray.jsx | 21 --- src/components/FieldDynamicArray.tsx | 16 ++ .../{FieldSource.jsx => FieldSource.tsx} | 19 ++- ...ldSourceLayer.jsx => FieldSourceLayer.tsx} | 17 +- src/components/InputDynamicArray.tsx | 2 +- src/components/InputJson.tsx | 8 +- src/components/{ModalAdd.jsx => ModalAdd.tsx} | 65 ++++---- .../{ModalDebug.jsx => ModalDebug.tsx} | 36 +++-- .../{ModalExport.jsx => ModalExport.tsx} | 34 ++-- .../{ModalSources.jsx => ModalSources.tsx} | 148 +++++++++--------- ...eEditor.jsx => ModalSourcesTypeEditor.tsx} | 98 +++++++----- 15 files changed, 268 insertions(+), 242 deletions(-) delete mode 100644 src/components/FieldCheckbox.jsx create mode 100644 src/components/FieldCheckbox.tsx delete mode 100644 src/components/FieldDynamicArray.jsx create mode 100644 src/components/FieldDynamicArray.tsx rename src/components/{FieldSource.jsx => FieldSource.tsx} (61%) rename src/components/{FieldSourceLayer.jsx => FieldSourceLayer.tsx} (65%) rename src/components/{ModalAdd.jsx => ModalAdd.tsx} (67%) rename src/components/{ModalDebug.jsx => ModalDebug.tsx} (60%) rename src/components/{ModalExport.jsx => ModalExport.tsx} (83%) rename src/components/{ModalSources.jsx => ModalSources.tsx} (60%) rename src/components/{ModalSourcesTypeEditor.jsx => ModalSourcesTypeEditor.tsx} (74%) diff --git a/package-lock.json b/package-lock.json index 24fa6919..4e86afa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,6 +70,7 @@ "@types/codemirror": "^5.60.15", "@types/color": "^3.0.6", "@types/cors": "^2.8.17", + "@types/file-saver": "^2.0.7", "@types/lodash.capitalize": "^4.2.9", "@types/lodash.isequal": "^4.5.8", "@types/lodash.throttle": "^4.1.9", @@ -4711,6 +4712,12 @@ "@types/send": "*" } }, + "node_modules/@types/file-saver": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz", + "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==", + "dev": true + }, "node_modules/@types/find-cache-dir": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", diff --git a/package.json b/package.json index fd9e9624..1d8d73ef 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "@types/codemirror": "^5.60.15", "@types/color": "^3.0.6", "@types/cors": "^2.8.17", + "@types/file-saver": "^2.0.7", "@types/lodash.capitalize": "^4.2.9", "@types/lodash.isequal": "^4.5.8", "@types/lodash.throttle": "^4.1.9", diff --git a/src/components/FieldCheckbox.jsx b/src/components/FieldCheckbox.jsx deleted file mode 100644 index 7cdc08b8..00000000 --- a/src/components/FieldCheckbox.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import Block from './Block' -import InputCheckbox from './InputCheckbox' - - -export default class FieldCheckbox extends React.Component { - static propTypes = { - ...InputCheckbox.propTypes, - } - - render() { - const {props} = this; - - return - - - } -} - diff --git a/src/components/FieldCheckbox.tsx b/src/components/FieldCheckbox.tsx new file mode 100644 index 00000000..28041ac4 --- /dev/null +++ b/src/components/FieldCheckbox.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import Block from './Block' +import InputCheckbox, {InputCheckboxProps} from './InputCheckbox' + + +type FieldCheckboxProps = InputCheckboxProps & { + label?: string; +}; + + +export default class FieldCheckbox extends React.Component { + render() { + return + + + } +} + diff --git a/src/components/FieldDynamicArray.jsx b/src/components/FieldDynamicArray.jsx deleted file mode 100644 index 47bbbaf5..00000000 --- a/src/components/FieldDynamicArray.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import Block from './Block' -import InputDynamicArray from './InputDynamicArray' -import Fieldset from './Fieldset' - -export default class FieldDynamicArray extends React.Component { - static propTypes = { - ...InputDynamicArray.propTypes, - name: PropTypes.string, - } - - render() { - const {props} = this; - - return
- -
- } -} - diff --git a/src/components/FieldDynamicArray.tsx b/src/components/FieldDynamicArray.tsx new file mode 100644 index 00000000..fc3666b6 --- /dev/null +++ b/src/components/FieldDynamicArray.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import InputDynamicArray, {FieldDynamicArrayProps as InputDynamicArrayProps} from './InputDynamicArray' +import Fieldset from './Fieldset' + +type FieldDynamicArrayProps = InputDynamicArrayProps & { + name?: string +}; + +export default class FieldDynamicArray extends React.Component { + render() { + return
+ +
+ } +} + diff --git a/src/components/FieldSource.jsx b/src/components/FieldSource.tsx similarity index 61% rename from src/components/FieldSource.jsx rename to src/components/FieldSource.tsx index 68400f5e..c20e9eae 100644 --- a/src/components/FieldSource.jsx +++ b/src/components/FieldSource.tsx @@ -1,19 +1,18 @@ import React from 'react' -import PropTypes from 'prop-types' import {latest} from '@maplibre/maplibre-gl-style-spec' import Block from './Block' import InputAutocomplete from './InputAutocomplete' -export default class FieldSource extends React.Component { - static propTypes = { - value: PropTypes.string, - wdKey: PropTypes.string, - onChange: PropTypes.func, - sourceIds: PropTypes.array, - error: PropTypes.object, - } +type FieldSourceProps = { + value?: string + wdKey?: string + onChange?(...args: unknown[]): unknown + sourceIds?: unknown[] + error?: unknown[] +}; +export default class FieldSource extends React.Component { static defaultProps = { onChange: () => {}, sourceIds: [], @@ -29,7 +28,7 @@ export default class FieldSource extends React.Component { [src, src])} + options={this.props.sourceIds?.map(src => [src, src])} /> } diff --git a/src/components/FieldSourceLayer.jsx b/src/components/FieldSourceLayer.tsx similarity index 65% rename from src/components/FieldSourceLayer.jsx rename to src/components/FieldSourceLayer.tsx index 044a673a..6bc056c8 100644 --- a/src/components/FieldSourceLayer.jsx +++ b/src/components/FieldSourceLayer.tsx @@ -1,18 +1,17 @@ import React from 'react' -import PropTypes from 'prop-types' import {latest} from '@maplibre/maplibre-gl-style-spec' import Block from './Block' import InputAutocomplete from './InputAutocomplete' -export default class FieldSourceLayer extends React.Component { - static propTypes = { - value: PropTypes.string, - onChange: PropTypes.func, - sourceLayerIds: PropTypes.array, - isFixed: PropTypes.bool, - } +type FieldSourceLayerProps = { + value?: string + onChange?(...args: unknown[]): unknown + sourceLayerIds?: unknown[] + isFixed?: boolean +}; +export default class FieldSourceLayer extends React.Component { static defaultProps = { onChange: () => {}, sourceLayerIds: [], @@ -27,7 +26,7 @@ export default class FieldSourceLayer extends React.Component { keepMenuWithinWindowBounds={!!this.props.isFixed} value={this.props.value} onChange={this.props.onChange} - options={this.props.sourceLayerIds.map(l => [l, l])} + options={this.props.sourceLayerIds?.map(l => [l, l])} /> } diff --git a/src/components/InputDynamicArray.tsx b/src/components/InputDynamicArray.tsx index aef615f7..4de4ab18 100644 --- a/src/components/InputDynamicArray.tsx +++ b/src/components/InputDynamicArray.tsx @@ -12,7 +12,7 @@ import InputUrl from './InputUrl' export type FieldDynamicArrayProps = { value?: (string | number)[] - type?: 'url' | 'number' | 'enum' + type?: 'url' | 'number' | 'enum' | 'string' default?: (string | number)[] onChange?(...args: unknown[]): unknown style?: object diff --git a/src/components/InputJson.tsx b/src/components/InputJson.tsx index cf1d3529..544fbe29 100644 --- a/src/components/InputJson.tsx +++ b/src/components/InputJson.tsx @@ -17,7 +17,7 @@ export type InputJsonProps = { onChange?(...args: unknown[]): unknown lineNumbers?: boolean lineWrapping?: boolean - getValue(data: any): string + getValue?(data: any): string gutters?: string[] className?: string onFocus?(...args: unknown[]): unknown @@ -58,13 +58,13 @@ export default class InputJson extends React.Component { addLayer = () => { const changedLayers = this.props.layers.slice(0) - const layer = { + const layer: ModalAddState = { id: this.state.id, type: this.state.type, } @@ -41,20 +44,21 @@ export default class ModalAdd extends React.Component { this.props.onOpenToggle(false) } - constructor(props) { + constructor(props: ModalAddProps) { super(props) - this.state = { + const state: ModalAddState = { type: 'fill', id: '', } if(props.sources.length > 0) { - this.state.source = Object.keys(this.props.sources)[0] - this.state['source-layer'] = this.props.sources[this.state.source][0] + state.source = Object.keys(this.props.sources)[0]; + state['source-layer'] = this.props.sources[state.source as keyof ModalAddProps["sources"]][0] } + this.state = state; } - componentDidUpdate(prevProps, prevState) { + componentDidUpdate(_prevProps: ModalAddProps, prevState: ModalAddState) { // Check if source is valid for new type const oldType = prevState.type; const newType = this.state.type; @@ -67,9 +71,9 @@ export default class ModalAdd extends React.Component { oldType !== newType && prevState.source !== "" // Was a valid source previously - && availableSourcesOld.indexOf(prevState.source) > -1 + && availableSourcesOld.indexOf(prevState.source!) > -1 // And is not a valid source now - && availableSourcesNew.indexOf(this.state.source) < 0 + && availableSourcesNew.indexOf(this.state.source!) < 0 ) { // Clear the source this.setState({ @@ -78,12 +82,12 @@ export default class ModalAdd extends React.Component { } } - getLayersForSource(source) { + getLayersForSource(source: string) { const sourceObj = this.props.sources[source] || {}; return sourceObj.layers || []; } - getSources(type) { + getSources(type: string) { const sources = []; const types = { @@ -108,8 +112,9 @@ export default class ModalAdd extends React.Component { ] } - for(let [key, val] of Object.entries(this.props.sources)) { - if(types[val.type] && types[val.type].indexOf(type) > -1) { + for(let [key, val] of Object.entries(this.props.sources) as any) { + const valType = val.type as keyof typeof types; + if(types[valType] && types[valType].indexOf(type) > -1) { sources.push(key); } } @@ -120,7 +125,7 @@ export default class ModalAdd extends React.Component { render() { const sources = this.getSources(this.state.type); - const layers = this.getLayersForSource(this.state.source); + const layers = this.getLayersForSource(this.state.source!); return
{ + onChange={(v: string) => { this.setState({ id: v }) }} /> this.setState({ type: v })} + onChange={(v: string) => this.setState({ type: v })} /> {this.state.type !== 'background' && this.setState({ source: v })} + onChange={(v: string) => this.setState({ source: v })} /> } {['background', 'raster', 'hillshade', 'heatmap'].indexOf(this.state.type) < 0 && @@ -157,7 +160,7 @@ export default class ModalAdd extends React.Component { isFixed={true} sourceLayerIds={layers} value={this.state['source-layer']} - onChange={v => this.setState({ 'source-layer': v })} + onChange={(v: string) => this.setState({ 'source-layer': v })} /> } { render() { const {mapView} = this.props; @@ -33,10 +39,10 @@ export default class ModalDebug extends React.Component {

Options

{this.props.renderer === 'mlgljs' &&
    - {Object.entries(this.props.maplibreGlDebugOptions).map(([key, val]) => { + {Object.entries(this.props.maplibreGlDebugOptions!).map(([key, val]) => { return
  • })} @@ -44,10 +50,10 @@ export default class ModalDebug extends React.Component { } {this.props.renderer === 'ol' &&
      - {Object.entries(this.props.openlayersDebugOptions).map(([key, val]) => { + {Object.entries(this.props.openlayersDebugOptions!).map(([key, val]) => { return
    • })} diff --git a/src/components/ModalExport.jsx b/src/components/ModalExport.tsx similarity index 83% rename from src/components/ModalExport.jsx rename to src/components/ModalExport.tsx index eab76464..e78782e4 100644 --- a/src/components/ModalExport.jsx +++ b/src/components/ModalExport.tsx @@ -1,13 +1,13 @@ import React from 'react' -import PropTypes from 'prop-types' import Slugify from 'slugify' import {saveAs} from 'file-saver' -import {version} from 'maplibre-gl' -import {format} from '@maplibre/maplibre-gl-style-spec' +import {version} from 'maplibre-gl/package.json' +import {StyleSpecification, format} from '@maplibre/maplibre-gl-style-spec' +import {MdFileDownload} from 'react-icons/md' + import FieldString from './FieldString' import InputButton from './InputButton' import Modal from './Modal' -import {MdFileDownload} from 'react-icons/md' import style from '../libs/style' import fieldSpecAdditional from '../libs/field-spec-additional' @@ -15,17 +15,15 @@ import fieldSpecAdditional from '../libs/field-spec-additional' const MAPLIBRE_GL_VERSION = version; -export default class ModalExport extends React.Component { - static propTypes = { - mapStyle: PropTypes.object.isRequired, - onStyleChanged: PropTypes.func.isRequired, - isOpen: PropTypes.bool.isRequired, - onOpenToggle: PropTypes.func.isRequired, - } +type ModalExportProps = { + mapStyle: StyleSpecification & { id: string } + onStyleChanged(...args: unknown[]): unknown + isOpen: boolean + onOpenToggle(...args: unknown[]): unknown +}; - constructor(props) { - super(props); - } + +export default class ModalExport extends React.Component { tokenizedStyle () { return format( @@ -88,11 +86,11 @@ export default class ModalExport extends React.Component { saveAs(blob, exportName + ".json"); } - changeMetadataProperty(property, value) { + changeMetadataProperty(property: string, value: any) { const changedStyle = { ...this.props.mapStyle, metadata: { - ...this.props.mapStyle.metadata, + ...this.props.mapStyle.metadata as any, [property]: value } } @@ -119,13 +117,13 @@ export default class ModalExport extends React.Component {
diff --git a/src/components/ModalSources.jsx b/src/components/ModalSources.tsx similarity index 60% rename from src/components/ModalSources.jsx rename to src/components/ModalSources.tsx index d6c1e788..aad35cf4 100644 --- a/src/components/ModalSources.jsx +++ b/src/components/ModalSources.tsx @@ -1,12 +1,10 @@ import React from 'react' -import PropTypes from 'prop-types' -import {latest} from '@maplibre/maplibre-gl-style-spec' +import {GeoJSONSourceSpecification, RasterDEMSourceSpecification, RasterSourceSpecification, SourceSpecification, StyleSpecification, VectorSourceSpecification, latest} from '@maplibre/maplibre-gl-style-spec' import Modal from './Modal' import InputButton from './InputButton' -import Block from './Block' import FieldString from './FieldString' import FieldSelect from './FieldSelect' -import ModalSourcesTypeEditor from './ModalSourcesTypeEditor' +import ModalSourcesTypeEditor, { EditorMode } from './ModalSourcesTypeEditor' import style from '../libs/style' import { deleteSource, addSource, changeSource } from '../libs/source' @@ -14,32 +12,32 @@ import publicSources from '../config/tilesets.json' import {MdAddCircleOutline, MdDelete} from 'react-icons/md' -class PublicSource extends React.Component { - static propTypes = { - id: PropTypes.string.isRequired, - type: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - onSelect: PropTypes.func.isRequired, - } +type PublicSourceProps = { + id: string + type: string + title: string + onSelect(...args: unknown[]): unknown +}; +class PublicSource extends React.Component { render() { return
- this.props.onSelect(this.props.id)} - > -
-

{this.props.title}

-

#{this.props.id}

-
- - -
+ onClick={() => this.props.onSelect(this.props.id)} + > +
+

{this.props.title}

+

#{this.props.id}

+
+ + +
} } -function editorMode(source) { +function editorMode(source: SourceSpecification) { if(source.type === 'raster') { if(source.tiles) return 'tilexyz_raster' return 'tilejson_raster' @@ -69,16 +67,15 @@ function editorMode(source) { return null } -class ActiveModalSourcesTypeEditor extends React.Component { - static propTypes = { - sourceId: PropTypes.string.isRequired, - source: PropTypes.object.isRequired, - onDelete: PropTypes.func.isRequired, - onChange: PropTypes.func.isRequired, - } +type ActiveModalSourcesTypeEditorProps = { + sourceId: string + source: SourceSpecification + onDelete(...args: unknown[]): unknown + onChange(...args: unknown[]): unknown +}; +class ActiveModalSourcesTypeEditor extends React.Component { render() { - const inputProps = { } return
#{this.props.sourceId} @@ -103,12 +100,18 @@ class ActiveModalSourcesTypeEditor extends React.Component { } } -class AddSource extends React.Component { - static propTypes = { - onAdd: PropTypes.func.isRequired, - } +type AddSourceProps = { + onAdd(...args: unknown[]): unknown +}; - constructor(props) { +type AddSourceState = { + mode: EditorMode + sourceId: string + source: SourceSpecification +}; + +class AddSource extends React.Component { + constructor(props: AddSourceProps) { super(props) this.state = { mode: 'tilejson_vector', @@ -117,7 +120,7 @@ class AddSource extends React.Component { } } - defaultSource(mode) { + defaultSource(mode: EditorMode): SourceSpecification { const source = (this.state || {}).source || {} const {protocol} = window.location; @@ -128,38 +131,38 @@ class AddSource extends React.Component { } case 'geojson_json': return { type: 'geojson', - cluster: source.cluster || false, + cluster: (source as GeoJSONSourceSpecification).cluster || false, data: {} } case 'tilejson_vector': return { type: 'vector', - url: source.url || `${protocol}//localhost:3000/tilejson.json` + url: (source as VectorSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json` } case 'tilexyz_vector': return { type: 'vector', - tiles: source.tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`], - minZoom: source.minzoom || 0, - maxZoom: source.maxzoom || 14 + tiles: (source as VectorSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`], + minzoom: (source as VectorSourceSpecification).minzoom || 0, + maxzoom: (source as VectorSourceSpecification).maxzoom || 14 } case 'tilejson_raster': return { type: 'raster', - url: source.url || `${protocol}//localhost:3000/tilejson.json` + url: (source as RasterSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json` } case 'tilexyz_raster': return { type: 'raster', - tiles: source.tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`], - minzoom: source.minzoom || 0, - maxzoom: source.maxzoom || 14 + tiles: (source as RasterSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`], + minzoom: (source as RasterSourceSpecification).minzoom || 0, + maxzoom: (source as RasterSourceSpecification).maxzoom || 14 } case 'tilejson_raster-dem': return { type: 'raster-dem', - url: source.url || `${protocol}//localhost:3000/tilejson.json` + url: (source as RasterDEMSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json` } case 'tilexyz_raster-dem': return { type: 'raster-dem', - tiles: source.tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`], - minzoom: source.minzoom || 0, - maxzoom: source.maxzoom || 14 + tiles: (source as RasterDEMSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`], + minzoom: (source as RasterDEMSourceSpecification).minzoom || 0, + maxzoom: (source as RasterDEMSourceSpecification).maxzoom || 14 } case 'image': return { type: 'image', @@ -183,7 +186,7 @@ class AddSource extends React.Component { [0,0], ], } - default: return {} + default: return {} as any } } @@ -192,7 +195,7 @@ class AddSource extends React.Component { this.props.onAdd(sourceId, source); } - onChangeSource = (source) => { + onChangeSource = (source: SourceSpecification) => { this.setState({source}); } @@ -213,7 +216,7 @@ class AddSource extends React.Component { label={"Source ID"} fieldSpec={{doc: "Unique ID that identifies the source and is used in the layer to reference the source."}} value={this.state.sourceId} - onChange={v => this.setState({ sourceId: v})} + onChange={(v: string) => this.setState({ sourceId: v})} /> this.setState({mode: mode, source: this.defaultSource(mode)})} - value={this.state.mode} + onChange={(mode: EditorMode) => this.setState({mode: mode, source: this.defaultSource(mode)})} + value={this.state.mode as string} /> Add Source @@ -248,15 +251,15 @@ class AddSource extends React.Component { } } -export default class ModalSources extends React.Component { - static propTypes = { - mapStyle: PropTypes.object.isRequired, - isOpen: PropTypes.bool.isRequired, - onOpenToggle: PropTypes.func.isRequired, - onStyleChanged: PropTypes.func.isRequired, - } +type ModalSourcesProps = { + mapStyle: StyleSpecification + isOpen: boolean + onOpenToggle(...args: unknown[]): unknown + onStyleChanged(...args: unknown[]): unknown +}; - stripTitle(source) { +export default class ModalSources extends React.Component { + stripTitle(source: SourceSpecification & {title?: string}): SourceSpecification { const strippedSource = {...source} delete strippedSource['title'] return strippedSource @@ -270,13 +273,13 @@ export default class ModalSources extends React.Component { key={sourceId} sourceId={sourceId} source={source} - onChange={src => this.props.onStyleChanged(changeSource(mapStyle, sourceId, src))} + onChange={(src: SourceSpecification) => this.props.onStyleChanged(changeSource(mapStyle, sourceId, src))} onDelete={() => this.props.onStyleChanged(deleteSource(mapStyle, sourceId))} /> }) - const tilesetOptions = Object.keys(publicSources).filter(sourceId => !(sourceId in mapStyle.sources)).map(sourceId => { - const source = publicSources[sourceId] + const tilesetOptions = Object.keys(publicSources).filter((sourceId: string) => !(sourceId in mapStyle.sources)).map((sourceId: string) => { + const source = publicSources[sourceId as keyof typeof publicSources] as SourceSpecification & {title: string}; return }) - const inputProps = { } return Add one of the publicly available sources to your style.

-
+
{tilesetOptions}
-

Add New Source

-

Add a new source to your style. You can only choose the source type and id at creation time!

- this.props.onStyleChanged(addSource(mapStyle, sourceId, source))} - /> +

Add New Source

+

Add a new source to your style. You can only choose the source type and id at creation time!

+ this.props.onStyleChanged(addSource(mapStyle, sourceId, source))} + />
} diff --git a/src/components/ModalSourcesTypeEditor.jsx b/src/components/ModalSourcesTypeEditor.tsx similarity index 74% rename from src/components/ModalSourcesTypeEditor.jsx rename to src/components/ModalSourcesTypeEditor.tsx index ba6ebf12..e51b7f30 100644 --- a/src/components/ModalSourcesTypeEditor.jsx +++ b/src/components/ModalSourcesTypeEditor.tsx @@ -1,5 +1,4 @@ import React from 'react' -import PropTypes from 'prop-types' import {latest} from '@maplibre/maplibre-gl-style-spec' import Block from './Block' import FieldUrl from './FieldUrl' @@ -10,14 +9,18 @@ import FieldArray from './FieldArray' import FieldJson from './FieldJson' import FieldCheckbox from './FieldCheckbox' +export type EditorMode = "video" | "image" | "tilejson_vector" | "tilexyz_raster" | "tilejson_raster" | "tilexyz_raster-dem" | "tilejson_raster-dem" | "tilexyz_vector" | "geojson_url" | "geojson_json" | null; -class TileJSONSourceEditor extends React.Component { - static propTypes = { - source: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, - children: PropTypes.node, +type TileJSONSourceEditorProps = { + source: { + url: string } + onChange(...args: unknown[]): unknown + children?: React.ReactNode +}; + +class TileJSONSourceEditor extends React.Component { render() { return
{ + changeTileUrls(tiles: string[]) { this.props.onChange({ ...this.props.source, tiles, @@ -86,14 +93,17 @@ class TileURLSourceEditor extends React.Component { } } -class ImageSourceEditor extends React.Component { - static propTypes = { - source: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, +type ImageSourceEditorProps = { + source: { + coordinates: [number, number][] + url: string } + onChange(...args: unknown[]): unknown +}; +class ImageSourceEditor extends React.Component { render() { - const changeCoord = (idx, val) => { + const changeCoord = (idx: number, val: [number, number]) => { const coordinates = this.props.source.coordinates.slice(0); coordinates[idx] = val; @@ -122,7 +132,7 @@ class ImageSourceEditor extends React.Component { type="number" value={this.props.source.coordinates[idx]} default={[0, 0]} - onChange={(val) => changeCoord(idx, val)} + onChange={(val: [number, number]) => changeCoord(idx, val)} /> ); })} @@ -130,14 +140,17 @@ class ImageSourceEditor extends React.Component { } } -class VideoSourceEditor extends React.Component { - static propTypes = { - source: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, +type VideoSourceEditorProps = { + source: { + coordinates: [number, number][] + urls: string[] } + onChange(...args: unknown[]): unknown +}; +class VideoSourceEditor extends React.Component { render() { - const changeCoord = (idx, val) => { + const changeCoord = (idx: number, val: [number, number]) => { const coordinates = this.props.source.coordinates.slice(0); coordinates[idx] = val; @@ -147,7 +160,7 @@ class VideoSourceEditor extends React.Component { }); } - const changeUrls = (urls) => { + const changeUrls = (urls: string[]) => { this.props.onChange({ ...this.props.source, urls, @@ -160,7 +173,7 @@ class VideoSourceEditor extends React.Component { fieldSpec={latest.source_video.urls} type="string" value={this.props.source.urls} - default={""} + default={[]} onChange={changeUrls} /> {["top left", "top right", "bottom right", "bottom left"].map((label, idx) => { @@ -172,7 +185,7 @@ class VideoSourceEditor extends React.Component { type="number" value={this.props.source.coordinates[idx]} default={[0, 0]} - onChange={val => changeCoord(idx, val)} + onChange={(val: [number, number]) => changeCoord(idx, val)} /> ); })} @@ -180,12 +193,14 @@ class VideoSourceEditor extends React.Component { } } -class GeoJSONSourceUrlEditor extends React.Component { - static propTypes = { - source: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, +type GeoJSONSourceUrlEditorProps = { + source: { + data: string } + onChange(...args: unknown[]): unknown +}; +class GeoJSONSourceUrlEditor extends React.Component { render() { return { render() { return
@@ -238,13 +256,13 @@ class GeoJSONSourceFieldJsonEditor extends React.Component { } } -export default class ModalSourcesTypeEditor extends React.Component { - static propTypes = { - mode: PropTypes.string.isRequired, - source: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, - } +type ModalSourcesTypeEditorProps = { + mode: EditorMode + source: any + onChange(...args: unknown[]): unknown +}; +export default class ModalSourcesTypeEditor extends React.Component { render() { const commonProps = { source: this.props.source,