diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ba88776..814e55b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Upgrade to MapLibre GL JS 6 and Vite 8, and update the remaining dependencies - Serve the RTL text plugin from `@mapbox/mapbox-gl-rtl-text` instead of a pinned CDN URL, so its version is tracked in `package.json` - Exported HTML now loads MapLibre GL JS as an ES module, since v6 no longer ships a UMD bundle +- Add `font-faces`, `sky`, `roll` and `centerAltitude` to the style settings modal - _...Add new stuff here..._ ### 🐞 Bug fixes diff --git a/e2e/maputnik-driver.ts b/e2e/maputnik-driver.ts index 6785fe11..f987d685 100644 --- a/e2e/maputnik-driver.ts +++ b/e2e/maputnik-driver.ts @@ -182,8 +182,9 @@ export class MaputnikDriver { await this.helper.when.typeText(text); }, - setTextInJsonEditor: async (text: string) => { - await this.helper.get.element(".cm-line").first().click(); + setTextInJsonEditor: async (text: string, selector?: string) => { + const scope = selector ? this.helper.get.elementByTestId(selector).locator(".cm-line") : this.helper.get.element(".cm-line"); + await scope.first().click(); await this.helper.when.typeKeys("{selectall}"); await this.helper.when.typeText(text); }, diff --git a/e2e/modals.spec.ts b/e2e/modals.spec.ts index e2d62dd7..65ca3d7f 100644 --- a/e2e/modals.spec.ts +++ b/e2e/modals.spec.ts @@ -338,6 +338,15 @@ describe("modals", () => { }); }); + test("font faces", async () => { + const fontFaces = { "Noto Sans Regular": [{ url: "http://example.com/font.ttf", "unicode-range": ["U+1780-17FF"] }] }; + await when.setTextInJsonEditor(JSON.stringify(fontFaces), "modal:settings.font-faces"); + await when.click("modal:settings.name"); + await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({ + "font-faces": fontFaces, + }); + }); + test("maptiler access token", async () => { const apiKey = "testing123"; await when.setValue("modal:settings.maputnik:openmaptiles_access_token", apiKey); @@ -378,11 +387,24 @@ describe("modals", () => { await when.setValue("modal:settings.zoom", "4"); await when.setValue("modal:settings.bearing", "12"); await when.setValue("modal:settings.pitch", "30"); + await when.setValue("modal:settings.roll", "15"); + await when.setValue("modal:settings.center-altitude", "100"); await when.click("modal:settings.name"); await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({ zoom: 4, bearing: 12, pitch: 30, + roll: 15, + centerAltitude: 100, + }); + }); + + test("sky and fog blends", async () => { + await when.setValue("modal:settings.sky-horizon-blend", "0.3"); + await when.setValue("modal:settings.fog-ground-blend", "0.2"); + await when.click("modal:settings.name"); + await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({ + sky: { "sky-horizon-blend": 0.3, "fog-ground-blend": 0.2 }, }); }); diff --git a/src/components/modals/ModalSettings.tsx b/src/components/modals/ModalSettings.tsx index b418d152..d9241c52 100644 --- a/src/components/modals/ModalSettings.tsx +++ b/src/components/modals/ModalSettings.tsx @@ -1,6 +1,6 @@ import React from "react"; import latest from "@maplibre/maplibre-gl-style-spec/dist/latest.json"; -import type {LightSpecification, ProjectionSpecification, StyleSpecification, TerrainSpecification, TransitionSpecification} from "maplibre-gl"; +import type {LightSpecification, ProjectionSpecification, SkySpecification, StyleSpecification, TerrainSpecification, TransitionSpecification} from "maplibre-gl"; import { type WithTranslation, withTranslation } from "react-i18next"; import { FieldArray } from "../FieldArray"; @@ -81,6 +81,24 @@ class ModalSettingsInternal extends React.Component }); } + changeSkyProperty(property: keyof SkySpecification, value: any) { + const sky = { + ...this.props.mapStyle.sky, + }; + + if (value === undefined) { + delete sky[property]; + } + else { + sky[property] = value; + } + + this.props.onStyleChanged({ + ...this.props.mapStyle, + sky, + }); + } + changeProjectionType(value: any) { const projection = { ...this.props.mapStyle.projection, @@ -124,6 +142,7 @@ class ModalSettingsInternal extends React.Component const transition = this.props.mapStyle.transition || {}; const terrain = this.props.mapStyle.terrain || {} as TerrainSpecification; const projection = this.props.mapStyle.projection || {} as ProjectionSpecification; + const sky = this.props.mapStyle.sky || {}; return onChange={(value) => this.changeStyleProperty("glyphs", value)} /> + + this.changeStyleProperty("font-faces", value)} + /> + + onChange={(value) => this.changeStyleProperty("pitch", value)} /> + this.changeStyleProperty("roll", value)} + /> + + this.changeStyleProperty("centerAltitude", value)} + /> + onChange={(value) => this.changeTerrainProperty("exaggeration", value)} /> + this.changeSkyProperty("sky-color", value)} + /> + + this.changeSkyProperty("horizon-color", value)} + /> + + this.changeSkyProperty("fog-color", value)} + /> + + this.changeSkyProperty("sky-horizon-blend", value)} + /> + + this.changeSkyProperty("horizon-fog-blend", value)} + /> + + this.changeSkyProperty("fog-ground-blend", value)} + /> + + this.changeSkyProperty("atmosphere-blend", value)} + /> +