The library that combines Icepick and Mapbox style spec
Built for the Maputnik editor, but should hopefully be generally useful.
Why does this exist?
- If we have an immutable data structure we can improve rendering performance in UI frameworks that checking object equality when updating the UI (for example React)
- More robust by having a library to deal with changes
Features include
- Methods for modifying data specific to the style spec, keeping object mutations to a minimum
- In library style specification validation
To install
npm install mgljs-contrib/icepick-style --save
General methods
valid- is the current style validerrors- list of current errorscurrent- the current immutable objecthistory- array of immutable objectsstack(idx)- get a item from the history stack, supports negative index lookups to start from the end of historycanUndo()- is there anything to undo in the history stackundo()- move backward in the history stackcanRedo()- is there anything to redo in the history stackredo()- move forward in the history stackmerge(styleObject)- merge a style into another stylereplace(styleObject)- replace the style keeping object equality where possibleaddHook(key, fn)- add a hook (see hooks)removeHook(key, fn)- remove a hook (see hooks)
MapboxGL spec specific. These methods are chainable
addRoot(keyPath, value)modifyRoot(keyPath, value)removeRoot(keyPath)addLayer(id, value)modifyLayer(id, value)renameLayer(id, newId)removeLayer(id)addSource(id, value)modifySource(id, value)removeSource(id)renameSource(id, newId)
Creating a new style
const IcepickStyle = require("icepick-style");
const style = new IcepickStyle();
style
.modifyRoot("name", "Test style")
.modifySource("openmaptiles", {...});
// Sometime later....
style
.modifySource("openmaptiles", function(doc) {
doc.maxZoom = 13;
});
assert.equal(style.current.name, "Test style");
assert.equal(style.history.length, 2);
assert.equal(style.current.sources.openmaptiles.maxZoom, 13);
assert.equal(style.history[0].sources.openmaptiles.maxZoom, 16);You can also start a transaction to group changes into a single history entry
style
.transaction((style) => {
style
.modifyRoot("name", "Foo bar")
.modifyLayer((layer) => {
layer.maxZoom = 14;
})
})
// Only a single history item
assert.equal(style.history.length, 1);It also comes with a validate hook which will validate the current state of the style and output errors to style.errors, see an example below
const IcepickStyle = require('icepick-style');
const mapboxGlValidateHook = require('icepick-style/hooks/validate/mapbox-gl');
const style = new IcepickStyle();
style.addHook('validate', mapboxGlValidateHook);
style.addLayer('foo', {
type: 'background',
paint: 1
});
assert.deepStrictEqual(
style.errors[0].message,
'layers[0].paint: object expected, number found'
);Why icepick and not immutable.js
Because
- It's a "tiny (1kb min/gzipped), zero-dependency library"
- It's fast https://github.com/aearly/icepick-benchmarks
