Add support for sprite object (#1488)

## Launch Checklist

- Fixes #1302

When a sprite object is used, the current settings modal does not
present it well and does not allow editing.
This changes the input from a string to json.
It does make the editing a bit more cumbersome as you need to type `"`
now instead of just placing the address, but if you click the info
button you should be able to understand that this is a special field.
The fact that it looks like a code editor should also help guide users
to place different input there.

Before:
<img width="710" height="297" alt="image"
src="https://github.com/user-attachments/assets/a615dddd-6c06-45fb-b5a9-1820e6a5c077"
/>


After:
<img width="710" height="297" alt="image"
src="https://github.com/user-attachments/assets/fdb89ada-91ca-4bf4-8380-ce3c25373b41"
/>


 - [x] Briefly describe the changes in this PR.
 - [x] Link to related issues.
- [x] Include before/after visuals or gifs if this PR includes visual
changes.
 - [x] Write tests for all new functionality.
 - [ ] Add an entry to `CHANGELOG.md` under the `## main` section.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Harel M
2025-11-06 14:18:30 +02:00
committed by GitHub
parent 85bf0e02a4
commit 4ba09144e9
4 changed files with 25 additions and 8 deletions
+1
View File
@@ -11,6 +11,7 @@
- Added color highlight for problematic properties - Added color highlight for problematic properties
- Upgraded codemirror from version 5 to version 6 - Upgraded codemirror from version 5 to version 6
- Add code editor to allow editing the entire style - Add code editor to allow editing the entire style
- Add support for sprite object in setting modal
- _...Add new stuff here..._ - _...Add new stuff here..._
### 🐞 Bug fixes ### 🐞 Bug fixes
+4
View File
@@ -199,6 +199,10 @@ export class MaputnikDriver {
appendTextInJsonEditor: (text: string) => { appendTextInJsonEditor: (text: string) => {
this.helper.get.element(".cm-line").first().click().type(text, { parseSpecialCharSequences: false }); this.helper.get.element(".cm-line").first().click().type(text, { parseSpecialCharSequences: false });
},
setTextInJsonEditor: (text: string) => {
this.helper.get.element(".cm-line").first().click().clear().type(text, { parseSpecialCharSequences: false });
} }
}; };
+11 -1
View File
@@ -170,12 +170,22 @@ describe("modals", () => {
}); });
it("sprite url", () => { it("sprite url", () => {
when.setValue("modal:settings.sprite", "http://example.com"); when.setTextInJsonEditor("\"http://example.com\"");
when.click("modal:settings.name"); when.click("modal:settings.name");
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({ then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
sprite: "http://example.com", sprite: "http://example.com",
}); });
}); });
it("sprite object", () => {
when.setTextInJsonEditor(JSON.stringify([{id: "1", url: "2"}]));
when.click("modal:settings.name");
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
sprite: [{ id: "1", url: "2"}],
});
});
it("glyphs url", () => { it("glyphs url", () => {
const glyphsUrl = "http://example.com/{fontstack}/{range}.pbf"; const glyphsUrl = "http://example.com/{fontstack}/{range}.pbf";
when.setValue("modal:settings.glyphs", glyphsUrl); when.setValue("modal:settings.glyphs", glyphsUrl);
+9 -7
View File
@@ -11,6 +11,8 @@ import FieldSelect from "../FieldSelect";
import FieldEnum from "../FieldEnum"; import FieldEnum from "../FieldEnum";
import FieldColor from "../FieldColor"; import FieldColor from "../FieldColor";
import Modal from "./Modal"; import Modal from "./Modal";
import FieldJson from "../FieldJson";
import Block from "../Block";
import fieldSpecAdditional from "../../libs/field-spec-additional"; import fieldSpecAdditional from "../../libs/field-spec-additional";
import type {OnStyleChangedCallback, StyleSpecificationWithId} from "../../libs/definitions"; import type {OnStyleChangedCallback, StyleSpecificationWithId} from "../../libs/definitions";
@@ -144,13 +146,13 @@ class ModalSettingsInternal extends React.Component<ModalSettingsInternalProps>
value={(this.props.mapStyle as any).owner} value={(this.props.mapStyle as any).owner}
onChange={(value) => this.changeStyleProperty("owner", value)} onChange={(value) => this.changeStyleProperty("owner", value)}
/> />
<FieldUrl <Block label={t("Sprite URL")} fieldSpec={latest.$root.sprite} data-wd-key="modal:settings.sprite">
fieldSpec={latest.$root.sprite} <FieldJson
label={t("Sprite URL")} lintType="json"
data-wd-key="modal:settings.sprite" value={this.props.mapStyle.sprite as any}
value={this.props.mapStyle.sprite as string} onChange={(value) => this.changeStyleProperty("sprite", value)}
onChange={(value) => this.changeStyleProperty("sprite", value)} />
/> </Block>
<FieldUrl <FieldUrl
label={t("Glyphs URL")} label={t("Glyphs URL")}