mirror of
https://github.com/maputnik/editor.git
synced 2026-02-05 20:20:02 +00:00
Migrate App to tsx
This commit is contained in:
37
package-lock.json
generated
37
package-lock.json
generated
@@ -72,6 +72,9 @@
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/lodash.capitalize": "^4.2.9",
|
||||
"@types/lodash.clamp": "^4.0.9",
|
||||
"@types/lodash.clonedeep": "^4.5.9",
|
||||
"@types/lodash.get": "^4.4.9",
|
||||
"@types/lodash.isequal": "^4.5.8",
|
||||
"@types/lodash.throttle": "^4.1.9",
|
||||
"@types/react": "^16.14.52",
|
||||
@@ -83,6 +86,7 @@
|
||||
"@types/react-dom": "^16.9.24",
|
||||
"@types/react-file-reader-input": "^2.0.4",
|
||||
"@types/react-icon-base": "^2.1.6",
|
||||
"@types/string-hash": "^1.1.3",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"cors": "^2.8.5",
|
||||
@@ -4762,6 +4766,33 @@
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash.clamp": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.clamp/-/lodash.clamp-4.0.9.tgz",
|
||||
"integrity": "sha512-t+hBIPHXyBVYkl0KEAEchOJwBrG8czt3E7r5fdpwMRrn3g+hkRzw6cjzWl+nJg3Z2QqRaQLt+W2n4ikwGr1u2g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash.clonedeep": {
|
||||
"version": "4.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.9.tgz",
|
||||
"integrity": "sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash.get": {
|
||||
"version": "4.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.get/-/lodash.get-4.4.9.tgz",
|
||||
"integrity": "sha512-J5dvW98sxmGnamqf+/aLP87PYXyrha9xIgc2ZlHl6OHMFR2Ejdxep50QfU0abO1+CH6+ugx+8wEUN1toImAinA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash.isequal": {
|
||||
"version": "4.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.8.tgz",
|
||||
@@ -5023,6 +5054,12 @@
|
||||
"integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/string-hash": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/string-hash/-/string-hash-1.1.3.tgz",
|
||||
"integrity": "sha512-p6skq756fJWiA59g2Uss+cMl6tpoDGuCBuxG0SI1t0NwJmYOU66LAMS6QiCgu7cUh3/hYCaMl5phcCW1JP5wOA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/tern": {
|
||||
"version": "0.23.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz",
|
||||
|
||||
@@ -101,6 +101,9 @@
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/lodash.capitalize": "^4.2.9",
|
||||
"@types/lodash.clamp": "^4.0.9",
|
||||
"@types/lodash.clonedeep": "^4.5.9",
|
||||
"@types/lodash.get": "^4.4.9",
|
||||
"@types/lodash.isequal": "^4.5.8",
|
||||
"@types/lodash.throttle": "^4.1.9",
|
||||
"@types/react": "^16.14.52",
|
||||
@@ -112,6 +115,7 @@
|
||||
"@types/react-dom": "^16.9.24",
|
||||
"@types/react-file-reader-input": "^2.0.4",
|
||||
"@types/react-icon-base": "^2.1.6",
|
||||
"@types/string-hash": "^1.1.3",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import autoBind from 'react-autobind';
|
||||
// @ts-ignore
|
||||
import autoBind from 'react-autobind'; // this can be easily replaced with arrow functions
|
||||
import React from 'react'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import clamp from 'lodash.clamp'
|
||||
@@ -6,14 +7,15 @@ import buffer from 'buffer'
|
||||
import get from 'lodash.get'
|
||||
import {unset} from 'lodash'
|
||||
import {arrayMoveMutable} from 'array-move'
|
||||
import url from 'url'
|
||||
import hash from "string-hash";
|
||||
import {Map, LayerSpecification, StyleSpecification, ValidationError, SourceSpecification} from 'maplibre-gl'
|
||||
import {latest, validate} from '@maplibre/maplibre-gl-style-spec'
|
||||
|
||||
import MapMaplibreGl from './MapMaplibreGl'
|
||||
import MapOpenLayers from './MapOpenLayers'
|
||||
import LayerList from './LayerList'
|
||||
import LayerEditor from './LayerEditor'
|
||||
import AppToolbar from './AppToolbar'
|
||||
import AppToolbar, { MapState } from './AppToolbar'
|
||||
import AppLayout from './AppLayout'
|
||||
import MessagePanel from './AppMessagePanel'
|
||||
|
||||
@@ -25,8 +27,7 @@ import ModalShortcuts from './ModalShortcuts'
|
||||
import ModalSurvey from './ModalSurvey'
|
||||
import ModalDebug from './ModalDebug'
|
||||
|
||||
import { downloadGlyphsMetadata, downloadSpriteMetadata } from '../libs/metadata'
|
||||
import {latest, validate} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {downloadGlyphsMetadata, downloadSpriteMetadata} from '../libs/metadata'
|
||||
import style from '../libs/style'
|
||||
import { initialStyleUrl, loadStyleUrl, removeStyleQuerystring } from '../libs/urlopen'
|
||||
import { undoMessages, redoMessages } from '../libs/diffmessage'
|
||||
@@ -37,12 +38,13 @@ import LayerWatcher from '../libs/layerwatcher'
|
||||
import tokens from '../config/tokens.json'
|
||||
import isEqual from 'lodash.isequal'
|
||||
import Debug from '../libs/debug'
|
||||
import {formatLayerId} from '../util/format';
|
||||
import { SortEnd } from 'react-sortable-hoc';
|
||||
import { MapOptions } from 'maplibre-gl';
|
||||
|
||||
// Buffer must be defined globally for @maplibre/maplibre-gl-style-spec validate() function to succeed.
|
||||
window.Buffer = buffer.Buffer;
|
||||
|
||||
function setFetchAccessToken(url, mapStyle) {
|
||||
function setFetchAccessToken(url: string, mapStyle: StyleSpecification) {
|
||||
const matchesTilehosting = url.match(/\.tilehosting\.com/);
|
||||
const matchesMaptiler = url.match(/\.maptiler\.com/);
|
||||
const matchesThunderforest = url.match(/\.thunderforest\.com/);
|
||||
@@ -63,7 +65,7 @@ function setFetchAccessToken(url, mapStyle) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateRootSpec(spec, fieldName, newValues) {
|
||||
function updateRootSpec(spec: any, fieldName: string, newValues: any) {
|
||||
return {
|
||||
...spec,
|
||||
$root: {
|
||||
@@ -76,15 +78,75 @@ function updateRootSpec(spec, fieldName, newValues) {
|
||||
}
|
||||
}
|
||||
|
||||
export default class App extends React.Component {
|
||||
constructor(props) {
|
||||
type OnStyleChangedOpts = {
|
||||
save?: boolean
|
||||
addRevision?: boolean
|
||||
initialLoad?: boolean
|
||||
}
|
||||
|
||||
type MappedErrors = {
|
||||
message: string
|
||||
parsed?: {
|
||||
type: string
|
||||
data: {
|
||||
index: number
|
||||
key: string
|
||||
message: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type AppState = {
|
||||
errors: MappedErrors[],
|
||||
infos: string[],
|
||||
mapStyle: StyleSpecification & {id: string},
|
||||
dirtyMapStyle?: StyleSpecification,
|
||||
selectedLayerIndex: number,
|
||||
selectedLayerOriginalId?: string,
|
||||
sources: {[key: string]: SourceSpecification},
|
||||
vectorLayers: {},
|
||||
spec: any,
|
||||
mapView: {
|
||||
zoom: number,
|
||||
center: {
|
||||
lng: number,
|
||||
lat: number,
|
||||
},
|
||||
},
|
||||
maplibreGlDebugOptions: Partial<MapOptions> & {
|
||||
showTileBoundaries: boolean,
|
||||
showCollisionBoxes: boolean,
|
||||
showOverdrawInspector: boolean,
|
||||
},
|
||||
openlayersDebugOptions: {
|
||||
debugToolbox: boolean,
|
||||
},
|
||||
mapState: MapState
|
||||
isOpen: {
|
||||
settings: boolean
|
||||
sources: boolean
|
||||
open: boolean
|
||||
shortcuts: boolean
|
||||
export: boolean
|
||||
survey: boolean
|
||||
debug: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export default class App extends React.Component<any, AppState> {
|
||||
revisionStore: RevisionStore;
|
||||
styleStore: StyleStore | ApiStyleStore;
|
||||
layerWatcher: LayerWatcher;
|
||||
shortcutEl: ModalShortcuts | null = null;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
autoBind(this);
|
||||
|
||||
this.revisionStore = new RevisionStore()
|
||||
const params = new URLSearchParams(window.location.search.substring(1))
|
||||
let port = params.get("localport")
|
||||
if (port == null && (window.location.port != 80 && window.location.port != 443)) {
|
||||
if (port == null && (window.location.port !== "80" && window.location.port !== "443")) {
|
||||
port = window.location.port
|
||||
}
|
||||
this.styleStore = new ApiStyleStore({
|
||||
@@ -136,7 +198,7 @@ export default class App extends React.Component {
|
||||
{
|
||||
key: "m",
|
||||
handler: () => {
|
||||
document.querySelector(".maplibregl-canvas").focus();
|
||||
(document.querySelector(".maplibregl-canvas") as HTMLCanvasElement).focus();
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -149,7 +211,7 @@ export default class App extends React.Component {
|
||||
|
||||
document.body.addEventListener("keyup", (e) => {
|
||||
if(e.key === "Escape") {
|
||||
e.target.blur();
|
||||
(e.target as HTMLElement).blur();
|
||||
document.body.focus();
|
||||
}
|
||||
else if(this.state.isOpen.shortcuts || document.activeElement === document.body) {
|
||||
@@ -159,7 +221,7 @@ export default class App extends React.Component {
|
||||
|
||||
if(shortcut) {
|
||||
this.setModal("shortcuts", false);
|
||||
shortcut.handler(e);
|
||||
shortcut.handler();
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -192,8 +254,6 @@ export default class App extends React.Component {
|
||||
Debug.set("maputnik", "styleStore", this.styleStore);
|
||||
}
|
||||
|
||||
const queryObj = url.parse(window.location.href, true).query;
|
||||
|
||||
this.state = {
|
||||
errors: [],
|
||||
infos: [],
|
||||
@@ -235,25 +295,25 @@ export default class App extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
handleKeyPress = (e) => {
|
||||
handleKeyPress = (e: KeyboardEvent) => {
|
||||
if(navigator.platform.toUpperCase().indexOf('MAC') >= 0) {
|
||||
if(e.metaKey && e.shiftKey && e.keyCode === 90) {
|
||||
e.preventDefault();
|
||||
this.onRedo(e);
|
||||
this.onRedo();
|
||||
}
|
||||
else if(e.metaKey && e.keyCode === 90) {
|
||||
e.preventDefault();
|
||||
this.onUndo(e);
|
||||
this.onUndo();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(e.ctrlKey && e.keyCode === 90) {
|
||||
e.preventDefault();
|
||||
this.onUndo(e);
|
||||
this.onUndo();
|
||||
}
|
||||
else if(e.ctrlKey && e.keyCode === 89) {
|
||||
e.preventDefault();
|
||||
this.onRedo(e);
|
||||
this.onRedo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,12 +326,12 @@ export default class App extends React.Component {
|
||||
window.removeEventListener("keydown", this.handleKeyPress);
|
||||
}
|
||||
|
||||
saveStyle(snapshotStyle) {
|
||||
saveStyle(snapshotStyle: StyleSpecification & {id: string}) {
|
||||
this.styleStore.save(snapshotStyle)
|
||||
}
|
||||
|
||||
updateFonts(urlTemplate) {
|
||||
const metadata = this.state.mapStyle.metadata || {}
|
||||
updateFonts(urlTemplate: string) {
|
||||
const metadata: {[key: string]: string} = this.state.mapStyle.metadata || {} as any
|
||||
const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
|
||||
|
||||
let glyphUrl = (typeof urlTemplate === 'string')? urlTemplate.replace('{key}', accessToken): urlTemplate;
|
||||
@@ -280,13 +340,13 @@ export default class App extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
updateIcons(baseUrl) {
|
||||
updateIcons(baseUrl: string) {
|
||||
downloadSpriteMetadata(baseUrl, icons => {
|
||||
this.setState({ spec: updateRootSpec(this.state.spec, 'sprite', icons)})
|
||||
})
|
||||
}
|
||||
|
||||
onChangeMetadataProperty = (property, value) => {
|
||||
onChangeMetadataProperty = (property: string, value: any) => {
|
||||
// If we're changing renderer reset the map state.
|
||||
if (
|
||||
property === 'maputnik:renderer' &&
|
||||
@@ -300,14 +360,14 @@ export default class App extends React.Component {
|
||||
const changedStyle = {
|
||||
...this.state.mapStyle,
|
||||
metadata: {
|
||||
...this.state.mapStyle.metadata,
|
||||
...(this.state.mapStyle as any).metadata,
|
||||
[property]: value
|
||||
}
|
||||
}
|
||||
this.onStyleChanged(changedStyle)
|
||||
}
|
||||
|
||||
onStyleChanged = (newStyle, opts={}) => {
|
||||
onStyleChanged = (newStyle: StyleSpecification & {id: string}, opts: OnStyleChangedOpts={}) => {
|
||||
opts = {
|
||||
save: true,
|
||||
addRevision: true,
|
||||
@@ -319,16 +379,16 @@ export default class App extends React.Component {
|
||||
this.getInitialStateFromUrl(newStyle);
|
||||
}
|
||||
|
||||
const errors = validate(newStyle, latest) || [];
|
||||
// This "any" can be removed in latest version of maplibre where maplibre re-exported types from style-spec
|
||||
const errors = validate(newStyle as any, latest) || [];
|
||||
|
||||
// The validate function doesn't give us errors for duplicate error with
|
||||
// empty string for layer.id, manually deal with that here.
|
||||
const layerErrors = [];
|
||||
const layerErrors: (Error | ValidationError)[] = [];
|
||||
if (newStyle && newStyle.layers) {
|
||||
const foundLayers = new Map();
|
||||
const foundLayers = new global.Map();
|
||||
newStyle.layers.forEach((layer, index) => {
|
||||
if (layer.id === "" && foundLayers.has(layer.id)) {
|
||||
const message = `Duplicate layer: ${formatLayerId(layer.id)}`;
|
||||
const error = new Error(
|
||||
`layers[${index}]: duplicate layer id [empty_string], previously used`
|
||||
);
|
||||
@@ -342,7 +402,7 @@ export default class App extends React.Component {
|
||||
// Special case: Duplicate layer id
|
||||
const dupMatch = error.message.match(/layers\[(\d+)\]: (duplicate layer id "?(.*)"?, previously used)/);
|
||||
if (dupMatch) {
|
||||
const [matchStr, index, message] = dupMatch;
|
||||
const [_matchStr, index, message] = dupMatch;
|
||||
return {
|
||||
message: error.message,
|
||||
parsed: {
|
||||
@@ -359,7 +419,7 @@ export default class App extends React.Component {
|
||||
// Special case: Invalid source
|
||||
const invalidSourceMatch = error.message.match(/layers\[(\d+)\]: (source "(?:.*)" not found)/);
|
||||
if (invalidSourceMatch) {
|
||||
const [matchStr, index, message] = invalidSourceMatch;
|
||||
const [_matchStr, index, message] = invalidSourceMatch;
|
||||
return {
|
||||
message: error.message,
|
||||
parsed: {
|
||||
@@ -375,7 +435,7 @@ export default class App extends React.Component {
|
||||
|
||||
const layerMatch = error.message.match(/layers\[(\d+)\]\.(?:(\S+)\.)?(\S+): (.*)/);
|
||||
if (layerMatch) {
|
||||
const [matchStr, index, group, property, message] = layerMatch;
|
||||
const [_matchStr, index, group, property, message] = layerMatch;
|
||||
const key = (group && property) ? [group, property].join(".") : property;
|
||||
return {
|
||||
message: error.message,
|
||||
@@ -396,7 +456,7 @@ export default class App extends React.Component {
|
||||
}
|
||||
});
|
||||
|
||||
let dirtyMapStyle = undefined;
|
||||
let dirtyMapStyle: StyleSpecification | undefined = undefined;
|
||||
if (errors.length > 0) {
|
||||
dirtyMapStyle = cloneDeep(newStyle);
|
||||
|
||||
@@ -406,7 +466,7 @@ export default class App extends React.Component {
|
||||
try {
|
||||
const objPath = message.split(":")[0];
|
||||
// Errors can be deply nested for example 'layers[0].filter[1][1][0]' we only care upto the property 'layers[0].filter'
|
||||
const unsetPath = objPath.match(/^\S+?\[\d+\]\.[^\[]+/)[0];
|
||||
const unsetPath = objPath.match(/^\S+?\[\d+\]\.[^\[]+/)![0];
|
||||
unset(dirtyMapStyle, unsetPath);
|
||||
}
|
||||
catch (err) {
|
||||
@@ -417,17 +477,17 @@ export default class App extends React.Component {
|
||||
}
|
||||
|
||||
if(newStyle.glyphs !== this.state.mapStyle.glyphs) {
|
||||
this.updateFonts(newStyle.glyphs)
|
||||
this.updateFonts(newStyle.glyphs as string)
|
||||
}
|
||||
if(newStyle.sprite !== this.state.mapStyle.sprite) {
|
||||
this.updateIcons(newStyle.sprite)
|
||||
this.updateIcons(newStyle.sprite as string)
|
||||
}
|
||||
|
||||
if (opts.addRevision) {
|
||||
this.revisionStore.addRevision(newStyle);
|
||||
}
|
||||
if (opts.save) {
|
||||
this.saveStyle(newStyle);
|
||||
this.saveStyle(newStyle as StyleSpecification & {id: string});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
@@ -460,7 +520,7 @@ export default class App extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
onMoveLayer = (move) => {
|
||||
onMoveLayer = (move: SortEnd) => {
|
||||
let { oldIndex, newIndex } = move;
|
||||
let layers = this.state.mapStyle.layers;
|
||||
oldIndex = clamp(oldIndex, 0, layers.length-1);
|
||||
@@ -478,7 +538,7 @@ export default class App extends React.Component {
|
||||
this.onLayersChange(layers);
|
||||
}
|
||||
|
||||
onLayersChange = (changedLayers) => {
|
||||
onLayersChange = (changedLayers: LayerSpecification[]) => {
|
||||
const changedStyle = {
|
||||
...this.state.mapStyle,
|
||||
layers: changedLayers
|
||||
@@ -486,14 +546,14 @@ export default class App extends React.Component {
|
||||
this.onStyleChanged(changedStyle)
|
||||
}
|
||||
|
||||
onLayerDestroy = (index) => {
|
||||
onLayerDestroy = (index: number) => {
|
||||
let layers = this.state.mapStyle.layers;
|
||||
const remainingLayers = layers.slice(0);
|
||||
remainingLayers.splice(index, 1);
|
||||
this.onLayersChange(remainingLayers);
|
||||
}
|
||||
|
||||
onLayerCopy = (index) => {
|
||||
onLayerCopy = (index: number) => {
|
||||
let layers = this.state.mapStyle.layers;
|
||||
const changedLayers = layers.slice(0)
|
||||
|
||||
@@ -503,7 +563,7 @@ export default class App extends React.Component {
|
||||
this.onLayersChange(changedLayers)
|
||||
}
|
||||
|
||||
onLayerVisibilityToggle = (index) => {
|
||||
onLayerVisibilityToggle = (index: number) => {
|
||||
let layers = this.state.mapStyle.layers;
|
||||
const changedLayers = layers.slice(0)
|
||||
|
||||
@@ -517,7 +577,7 @@ export default class App extends React.Component {
|
||||
}
|
||||
|
||||
|
||||
onLayerIdChange = (index, oldId, newId) => {
|
||||
onLayerIdChange = (index: number, _oldId: string, newId: string) => {
|
||||
const changedLayers = this.state.mapStyle.layers.slice(0)
|
||||
changedLayers[index] = {
|
||||
...changedLayers[index],
|
||||
@@ -527,26 +587,26 @@ export default class App extends React.Component {
|
||||
this.onLayersChange(changedLayers)
|
||||
}
|
||||
|
||||
onLayerChanged = (index, layer) => {
|
||||
onLayerChanged = (index: number, layer: LayerSpecification) => {
|
||||
const changedLayers = this.state.mapStyle.layers.slice(0)
|
||||
changedLayers[index] = layer
|
||||
|
||||
this.onLayersChange(changedLayers)
|
||||
}
|
||||
|
||||
setMapState = (newState) => {
|
||||
setMapState = (newState: MapState) => {
|
||||
this.setState({
|
||||
mapState: newState
|
||||
}, this.setStateInUrl);
|
||||
}
|
||||
|
||||
setDefaultValues = (styleObj) => {
|
||||
const metadata = styleObj.metadata || {}
|
||||
setDefaultValues = (styleObj: StyleSpecification & {id: string}) => {
|
||||
const metadata: {[key: string]: string} = styleObj.metadata || {} as any
|
||||
if(metadata['maputnik:renderer'] === undefined) {
|
||||
const changedStyle = {
|
||||
...styleObj,
|
||||
metadata: {
|
||||
...styleObj.metadata,
|
||||
...styleObj.metadata as any,
|
||||
'maputnik:renderer': 'mlgljs'
|
||||
}
|
||||
}
|
||||
@@ -556,13 +616,13 @@ export default class App extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
openStyle = (styleObj) => {
|
||||
openStyle = (styleObj: StyleSpecification & {id: string}) => {
|
||||
styleObj = this.setDefaultValues(styleObj)
|
||||
this.onStyleChanged(styleObj)
|
||||
}
|
||||
|
||||
fetchSources() {
|
||||
const sourceList = {};
|
||||
const sourceList: {[key: string]: any} = {};
|
||||
|
||||
for(let [key, val] of Object.entries(this.state.mapStyle.sources)) {
|
||||
if(
|
||||
@@ -578,12 +638,12 @@ export default class App extends React.Component {
|
||||
let url = val.url;
|
||||
|
||||
try {
|
||||
url = setFetchAccessToken(url, this.state.mapStyle)
|
||||
url = setFetchAccessToken(url!, this.state.mapStyle)
|
||||
} catch(err) {
|
||||
console.warn("Failed to setFetchAccessToken: ", err);
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
fetch(url!, {
|
||||
mode: 'cors',
|
||||
})
|
||||
.then(response => response.json())
|
||||
@@ -599,7 +659,7 @@ export default class App extends React.Component {
|
||||
});
|
||||
|
||||
for(let layer of json.vector_layers) {
|
||||
sources[key].layers.push(layer.id)
|
||||
(sources[key] as any).layers.push(layer.id)
|
||||
}
|
||||
|
||||
console.debug("Updating source: "+key);
|
||||
@@ -625,11 +685,17 @@ export default class App extends React.Component {
|
||||
}
|
||||
|
||||
_getRenderer () {
|
||||
const metadata = this.state.mapStyle.metadata || {};
|
||||
const metadata: {[key:string]: string} = this.state.mapStyle.metadata || {} as any;
|
||||
return metadata['maputnik:renderer'] || 'mlgljs';
|
||||
}
|
||||
|
||||
onMapChange = (mapView) => {
|
||||
onMapChange = (mapView: {
|
||||
zoom: number,
|
||||
center: {
|
||||
lng: number,
|
||||
lat: number,
|
||||
},
|
||||
}) => {
|
||||
this.setState({
|
||||
mapView,
|
||||
});
|
||||
@@ -637,16 +703,15 @@ export default class App extends React.Component {
|
||||
|
||||
mapRenderer() {
|
||||
const {mapStyle, dirtyMapStyle} = this.state;
|
||||
const metadata = this.state.mapStyle.metadata || {};
|
||||
|
||||
const mapProps = {
|
||||
mapStyle: (dirtyMapStyle || mapStyle),
|
||||
replaceAccessTokens: (mapStyle) => {
|
||||
replaceAccessTokens: (mapStyle: StyleSpecification) => {
|
||||
return style.replaceAccessTokens(mapStyle, {
|
||||
allowFallback: true
|
||||
});
|
||||
},
|
||||
onDataChange: (e) => {
|
||||
onDataChange: (e: {map: Map}) => {
|
||||
this.layerWatcher.analyzeMap(e.map)
|
||||
this.fetchSources();
|
||||
},
|
||||
@@ -677,7 +742,7 @@ export default class App extends React.Component {
|
||||
if(this.state.mapState.match(/^filter-/)) {
|
||||
filterName = this.state.mapState.replace(/^filter-/, "");
|
||||
}
|
||||
const elementStyle = {};
|
||||
const elementStyle: {filter?: string} = {};
|
||||
if (filterName) {
|
||||
elementStyle.filter = `url('#${filterName}')`;
|
||||
}
|
||||
@@ -715,12 +780,12 @@ export default class App extends React.Component {
|
||||
history.replaceState({selectedLayerIndex}, "Maputnik", url.href);
|
||||
}
|
||||
|
||||
getInitialStateFromUrl = (mapStyle) => {
|
||||
getInitialStateFromUrl = (mapStyle: StyleSpecification) => {
|
||||
const url = new URL(location.href);
|
||||
const modalParam = url.searchParams.get("modal");
|
||||
if (modalParam && modalParam !== "") {
|
||||
const modals = modalParam.split(",");
|
||||
const modalObj = {};
|
||||
const modalObj: {[key: string]: boolean} = {};
|
||||
modals.forEach(modalName => {
|
||||
modalObj[modalName] = true;
|
||||
});
|
||||
@@ -735,7 +800,7 @@ export default class App extends React.Component {
|
||||
|
||||
const view = url.searchParams.get("view");
|
||||
if (view && view !== "") {
|
||||
this.setMapState(view);
|
||||
this.setMapState(view as MapState);
|
||||
}
|
||||
|
||||
const path = url.searchParams.get("layer");
|
||||
@@ -767,14 +832,14 @@ export default class App extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onLayerSelect = (index) => {
|
||||
onLayerSelect = (index: number) => {
|
||||
this.setState({
|
||||
selectedLayerIndex: index,
|
||||
selectedLayerOriginalId: this.state.mapStyle.layers[index].id,
|
||||
}, this.setStateInUrl);
|
||||
}
|
||||
|
||||
setModal(modalName, value) {
|
||||
setModal(modalName: keyof AppState["isOpen"], value: boolean) {
|
||||
if(modalName === 'survey' && value === false) {
|
||||
localStorage.setItem('survey', '');
|
||||
}
|
||||
@@ -787,11 +852,11 @@ export default class App extends React.Component {
|
||||
}, this.setStateInUrl)
|
||||
}
|
||||
|
||||
toggleModal(modalName) {
|
||||
toggleModal(modalName: keyof AppState["isOpen"]) {
|
||||
this.setModal(modalName, !this.state.isOpen[modalName]);
|
||||
}
|
||||
|
||||
onChangeOpenlayersDebug = (key, value) => {
|
||||
onChangeOpenlayersDebug = (key: keyof AppState["openlayersDebugOptions"], value: boolean) => {
|
||||
this.setState({
|
||||
openlayersDebugOptions: {
|
||||
...this.state.openlayersDebugOptions,
|
||||
@@ -800,7 +865,7 @@ export default class App extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
onChangeMaplibreGlDebug = (key, value) => {
|
||||
onChangeMaplibreGlDebug = (key: keyof AppState["maplibreGlDebugOptions"], value: any) => {
|
||||
this.setState({
|
||||
maplibreGlDebugOptions: {
|
||||
...this.state.maplibreGlDebugOptions,
|
||||
@@ -811,8 +876,7 @@ export default class App extends React.Component {
|
||||
|
||||
render() {
|
||||
const layers = this.state.mapStyle.layers || []
|
||||
const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : null
|
||||
const metadata = this.state.mapStyle.metadata || {}
|
||||
const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : undefined
|
||||
|
||||
const toolbar = <AppToolbar
|
||||
renderer={this._getRenderer()}
|
||||
@@ -855,7 +919,7 @@ export default class App extends React.Component {
|
||||
onLayerVisibilityToggle={this.onLayerVisibilityToggle}
|
||||
onLayerIdChange={this.onLayerIdChange}
|
||||
errors={this.state.errors}
|
||||
/> : null
|
||||
/> : undefined
|
||||
|
||||
const bottomPanel = (this.state.errors.length + this.state.infos.length) > 0 ? <MessagePanel
|
||||
currentLayer={selectedLayer}
|
||||
@@ -864,7 +928,7 @@ export default class App extends React.Component {
|
||||
mapStyle={this.state.mapStyle}
|
||||
errors={this.state.errors}
|
||||
infos={this.state.infos}
|
||||
/> : null
|
||||
/> : undefined
|
||||
|
||||
|
||||
const modals = <div>
|
||||
@@ -889,7 +953,6 @@ export default class App extends React.Component {
|
||||
onChangeMetadataProperty={this.onChangeMetadataProperty}
|
||||
isOpen={this.state.isOpen.settings}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'settings')}
|
||||
openlayersDebugOptions={this.state.openlayersDebugOptions}
|
||||
/>
|
||||
<ModalExport
|
||||
mapStyle={this.state.mapStyle}
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from 'react'
|
||||
import {formatLayerId} from '../util/format';
|
||||
import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||
import {LayerSpecification, StyleSpecification} from 'maplibre-gl';
|
||||
|
||||
type AppMessagePanelProps = {
|
||||
errors?: unknown[]
|
||||
infos?: unknown[]
|
||||
mapStyle?: StyleSpecification
|
||||
onLayerSelect?(...args: unknown[]): unknown
|
||||
currentLayer?: object
|
||||
currentLayer?: LayerSpecification
|
||||
selectedLayerIndex?: number
|
||||
};
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ class ToolbarAction extends React.Component<ToolbarActionProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export type MapState = "map" | "inspect" | "filter-achromatopsia" | "filter-deuteranopia" | "filter-protanopia" | "filter-tritanopia";
|
||||
|
||||
type AppToolbarProps = {
|
||||
mapStyle: object
|
||||
inspectModeEnabled: boolean
|
||||
@@ -108,8 +110,8 @@ type AppToolbarProps = {
|
||||
sources: object
|
||||
children?: React.ReactNode
|
||||
onToggleModal(...args: unknown[]): unknown
|
||||
onSetMapState(...args: unknown[]): unknown
|
||||
mapState?: string
|
||||
onSetMapState(mapState: MapState): unknown
|
||||
mapState?: MapState
|
||||
renderer?: string
|
||||
};
|
||||
|
||||
@@ -124,7 +126,7 @@ export default class AppToolbar extends React.Component<AppToolbarProps> {
|
||||
}
|
||||
}
|
||||
|
||||
handleSelection(val: string | undefined) {
|
||||
handleSelection(val: MapState) {
|
||||
this.props.onSetMapState(val);
|
||||
}
|
||||
|
||||
@@ -245,7 +247,7 @@ export default class AppToolbar extends React.Component<AppToolbarProps> {
|
||||
<select
|
||||
className="maputnik-select"
|
||||
data-wd-key="maputnik-select"
|
||||
onChange={(e) => this.handleSelection(e.target.value)}
|
||||
onChange={(e) => this.handleSelection(e.target.value as MapState)}
|
||||
value={currentView?.id}
|
||||
>
|
||||
{views.filter(v => v.group === "general").map((item) => {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import React from 'react'
|
||||
import {combiningFilterOps} from '../libs/filterops'
|
||||
import {mdiTableRowPlusAfter} from '@mdi/js';
|
||||
import {isEqual} from 'lodash';
|
||||
import {ExpressionSpecification, LegacyFilterSpecification, StyleSpecification} from 'maplibre-gl'
|
||||
import {latest, migrate, convertFilter} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {mdiFunctionVariant} from '@mdi/js';
|
||||
|
||||
import {latest, migrate, convertFilter, ExpressionSpecification, LegacyFilterSpecification, StyleSpecification} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {combiningFilterOps} from '../libs/filterops'
|
||||
import InputSelect from './InputSelect'
|
||||
import Block from './Block'
|
||||
import SingleFilterEditor from './SingleFilterEditor'
|
||||
@@ -11,7 +13,6 @@ import FilterEditorBlock from './FilterEditorBlock'
|
||||
import InputButton from './InputButton'
|
||||
import Doc from './Doc'
|
||||
import ExpressionProperty from './_ExpressionProperty';
|
||||
import {mdiFunctionVariant} from '@mdi/js';
|
||||
|
||||
|
||||
function combiningFilter(props: FilterEditorProps): LegacyFilterSpecification | ExpressionSpecification {
|
||||
@@ -33,7 +34,8 @@ function combiningFilter(props: FilterEditorProps): LegacyFilterSpecification |
|
||||
}
|
||||
|
||||
function migrateFilter(filter: LegacyFilterSpecification | ExpressionSpecification) {
|
||||
return (migrate(createStyleFromFilter(filter)).layers[0] as any).filter;
|
||||
// This "any" can be removed in latest version of maplibre where maplibre re-exported types from style-spec
|
||||
return (migrate(createStyleFromFilter(filter) as any).layers[0] as any).filter;
|
||||
}
|
||||
|
||||
function createStyleFromFilter(filter: LegacyFilterSpecification | ExpressionSpecification): StyleSpecification & {id: string} {
|
||||
|
||||
@@ -137,7 +137,6 @@ class DeleteValueInputButton extends React.Component<DeleteValueInputButtonProps
|
||||
>
|
||||
<FieldDocLabel
|
||||
label={<MdDelete />}
|
||||
fieldSpec={{doc:" Remove array item."}}
|
||||
/>
|
||||
</InputButton>
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
|
||||
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'
|
||||
import {Accordion} from 'react-accessible-accordion';
|
||||
import {MdMoreVert} from 'react-icons/md'
|
||||
import {BackgroundLayerSpecification, LayerSpecification, SourceSpecification} from 'maplibre-gl';
|
||||
|
||||
import FieldJson from './FieldJson'
|
||||
import FilterEditor from './FilterEditor'
|
||||
@@ -18,8 +19,6 @@ import FieldSourceLayer from './FieldSourceLayer'
|
||||
import { changeType, changeProperty } from '../libs/layer'
|
||||
import layout from '../config/layout.json'
|
||||
import {formatLayerId} from '../util/format';
|
||||
import { SourceSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||
import { BackgroundLayerSpecification, LayerSpecification } from 'maplibre-gl';
|
||||
|
||||
|
||||
function getLayoutForType(type: LayerSpecification["type"]) {
|
||||
@@ -46,7 +45,7 @@ function layoutGroups(layerType: LayerSpecification["type"]): {title: string, ty
|
||||
|
||||
type LayerEditorProps = {
|
||||
layer: LayerSpecification
|
||||
sources?: SourceSpecification
|
||||
sources: {[key: string]: SourceSpecification}
|
||||
vectorLayers: {[key: string]: any}
|
||||
spec: object
|
||||
onLayerChanged(...args: unknown[]): unknown
|
||||
@@ -150,8 +149,9 @@ export default class LayerEditor extends React.Component<LayerEditorProps, Layer
|
||||
})
|
||||
|
||||
let sourceLayerIds;
|
||||
if(this.props.sources?.hasOwnProperty((this.props.layer as Exclude<LayerSpecification, BackgroundLayerSpecification>).source)) {
|
||||
sourceLayerIds = (this.props.sources as any)[(this.props.layer as any).source].layers;
|
||||
const layer = this.props.layer as Exclude<LayerSpecification, BackgroundLayerSpecification>;
|
||||
if(this.props.sources.hasOwnProperty(layer.source)) {
|
||||
sourceLayerIds = (this.props.sources[layer.source] as any).layers;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
|
||||
@@ -6,8 +6,8 @@ import LayerListGroup from './LayerListGroup'
|
||||
import LayerListItem from './LayerListItem'
|
||||
import ModalAdd from './ModalAdd'
|
||||
|
||||
import {SortableContainer} from 'react-sortable-hoc';
|
||||
import { LayerSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||
import {SortEndHandler, SortableContainer} from 'react-sortable-hoc';
|
||||
import type {LayerSpecification} from 'maplibre-gl';
|
||||
|
||||
function layerPrefix(name: string) {
|
||||
return name.replace(' ', '-').replace('_', '-').split('-')[0]
|
||||
@@ -32,7 +32,7 @@ let UID = 0;
|
||||
type LayerListContainerProps = {
|
||||
layers: LayerSpecification[]
|
||||
selectedLayerIndex: number
|
||||
onLayersChange(...args: unknown[]): unknown
|
||||
onLayersChange(layers: LayerSpecification[]): unknown
|
||||
onLayerSelect(...args: unknown[]): unknown
|
||||
onLayerDestroy?(...args: unknown[]): unknown
|
||||
onLayerCopy(...args: unknown[]): unknown
|
||||
@@ -331,7 +331,7 @@ class LayerListContainer extends React.Component<LayerListContainerProps, LayerL
|
||||
const LayerListContainerSortable = SortableContainer((props: LayerListContainerProps) => <LayerListContainer {...props} />)
|
||||
|
||||
type LayerListProps = LayerListContainerProps & {
|
||||
onMoveLayer(...args: unknown[]): unknown
|
||||
onMoveLayer: SortEndHandler
|
||||
};
|
||||
|
||||
export default class LayerList extends React.Component<LayerListProps> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import MapLibreGl, {LayerSpecification, Map, MapOptions, SourceSpecification, StyleSpecification} from 'maplibre-gl'
|
||||
import MapLibreGl, {LayerSpecification, LngLat, Map, MapOptions, SourceSpecification, StyleSpecification} from 'maplibre-gl'
|
||||
// @ts-ignore
|
||||
import MapboxInspect from 'mapbox-gl-inspect'
|
||||
// @ts-ignore
|
||||
@@ -53,18 +53,18 @@ function buildInspectStyle(originalMapStyle: StyleSpecification, coloredLayers:
|
||||
}
|
||||
|
||||
type MapMaplibreGlProps = {
|
||||
onDataChange?(...args: unknown[]): unknown
|
||||
onDataChange?(event: {map: Map | null}): unknown
|
||||
onLayerSelect(...args: unknown[]): unknown
|
||||
mapStyle: StyleSpecification
|
||||
inspectModeEnabled: boolean
|
||||
highlightedLayer?: HighlightedLayer
|
||||
options?: MapOptions & {
|
||||
options?: Partial<MapOptions> & {
|
||||
showTileBoundaries?: boolean
|
||||
showCollisionBoxes?: boolean
|
||||
showOverdrawInspector?: boolean
|
||||
}
|
||||
replaceAccessTokens(mapStyle: StyleSpecification): StyleSpecification
|
||||
onChange(...args: unknown[]): unknown
|
||||
onChange(value: {center: LngLat, zoom: number}): unknown
|
||||
};
|
||||
|
||||
type MapMaplibreGlState = {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {apply} from 'ol-mapbox-style';
|
||||
import {Map, View, Overlay} from 'ol';
|
||||
|
||||
import {toLonLat} from 'ol/proj';
|
||||
import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||
import type {StyleSpecification} from 'maplibre-gl';
|
||||
|
||||
|
||||
function renderCoords (coords: string[]) {
|
||||
|
||||
@@ -8,7 +8,7 @@ type ModalProps = {
|
||||
"data-wd-key"?: string
|
||||
isOpen: boolean
|
||||
title: string
|
||||
onOpenToggle(...args: unknown[]): unknown
|
||||
onOpenToggle(value: boolean): unknown
|
||||
underlayClickExits?: boolean
|
||||
underlayProps?: any
|
||||
className?: string
|
||||
|
||||
@@ -6,18 +6,19 @@ import FieldType from './FieldType'
|
||||
import FieldId from './FieldId'
|
||||
import FieldSource from './FieldSource'
|
||||
import FieldSourceLayer from './FieldSourceLayer'
|
||||
import type {LayerSpecification} from 'maplibre-gl'
|
||||
|
||||
type ModalAddProps = {
|
||||
layers: unknown[]
|
||||
onLayersChange(...args: unknown[]): unknown
|
||||
layers: LayerSpecification[]
|
||||
onLayersChange(layers: LayerSpecification[]): unknown
|
||||
isOpen: boolean
|
||||
onOpenToggle(...args: unknown[]): unknown
|
||||
onOpenToggle(open: boolean): unknown
|
||||
// A dict of source id's and the available source layers
|
||||
sources: any
|
||||
};
|
||||
|
||||
type ModalAddState = {
|
||||
type: string
|
||||
type: LayerSpecification["type"]
|
||||
id: string
|
||||
source?: string
|
||||
'source-layer'?: string
|
||||
@@ -38,7 +39,7 @@ export default class ModalAdd extends React.Component<ModalAddProps, ModalAddSta
|
||||
}
|
||||
}
|
||||
|
||||
changedLayers.push(layer)
|
||||
changedLayers.push(layer as LayerSpecification)
|
||||
|
||||
this.props.onLayersChange(changedLayers)
|
||||
this.props.onOpenToggle(false)
|
||||
@@ -145,7 +146,7 @@ export default class ModalAdd extends React.Component<ModalAddProps, ModalAddSta
|
||||
<FieldType
|
||||
value={this.state.type}
|
||||
wdKey="add-layer.layer-type"
|
||||
onChange={(v: string) => this.setState({ type: v })}
|
||||
onChange={(v: LayerSpecification["type"]) => this.setState({ type: v })}
|
||||
/>
|
||||
{this.state.type !== 'background' &&
|
||||
<FieldSource
|
||||
|
||||
@@ -6,16 +6,16 @@ import Modal from './Modal'
|
||||
type ModalDebugProps = {
|
||||
isOpen: boolean
|
||||
renderer: string
|
||||
onChangeMaboxGlDebug(...args: unknown[]): unknown
|
||||
onChangeOpenlayersDebug(...args: unknown[]): unknown
|
||||
onOpenToggle(...args: unknown[]): unknown
|
||||
onChangeMaplibreGlDebug(key: string, checked: boolean): unknown
|
||||
onChangeOpenlayersDebug(key: string, checked: boolean): unknown
|
||||
onOpenToggle(value: boolean): unknown
|
||||
maplibreGlDebugOptions?: object
|
||||
openlayersDebugOptions?: object
|
||||
mapView: {
|
||||
zoom: number
|
||||
center: {
|
||||
lng: string
|
||||
lat: string
|
||||
lng: number
|
||||
lat: number
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -26,8 +26,8 @@ export default class ModalDebug extends React.Component<ModalDebugProps> {
|
||||
const {mapView} = this.props;
|
||||
|
||||
const osmZoom = Math.round(mapView.zoom)+1;
|
||||
const osmLon = Number.parseFloat(mapView.center.lng).toFixed(5);
|
||||
const osmLat = Number.parseFloat(mapView.center.lat).toFixed(5);
|
||||
const osmLon = +(mapView.center.lng).toFixed(5);
|
||||
const osmLat = +(mapView.center.lat).toFixed(5);
|
||||
|
||||
return <Modal
|
||||
data-wd-key="modal:debug"
|
||||
@@ -42,7 +42,7 @@ export default class ModalDebug extends React.Component<ModalDebugProps> {
|
||||
{Object.entries(this.props.maplibreGlDebugOptions!).map(([key, val]) => {
|
||||
return <li key={key}>
|
||||
<label>
|
||||
<input type="checkbox" checked={val} onChange={(e) => this.props.onChangeMaboxGlDebug(key, e.target.checked)} /> {key}
|
||||
<input type="checkbox" checked={val} onChange={(e) => this.props.onChangeMaplibreGlDebug(key, e.target.checked)} /> {key}
|
||||
</label>
|
||||
</li>
|
||||
})}
|
||||
|
||||
@@ -2,7 +2,8 @@ import React from 'react'
|
||||
import Slugify from 'slugify'
|
||||
import {saveAs} from 'file-saver'
|
||||
import {version} from 'maplibre-gl/package.json'
|
||||
import {StyleSpecification, format} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {format} from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {StyleSpecification} from 'maplibre-gl'
|
||||
import {MdFileDownload} from 'react-icons/md'
|
||||
|
||||
import FieldString from './FieldString'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react'
|
||||
import {LightSpecification, StyleSpecification, TransitionSpecification, latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {LightSpecification, StyleSpecification, TransitionSpecification} from 'maplibre-gl'
|
||||
|
||||
import FieldArray from './FieldArray'
|
||||
import FieldNumber from './FieldNumber'
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import React from 'react'
|
||||
import {GeoJSONSourceSpecification, RasterDEMSourceSpecification, RasterSourceSpecification, SourceSpecification, StyleSpecification, VectorSourceSpecification, latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {MdAddCircleOutline, MdDelete} from 'react-icons/md'
|
||||
import {latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {GeoJSONSourceSpecification, RasterDEMSourceSpecification, RasterSourceSpecification, SourceSpecification, StyleSpecification, VectorSourceSpecification} from 'maplibre-gl'
|
||||
|
||||
import Modal from './Modal'
|
||||
import InputButton from './InputButton'
|
||||
import FieldString from './FieldString'
|
||||
@@ -10,7 +13,6 @@ import style from '../libs/style'
|
||||
import { deleteSource, addSource, changeSource } from '../libs/source'
|
||||
import publicSources from '../config/tilesets.json'
|
||||
|
||||
import {MdAddCircleOutline, MdDelete} from 'react-icons/md'
|
||||
|
||||
type PublicSourceProps = {
|
||||
id: string
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from 'react'
|
||||
|
||||
import FieldFunction from './FieldFunction'
|
||||
import { LayerSpecification } from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {LayerSpecification} from 'maplibre-gl'
|
||||
|
||||
const iconProperties = ['background-pattern', 'fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'icon-image']
|
||||
|
||||
/** Extract field spec by {@fieldName} from the {@layerType} in the
|
||||
|
||||
@@ -13,6 +13,7 @@ const typeMap = {
|
||||
number: () => Block,
|
||||
string: () => Block,
|
||||
formatted: () => Block,
|
||||
padding: () => Block,
|
||||
};
|
||||
|
||||
export type SpecFieldProps = InputFieldSpecProps & {
|
||||
|
||||
@@ -31,10 +31,11 @@ function setStopRefs(props: ZoomPropertyProps, state: ZoomPropertyState) {
|
||||
newRefs = {...state};
|
||||
}
|
||||
newRefs[idx] = docUid("stop-");
|
||||
} else {
|
||||
newRefs[idx] = state.refs[idx];
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return newRefs;
|
||||
}
|
||||
|
||||
@@ -156,7 +157,6 @@ export default class ZoomProperty extends React.Component<ZoomPropertyProps, Zoo
|
||||
const key = this.state.refs[idx];
|
||||
const value = stop[1]
|
||||
const deleteStopBtn= <DeleteStopButton onClick={this.props.onDeleteStop?.bind(this, idx)} />
|
||||
|
||||
return <tr
|
||||
key={key}
|
||||
>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import style from './style.js'
|
||||
import {StyleSpecification, format} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {format} from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {StyleSpecification} from 'maplibre-gl'
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
|
||||
export type ApiStyleStoreOptions = {
|
||||
port?: string
|
||||
host?: string
|
||||
port: string | null
|
||||
host: string | null
|
||||
onLocalStyleChange?: (style: any) => void
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {StyleSpecification, diff} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {diff} from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {StyleSpecification} from 'maplibre-gl'
|
||||
|
||||
function diffMessages(beforeStyle: StyleSpecification, afterStyle: StyleSpecification) {
|
||||
const changes = diff(beforeStyle, afterStyle)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import stylegen from 'mapbox-gl-inspect/lib/stylegen'
|
||||
// @ts-ignore
|
||||
import colors from 'mapbox-gl-inspect/lib/colors'
|
||||
import {FilterSpecification,LayerSpecification } from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {FilterSpecification,LayerSpecification } from 'maplibre-gl'
|
||||
|
||||
export type HighlightedLayer = LayerSpecification & {filter?: FilterSpecification};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type {StyleSpecification} from "@maplibre/maplibre-gl-style-spec";
|
||||
import type {StyleSpecification} from "maplibre-gl";
|
||||
|
||||
export class RevisionStore {
|
||||
revisions: StyleSpecification[];
|
||||
revisions: (StyleSpecification & {id: string})[];
|
||||
currentIdx: number;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export class RevisionStore {
|
||||
return this.revisions[this.currentIdx]
|
||||
}
|
||||
|
||||
addRevision(revision: StyleSpecification) {
|
||||
addRevision(revision: StyleSpecification & {id: string}) {
|
||||
//TODO: compare new revision style id with old ones
|
||||
//and ensure that it is always the same id
|
||||
this.revisions.push(revision)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type {StyleSpecification, SourceSpecification} from "@maplibre/maplibre-gl-style-spec";
|
||||
import type {StyleSpecification, SourceSpecification} from "maplibre-gl";
|
||||
|
||||
export function deleteSource(mapStyle: StyleSpecification, sourceId: string) {
|
||||
const remainingSources = { ...mapStyle.sources}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {derefLayers, StyleSpecification, LayerSpecification} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {derefLayers} from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {StyleSpecification, LayerSpecification} from 'maplibre-gl'
|
||||
import tokens from '../config/tokens.json'
|
||||
|
||||
// Empty style is always used if no style could be restored or fetched
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import style from './style'
|
||||
import {loadStyleUrl} from './urlopen'
|
||||
import publicSources from '../config/styles.json'
|
||||
import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {StyleSpecification} from 'maplibre-gl'
|
||||
|
||||
const storagePrefix = "maputnik"
|
||||
const stylePrefix = 'style'
|
||||
|
||||
Reference in New Issue
Block a user