mirror of
https://github.com/maputnik/editor.git
synced 2026-09-11 14:57:26 +00:00
Fix zoom property crash after deleting a stop (#2153)
## Launch Checklist <!-- Thanks for the PR! Feel free to add or remove items from the checklist. --> When a fixed paint value is converted to a zoom function, Maputnik creates exactly two stops. <img width="362" height="226" alt="image" src="https://github.com/user-attachments/assets/209aebbf-7bb3-4422-b0c7-1019e20a9ddb" /> Deleting either one of those two stops leaves a single remaining value. During the transition back to the ordinary field editor, `ZoomProperty` can render with `stops` undefined. It previously called `.map` unconditionally, causing the editor to crash. <img width="2551" height="1248" alt="image" src="https://github.com/user-attachments/assets/f5c2af59-dcae-4ffe-8245-f175eea9c843" /> This PR guards the stop list with optional chaining. The change only protects the render path and does not alter zoom-function conversion or value persistence. Now, the remaining stop's value will be restored after deleting the other stop: <img width="367" height="168" alt="image" src="https://github.com/user-attachments/assets/8d13236b-6140-451b-8613-0bc5f11893de" /> The regression test covers `circle-opacity`: 1. Convert a fixed value to a zoom function. 2. Change the second stop's value. 3. Delete the first of the two stops. 4. Verify that the ordinary field editor reappears. 5. Verify that the remaining stop's value is restored. 6. Edit the restored field and verify that the style updates successfully. - [x] Briefly describe the changes in this PR. - [ ] Link to related issues. - [x] Include before/after visuals or gifs if this PR includes visual changes. - [x] Write tests for all new functionality. - [x] Add an entry to `CHANGELOG.md` under the `## main` section.
This commit is contained in:
@@ -289,6 +289,20 @@ describe("layer editor", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("should leave a plain editable value after deleting a stop", async () => {
|
||||
await when.setFunctionStopValue("circle-radius", "Output value", 1, "0");
|
||||
await when.deleteFunctionStop("circle-radius");
|
||||
await then(get.elementByTestId("spec-field:circle-radius")).shouldBeVisible();
|
||||
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||
layers: [{ id, paint: { "circle-radius": 0 } }],
|
||||
});
|
||||
|
||||
await when.setValue("spec-field-input:circle-radius", "7");
|
||||
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||
layers: [{ id, paint: { "circle-radius": 7 } }],
|
||||
});
|
||||
});
|
||||
|
||||
test("should set the base", async () => {
|
||||
await when.setFunctionBase("circle-radius", "2");
|
||||
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||
@@ -310,8 +324,9 @@ describe("layer editor", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("should convert to an expression", async () => {
|
||||
test("should convert to an expression without crashing", async () => {
|
||||
await when.makeExpression("circle-radius");
|
||||
await then(get.element("[data-wd-key='spec-field-container:circle-radius'] .maputnik-expression-editor")).shouldBeVisible();
|
||||
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||
layers: [{ id, paint: { "circle-radius": ["interpolate", ["linear"], ["zoom"], 6, 5, 10, 5] } }],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user