Merge branch 'main' into pmtiles-support

This commit is contained in:
Pirmin Kalberer
2025-01-22 21:24:23 +01:00
committed by GitHub
45 changed files with 682 additions and 475 deletions

View File

@@ -1,46 +0,0 @@
{
"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],
"no-var": ["error"]
},
"globals": {
"global": "readonly"
}
}

View File

@@ -1,14 +1,17 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
open-pull-requests-limit: 2
open-pull-requests-limit: 20
versioning-strategy: increase
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 2
versioning-strategy: increase

View File

@@ -0,0 +1,26 @@
name: Automerge Dependabot
on: pull_request
permissions: write-all
jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2.2.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Approve Dependabot PRs
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Enable auto-merge for Dependabot PRs
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

View File

@@ -107,7 +107,7 @@ jobs:
start: npm run start
browser: ${{ matrix.browser }}
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
with:
files: ${{ github.workspace }}/.nyc_output/out.json
verbose: true

70
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '17 0 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

View File

@@ -32,7 +32,7 @@ jobs:
./build/bump-version-changelog.js ${{ inputs.version }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v7
with:
commit-message: Bump version to ${{ inputs.version }}
branch: bump-version-to-${{ inputs.version }}

View File

@@ -24,7 +24,7 @@ jobs:
run: npm run build
- name: Upload to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: dist

2
.nvmrc
View File

@@ -1 +1 @@
18.19
22.13

View File

@@ -6,10 +6,15 @@
- Add scheme type options for vector/raster tile
- Add `tileSize` field for raster and raster-dem tile sources
- Update Protomaps Light gallery style to v4
- Add support to edit local files on the file system
- Add support to edit local files on the file system if supported by the browser
- Upgrade to MapLibre LG JS v5
- Upgrade Vite 6 and Cypress 14 ([#970](https://github.com/maplibre/maputnik/pull/970))
- Upgrade OpenLayers from v6 to v10
- _...Add new stuff here..._
### 🐞 Bug fixes
- Fix incorrect handing of network error response (#944)
- _...Add new stuff here..._
## 2.1.1

View File

@@ -20,14 +20,14 @@ const changelog = fs.readFileSync(changelogPath, 'utf8');
*/
const regex = /^## (\d+\.\d+\.\d+.*?)\n(.+?)(?=\n^## \d+\.\d+\.\d+.*?\n)/gms;
let releaseNotes = [];
const releaseNotes = [];
let match;
// eslint-disable-next-line no-cond-assign
while (match = regex.exec(changelog)) {
releaseNotes.push({
'version': match[1],
'changelog': match[2].trim(),
});
releaseNotes.push({
'version': match[1],
'changelog': match[2].trim(),
});
}
const latest = releaseNotes[0];
@@ -44,5 +44,4 @@ const templatedReleaseNotes = `${header}
${latest.changelog}`;
// eslint-disable-next-line eol-last
process.stdout.write(templatedReleaseNotes.trimEnd());

View File

@@ -1,7 +1,7 @@
import { MaputnikDriver } from "./maputnik-driver";
describe("accessibility", () => {
let { beforeAndAfter, get, when, then } = new MaputnikDriver();
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
describe("skip links", () => {

View File

@@ -1,7 +1,7 @@
import { MaputnikDriver } from "./maputnik-driver";
describe("history", () => {
let { beforeAndAfter, when, get, then } = new MaputnikDriver();
const { beforeAndAfter, when, get, then } = new MaputnikDriver();
beforeAndAfter();
let undoKeyCombo: string;

View File

@@ -1,7 +1,7 @@
import { MaputnikDriver } from "./maputnik-driver";
describe("i18n", () => {
let { beforeAndAfter, get, when, then } = new MaputnikDriver();
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
describe("language detector", () => {

View File

@@ -1,7 +1,7 @@
import { MaputnikDriver } from "./maputnik-driver";
describe("keyboard", () => {
let { beforeAndAfter, given, when, get, then } = new MaputnikDriver();
const { beforeAndAfter, given, when, get, then } = new MaputnikDriver();
beforeAndAfter();
describe("shortcuts", () => {
beforeEach(() => {

View File

@@ -2,7 +2,7 @@ import { v1 as uuid } from "uuid";
import { MaputnikDriver } from "./maputnik-driver";
describe("layers", () => {
let { beforeAndAfter, get, when, then } = new MaputnikDriver();
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
beforeEach(() => {
when.setStyle("both");
@@ -101,7 +101,7 @@ describe("layers", () => {
});
describe("background", () => {
it("add", () => {
let id = when.modal.fillLayers({
const id = when.modal.fillLayers({
type: "background",
});
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
@@ -117,7 +117,7 @@ describe("layers", () => {
describe("modify", () => {
function createBackground() {
// Setup
let id = uuid();
const id = uuid();
when.selectWithin("add-layer.layer-type", "background");
when.setValue("add-layer.layer-id.input", "background:" + id);
@@ -139,11 +139,11 @@ describe("layers", () => {
describe("layer", () => {
it("expand/collapse");
it("id", () => {
let bgId = createBackground();
const bgId = createBackground();
when.click("layer-list-item:background:" + bgId);
let id = uuid();
const id = uuid();
when.setValue("layer-editor.layer-id.input", "foobar:" + id);
when.click("min-zoom");
@@ -219,7 +219,7 @@ describe("layers", () => {
describe("comments", () => {
let bgId: string;
let comment = "42";
const comment = "42";
beforeEach(() => {
bgId = createBackground();
@@ -320,11 +320,11 @@ describe("layers", () => {
// TODO
it.skip("parse error", () => {
let bgId = createBackground();
const bgId = createBackground();
when.click("layer-list-item:background:" + bgId);
let errorSelector = ".CodeMirror-lint-marker-error";
const errorSelector = ".CodeMirror-lint-marker-error";
then(get.elementByTestId(errorSelector)).shouldNotExist();
when.click(".CodeMirror");
@@ -339,7 +339,7 @@ describe("layers", () => {
describe("fill", () => {
it("add", () => {
let id = when.modal.fillLayers({
const id = when.modal.fillLayers({
type: "fill",
layer: "example",
});
@@ -361,7 +361,7 @@ describe("layers", () => {
describe("line", () => {
it("add", () => {
let id = when.modal.fillLayers({
const id = when.modal.fillLayers({
type: "line",
layer: "example",
});
@@ -385,7 +385,7 @@ describe("layers", () => {
describe("symbol", () => {
it("add", () => {
let id = when.modal.fillLayers({
const id = when.modal.fillLayers({
type: "symbol",
layer: "example",
});
@@ -404,7 +404,7 @@ describe("layers", () => {
describe("raster", () => {
it("add", () => {
let id = when.modal.fillLayers({
const id = when.modal.fillLayers({
type: "raster",
layer: "raster",
});
@@ -423,7 +423,7 @@ describe("layers", () => {
describe("circle", () => {
it("add", () => {
let id = when.modal.fillLayers({
const id = when.modal.fillLayers({
type: "circle",
layer: "example",
});
@@ -442,7 +442,7 @@ describe("layers", () => {
describe("fill extrusion", () => {
it("add", () => {
let id = when.modal.fillLayers({
const id = when.modal.fillLayers({
type: "fill-extrusion",
layer: "example",
});
@@ -494,4 +494,33 @@ describe("layers", () => {
).shouldBeVisible();
});
});
describe("layereditor jsonlint should error", ()=>{
it("add", () => {
const id = when.modal.fillLayers({
type: "circle",
layer: "example",
});
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
id: id,
type: "circle",
source: "example",
},
],
});
const sourceText = get.elementByText('"source"');
sourceText.click();
sourceText.type("\"");
const error = get.element('.CodeMirror-lint-marker-error');
error.should('exist');
});
});
});

View File

@@ -1,11 +1,11 @@
import { MaputnikDriver } from "./maputnik-driver";
describe("map", () => {
let { beforeAndAfter, get, when, then } = new MaputnikDriver();
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
describe("zoom level", () => {
it("via url", () => {
let zoomLevel = 12.37;
const zoomLevel = 12.37;
when.setStyle("geojson", zoomLevel);
then(get.elementByTestId("maplibre:ctrl-zoom")).shouldBeVisible();
then(get.elementByTestId("maplibre:ctrl-zoom")).shouldContainText(
@@ -14,7 +14,7 @@ describe("map", () => {
});
it("via map controls", () => {
let zoomLevel = 12.37;
const zoomLevel = 12.37;
when.setStyle("geojson", zoomLevel);
then(get.elementByTestId("maplibre:ctrl-zoom")).shouldBeVisible();
when.clickZoomIn();

View File

@@ -8,8 +8,8 @@ export default class ModalDriver {
fillLayers: (opts: { type: string; layer?: string; id?: string }) => {
// Having logic in test code is an anti pattern.
// This should be splitted to multiple single responsibility functions
let type = opts.type;
let layer = opts.layer;
const type = opts.type;
const layer = opts.layer;
let id;
if (opts.id) {
id = opts.id;

View File

@@ -1,7 +1,7 @@
import { MaputnikDriver } from "./maputnik-driver";
describe("modals", () => {
let { beforeAndAfter, when, get, then } = new MaputnikDriver();
const { beforeAndAfter, when, get, then } = new MaputnikDriver();
beforeAndAfter();
beforeEach(() => {
@@ -25,7 +25,7 @@ describe("modals", () => {
describe("when click open url", () => {
beforeEach(() => {
let styleFileUrl = get.exampleFileUrl();
const styleFileUrl = get.exampleFileUrl();
when.setValue("modal:open.url.input", styleFileUrl);
when.click("modal:open.url.button");
@@ -70,7 +70,7 @@ describe("modals", () => {
it("public source");
it("add new source", () => {
let sourceId = "n1z2v3r";
const sourceId = "n1z2v3r";
when.setValue("modal:sources.add.source_id", sourceId);
when.select("modal:sources.add.source_type", "tile_vector");
when.select("modal:sources.add.scheme_type", "tms");
@@ -102,7 +102,7 @@ describe("modals", () => {
});
it("add new raster source", () => {
let sourceId = "rastertest";
const sourceId = "rastertest";
when.setValue("modal:sources.add.source_id", sourceId);
when.select("modal:sources.add.source_type", "tile_raster");
when.select("modal:sources.add.scheme_type", "xyz");
@@ -177,7 +177,7 @@ describe("modals", () => {
});
});
it("glyphs url", () => {
let glyphsUrl = "http://example.com/{fontstack}/{range}.pbf";
const glyphsUrl = "http://example.com/{fontstack}/{range}.pbf";
when.setValue("modal:settings.glyphs", glyphsUrl);
when.click("modal:settings.name");
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
@@ -186,7 +186,7 @@ describe("modals", () => {
});
it("maptiler access token", () => {
let apiKey = "testing123";
const apiKey = "testing123";
when.setValue(
"modal:settings.maputnik:openmaptiles_access_token",
apiKey
@@ -200,7 +200,7 @@ describe("modals", () => {
});
it("thunderforest access token", () => {
let apiKey = "testing123";
const apiKey = "testing123";
when.setValue(
"modal:settings.maputnik:thunderforest_access_token",
apiKey
@@ -212,7 +212,7 @@ describe("modals", () => {
});
it("stadia access token", () => {
let apiKey = "testing123";
const apiKey = "testing123";
when.setValue(
"modal:settings.maputnik:stadia_access_token",
apiKey

61
eslint.config.js Normal file
View File

@@ -0,0 +1,61 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import reactPlugin from 'eslint-plugin-react';
import reactHooksPlugin from 'eslint-plugin-react-hooks';
import reactRefreshPlugin from 'eslint-plugin-react-refresh';
export default tseslint.config({
extends: [
eslint.configs.recommended,
tseslint.configs.recommended,
],
files: ['**/*.{js,jsx,ts,tsx}'],
ignores: [
"dist/**/*",
],
languageOptions: {
ecmaVersion: 2024,
sourceType: 'module',
globals: {
global: 'readonly'
}
},
settings: {
react: { version: '18.2' }
},
plugins: {
'react': reactPlugin,
'react-hooks': reactHooksPlugin,
'react-refresh': reactRefreshPlugin
},
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true }
],
"@typescript-eslint/no-explicit-any": "off",
'@typescript-eslint/no-unused-vars': [
'warn',
{
varsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
argsIgnorePattern: '^_'
}
],
'no-unused-vars': 'off',
'react/prop-types': 'off',
'no-undef': 'off',
'indent': ['error', 2],
'no-var': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
},
linterOptions: {
reportUnusedDisableDirectives: true,
noInlineConfig: false
}
}
)

View File

@@ -10,7 +10,7 @@ export default {
keySeparator: false,
namespaceSeparator: false,
defaultValue: (locale, ns, key) => {
defaultValue: (_locale, _ns, _key) => {
// The default value is a string that indicates that the string is not translated.
return '__STRING_NOT_TRANSLATED__';
}

View File

@@ -15,7 +15,7 @@ function validate(url: string, t: TFunction): JSX.Element | undefined {
const urlObj = new URL(url);
return urlObj.protocol;
}
catch (err) {
catch (_err) {
return undefined;
}
};

View File

@@ -318,14 +318,7 @@ class LayerListContainerInternal extends React.Component<LayerListContainerInter
}
}
// The next two lines have react-refresh/only-export-components disabled because they are
// internal components that are not intended to be used outside of this file.
// For some reason, the linter is not recognizing these components correctly.
// When these components are migrated to functional components, the HOCs will no longer be needed
// and the comments can be removed.
// eslint-disable-next-line react-refresh/only-export-components
const LayerListContainer = withTranslation()(LayerListContainerInternal);
// eslint-disable-next-line react-refresh/only-export-components
const LayerListContainerSortable = SortableContainer((props: LayerListContainerProps) => <LayerListContainer {...props} />)
type LayerListProps = LayerListContainerProps & {

View File

@@ -104,7 +104,7 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
let should = false;
try {
should = JSON.stringify(this.props) !== JSON.stringify(nextProps) || JSON.stringify(this.state) !== JSON.stringify(nextState);
} catch(e) {
} catch(_e) {
// no biggie, carry on
}
return should;
@@ -164,7 +164,7 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
map.showCollisionBoxes = mapOpts.showCollisionBoxes!;
map.showOverdrawInspector = mapOpts.showOverdrawInspector!;
let geocoder = this.initGeocoder(map);
const geocoder = this.initGeocoder(map);
const zoomControl = new ZoomControl();
map.addControl(zoomControl, 'top-right');

View File

@@ -85,10 +85,11 @@ class MapOpenLayersInternal extends React.Component<MapOpenLayersInternalProps,
componentDidMount() {
this.overlay = new Overlay({
element: this.popupContainer!,
autoPan: true,
autoPanAnimation: {
duration: 250
}
autoPan: {
animation: {
duration: 250
}
},
});
const map = new Map({

View File

@@ -5,7 +5,7 @@ import {version} from 'maplibre-gl/package.json'
import {format} from '@maplibre/maplibre-gl-style-spec'
import type {StyleSpecification} from 'maplibre-gl'
import {MdMap, MdSave} from 'react-icons/md'
import { WithTranslation, withTranslation } from 'react-i18next';
import {WithTranslation, withTranslation} from 'react-i18next';
import FieldString from './FieldString'
import InputButton from './InputButton'
@@ -15,6 +15,7 @@ import fieldSpecAdditional from '../libs/field-spec-additional'
const MAPLIBRE_GL_VERSION = version;
const showSaveFilePickerAvailable = typeof window.showSaveFilePicker === "function";
type ModalExportInternalProps = {
@@ -29,7 +30,7 @@ type ModalExportInternalProps = {
class ModalExportInternal extends React.Component<ModalExportInternalProps> {
tokenizedStyle () {
tokenizedStyle() {
return format(
style.stripAccessTokens(
style.replaceAccessTokens(this.props.mapStyle)
@@ -37,8 +38,8 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
);
}
exportName () {
if(this.props.mapStyle.name) {
exportName() {
if (this.props.mapStyle.name) {
return Slugify(this.props.mapStyle.name, {
replacement: '_',
remove: /[*\-+~.()'"!:]/g,
@@ -86,6 +87,15 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
async saveStyle() {
const tokenStyle = this.tokenizedStyle();
// it is not guaranteed that the File System Access API is available on all
// browsers. If the function is not available, a fallback behavior is used.
if (!showSaveFilePickerAvailable) {
const blob = new Blob([tokenStyle], {type: "application/json;charset=utf-8"});
const exportName = this.exportName();
saveAs(blob, exportName + ".json");
return;
}
let fileHandle = this.props.fileHandle;
if (fileHandle == null) {
fileHandle = await this.createFileHandle();
@@ -112,12 +122,12 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
this.props.onOpenToggle();
}
async createFileHandle() : Promise<FileSystemFileHandle | null> {
async createFileHandle(): Promise<FileSystemFileHandle | null> {
const pickerOpts: SaveFilePickerOptions = {
types: [
{
description: "json",
accept: { "application/json": [".json"] },
accept: {"application/json": [".json"]},
},
],
suggestedName: this.exportName(),
@@ -179,23 +189,19 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
</div>
<div className="maputnik-modal-export-buttons">
<InputButton
onClick={this.saveStyle.bind(this)}
>
<MdSave />
<InputButton onClick={this.saveStyle.bind(this)}>
<MdSave/>
{t("Save")}
</InputButton>
<InputButton
onClick={this.saveStyleAs.bind(this)}
>
<MdSave />
{t("Save as")}
</InputButton>
{showSaveFilePickerAvailable && (
<InputButton onClick={this.saveStyleAs.bind(this)}>
<MdSave/>
{t("Save as")}
</InputButton>
)}
<InputButton
onClick={this.createHtml.bind(this)}
>
<MdMap />
<InputButton onClick={this.createHtml.bind(this)}>
<MdMap/>
{t("Create HTML")}
</InputButton>
</div>

View File

@@ -1,6 +1,7 @@
import React, { FormEvent } from 'react'
import {MdFileUpload} from 'react-icons/md'
import {MdAddCircleOutline} from 'react-icons/md'
import FileReaderInput, { Result } from 'react-file-reader-input'
import { Trans, WithTranslation, withTranslation } from 'react-i18next';
import ModalLoading from './ModalLoading'
@@ -168,6 +169,32 @@ class ModalOpenInternal extends React.Component<ModalOpenInternalProps, ModalOpe
return file;
}
// it is not guaranteed that the File System Access API is available on all
// browsers. If the function is not available, a fallback behavior is used.
onFileChanged = async (_: any, files: Result[]) => {
const [, file] = files[0];
const reader = new FileReader();
this.clearError();
reader.readAsText(file, "UTF-8");
reader.onload = e => {
let mapStyle;
try {
mapStyle = JSON.parse(e.target?.result as string)
}
catch(err) {
this.setState({
error: (err as Error).toString()
});
return;
}
mapStyle = style.ensureStyleValidity(mapStyle)
this.props.onStyleOpen(mapStyle);
this.onOpenToggle();
}
reader.onerror = e => console.log(e.target);
}
onOpenToggle() {
this.setState({
styleUrl: ""
@@ -217,10 +244,16 @@ class ModalOpenInternal extends React.Component<ModalOpenInternalProps, ModalOpe
<h1>{t("Open local Style")}</h1>
<p>{t("Open a local JSON style from your computer.")}</p>
<div>
<InputButton
className="maputnik-big-button"
onClick={this.onOpenFile}><MdFileUpload/> {t("Open Style")}
</InputButton>
{typeof window.showOpenFilePicker === "function" ? (
<InputButton
className="maputnik-big-button"
onClick={this.onOpenFile}><MdFileUpload/> {t("Open Style")}
</InputButton>
) : (
<FileReaderInput onChange={this.onFileChanged} tabIndex={-1} aria-label={t("Open Style")}>
<InputButton className="maputnik-upload-button"><MdFileUpload /> {t("Open Style")}</InputButton>
</FileReaderInput>
)}
</div>
</section>

View File

@@ -1,7 +1,7 @@
@import '../styles/vars';
@use '../styles/vars';
.SmallError {
color: #E57373;
font-size: $font-size-6;
margin-top: $margin-2
font-size: vars.$font-size-6;
margin-top: vars.$margin-2
}

View File

@@ -1,5 +1,4 @@
// @ts-ignore - this is a fork of jsonlint
import jsonlint from 'jsonlint';
import {parse} from '@prantlf/jsonlint';
import CodeMirror, { MarkerRange } from 'codemirror';
import jsonToAst from 'json-to-ast';
import {expression, validateStyleMin} from '@maplibre/maplibre-gl-style-spec';
@@ -15,49 +14,45 @@ CodeMirror.defineMode("mgl", (config, parserConfig) => {
);
});
CodeMirror.registerHelper("lint", "json", (text: string) => {
function tryToParse(text: string) {
const found: MarkerRangeWithMessage[] = [];
// NOTE: This was modified from the original to remove the global, also the
// old jsonlint API was 'jsonlint.parseError' its now
// 'jsonlint.parser.parseError'
(jsonlint as any).parser.parseError = (str: string, hash: any) => {
const loc = hash.loc;
found.push({
from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
message: str
});
};
try {
jsonlint.parse(text);
parse(text);
}
catch(e) {
// Do nothing we catch the error above
catch(err: any) {
const errorMatch = err.toString().match(/line (\d+), column (\d+)/);
if (errorMatch) {
const loc = {
first_line: parseInt(errorMatch[1], 10),
first_column: parseInt(errorMatch[2], 10),
last_line: parseInt(errorMatch[1], 10),
last_column: parseInt(errorMatch[2], 10)
};
// const loc = hash.loc;
found.push({
from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
message: err
});
}
}
return found;
}
CodeMirror.registerHelper("lint", "json", (text: string) => {
return tryToParse(text);
});
CodeMirror.registerHelper("lint", "mgl", (text: string, opts: any, doc: any) => {
const found: MarkerRangeWithMessage[] = [];
const {parser} = jsonlint as any;
const {context} = opts;
const found: MarkerRangeWithMessage[] = tryToParse(text);
parser.parseError = (str: string, hash: any) => {
const loc = hash.loc;
found.push({
from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
message: str
});
};
try {
parser.parse(text);
}
catch (e) {
// ignore errors
}
const {context} = opts;
if (found.length > 0) {
// JSON invalid so don't go any further

View File

@@ -5,14 +5,17 @@ function loadJSON(url: string, defaultValue: any, cb: (...args: any[]) => void)
mode: 'cors',
credentials: "same-origin"
})
.then(function(response) {
.then((response) => {
if (!response.ok) {
throw new Error('Failed to load metadata for ' + url);
}
return response.json();
})
.then(function(body) {
.then((body) => {
cb(body)
})
.catch(function() {
console.warn('Can not metadata for ' + url)
.catch(() => {
console.warn('Can not load metadata for ' + url + ', using default value ' + defaultValue);
cb(defaultValue)
})
}

View File

@@ -1,4 +1,3 @@
// @ts-ignore
import style from './style'
export function initialStyleUrl() {

View File

@@ -1,3 +1,5 @@
@use "vars";
@font-face {
font-family: 'Roboto';
src: url('../fonts/Roboto-Regular.ttf') format('truetype');
@@ -15,8 +17,8 @@
}
html {
color: $color-white;
font-size: $font-size-5;
color: vars.$color-white;
font-size: vars.$font-size-5;
box-sizing: border-box;
}
@@ -32,34 +34,34 @@ body {
}
p {
font-size: $font-size-6;
margin-top: $margin-2;
margin-bottom: $margin-2;
color: $color-lowgray;
font-size: vars.$font-size-6;
margin-top: vars.$margin-2;
margin-bottom: vars.$margin-2;
color: vars.$color-lowgray;
line-height: 1.3;
}
h1 {
font-size: $font-size-2;
margin-bottom: $margin-3;
font-size: vars.$font-size-2;
margin-bottom: vars.$margin-3;
font-weight: bold;
}
h2 {
font-size: $font-size-3;
margin-bottom: $margin-3;
font-size: vars.$font-size-3;
margin-bottom: vars.$margin-3;
font-weight: bold;
}
h3 {
font-size: $font-size-4;
margin-bottom: $margin-3;
font-size: vars.$font-size-4;
margin-bottom: vars.$margin-3;
font-weight: bold;
}
h4 {
font-size: $font-size-5;
margin-bottom: $margin-3;
font-size: vars.$font-size-5;
margin-bottom: vars.$margin-3;
}
input:focus,
@@ -68,12 +70,12 @@ textarea:focus,
button:focus,
.maputnik-toolbar-link:focus,
select:focus {
color: $color-white;
color: vars.$color-white;
outline: #8e8e8e auto 1px;
}
label:hover {
color: $color-white;
color: vars.$color-white;
}
.clearfix {

View File

@@ -1,3 +1,5 @@
@use "vars";
.CodeMirror-lint-tooltip {
z-index: 2000 !important;
}
@@ -55,7 +57,7 @@
.cm-s-maputnik .CodeMirror-matchingbracket {
background: hsla(223, 12%, 35%, 1);
color: $color-white !important;
color: vars.$color-white !important;
}
.cm-s-maputnik .CodeMirror-nonmatchingbracket {
@@ -79,7 +81,7 @@
z-index: 99999;
padding: 0.3em 0.5em;
background: hsla(0, 0%, 0%, 0.3);
color: $color-lowgray;
color: vars.$color-lowgray;
border-bottom-left-radius: 2px;
transition: opacity 320ms ease;
opacity: 0;

View File

@@ -1,9 +1,12 @@
@use "mixins";
@use "vars";
@use 'sass:color';
// MAP
.maputnik-map__container {
background: white;
display: flex;
width: $layout-map-width;
width: vars.$layout-map-width;
&--error {
align-items: center;
@@ -36,7 +39,7 @@
&-wrapper {
display: inline-block;
box-sizing: border-box;
font-size: $font-size-6;
font-size: vars.$font-size-6;
line-height: 2;
user-select: none;
position: relative;
@@ -45,9 +48,9 @@
&-popup {
display: none;
color: $color-lowgray;
background-color: $color-gray;
padding: $margin-2;
color: vars.$color-lowgray;
background-color: vars.$color-gray;
padding: vars.$margin-2;
font-size: 10px;
position: absolute;
top: 20px;
@@ -60,7 +63,7 @@
&-button {
opacity: 0;
pointer-events: none;
background: $color-black;
background: vars.$color-black;
color: white;
border: none;
padding: 4px;
@@ -77,11 +80,11 @@
}
.maputnik-doc-inline {
color: $color-lowgray;
background-color: $color-gray;
padding: $margin-2;
color: vars.$color-lowgray;
background-color: vars.$color-gray;
padding: vars.$margin-2;
font-size: 12px;
margin-top: $margin-3;
margin-top: vars.$margin-3;
line-height: 1.5;
flex: 1 0;
}
@@ -95,10 +98,10 @@
.maputnik-button {
display: inline-block;
cursor: pointer;
background-color: $color-midgray;
color: $color-lowgray;
font-size: $font-size-6;
padding: $margin-2;
background-color: vars.$color-midgray;
color: vars.$color-lowgray;
font-size: vars.$font-size-6;
padding: vars.$margin-2;
user-select: none;
border-width: 0;
border-radius: 2px;
@@ -106,36 +109,36 @@
text-decoration: none;
&:hover {
background-color: color.adjust($color-midgray, $lightness: 12%);
color: $color-white;
background-color: color.adjust(vars.$color-midgray, $lightness: 12%);
color: vars.$color-white;
}
&:disabled {
background-color: color.adjust($color-midgray, $lightness: -5%);
color: $color-midgray;
background-color: color.adjust(vars.$color-midgray, $lightness: -5%);
color: vars.$color-midgray;
cursor: not-allowed;
}
}
.maputnik-big-button {
margin-top: $margin-3;
margin-top: vars.$margin-3;
display: inline-block;
padding: $margin-3;
font-size: $font-size-5;
padding: vars.$margin-3;
font-size: vars.$font-size-5;
}
.maputnik-wide-button {
padding: $margin-2 $margin-3;
padding: vars.$margin-2 vars.$margin-3;
}
.maputnik-green-button {
background-color: $color-green;
color: $color-black;
background-color: vars.$color-green;
color: vars.$color-black;
}
.maputnik-white-button {
background-color: $color-white;
color: $color-black;
background-color: vars.$color-white;
color: vars.$color-black;
}
.maputnik-icon-button {
@@ -150,19 +153,19 @@
}
svg {
fill: $color-white;
fill: vars.$color-white;
}
}
}
// INPUT BLOCK
.maputnik-input-block {
margin: $margin-3;
margin: vars.$margin-3;
display: flex;
flex-wrap: wrap;
&-label {
color: $color-lowgray;
color: vars.$color-lowgray;
user-select: none;
width: 32%;
vertical-align: top;
@@ -170,7 +173,7 @@
}
&-action {
color: $color-lowgray;
color: vars.$color-lowgray;
user-select: none;
width: 18%;
vertical-align: top;
@@ -187,7 +190,7 @@
.maputnik-input-block-label {
display: inline-block;
width: 32%;
margin-bottom: $margin-3;
margin-bottom: vars.$margin-3;
}
.maputnik-input-block-action {
@@ -211,15 +214,15 @@
// SPACE HELPER
.maputnik-space {
@include vendor-prefix(flex-grow, 1);
@include mixins.vendor-prefix(flex-grow, 1);
}
// MESSAGE PANEL
.maputnik-message-panel {
padding: $margin-2;
padding: vars.$margin-2;
&-error {
color: $color-red;
color: vars.$color-red;
}
&__switch-button {
@@ -241,7 +244,7 @@
&__menu {
position: absolute;
z-index: 999999;
background: $color-black;
background: vars.$color-black;
display: flex;
flex-direction: column;
align-content: stretch;
@@ -262,13 +265,13 @@
color: #a4a4a4;
padding: 0.4em 0.4em;
font-size: 0.9em;
border: solid 1px $color-red;
border: solid 1px vars.$color-red;
border-radius: 2px;
margin: $margin-2 0px;
margin: vars.$margin-2 0px;
}
.maputnik-expression-editor {
border: solid 1px $color-gray;
border: solid 1px vars.$color-gray;
}
.maputnik-input-block--wide {
@@ -288,13 +291,13 @@
}
.maputnik-expr-infobox {
font-size: $font-size-6;
background: $color-midgray;
padding: $margin-2;
font-size: vars.$font-size-6;
background: vars.$color-midgray;
padding: vars.$margin-2;
border-radius: 2px;
border-top-right-radius: 0px;
border-top-left-radius: 0px;
color: $color-white;
color: vars.$color-white;
}
.maputnik-expr-infobox__button {

View File

@@ -1,5 +1,7 @@
@use "vars";
.maputnik-filter-editor-wrapper {
padding: $margin-3;
padding: vars.$margin-3;
overflow: hidden;
.maputnik-input-block {
@@ -8,8 +10,8 @@
}
.maputnik-filter-editor {
@extend .clearfix; /* stylelint-disable-line */
color: $color-lowgray;
@extend .clearfix !optional; /* stylelint-disable-line */
color: vars.$color-lowgray;
}
.maputnik-filter-editor-property {
@@ -39,7 +41,7 @@
}
.maputnik-filter-editor-compound-select {
margin-bottom: $margin-2;
margin-bottom: vars.$margin-2;
.maputnik-doc-wrapper {
width: 50%;
@@ -52,22 +54,22 @@
}
.maputnik-filter-editor-unsupported {
color: $color-midgray;
color: vars.$color-midgray;
}
.maputnik-add-filter {
display: inline-block;
float: right;
margin-top: $margin-3;
margin-top: vars.$margin-3;
}
.maputnik-delete-filter {
@extend .maputnik-icon-button; /* stylelint-disable-line */
@extend .maputnik-icon-button !optional; /* stylelint-disable-line */
}
.maputnik-filter-editor-block-action {
margin-top: $margin-2;
margin-bottom: $margin-2;
margin-top: vars.$margin-2;
margin-bottom: vars.$margin-2;
display: inline-block;
width: 6%;
margin-right: 1.5%;
@@ -79,12 +81,12 @@
}
.maputnik-radio-as-button {
@extend .maputnik-button; /* stylelint-disable-line */
@extend .maputnik-button !optional; /* stylelint-disable-line */
border: solid 1px transparent;
&:focus-within {
border: solid 1px $color-white;
border: solid 1px vars.$color-white;
}
input {

View File

@@ -1,3 +1,6 @@
@use "mixins";
@use "vars";
@use 'sass:color';
//INPUT
.maputnik-input {
@@ -5,13 +8,13 @@
width: 100%;
display: block;
box-sizing: border-box;
font-size: $font-size-6;
font-size: vars.$font-size-6;
line-height: 2;
padding-left: $margin-2;
padding-right: $margin-2;
padding-left: vars.$margin-2;
padding-right: vars.$margin-2;
border: none;
background-color: $color-gray;
color: color.adjust($color-lowgray, $lightness: 12%);
background-color: vars.$color-gray;
color: color.adjust(vars.$color-lowgray, $lightness: 12%);
&:invalid {
border: solid 1px #B71C1C;
@@ -20,7 +23,7 @@
}
.maputnik-string {
@extend .maputnik-input; /* stylelint-disable-line */
@extend .maputnik-input !optional; /* stylelint-disable-line */
&--multi {
resize: vertical;
@@ -44,12 +47,12 @@
}
.maputnik-number {
@extend .maputnik-input; /* stylelint-disable-line */
@extend .maputnik-input !optional; /* stylelint-disable-line */
}
//COLOR PICKER
.maputnik-color {
@extend .maputnik-input; /* stylelint-disable-line */
@extend .maputnik-input !optional; /* stylelint-disable-line */
height: 26px;
}
@@ -57,7 +60,7 @@
.maputnik-color-wrapper {
position: relative;
@include flex-row;
@include mixins.flex-row;
}
.maputnik-color-swatch {
@@ -71,7 +74,7 @@
.maputnik-array {
> * {
margin-bottom: $margin-3;
margin-bottom: vars.$margin-3;
}
.maputnik-array-block {
@@ -96,19 +99,19 @@
// SELECT
.maputnik-select {
@extend .maputnik-input; /* stylelint-disable-line */
@extend .maputnik-input !optional; /* stylelint-disable-line */
-moz-appearance: none;
-webkit-appearance: none;
background: $color-gray url("#{$icon-down-arrow}") right center no-repeat;
color: $color-white;
background: vars.$color-gray url("#{vars.$icon-down-arrow}") right center no-repeat;
color: vars.$color-white;
background-position: calc(100% - 2px) center;
padding-right: 20px;
height: 24px;
}
[dir="rtl"] .maputnik-select {
background: $color-gray url("#{$icon-down-arrow}") left center no-repeat;
background: vars.$color-gray url("#{vars.$icon-down-arrow}") left center no-repeat;
}
// MULTIBUTTON
@@ -116,12 +119,12 @@
padding: 0;
.maputnik-button {
margin-right: $margin-1;
margin-right: vars.$margin-1;
}
}
.maputnik-button-selected {
background-color: color.adjust($color-midgray, $lightness: 12%);
background-color: color.adjust(vars.$color-midgray, $lightness: 12%);
color: white;
}
@@ -137,7 +140,7 @@
outline: none;
&-wrapper {
@extend .maputnik-input; /* stylelint-disable-line */
@extend .maputnik-input !optional; /* stylelint-disable-line */
padding-left: 0;
padding-right: 0;
@@ -154,12 +157,12 @@
text-align: center;
height: 24px;
width: 24px;
margin-right: $margin-2;
background-color: $color-gray;
margin-right: vars.$margin-2;
background-color: vars.$color-gray;
border-radius: 2px;
border-style: solid;
border-width: 2px;
border-color: $color-gray;
border-color: vars.$color-gray;
transition: background-color 0.1s ease-out;
position: absolute;
top: 0;
@@ -185,7 +188,7 @@
width: 50%;
height: 50%;
margin-top: 1px;
fill: $color-lowgray;
fill: vars.$color-lowgray;
}
}
@@ -198,29 +201,29 @@
position: absolute;
overflow: auto;
max-height: 50%;
background: $color-gray;
background: vars.$color-gray;
z-index: 3;
}
&-menu-item {
user-select: none;
color: $color-lowgray;
color: vars.$color-lowgray;
cursor: default;
padding: $margin-1;
font-size: $font-size-6;
padding: vars.$margin-1;
font-size: vars.$font-size-6;
z-index: 3;
background: $color-gray;
background: vars.$color-gray;
}
&-menu-item-selected {
background: $color-midgray;
background: vars.$color-midgray;
}
}
// FONT
.maputnik-font {
.maputnik-autocomplete:not(:last-child) {
margin-bottom: $margin-3;
margin-bottom: vars.$margin-3;
}
}
@@ -236,21 +239,21 @@
.SpecDoc__sdk-support__table {
width: 100%;
margin-top: $margin-3;
margin-top: vars.$margin-3;
td, th {
border: solid 1px $color-midgray;
border: solid 1px vars.$color-midgray;
padding: 4px 6px;
white-space: nowrap;
}
}
.SpecDoc__values li {
margin-top: $margin-3;
margin-top: vars.$margin-3;
}
.SpecDoc__values code {
background: $color-midgray;
background: vars.$color-midgray;
padding: 0.1em 0.3em;
border-radius: 2px;
}

View File

@@ -1,3 +1,6 @@
@use "mixins";
@use "vars";
@use 'sass:color';
// LAYER LIST
.maputnik-layer-list {
@@ -7,9 +10,9 @@
flex-direction: column;
&-header {
padding: $margin-2 $margin-2 $margin-3;
padding: vars.$margin-2 vars.$margin-2 vars.$margin-3;
@include flex-row;
@include mixins.flex-row;
flex: 0 0;
> * {
@@ -19,8 +22,8 @@
}
&-header-title {
font-size: $font-size-5;
color: $color-white;
font-size: vars.$font-size-5;
color: vars.$color-white;
font-weight: bold;
line-height: 1.3;
}
@@ -28,7 +31,7 @@
&-container {
padding: 0;
margin: 0;
padding-bottom: $margin-5;
padding-bottom: vars.$margin-5;
flex: 1;
overflow-x: hidden;
overflow-y: auto;
@@ -47,9 +50,9 @@
&-item {
border: solid 1px transparent;
font-weight: 400;
color: $color-lowgray;
font-size: $font-size-6;
border-bottom-color: color.adjust($color-black, $lightness: 0.1%);
color: vars.$color-lowgray;
font-size: vars.$font-size-6;
border-bottom-color: color.adjust(vars.$color-black, $lightness: 0.1%);
user-select: none;
list-style: none;
z-index: 2000;
@@ -63,21 +66,22 @@
transition: opacity 600ms, visibility 600ms;
&:focus-within {
border: solid 1px $color-lowgray;
border: solid 1px vars.$color-lowgray;
}
@include mixins.flex-row;
@media screen and (prefers-reduced-motion: reduce) {
transition-duration: 0;
}
@include flex-row;
}
&-icon-action {
display: none;
svg {
fill: $color-black;
fill: vars.$color-black;
}
}
@@ -88,10 +92,10 @@
height: 15px;
svg {
fill: color.adjust($color-lowgray, $lightness: -20%);
fill: color.adjust(vars.$color-lowgray, $lightness: -20%);
&:hover {
fill: $color-white;
fill: vars.$color-white;
}
}
}
@@ -102,24 +106,24 @@
.maputnik-layer-list-item:hover,
.maputnik-layer-list-item-selected {
background-color: color.adjust($color-black, $lightness: 2%);
background-color: color.adjust(vars.$color-black, $lightness: 2%);
.maputnik-layer-list-icon-action {
display: block;
svg {
fill: color.adjust($color-lowgray, $lightness: -0.5%);
fill: color.adjust(vars.$color-lowgray, $lightness: -0.5%);
}
}
}
.maputnik-layer-list-item--error {
color: $color-red;
color: vars.$color-red;
}
&-item-selected {
color: $color-white;
color: vars.$color-white;
}
&-item-collapsed {
@@ -132,7 +136,7 @@
}
&-item-group-last {
border-bottom: 2px solid $color-gray;
border-bottom: 2px solid vars.$color-gray;
}
&-item-id {
@@ -150,14 +154,14 @@
&-group-header {
border: solid 1px transparent;
font-size: $font-size-6;
color: $color-lowgray;
background-color: color.adjust($color-black, $lightness: 2%);
font-size: vars.$font-size-6;
color: vars.$color-lowgray;
background-color: color.adjust(vars.$color-black, $lightness: 2%);
user-select: none;
padding: $margin-2;
padding: vars.$margin-2;
&:focus-within {
border: solid 1px $color-lowgray;
border: solid 1px vars.$color-lowgray;
}
button {
@@ -165,7 +169,7 @@
cursor: pointer;
}
@include flex-row;
@include mixins.flex-row;
svg {
width: 14px;
@@ -178,25 +182,27 @@
}
&-group-content {
margin: 0 $margin-3;
margin: 0 vars.$margin-3;
}
}
// FILTER EDITOR
.maputnik-layer-editor-group {
font-weight: bold;
font-size: $font-size-5;
background-color: color.adjust($color-black, $lightness: 2%);
color: $color-white;
font-size: vars.$font-size-5;
background-color: color.adjust(vars.$color-black, $lightness: 2%);
color: vars.$color-white;
cursor: pointer;
user-select: none;
line-height: 20px;
border-top: solid 1px #36383e;
@include mixins.flex-row;
&__button {
flex: 1;
display: flex;
padding: $margin-2;
padding: vars.$margin-2;
&__icon {
fill: white;
@@ -223,17 +229,17 @@
}
@include flex-row;
&:hover {
background-color: $color-gray;
background-color: vars.$color-gray;
}
}
// PROPERTY
.maputnik-default-property {
.maputnik-input-block-label {
color: color.adjust($color-lowgray, $lightness: -20%);
color: color.adjust(vars.$color-lowgray, $lightness: -20%);
}
.maputnik-string,
@@ -241,8 +247,8 @@
.maputnik-color,
.maputnik-select,
.maputnik-checkbox-wrapper {
background-color: color.adjust($color-gray, $lightness: -2%);
color: color.adjust($color-lowgray, $lightness: -20%);
background-color: color.adjust(vars.$color-gray, $lightness: -2%);
color: color.adjust(vars.$color-lowgray, $lightness: -20%);
}
.maputnik-make-zoom-function svg {
@@ -250,18 +256,18 @@
}
.maputnik-multibutton .maputnik-button {
background-color: color.adjust($color-midgray, $lightness: -10%);
color: color.adjust($color-lowgray, $lightness: -20%);
background-color: color.adjust(vars.$color-midgray, $lightness: -10%);
color: color.adjust(vars.$color-lowgray, $lightness: -20%);
&:hover {
background-color: color.adjust($color-midgray, $lightness: 12%);
color: $color-white;
background-color: color.adjust(vars.$color-midgray, $lightness: 12%);
color: vars.$color-white;
}
}
.maputnik-multibutton .maputnik-button-selected {
background-color: color.adjust($color-midgray, $lightness: -2%);
color: $color-lowgray;
background-color: color.adjust(vars.$color-midgray, $lightness: -2%);
color: vars.$color-lowgray;
}
}
@@ -276,8 +282,8 @@
&__menu {
position: absolute;
z-index: 9999;
background: $color-black;
border: solid 1px $color-midgray;
background: vars.$color-black;
border: solid 1px vars.$color-midgray;
right: 0;
min-width: 120px;
}
@@ -295,7 +301,7 @@
.layer-header {
display: flex;
padding: 6px;
background: $color-black;
background: vars.$color-black;
&__title {
flex: 1;
@@ -310,7 +316,7 @@
// Clone of the element which is sorted
.sortableHelper {
font-family: $font-family;
font-family: vars.$font-family;
z-index: 9999;
border: none;
}

View File

@@ -1,3 +1,5 @@
@use "vars";
//SCROLLING
.maputnik-scroll-container {
overflow-x: hidden;
@@ -11,14 +13,14 @@
//APP LAYOUT
.maputnik-layout {
font-family: $font-family;
color: $color-white;
font-family: vars.$font-family;
color: vars.$color-white;
&-main {
position: fixed;
bottom: 0;
height: calc(100% - #{$toolbar-height + $toolbar-offset});
top: $toolbar-height + $toolbar-offset;
height: calc(100% - #{vars.$toolbar-height + vars.$toolbar-offset});
top: vars.$toolbar-height + vars.$toolbar-offset;
left: 0;
right: 0;
z-index: 3;
@@ -28,12 +30,12 @@
&-list {
width: 200px;
background-color: $color-black;
background-color: vars.$color-black;
}
&-drawer {
width: 370px;
background-color: $color-black;
background-color: vars.$color-black;
// scroll-container is position: absolute
position: relative;
}
@@ -43,7 +45,7 @@
bottom: 0;
right: 0;
z-index: 1;
width: $layout-map-width;
background-color: $color-black;
width: vars.$layout-map-width;
background-color: vars.$color-black;
}
}

View File

@@ -1,3 +1,5 @@
@use "vars";
//OPENLAYERS
.maputnik-layout {
.ol-zoom {
@@ -39,7 +41,7 @@
}
.maputnik-ol-popup {
background: $color-black;
background: vars.$color-black;
}
@@ -74,7 +76,7 @@
background: #1c1f24;
border-radius: 2px;
padding: 6px 8px;
color: $color-lowgray;
color: vars.$color-lowgray;
z-index: 9999;
font-size: 12px;
font-weight: bold;

View File

@@ -1,40 +1,43 @@
@use "mixins";
@use "vars";
//MODAL
.maputnik-modal {
min-width: 350px;
max-width: 600px;
overflow: hidden;
background-color: $color-black;
background-color: vars.$color-black;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.3);
z-index: 3;
position: relative;
font-family: $font-family;
font-family: vars.$font-family;
display: flex;
flex-direction: column;
max-height: 100vh;
}
.maputnik-modal-section {
padding-top: $margin-3;
padding-bottom: $margin-3;
padding-top: vars.$margin-3;
padding-bottom: vars.$margin-3;
h1 {
font-size: $font-size-4;
font-size: vars.$font-size-4;
}
h2 {
font-size: $font-size-5;
font-size: vars.$font-size-5;
}
/* Bug fix: <http://stackoverflow.com/questions/28636832/firefox-overflow-y-not-working-with-nested-flexbox> */
min-height: 0;
@include flex-column;
@include mixins.flex-column;
flex-shrink: 0;
}
.maputnik-modal-sub-section {
margin-top: $margin-1;
margin-top: vars.$margin-1;
}
.maputnik-modal-section--shrink {
@@ -42,14 +45,14 @@
}
.maputnik-modal-header {
background-color: $color-gray;
padding: $margin-3;
background-color: vars.$color-gray;
padding: vars.$margin-3;
@include flex-row;
@include mixins.flex-row;
}
.maputnik-modal-header-title {
font-size: $font-size-5;
font-size: vars.$font-size-5;
margin: 0;
}
@@ -66,18 +69,18 @@
}
.maputnik-modal-content {
padding: $margin-3;
padding: vars.$margin-3;
@include flex-column;
@include mixins.flex-column;
}
.maputnik-modal-header-space {
@extend .maputnik-space; /* stylelint-disable-line */
@extend .maputnik-space !optional; /* stylelint-disable-line */
}
//OPEN MODAL
.maputnik-upload-button {
@extend .maputnik-big-button; /* stylelint-disable-line */
@extend .maputnik-big-button !optional; /* stylelint-disable-line */
}
.maputnik-style-gallery-container {
@@ -88,35 +91,35 @@
vertical-align: top;
margin-top: 10px;
margin-right: 10px;
background-color: $color-gray;
background-color: vars.$color-gray;
display: inline-block;
width: 180px;
font-size: $font-size-2;
color: $color-lowgray;
font-size: vars.$font-size-2;
color: vars.$color-lowgray;
}
.maputnik-public-style-button {
background-color: $color-gray;
padding: $margin-3;
background-color: vars.$color-gray;
padding: vars.$margin-3;
display: block;
width: 100%;
&:hover {
background-color: $color-midgray;
background-color: vars.$color-midgray;
}
}
.maputnik-public-style-header {
@include flex-row;
@include mixins.flex-row;
}
.maputnik-public-style-thumbnail {
display: block;
margin-top: $margin-2;
margin-top: vars.$margin-2;
width: 100%;
padding-top: calc(400 / 600 * 100%);
background-size: cover;
background-color: $color-midgray;
background-color: vars.$color-midgray;
}
.maputnik-add-modal {
@@ -139,18 +142,18 @@
}
.maputnik-add-layer {
@extend .clearfix; /* stylelint-disable-line */
@extend .clearfix !optional; /* stylelint-disable-line */
}
//ADD MODAL
.maputnik-add-layer-button {
@extend .maputnik-big-button; /* stylelint-disable-line */
@extend .maputnik-big-button !optional; /* stylelint-disable-line */
margin-right: $margin-3;
margin-right: vars.$margin-3;
float: right;
display: inline-block;
margin-top: 3;
margin-bottom: $margin-3;
margin-bottom: vars.$margin-3;
text-align: right;
}
@@ -163,19 +166,19 @@
vertical-align: top;
margin-top: 1.5%;
margin-right: 1.5%;
background-color: $color-gray;
background-color: vars.$color-gray;
width: 48.5%;
display: inline-block;
}
.maputnik-public-source-select {
padding: $margin-3;
font-size: $font-size-5;
color: $color-lowgray;
padding: vars.$margin-3;
font-size: vars.$font-size-5;
color: vars.$color-lowgray;
background-color: transparent;
width: 100%;
@include flex-row;
@include mixins.flex-row;
}
.maputnik-public-source-name {
@@ -192,24 +195,24 @@
}
.maputnik-active-source-type-editor-header {
background-color: $color-gray;
color: $color-lowgray;
padding: $margin-2;
background-color: vars.$color-gray;
color: vars.$color-lowgray;
padding: vars.$margin-2;
@include flex-row;
@include mixins.flex-row;
}
.maputnik-active-source-type-editor-header-id {
font-weight: 700;
line-height: 2;
font-size: $font-size-5;
font-size: vars.$font-size-5;
}
.maputnik-active-source-type-editor-content {
border-color: $color-gray;
border-color: vars.$color-gray;
border-width: 2px;
border-style: solid;
padding: $margin-2;
padding: vars.$margin-2;
.maputnik-input-block-label {
width: 30%;
@@ -221,7 +224,7 @@
}
.maputnik-add-source {
@extend .clearfix; /* stylelint-disable-line */
@extend .clearfix !optional; /* stylelint-disable-line */
.maputnik-input-block-label {
width: 30%;
@@ -233,17 +236,17 @@
}
.maputnik-add-source-button {
@extend .maputnik-big-button; /* stylelint-disable-line */
@extend .maputnik-big-button !optional; /* stylelint-disable-line */
display: inline-block;
margin-top: 0;
margin-right: $margin-3;
margin-right: vars.$margin-3;
float: right;
}
//EXPORT MODAL
.maputnik-export-gist {
font-size: $font-size-6;
font-size: vars.$font-size-6;
.maputnik-input-block {
margin-left: 0;
@@ -255,7 +258,7 @@
}
span {
color: $color-lowgray;
color: vars.$color-lowgray;
}
}
@@ -291,12 +294,12 @@
}
&__shortcut {
margin-bottom: $margin-2;
margin-bottom: vars.$margin-2;
}
dt {
display: inline;
margin-right: $margin-2;
margin-right: vars.$margin-2;
}
dd {

View File

@@ -1,3 +1,5 @@
@use "vars";
.maputnik-popup-layer {
display: flex;
flex-direction: row;
@@ -11,20 +13,20 @@
.maputnik-popup-layer__label {
display: block;
color: $color-lowgray;
color: vars.$color-lowgray;
cursor: pointer;
user-select: none;
line-height: 1.2;
padding: $margin-2;
padding-top: $margin-1;
padding-bottom: $margin-1;
padding: vars.$margin-2;
padding-top: vars.$margin-1;
padding-bottom: vars.$margin-1;
}
.maputnik-popup-layer-id {
padding-left: $margin-2;
padding-right: $margin-2;
background-color: $color-midgray;
color: $color-white;
padding-left: vars.$margin-2;
padding-right: vars.$margin-2;
background-color: vars.$color-midgray;
color: vars.$color-white;
}
.maputnik-feature-property-popup {
@@ -32,9 +34,9 @@
overflow-y: auto;
.maputnik-input-block {
margin: 0;
margin-left: $margin-2;
margin-right: $margin-2;
margin-top: $margin-2;
margin-left: vars.$margin-2;
margin-right: vars.$margin-2;
margin-top: vars.$margin-2;
}
}
@@ -43,7 +45,7 @@
}
.maputnik-popup-table-cell {
color: $color-lowgray;
padding-left: $margin-2;
padding-right: $margin-2;
color: vars.$color-lowgray;
padding-left: vars.$margin-2;
padding-right: vars.$margin-2;
}

View File

@@ -1,13 +1,15 @@
@use "vars";
@use 'sass:color';
// TOOLBAR
.maputnik-toolbar {
position: fixed;
height: $toolbar-height;
height: vars.$toolbar-height;
width: 100%;
z-index: 100;
left: 0;
top: $toolbar-offset;
background-color: $color-black;
top: vars.$toolbar-offset;
background-color: vars.$color-black;
}
.maputnik-toolbar-logo-container {
@@ -20,9 +22,9 @@
flex: 0 0 190px;
width: 200px;
text-align: left;
background-color: $color-black;
padding: $margin-2;
height: $toolbar-height;
background-color: vars.$color-black;
padding: vars.$margin-2;
height: vars.$toolbar-height;
position: relative;
overflow: hidden;
@@ -33,19 +35,19 @@
img {
width: 30px;
padding-right: $margin-2;
padding-right: vars.$margin-2;
vertical-align: top;
}
}
.maputnik-toolbar-link {
vertical-align: top;
height: $toolbar-height;
height: vars.$toolbar-height;
display: inline-block;
padding: $margin-3;
font-size: $font-size-5;
padding: vars.$margin-3;
font-size: vars.$font-size-5;
cursor: pointer;
color: $color-white;
color: vars.$color-white;
text-decoration: none;
line-height: 20px;
@@ -54,30 +56,30 @@
}
&:hover {
background-color: $color-midgray;
background-color: vars.$color-midgray;
}
}
.maputnik-toolbar-link--highlighted {
line-height: 1;
padding: $margin-2 $margin-3;
padding: vars.$margin-2 vars.$margin-3;
.maputnik-toolbar-link-wrapper {
background-color: $color-white;
background-color: vars.$color-white;
border-radius: 2px;
padding: $margin-2;
margin-top: $margin-1;
color: $color-black;
padding: vars.$margin-2;
margin-top: vars.$margin-1;
color: vars.$color-black;
display: block;
}
&:hover {
background-color: $color-black;
background-color: vars.$color-black;
}
&:hover .maputnik-toolbar-link-wrapper {
background-color: color.adjust($color-midgray, $lightness: 12%);
color: $color-white;
background-color: color.adjust(vars.$color-midgray, $lightness: 12%);
color: vars.$color-white;
}
}
@@ -94,32 +96,31 @@
.maputnik-toolbar-action {
background: inherit;
border-width: 0;
@extend .maputnik-toolbar-link; /* stylelint-disable-line */
@extend .maputnik-toolbar-link !optional; /* stylelint-disable-line */
}
.maputnik-toolbar-select {
background: inherit;
border-width: 0;
@extend .maputnik-toolbar-link; /* stylelint-disable-line */
@extend .maputnik-toolbar-link !optional; /* stylelint-disable-line */
select {
margin: 0 6px;
border-width: 0;
display: inline;
width: auto;
border: solid 1px $color-midgray;
border: solid 1px vars.$color-midgray;
vertical-align: inherit;
margin-top: -2px;
}
}
.maputnik-icon-text {
padding: 0 $margin-1;
padding: 0 vars.$margin-1;
}
.maputnik-icon-action {
display: inline;
margin: 0 $margin-1;
margin: 0 vars.$margin-1;
}
.maputnik-toolbar__inner {
@@ -141,7 +142,7 @@
height: 100%;
text-align: center;
display: block;
background-color: $color-black;
background-color: vars.$color-black;
z-index: 999;
line-height: 40px;
left: 0;
@@ -150,7 +151,7 @@
&:active,
&:focus {
width: 100%;
border-color: $color-lowgray;
border-color: vars.$color-lowgray;
}
}

View File

@@ -1,16 +1,18 @@
@use "vars";
// ZOOM FUNC
.maputnik-make-zoom-function {
background-color: transparent;
display: inline-block;
vertical-align: middle;
padding: 0 $margin-2 0 0;
padding: 0 vars.$margin-2 0 0;
@extend .maputnik-icon-button; /* stylelint-disable-line */
@extend .maputnik-icon-button !optional; /* stylelint-disable-line */
}
// ZOOM PROPERTY
.maputnik-zoom-spec-property {
@extend .clearfix; /* stylelint-disable-line */
@extend .clearfix !optional; /* stylelint-disable-line */
}
.maputnik-zoom-spec-property-label {
@@ -19,8 +21,8 @@
}
.maputnik-zoom-spec-property-stop-item {
margin-bottom: $margin-2;
margin-top: $margin-2;
margin-bottom: vars.$margin-2;
margin-top: vars.$margin-2;
}
.maputnik-zoom-spec-property-stop-edit {
@@ -49,13 +51,12 @@
padding-top: 0;
vertical-align: middle;
@extend .maputnik-icon-button; /* stylelint-disable-line */
@extend .maputnik-icon-button !optional; /* stylelint-disable-line */
}
.maputnik-add-stop {
display: inline-block;
float: right;
margin-right: $margin-3;
margin-right: vars.$margin-3;
}
// DATA FUNC
@@ -63,9 +64,9 @@
background-color: transparent;
display: inline-block;
vertical-align: middle;
padding: 0 $margin-2 0 0;
padding: 0 vars.$margin-2 0 0;
@extend .maputnik-icon-button; /* stylelint-disable-line */
@extend .maputnik-icon-button !optional; /* stylelint-disable-line */
}
.maputnik-data-spec-property {
@@ -86,7 +87,7 @@
.maputnik-doc-wrapper {
width: 25%;
color: $color-lowgray;
color: vars.$color-lowgray;
}
.maputnik-doc-wrapper:hover {

View File

@@ -1,22 +1,22 @@
@import 'vars';
@import 'mixins';
@import 'reset';
@import 'base';
@import 'components';
@import 'scrollbar';
@import 'picker';
@import 'toolbar';
@import 'modal';
@import 'export';
@import 'layout';
@import 'layer';
@import 'input';
@import 'filtereditor';
@import 'zoomproperty';
@import 'popup';
@import 'map';
@import 'codemirror';
@import 'react-collapse';
@use 'vars';
@use 'mixins';
@use 'reset';
@use 'base';
@use 'components';
@use 'scrollbar';
@use 'picker';
@use 'toolbar';
@use 'modal';
@use 'export';
@use 'layout';
@use 'layer';
@use 'input';
@use 'filtereditor';
@use 'zoomproperty';
@use 'popup';
@use 'map';
@use 'codemirror';
@use 'react-collapse';
.maputnik-layout {
height: 100vh;
@@ -29,14 +29,14 @@
}
.maputnik-data-fieldset-inner {
background: $color-black;
border: solid 1px $color-midgray;
background: vars.$color-black;
border: solid 1px vars.$color-midgray;
border-radius: 2px;
position: relative;
// HACK: Overide
.maputnik-input-block {
margin: $margin-2;
margin: vars.$margin-2;
}
.maputnik-add-stop {
@@ -49,8 +49,8 @@
}
.maputnik-toolbox {
margin: $margin-3;
margin-top: $margin-3;
margin: vars.$margin-3;
margin-top: vars.$margin-3;
text-align: right;
}
@@ -58,40 +58,40 @@
.maputnik-data-spec-property {
legend {
font-size: $font-size-6;
color: $color-lowgray;
margin-bottom: $margin-3;
font-size: vars.$font-size-6;
color: vars.$color-lowgray;
margin-bottom: vars.$margin-3;
}
.maputnik-data-spec-property-group {
margin-bottom: $margin-2;
margin-bottom: vars.$margin-2;
}
}
.maputnik-data-spec-block {
margin: $margin-3;
margin: vars.$margin-3;
}
.maputnik-function-stop {
padding-left: $margin-2;
padding-right: $margin-2;
padding-left: vars.$margin-2;
padding-right: vars.$margin-2;
}
.maputnik-function-stop-table {
text-align: left;
margin-bottom: $margin-2;
margin-bottom: vars.$margin-2;
box-sizing: border-box;
width: 100%;
thead th {
padding: $margin-1 $margin-2;
padding: vars.$margin-1 vars.$margin-2;
padding-left: 0;
color: $color-lowgray;
color: vars.$color-lowgray;
}
td, th {
font-size: $font-size-6;
color: $color-white;
font-size: vars.$font-size-6;
color: vars.$color-white;
// HACK
> * {
@@ -102,7 +102,7 @@
&:not(:first-child)
{
padding: $margin-1;
padding: vars.$margin-1;
}
&:nth-child(1) {
@@ -147,10 +147,10 @@
}
caption {
color: $color-lowgray;
color: vars.$color-lowgray;
text-align: left;
border-top: solid 1px $color-black;
font-size: $font-size-6;
border-top: solid 1px vars.$color-black;
font-size: vars.$font-size-6;
height: 0px;
overflow: hidden;
}

View File

@@ -22,6 +22,7 @@
"noFallthroughCasesInSwitch": true
},
"include": ["src", "cypress/e2e"],
"exclude": ["dist"],
"references": [{ "path": "./tsconfig.node.json" }],
// TODO: Remove when issue is resolved https://github.com/cypress-io/cypress/issues/27448
"ts-node": {

View File

@@ -18,7 +18,7 @@ export default defineConfig({
values: {
"_token_stack:": "",
},
}) as any,
}),
react(),
istanbul({
cypress: true,