mirror of
https://github.com/maputnik/editor.git
synced 2026-09-10 22:37:27 +00:00
Compare commits
2 Commits
a324ddb654
...
09a1f3f87b
| Author | SHA1 | Date | |
|---|---|---|---|
| 09a1f3f87b | |||
| a22476cab2 |
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2020": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:react/jsx-runtime",
|
||||||
|
"plugin:react-hooks/recommended",
|
||||||
|
],
|
||||||
|
"ignorePatterns": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": { "version": "16.4" }
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"@typescript-eslint",
|
||||||
|
"react-refresh"],
|
||||||
|
"rules": {
|
||||||
|
"react-refresh/only-export-components": [
|
||||||
|
"warn",
|
||||||
|
{ "allowConstantExport": true }
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{ "argsIgnorePattern": "^_" }
|
||||||
|
],
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"react/prop-types": ["off"],
|
||||||
|
// Disable no-undef. It's covered by @typescript-eslint
|
||||||
|
"no-undef": "off",
|
||||||
|
"indent": ["error", 2]
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"global": "readonly"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
env: { browser: true, es2020: true },
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:react/recommended',
|
|
||||||
'plugin:react/jsx-runtime',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
],
|
|
||||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
|
||||||
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
||||||
settings: { react: { version: '18.2' } },
|
|
||||||
plugins: ['react-refresh'],
|
|
||||||
rules: {
|
|
||||||
'react-refresh/only-export-components': [
|
|
||||||
'warn',
|
|
||||||
{ allowConstantExport: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -42,6 +42,9 @@ jobs:
|
|||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
|
- run: npm run lint
|
||||||
|
- run: npm run lint-css
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
build-artifacts:
|
build-artifacts:
|
||||||
|
|||||||
+3
-9
@@ -6,17 +6,11 @@ COPY package.json package-lock.json ./
|
|||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
# Build maputnik
|
# Build maputnik
|
||||||
# TODO: we should also do a npm run test here (needs more dependencies)
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
# Create a clean nginx-alpine slim image with just the build results
|
||||||
|
FROM nginx:alpine-slim
|
||||||
|
|
||||||
# Create a clean python-based image with just the build results
|
COPY --from=builder /maputnik/dist /usr/share/nginx/html/
|
||||||
FROM python:3-slim
|
|
||||||
WORKDIR /maputnik
|
|
||||||
|
|
||||||
COPY --from=builder /maputnik/dist .
|
|
||||||
|
|
||||||
EXPOSE 8888
|
|
||||||
CMD python -m http.server 8888
|
|
||||||
|
|||||||
Generated
+244
-139
File diff suppressed because it is too large
Load Diff
+6
-3
@@ -7,7 +7,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"lint": "eslint ./src --ext ts,tsx,js,jsx --report-unused-disable-directives --max-warnings 0 && npm run lint-css",
|
"lint": "eslint ./src --ext ts,tsx,js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"test": "cypress run",
|
"test": "cypress run",
|
||||||
"cy:open": "cypress open",
|
"cy:open": "cypress open",
|
||||||
"lint-css": "stylelint \"src/styles/*.scss\"",
|
"lint-css": "stylelint \"src/styles/*.scss\"",
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
"@maplibre/maplibre-gl-style-spec": "^17.0.1",
|
"@maplibre/maplibre-gl-style-spec": "^17.0.1",
|
||||||
"@mdi/js": "^6.6.96",
|
"@mdi/js": "^6.6.96",
|
||||||
"@mdi/react": "^1.5.0",
|
"@mdi/react": "^1.5.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.16.0",
|
||||||
|
"@typescript-eslint/parser": "^6.16.0",
|
||||||
"array-move": "^4.0.0",
|
"array-move": "^4.0.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
@@ -103,6 +105,7 @@
|
|||||||
"@types/color": "^3.0.6",
|
"@types/color": "^3.0.6",
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
|
"@types/geojson": "^7946.0.13",
|
||||||
"@types/json-to-ast": "^2.1.4",
|
"@types/json-to-ast": "^2.1.4",
|
||||||
"@types/lodash.capitalize": "^4.2.9",
|
"@types/lodash.capitalize": "^4.2.9",
|
||||||
"@types/lodash.clamp": "^4.0.9",
|
"@types/lodash.clamp": "^4.0.9",
|
||||||
@@ -124,10 +127,10 @@
|
|||||||
"@vitejs/plugin-react": "^4.2.0",
|
"@vitejs/plugin-react": "^4.2.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"cypress": "^13.6.1",
|
"cypress": "^13.6.1",
|
||||||
"eslint": "^8.53.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.4",
|
"eslint-plugin-react-refresh": "^0.4.5",
|
||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"istanbul": "^0.4.5",
|
"istanbul": "^0.4.5",
|
||||||
"istanbul-lib-coverage": "^3.2.0",
|
"istanbul-lib-coverage": "^3.2.0",
|
||||||
|
|||||||
+13
-13
@@ -334,7 +334,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
const metadata: {[key: string]: string} = this.state.mapStyle.metadata || {} as any
|
const metadata: {[key: string]: string} = this.state.mapStyle.metadata || {} as any
|
||||||
const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
|
const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
|
||||||
|
|
||||||
let glyphUrl = (typeof urlTemplate === 'string')? urlTemplate.replace('{key}', accessToken): urlTemplate;
|
const glyphUrl = (typeof urlTemplate === 'string')? urlTemplate.replace('{key}', accessToken): urlTemplate;
|
||||||
downloadGlyphsMetadata(glyphUrl, fonts => {
|
downloadGlyphsMetadata(glyphUrl, fonts => {
|
||||||
this.setState({ spec: updateRootSpec(this.state.spec, 'glyphs', fonts)})
|
this.setState({ spec: updateRootSpec(this.state.spec, 'glyphs', fonts)})
|
||||||
})
|
})
|
||||||
@@ -402,7 +402,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
// Special case: Duplicate layer id
|
// Special case: Duplicate layer id
|
||||||
const dupMatch = error.message.match(/layers\[(\d+)\]: (duplicate layer id "?(.*)"?, previously used)/);
|
const dupMatch = error.message.match(/layers\[(\d+)\]: (duplicate layer id "?(.*)"?, previously used)/);
|
||||||
if (dupMatch) {
|
if (dupMatch) {
|
||||||
const [_matchStr, index, message] = dupMatch;
|
const [, index, message] = dupMatch;
|
||||||
return {
|
return {
|
||||||
message: error.message,
|
message: error.message,
|
||||||
parsed: {
|
parsed: {
|
||||||
@@ -419,7 +419,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
// Special case: Invalid source
|
// Special case: Invalid source
|
||||||
const invalidSourceMatch = error.message.match(/layers\[(\d+)\]: (source "(?:.*)" not found)/);
|
const invalidSourceMatch = error.message.match(/layers\[(\d+)\]: (source "(?:.*)" not found)/);
|
||||||
if (invalidSourceMatch) {
|
if (invalidSourceMatch) {
|
||||||
const [_matchStr, index, message] = invalidSourceMatch;
|
const [, index, message] = invalidSourceMatch;
|
||||||
return {
|
return {
|
||||||
message: error.message,
|
message: error.message,
|
||||||
parsed: {
|
parsed: {
|
||||||
@@ -435,7 +435,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
|
|
||||||
const layerMatch = error.message.match(/layers\[(\d+)\]\.(?:(\S+)\.)?(\S+): (.*)/);
|
const layerMatch = error.message.match(/layers\[(\d+)\]\.(?:(\S+)\.)?(\S+): (.*)/);
|
||||||
if (layerMatch) {
|
if (layerMatch) {
|
||||||
const [_matchStr, index, group, property, message] = layerMatch;
|
const [, index, group, property, message] = layerMatch;
|
||||||
const key = (group && property) ? [group, property].join(".") : property;
|
const key = (group && property) ? [group, property].join(".") : property;
|
||||||
return {
|
return {
|
||||||
message: error.message,
|
message: error.message,
|
||||||
@@ -466,7 +466,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
try {
|
try {
|
||||||
const objPath = message.split(":")[0];
|
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'
|
// 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);
|
unset(dirtyMapStyle, unsetPath);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@@ -547,14 +547,14 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onLayerDestroy = (index: number) => {
|
onLayerDestroy = (index: number) => {
|
||||||
let layers = this.state.mapStyle.layers;
|
const layers = this.state.mapStyle.layers;
|
||||||
const remainingLayers = layers.slice(0);
|
const remainingLayers = layers.slice(0);
|
||||||
remainingLayers.splice(index, 1);
|
remainingLayers.splice(index, 1);
|
||||||
this.onLayersChange(remainingLayers);
|
this.onLayersChange(remainingLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerCopy = (index: number) => {
|
onLayerCopy = (index: number) => {
|
||||||
let layers = this.state.mapStyle.layers;
|
const layers = this.state.mapStyle.layers;
|
||||||
const changedLayers = layers.slice(0)
|
const changedLayers = layers.slice(0)
|
||||||
|
|
||||||
const clonedLayer = cloneDeep(changedLayers[index])
|
const clonedLayer = cloneDeep(changedLayers[index])
|
||||||
@@ -564,7 +564,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onLayerVisibilityToggle = (index: number) => {
|
onLayerVisibilityToggle = (index: number) => {
|
||||||
let layers = this.state.mapStyle.layers;
|
const layers = this.state.mapStyle.layers;
|
||||||
const changedLayers = layers.slice(0)
|
const changedLayers = layers.slice(0)
|
||||||
|
|
||||||
const layer = { ...changedLayers[index] }
|
const layer = { ...changedLayers[index] }
|
||||||
@@ -624,11 +624,11 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
fetchSources() {
|
fetchSources() {
|
||||||
const sourceList: {[key: string]: any} = {};
|
const sourceList: {[key: string]: any} = {};
|
||||||
|
|
||||||
for(let [key, val] of Object.entries(this.state.mapStyle.sources)) {
|
for(const [key, val] of Object.entries(this.state.mapStyle.sources)) {
|
||||||
if(
|
if(
|
||||||
!this.state.sources.hasOwnProperty(key) &&
|
!Object.prototype.hasOwnProperty.call(this.state.sources, key) &&
|
||||||
val.type === "vector" &&
|
val.type === "vector" &&
|
||||||
val.hasOwnProperty("url")
|
Object.prototype.hasOwnProperty.call(val, "url")
|
||||||
) {
|
) {
|
||||||
sourceList[key] = {
|
sourceList[key] = {
|
||||||
type: val.type,
|
type: val.type,
|
||||||
@@ -649,7 +649,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(json => {
|
.then(json => {
|
||||||
|
|
||||||
if(!json.hasOwnProperty("vector_layers")) {
|
if(!Object.prototype.hasOwnProperty.call(json, "vector_layers")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -658,7 +658,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
[key]: this.state.sources[key],
|
[key]: this.state.sources[key],
|
||||||
});
|
});
|
||||||
|
|
||||||
for(let layer of json.vector_layers) {
|
for(const layer of json.vector_layers) {
|
||||||
(sources[key] as any).layers.push(layer.id)
|
(sources[key] as any).layers.push(layer.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export default class Doc extends React.Component<DocProps> {
|
|||||||
<tr key={key}>
|
<tr key={key}>
|
||||||
<td>{key}</td>
|
<td>{key}</td>
|
||||||
{Object.keys(headers).map((k) => {
|
{Object.keys(headers).map((k) => {
|
||||||
if (supportObj.hasOwnProperty(k)) {
|
if (Object.prototype.hasOwnProperty.call(supportObj, k)) {
|
||||||
return <td key={k}>{supportObj[k as keyof typeof headers]}</td>;
|
return <td key={k}>{supportObj[k as keyof typeof headers]}</td>;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function isIdentityProperty(value: any) {
|
|||||||
return (
|
return (
|
||||||
typeof(value) === 'object' &&
|
typeof(value) === 'object' &&
|
||||||
value.type === "identity" &&
|
value.type === "identity" &&
|
||||||
value.hasOwnProperty("property")
|
Object.prototype.hasOwnProperty.call(value, "property")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import FieldDocLabel from './FieldDocLabel'
|
import FieldDocLabel from './FieldDocLabel'
|
||||||
import Doc from './Doc'
|
import Doc from './Doc'
|
||||||
|
import generateUniqueId from '../libs/document-uid';
|
||||||
|
|
||||||
type FieldsetProps = {
|
type FieldsetProps = {
|
||||||
label?: string,
|
label?: string,
|
||||||
@@ -12,14 +13,12 @@ type FieldsetState = {
|
|||||||
showDoc: boolean
|
showDoc: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
let IDX = 0;
|
|
||||||
|
|
||||||
export default class Fieldset extends React.Component<FieldsetProps, FieldsetState> {
|
export default class Fieldset extends React.Component<FieldsetProps, FieldsetState> {
|
||||||
_labelId: string;
|
_labelId: string;
|
||||||
|
|
||||||
constructor (props: FieldsetProps) {
|
constructor (props: FieldsetProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this._labelId = `fieldset_label_${(IDX++)}`;
|
this._labelId = generateUniqueId(`fieldset_label_`);
|
||||||
this.state = {
|
this.state = {
|
||||||
showDoc: false,
|
showDoc: false,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import ExpressionProperty from './_ExpressionProperty';
|
|||||||
|
|
||||||
|
|
||||||
function combiningFilter(props: FilterEditorProps): LegacyFilterSpecification | ExpressionSpecification {
|
function combiningFilter(props: FilterEditorProps): LegacyFilterSpecification | ExpressionSpecification {
|
||||||
let filter = props.filter || ['all'];
|
const filter = props.filter || ['all'];
|
||||||
|
|
||||||
if (!Array.isArray(filter)) {
|
if (!Array.isArray(filter)) {
|
||||||
return filter;
|
return filter;
|
||||||
@@ -148,7 +148,7 @@ export default class FilterEditor extends React.Component<FilterEditorProps, Fil
|
|||||||
}
|
}
|
||||||
|
|
||||||
makeExpression = () => {
|
makeExpression = () => {
|
||||||
let filter = combiningFilter(this.props);
|
const filter = combiningFilter(this.props);
|
||||||
this.props.onChange(migrateFilter(filter));
|
this.props.onChange(migrateFilter(filter));
|
||||||
this.setState({
|
this.setState({
|
||||||
displaySimpleFilter: false,
|
displaySimpleFilter: false,
|
||||||
@@ -205,8 +205,8 @@ export default class FilterEditor extends React.Component<FilterEditorProps, Fil
|
|||||||
}
|
}
|
||||||
else if (displaySimpleFilter) {
|
else if (displaySimpleFilter) {
|
||||||
const filter = combiningFilter(this.props);
|
const filter = combiningFilter(this.props);
|
||||||
let combiningOp = filter[0];
|
const combiningOp = filter[0];
|
||||||
let filters = filter.slice(1) as (LegacyFilterSpecification | ExpressionSpecification)[];
|
const filters = filter.slice(1) as (LegacyFilterSpecification | ExpressionSpecification)[];
|
||||||
|
|
||||||
const actions = (
|
const actions = (
|
||||||
<div>
|
<div>
|
||||||
@@ -282,7 +282,7 @@ export default class FilterEditor extends React.Component<FilterEditorProps, Fil
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let {filter} = this.props;
|
const {filter} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export default class InputColor extends React.Component<InputColorProps> {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
var swatchStyle = {
|
const swatchStyle = {
|
||||||
backgroundColor: this.props.value
|
backgroundColor: this.props.value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React, { BaseSyntheticEvent } from 'react'
|
import React, { BaseSyntheticEvent } from 'react'
|
||||||
|
import generateUniqueId from '../libs/document-uid';
|
||||||
let IDX = 0;
|
|
||||||
|
|
||||||
export type InputNumberProps = {
|
export type InputNumberProps = {
|
||||||
value?: number
|
value?: number
|
||||||
@@ -32,7 +31,7 @@ export default class InputNumber extends React.Component<InputNumberProps, Input
|
|||||||
constructor(props: InputNumberProps) {
|
constructor(props: InputNumberProps) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
uuid: IDX++,
|
uuid: +generateUniqueId(),
|
||||||
editing: false,
|
editing: false,
|
||||||
value: props.value,
|
value: props.value,
|
||||||
dirtyValue: props.value,
|
dirtyValue: props.value,
|
||||||
@@ -140,7 +139,7 @@ export default class InputNumber extends React.Component<InputNumberProps, Input
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value = value + (step - snap);
|
value = value + (step - snap);
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +154,8 @@ export default class InputNumber extends React.Component<InputNumberProps, Input
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
if(
|
if(
|
||||||
this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") &&
|
Object.prototype.hasOwnProperty.call(this.props, "min") &&
|
||||||
|
Object.prototype.hasOwnProperty.call(this.props, "max") &&
|
||||||
this.props.min !== undefined && this.props.max !== undefined &&
|
this.props.min !== undefined && this.props.max !== undefined &&
|
||||||
this.props.allowRange
|
this.props.allowRange
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -60,13 +60,14 @@ export default class SpecField extends React.Component<SpecFieldProps> {
|
|||||||
max={this.props.fieldSpec.maximum}
|
max={this.props.fieldSpec.maximum}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'enum':
|
case 'enum': {
|
||||||
const options = Object.keys(this.props.fieldSpec.values || []).map(v => [v, capitalize(v)])
|
const options = Object.keys(this.props.fieldSpec.values || []).map(v => [v, capitalize(v)])
|
||||||
|
|
||||||
return <InputEnum
|
return <InputEnum
|
||||||
{...commonProps as Omit<InputEnumProps, "options">}
|
{...commonProps as Omit<InputEnumProps, "options">}
|
||||||
options={options}
|
options={options}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
case 'resolvedImage':
|
case 'resolvedImage':
|
||||||
case 'formatted':
|
case 'formatted':
|
||||||
case 'string':
|
case 'string':
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default class InputString extends React.Component<InputStringProps, Input
|
|||||||
let tag;
|
let tag;
|
||||||
let classes;
|
let classes;
|
||||||
|
|
||||||
if(!!this.props.multi) {
|
if(this.props.multi) {
|
||||||
tag = "textarea"
|
tag = "textarea"
|
||||||
classes = [
|
classes = [
|
||||||
"maputnik-string",
|
"maputnik-string",
|
||||||
@@ -60,14 +60,14 @@ export default class InputString extends React.Component<InputStringProps, Input
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!!this.props.disabled) {
|
if(this.props.disabled) {
|
||||||
classes.push("maputnik-string--disabled");
|
classes.push("maputnik-string--disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
return React.createElement(tag, {
|
return React.createElement(tag, {
|
||||||
"aria-label": this.props["aria-label"],
|
"aria-label": this.props["aria-label"],
|
||||||
"data-wd-key": this.props["data-wd-key"],
|
"data-wd-key": this.props["data-wd-key"],
|
||||||
spellCheck: this.props.hasOwnProperty("spellCheck") ? this.props.spellCheck : !(tag === "input"),
|
spellCheck: Object.prototype.hasOwnProperty.call(this.props, "spellCheck") ? this.props.spellCheck : !(tag === "input"),
|
||||||
disabled: this.props.disabled,
|
disabled: this.props.disabled,
|
||||||
className: classes.join(" "),
|
className: classes.join(" "),
|
||||||
style: this.props.style,
|
style: this.props.style,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, {type JSX} from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'
|
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'
|
||||||
import {Accordion} from 'react-accessible-accordion';
|
import {Accordion} from 'react-accessible-accordion';
|
||||||
@@ -150,7 +150,7 @@ export default class LayerEditor extends React.Component<LayerEditorProps, Layer
|
|||||||
|
|
||||||
let sourceLayerIds;
|
let sourceLayerIds;
|
||||||
const layer = this.props.layer as Exclude<LayerSpecification, BackgroundLayerSpecification>;
|
const layer = this.props.layer as Exclude<LayerSpecification, BackgroundLayerSpecification>;
|
||||||
if(this.props.sources.hasOwnProperty(layer.source)) {
|
if(Object.prototype.hasOwnProperty.call(this.props.sources, layer.source)) {
|
||||||
sourceLayerIds = (this.props.sources[layer.source] as any).layers;
|
sourceLayerIds = (this.props.sources[layer.source] as any).layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, {type JSX} from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
|
|
||||||
@@ -8,26 +8,8 @@ import ModalAdd from './ModalAdd'
|
|||||||
|
|
||||||
import {SortEndHandler, SortableContainer} from 'react-sortable-hoc';
|
import {SortEndHandler, SortableContainer} from 'react-sortable-hoc';
|
||||||
import type {LayerSpecification} from 'maplibre-gl';
|
import type {LayerSpecification} from 'maplibre-gl';
|
||||||
|
import generateUniqueId from '../libs/document-uid';
|
||||||
function layerPrefix(name: string) {
|
import { findClosestCommonPrefix, layerPrefix } from '../libs/layer';
|
||||||
return name.replace(' ', '-').replace('_', '-').split('-')[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
function findClosestCommonPrefix(layers: LayerSpecification[], idx: number) {
|
|
||||||
const currentLayerPrefix = layerPrefix(layers[idx].id)
|
|
||||||
let closestIdx = idx
|
|
||||||
for (let i = idx; i > 0; i--) {
|
|
||||||
const previousLayerPrefix = layerPrefix(layers[i-1].id)
|
|
||||||
if(previousLayerPrefix === currentLayerPrefix) {
|
|
||||||
closestIdx = i - 1
|
|
||||||
} else {
|
|
||||||
return closestIdx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return closestIdx
|
|
||||||
}
|
|
||||||
|
|
||||||
let UID = 0;
|
|
||||||
|
|
||||||
type LayerListContainerProps = {
|
type LayerListContainerProps = {
|
||||||
layers: LayerSpecification[]
|
layers: LayerSpecification[]
|
||||||
@@ -64,7 +46,7 @@ class LayerListContainer extends React.Component<LayerListContainerProps, LayerL
|
|||||||
collapsedGroups: {},
|
collapsedGroups: {},
|
||||||
areAllGroupsExpanded: false,
|
areAllGroupsExpanded: false,
|
||||||
keys: {
|
keys: {
|
||||||
add: UID++,
|
add: +generateUniqueId(),
|
||||||
},
|
},
|
||||||
isOpen: {
|
isOpen: {
|
||||||
add: false,
|
add: false,
|
||||||
@@ -76,7 +58,7 @@ class LayerListContainer extends React.Component<LayerListContainerProps, LayerL
|
|||||||
this.setState({
|
this.setState({
|
||||||
keys: {
|
keys: {
|
||||||
...this.state.keys,
|
...this.state.keys,
|
||||||
[modalName]: UID++,
|
[modalName]: +generateUniqueId(),
|
||||||
},
|
},
|
||||||
isOpen: {
|
isOpen: {
|
||||||
...this.state.isOpen,
|
...this.state.isOpen,
|
||||||
@@ -88,7 +70,7 @@ class LayerListContainer extends React.Component<LayerListContainerProps, LayerL
|
|||||||
toggleLayers = () => {
|
toggleLayers = () => {
|
||||||
let idx = 0
|
let idx = 0
|
||||||
|
|
||||||
let newGroups: {[key:string]: boolean} = {}
|
const newGroups: {[key:string]: boolean} = {}
|
||||||
|
|
||||||
this.groupedLayers().forEach(layers => {
|
this.groupedLayers().forEach(layers => {
|
||||||
const groupPrefix = layerPrefix(layers[0].id)
|
const groupPrefix = layerPrefix(layers[0].id)
|
||||||
@@ -328,6 +310,7 @@ class LayerListContainer extends React.Component<LayerListContainerProps, LayerL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-refresh/only-export-components
|
||||||
const LayerListContainerSortable = SortableContainer((props: LayerListContainerProps) => <LayerListContainer {...props} />)
|
const LayerListContainerSortable = SortableContainer((props: LayerListContainerProps) => <LayerListContainer {...props} />)
|
||||||
|
|
||||||
type LayerListProps = LayerListContainerProps & {
|
type LayerListProps = LayerListContainerProps & {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, {type JSX} from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import MapLibreGl, {LayerSpecification, LngLat, Map, MapOptions, SourceSpecification, StyleSpecification} from 'maplibre-gl'
|
import MapLibreGl, {LayerSpecification, LngLat, Map, MapOptions, SourceSpecification, StyleSpecification} from 'maplibre-gl'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ function renderFeatureId(feature: InspectFeature) {
|
|||||||
return <Block key={"feature-id"} label={"feature_id"}>
|
return <Block key={"feature-id"} label={"feature_id"}>
|
||||||
<FieldString value={displayValue(feature.id)} style={{backgroundColor: 'transparent'}} />
|
<FieldString value={displayValue(feature.id)} style={{backgroundColor: 'transparent'}} />
|
||||||
</Block>
|
</Block>
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFeature(feature: InspectFeature, idx: number) {
|
function renderFeature(feature: InspectFeature, idx: number) {
|
||||||
return <div key={`${feature.sourceLayer}-${idx}`}>
|
return <div key={`${feature.sourceLayer}-${idx}`}>
|
||||||
@@ -48,7 +48,7 @@ function renderFeature(feature: InspectFeature, idx: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeDuplicatedFeatures(features: InspectFeature[]) {
|
function removeDuplicatedFeatures(features: InspectFeature[]) {
|
||||||
let uniqueFeatures: InspectFeature[] = [];
|
const uniqueFeatures: InspectFeature[] = [];
|
||||||
|
|
||||||
features.forEach(feature => {
|
features.forEach(feature => {
|
||||||
const featureIndex = uniqueFeatures.findIndex(feature2 => {
|
const featureIndex = uniqueFeatures.findIndex(feature2 => {
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import type {InspectFeature} from './MapMaplibreGlFeaturePropertyPopup';
|
|||||||
function groupFeaturesBySourceLayer(features: InspectFeature[]) {
|
function groupFeaturesBySourceLayer(features: InspectFeature[]) {
|
||||||
const sources: {[key: string]: InspectFeature[]} = {}
|
const sources: {[key: string]: InspectFeature[]} = {}
|
||||||
|
|
||||||
let returnedFeatures: {[key: string]: number} = {}
|
const returnedFeatures: {[key: string]: number} = {}
|
||||||
|
|
||||||
features.forEach(feature => {
|
features.forEach(feature => {
|
||||||
if(returnedFeatures.hasOwnProperty(feature.layer.id)) {
|
if(Object.prototype.hasOwnProperty.call(returnedFeatures, feature.layer.id)) {
|
||||||
returnedFeatures[feature.layer.id]++
|
returnedFeatures[feature.layer.id]++
|
||||||
|
|
||||||
const featureObject = sources[feature.layer['source-layer']].find((f: InspectFeature) => f.layer.id === feature.layer.id)
|
const featureObject = sources[feature.layer['source-layer']].find((f: InspectFeature) => f.layer.id === feature.layer.id)
|
||||||
@@ -42,21 +42,21 @@ class FeatureLayerPopup extends React.Component<FeatureLayerPopupProps> {
|
|||||||
const paintProps = feature.layer.paint;
|
const paintProps = feature.layer.paint;
|
||||||
let propName;
|
let propName;
|
||||||
|
|
||||||
if(paintProps.hasOwnProperty("text-color") && paintProps["text-color"]) {
|
if(Object.prototype.hasOwnProperty.call(paintProps, "text-color") && paintProps["text-color"]) {
|
||||||
propName = "text-color";
|
propName = "text-color";
|
||||||
}
|
}
|
||||||
else if (paintProps.hasOwnProperty("fill-color") && paintProps["fill-color"]) {
|
else if (Object.prototype.hasOwnProperty.call(paintProps, "fill-color") && paintProps["fill-color"]) {
|
||||||
propName = "fill-color";
|
propName = "fill-color";
|
||||||
}
|
}
|
||||||
else if (paintProps.hasOwnProperty("line-color") && paintProps["line-color"]) {
|
else if (Object.prototype.hasOwnProperty.call(paintProps, "line-color") && paintProps["line-color"]) {
|
||||||
propName = "line-color";
|
propName = "line-color";
|
||||||
}
|
}
|
||||||
else if (paintProps.hasOwnProperty("fill-extrusion-color") && paintProps["fill-extrusion-color"]) {
|
else if (Object.prototype.hasOwnProperty.call(paintProps, "fill-extrusion-color") && paintProps["fill-extrusion-color"]) {
|
||||||
propName = "fill-extrusion-color";
|
propName = "fill-extrusion-color";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(propName) {
|
if(propName) {
|
||||||
let color = feature.layer.paint[propName];
|
const color = feature.layer.paint[propName];
|
||||||
return String(color);
|
return String(color);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export default class MapOpenLayers extends React.Component<MapOpenLayersProps, M
|
|||||||
});
|
});
|
||||||
|
|
||||||
map.on('pointermove', (evt) => {
|
map.on('pointermove', (evt) => {
|
||||||
var coords = toLonLat(evt.coordinate);
|
const coords = toLonLat(evt.coordinate);
|
||||||
this.setState({
|
this.setState({
|
||||||
cursor: [
|
cursor: [
|
||||||
coords[0].toFixed(2),
|
coords[0].toFixed(2),
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export default class ModalAdd extends React.Component<ModalAddProps, ModalAddSta
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let [key, val] of Object.entries(this.props.sources) as any) {
|
for(const [key, val] of Object.entries(this.props.sources) as any) {
|
||||||
const valType = val.type as keyof typeof types;
|
const valType = val.type as keyof typeof types;
|
||||||
if(types[valType] && types[valType].indexOf(type) > -1) {
|
if(types[valType] && types[valType].indexOf(type) > -1) {
|
||||||
sources.push(key);
|
sources.push(key);
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ export default class ModalOpen extends React.Component<ModalOpenProps, ModalOpen
|
|||||||
}
|
}
|
||||||
|
|
||||||
onUpload = (_: any, files: Result[]) => {
|
onUpload = (_: any, files: Result[]) => {
|
||||||
const [_e, file] = files[0];
|
const [, file] = files[0];
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
this.clearError();
|
this.clearError();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ function setStopRefs(props: DataPropertyProps, state: DataPropertyState) {
|
|||||||
|
|
||||||
if(props.value && props.value.stops) {
|
if(props.value && props.value.stops) {
|
||||||
props.value.stops.forEach((_val, idx) => {
|
props.value.stops.forEach((_val, idx) => {
|
||||||
if(!state.refs.hasOwnProperty(idx)) {
|
if(!Object.prototype.hasOwnProperty.call(state.refs, idx)) {
|
||||||
if(!newRefs) {
|
if(!newRefs) {
|
||||||
newRefs = {...state};
|
newRefs = {...state};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ function setStopRefs(props: ZoomPropertyProps, state: ZoomPropertyState) {
|
|||||||
|
|
||||||
if(props.value && (props.value as ZoomWithStops).stops) {
|
if(props.value && (props.value as ZoomWithStops).stops) {
|
||||||
(props.value as ZoomWithStops).stops.forEach((_val, idx: number) => {
|
(props.value as ZoomWithStops).stops.forEach((_val, idx: number) => {
|
||||||
if(!state.refs.hasOwnProperty(idx)) {
|
if(Object.prototype.hasOwnProperty.call(!state.refs, idx)) {
|
||||||
if(!newRefs) {
|
if(!newRefs) {
|
||||||
newRefs = {...state};
|
newRefs = {...state};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { IconContext } from "react-icons";
|
import { IconContext } from "react-icons";
|
||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import './favicon.ico'
|
import './favicon.ico'
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ function get(namespace: keyof DebugStore, key: string) {
|
|||||||
if(!enabled()) {
|
if(!enabled()) {
|
||||||
throw genErr();
|
throw genErr();
|
||||||
}
|
}
|
||||||
if(debugStore.hasOwnProperty(namespace)) {
|
if(Object.prototype.hasOwnProperty.call(debugStore, namespace)) {
|
||||||
return debugStore[namespace][key];
|
return debugStore[namespace][key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,3 +70,21 @@ export function changeProperty(layer: LayerSpecification, group: keyof LayerSpec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function layerPrefix(name: string) {
|
||||||
|
return name.replace(' ', '-').replace('_', '-').split('-')[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findClosestCommonPrefix(layers: LayerSpecification[], idx: number) {
|
||||||
|
const currentLayerPrefix = layerPrefix(layers[idx].id)
|
||||||
|
let closestIdx = idx
|
||||||
|
for (let i = idx; i > 0; i--) {
|
||||||
|
const previousLayerPrefix = layerPrefix(layers[i-1].id)
|
||||||
|
if(previousLayerPrefix === currentLayerPrefix) {
|
||||||
|
closestIdx = i - 1
|
||||||
|
} else {
|
||||||
|
return closestIdx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closestIdx
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ export function downloadGlyphsMetadata(urlTemplate: string, cb: (...args: any[])
|
|||||||
|
|
||||||
// Special handling because Tileserver GL serves the fontstacks metadata differently
|
// Special handling because Tileserver GL serves the fontstacks metadata differently
|
||||||
// https://github.com/klokantech/tileserver-gl/pull/104#issuecomment-274444087
|
// https://github.com/klokantech/tileserver-gl/pull/104#issuecomment-274444087
|
||||||
let urlObj = npmurl.parse(urlTemplate);
|
const urlObj = npmurl.parse(urlTemplate);
|
||||||
const normPathPart = '/%7Bfontstack%7D/%7Brange%7D.pbf';
|
const normPathPart = '/%7Bfontstack%7D/%7Brange%7D.pbf';
|
||||||
if(urlObj.pathname === normPathPart) {
|
if(urlObj.pathname === normPathPart) {
|
||||||
urlObj.pathname = '/fontstacks.json';
|
urlObj.pathname = '/fontstacks.json';
|
||||||
} else {
|
} else {
|
||||||
urlObj.pathname = urlObj.pathname!.replace(normPathPart, '.json');
|
urlObj.pathname = urlObj.pathname!.replace(normPathPart, '.json');
|
||||||
}
|
}
|
||||||
let url = npmurl.format(urlObj);
|
const url = npmurl.format(urlObj);
|
||||||
|
|
||||||
loadJSON(url, [], cb)
|
loadJSON(url, [], cb)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@use 'sass:color';
|
||||||
// MAP
|
// MAP
|
||||||
.maputnik-map__container {
|
.maputnik-map__container {
|
||||||
background: white;
|
background: white;
|
||||||
@@ -110,12 +111,12 @@
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: lighten($color-midgray, 12);
|
background-color: color.adjust($color-midgray, $lightness: 12%);
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background-color: darken($color-midgray, 5);
|
background-color: color.adjust($color-midgray, $lightness: -5%);
|
||||||
color: $color-midgray;
|
color: $color-midgray;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-filter-editor {
|
.maputnik-filter-editor {
|
||||||
@extend .clearfix;
|
@extend .clearfix; /* stylelint-disable-line */
|
||||||
color: $color-lowgray;
|
color: $color-lowgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-delete-filter {
|
.maputnik-delete-filter {
|
||||||
@extend .maputnik-icon-button;
|
@extend .maputnik-icon-button; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-filter-editor-block-action {
|
.maputnik-filter-editor-block-action {
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-radio-as-button {
|
.maputnik-radio-as-button {
|
||||||
@extend .maputnik-button;
|
@extend .maputnik-button; /* stylelint-disable-line */
|
||||||
|
|
||||||
border: solid 1px transparent;
|
border: solid 1px transparent;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@use 'sass:color';
|
||||||
//INPUT
|
//INPUT
|
||||||
.maputnik-input {
|
.maputnik-input {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
@@ -10,7 +11,7 @@
|
|||||||
padding-right: $margin-2;
|
padding-right: $margin-2;
|
||||||
border: none;
|
border: none;
|
||||||
background-color: $color-gray;
|
background-color: $color-gray;
|
||||||
color: lighten($color-lowgray, 12);
|
color: color.adjust($color-lowgray, $lightness: 12%);
|
||||||
|
|
||||||
&:invalid {
|
&:invalid {
|
||||||
border: solid 1px #B71C1C;
|
border: solid 1px #B71C1C;
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-string {
|
.maputnik-string {
|
||||||
@extend .maputnik-input;
|
@extend .maputnik-input; /* stylelint-disable-line */
|
||||||
|
|
||||||
&--multi {
|
&--multi {
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
@@ -43,12 +44,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-number {
|
.maputnik-number {
|
||||||
@extend .maputnik-input;
|
@extend .maputnik-input; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
//COLOR PICKER
|
//COLOR PICKER
|
||||||
.maputnik-color {
|
.maputnik-color {
|
||||||
@extend .maputnik-input;
|
@extend .maputnik-input; /* stylelint-disable-line */
|
||||||
|
|
||||||
height: 26px;
|
height: 26px;
|
||||||
}
|
}
|
||||||
@@ -95,7 +96,7 @@
|
|||||||
|
|
||||||
// SELECT
|
// SELECT
|
||||||
.maputnik-select {
|
.maputnik-select {
|
||||||
@extend .maputnik-input;
|
@extend .maputnik-input; /* stylelint-disable-line */
|
||||||
|
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
@@ -117,7 +118,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-button-selected {
|
.maputnik-button-selected {
|
||||||
background-color: lighten($color-midgray, 12);
|
background-color: color.adjust($color-midgray, $lightness: 12%);
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +134,7 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
&-wrapper {
|
&-wrapper {
|
||||||
@extend .maputnik-input;
|
@extend .maputnik-input; /* stylelint-disable-line */
|
||||||
|
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
|
|||||||
+14
-13
@@ -1,3 +1,4 @@
|
|||||||
|
@use 'sass:color';
|
||||||
// LAYER LIST
|
// LAYER LIST
|
||||||
.maputnik-layer-list {
|
.maputnik-layer-list {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -48,7 +49,7 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: $color-lowgray;
|
color: $color-lowgray;
|
||||||
font-size: $font-size-6;
|
font-size: $font-size-6;
|
||||||
border-bottom-color: lighten($color-black, 0.1);
|
border-bottom-color: color.adjust($color-black, $lightness: 0.1%);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
@@ -87,7 +88,7 @@
|
|||||||
height: 15px;
|
height: 15px;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: darken($color-lowgray, 20);
|
fill: color.adjust($color-lowgray, $lightness: -20%);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
fill: $color-white;
|
fill: $color-white;
|
||||||
@@ -101,13 +102,13 @@
|
|||||||
|
|
||||||
.maputnik-layer-list-item:hover,
|
.maputnik-layer-list-item:hover,
|
||||||
.maputnik-layer-list-item-selected {
|
.maputnik-layer-list-item-selected {
|
||||||
background-color: lighten($color-black, 2);
|
background-color: color.adjust($color-black, $lightness: 2%);
|
||||||
|
|
||||||
.maputnik-layer-list-icon-action {
|
.maputnik-layer-list-icon-action {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: darken($color-lowgray, 0.5);
|
fill: color.adjust($color-lowgray, $lightness: -0.5%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +152,7 @@
|
|||||||
border: solid 1px transparent;
|
border: solid 1px transparent;
|
||||||
font-size: $font-size-6;
|
font-size: $font-size-6;
|
||||||
color: $color-lowgray;
|
color: $color-lowgray;
|
||||||
background-color: lighten($color-black, 2);
|
background-color: color.adjust($color-black, $lightness: 2%);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding: $margin-2;
|
padding: $margin-2;
|
||||||
|
|
||||||
@@ -185,7 +186,7 @@
|
|||||||
.maputnik-layer-editor-group {
|
.maputnik-layer-editor-group {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: $font-size-5;
|
font-size: $font-size-5;
|
||||||
background-color: lighten($color-black, 2);
|
background-color: color.adjust($color-black, $lightness: 2%);
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@@ -232,7 +233,7 @@
|
|||||||
// PROPERTY
|
// PROPERTY
|
||||||
.maputnik-default-property {
|
.maputnik-default-property {
|
||||||
.maputnik-input-block-label {
|
.maputnik-input-block-label {
|
||||||
color: darken($color-lowgray, 20%);
|
color: color.adjust($color-lowgray, $lightness: -20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-string,
|
.maputnik-string,
|
||||||
@@ -240,8 +241,8 @@
|
|||||||
.maputnik-color,
|
.maputnik-color,
|
||||||
.maputnik-select,
|
.maputnik-select,
|
||||||
.maputnik-checkbox-wrapper {
|
.maputnik-checkbox-wrapper {
|
||||||
background-color: darken($color-gray, 2%);
|
background-color: color.adjust($color-gray, $lightness: -2%);
|
||||||
color: darken($color-lowgray, 20%);
|
color: color.adjust($color-lowgray, $lightness: -20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-make-zoom-function svg {
|
.maputnik-make-zoom-function svg {
|
||||||
@@ -249,17 +250,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-multibutton .maputnik-button {
|
.maputnik-multibutton .maputnik-button {
|
||||||
background-color: darken($color-midgray, 10%);
|
background-color: color.adjust($color-midgray, $lightness: -10%);
|
||||||
color: darken($color-lowgray, 20%);
|
color: color.adjust($color-lowgray, $lightness: -20%);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: lighten($color-midgray, 12);
|
background-color: color.adjust($color-midgray, $lightness: 12%);
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-multibutton .maputnik-button-selected {
|
.maputnik-multibutton .maputnik-button-selected {
|
||||||
background-color: darken($color-midgray, 2%);
|
background-color: color.adjust($color-midgray, $lightness: -2%);
|
||||||
color: $color-lowgray;
|
color: $color-lowgray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,12 +72,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-modal-header-space {
|
.maputnik-modal-header-space {
|
||||||
@extend .maputnik-space;
|
@extend .maputnik-space; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
//OPEN MODAL
|
//OPEN MODAL
|
||||||
.maputnik-upload-button {
|
.maputnik-upload-button {
|
||||||
@extend .maputnik-big-button;
|
@extend .maputnik-big-button; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-style-gallery-container {
|
.maputnik-style-gallery-container {
|
||||||
@@ -139,12 +139,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-add-layer {
|
.maputnik-add-layer {
|
||||||
@extend .clearfix;
|
@extend .clearfix; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
//ADD MODAL
|
//ADD MODAL
|
||||||
.maputnik-add-layer-button {
|
.maputnik-add-layer-button {
|
||||||
@extend .maputnik-big-button;
|
@extend .maputnik-big-button; /* stylelint-disable-line */
|
||||||
|
|
||||||
margin-right: $margin-3;
|
margin-right: $margin-3;
|
||||||
float: right;
|
float: right;
|
||||||
@@ -221,7 +221,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-add-source {
|
.maputnik-add-source {
|
||||||
@extend .clearfix;
|
@extend .clearfix; /* stylelint-disable-line */
|
||||||
|
|
||||||
.maputnik-input-block-label {
|
.maputnik-input-block-label {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
@@ -233,7 +233,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-add-source-button {
|
.maputnik-add-source-button {
|
||||||
@extend .maputnik-big-button;
|
@extend .maputnik-big-button; /* stylelint-disable-line */
|
||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@use 'sass:color';
|
||||||
// TOOLBAR
|
// TOOLBAR
|
||||||
.maputnik-toolbar {
|
.maputnik-toolbar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -75,7 +76,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover .maputnik-toolbar-link-wrapper {
|
&:hover .maputnik-toolbar-link-wrapper {
|
||||||
background-color: lighten($color-midgray, 12);
|
background-color: color.adjust($color-midgray, $lightness: 12%);
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,13 +94,13 @@
|
|||||||
.maputnik-toolbar-action {
|
.maputnik-toolbar-action {
|
||||||
background: inherit;
|
background: inherit;
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
@extend .maputnik-toolbar-link;
|
@extend .maputnik-toolbar-link; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-toolbar-select {
|
.maputnik-toolbar-select {
|
||||||
background: inherit;
|
background: inherit;
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
@extend .maputnik-toolbar-link;
|
@extend .maputnik-toolbar-link; /* stylelint-disable-line */
|
||||||
|
|
||||||
select {
|
select {
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding: 0 $margin-2 0 0;
|
padding: 0 $margin-2 0 0;
|
||||||
|
|
||||||
@extend .maputnik-icon-button;
|
@extend .maputnik-icon-button; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
// ZOOM PROPERTY
|
// ZOOM PROPERTY
|
||||||
.maputnik-zoom-spec-property {
|
.maputnik-zoom-spec-property {
|
||||||
@extend .clearfix;
|
@extend .clearfix; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-zoom-spec-property-label {
|
.maputnik-zoom-spec-property-label {
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
@extend .maputnik-icon-button;
|
@extend .maputnik-icon-button; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-add-stop {
|
.maputnik-add-stop {
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding: 0 $margin-2 0 0;
|
padding: 0 $margin-2 0 0;
|
||||||
|
|
||||||
@extend .maputnik-icon-button;
|
@extend .maputnik-icon-button; /* stylelint-disable-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-data-spec-property {
|
.maputnik-data-spec-property {
|
||||||
|
|||||||
@@ -28,9 +28,6 @@
|
|||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maputnik-data-spec-property {
|
|
||||||
}
|
|
||||||
|
|
||||||
.maputnik-data-fieldset-inner {
|
.maputnik-data-fieldset-inner {
|
||||||
background: $color-black;
|
background: $color-black;
|
||||||
border: solid 1px $color-midgray;
|
border: solid 1px $color-midgray;
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ CodeMirror.registerHelper("lint", "mgl", (text: string, opts: any, doc: any) =>
|
|||||||
try {
|
try {
|
||||||
parser.parse(text);
|
parser.parse(text);
|
||||||
}
|
}
|
||||||
catch (e) {}
|
catch (e) {
|
||||||
|
// ignore errors
|
||||||
|
}
|
||||||
|
|
||||||
if (found.length > 0) {
|
if (found.length > 0) {
|
||||||
// JSON invalid so don't go any further
|
// JSON invalid so don't go any further
|
||||||
@@ -154,7 +156,7 @@ CodeMirror.registerHelper("lint", "mgl", (text: string, opts: any, doc: any) =>
|
|||||||
found.push(err);
|
found.push(err);
|
||||||
}
|
}
|
||||||
else if (key) {
|
else if (key) {
|
||||||
const path = key.replace(/^\[|\]$/g, "").split(/\.|[\[\]]+/).filter(Boolean)
|
const path = key.replace(/^\[|\]$/g, "").split(/\.|[[\]]+/).filter(Boolean)
|
||||||
const parsedError = getArrayPositionalFromAst(ast, path);
|
const parsedError = getArrayPositionalFromAst(ast, path);
|
||||||
if (!parsedError) {
|
if (!parsedError) {
|
||||||
console.warn("Something went wrong parsing error:", error);
|
console.warn("Something went wrong parsing error:", error);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* If we don't have a default value just make one up
|
* If we don't have a default value just make one up
|
||||||
*/
|
*/
|
||||||
export function findDefaultFromSpec(spec: { type: 'string' | 'color' | 'boolean' | 'array', default?: any }) {
|
export function findDefaultFromSpec(spec: { type: 'string' | 'color' | 'boolean' | 'array', default?: any }) {
|
||||||
if (spec.hasOwnProperty('default')) {
|
if (Object.prototype.hasOwnProperty.call(spec, 'default')) {
|
||||||
return spec.default;
|
return spec.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"types": ["geojson"],
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user