Skip to content

mapparatus/icepick-style

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

75 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

icepick-style

The library that combines Icepick and Mapbox style spec

stability-wip Build Status Coverage Status Dependency Status Dev Dependency Status

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

Install

To install

npm install mgljs-contrib/icepick-style --save

API

General methods

  • valid - is the current style valid
  • errors - list of current errors
  • current - the current immutable object
  • history - array of immutable objects
  • stack(idx) - get a item from the history stack, supports negative index lookups to start from the end of history
  • canUndo() - is there anything to undo in the history stack
  • undo() - move backward in the history stack
  • canRedo() - is there anything to redo in the history stack
  • redo() - move forward in the history stack
  • merge(styleObject) - merge a style into another style
  • replace(styleObject) - replace the style keeping object equality where possible
  • addHook(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)

Usage

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);

Hooks

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'
);

FAQ

Why icepick and not immutable.js

Because

  1. It's a "tiny (1kb min/gzipped), zero-dependency library"
  2. It's fast https://github.com/aearly/icepick-benchmarks

License

MIT