Map modules

A map module adds one capability to a TomTomMap, such as showing places or routes, filtering traffic, shading terrain or restyling the whole map. Every module follows the contract this page describes:

  • A module is style-owned or data-owned, which decides its factory and how many instances a map takes.
  • You configure a module at creation, then change it with applyConfig(config), updateConfig(partial) and resetConfig(). getConfig() reads it back and events.on('config-change', …) reports changes.
  • Each module publishes its settings as a knob catalogue, and setKnob and setKnobs set them by id, checking each value. Changing a setting says when to use them and when to use the configuration methods.
  • The SDK restores data, configuration and layer placement after every setStyle.
  • Each module has typed user events that hand you your original data.
  • Modules are tree-shaken, so a module you don’t import isn’t in your bundle.

Types of modules

Who owns the sources and layers a module controls decides the factory you call and how many instances make sense on one map.

Style-owned modules: get(map, config?)

  • They control sources and layers the map style already provides under fixed, global ids, such as the base map, POIs, the traffic tiles and the terrain elevation. They display no data of their own.
  • There is one per map. get() is a lookup, so a second call returns the same instance. Two components can each ask for the terrain without sharing a reference.
  • get(map) without a configuration leaves its configuration as it is. With one, it applies it to the existing instance, as applyConfig does. StylingFoundationsModule merges it instead, as updateConfig does.
  • If the style lacks their style part, the traffic and terrain modules’ get() adds it.
  • To handle events on part of what a module covers, scope its events instead of looking for a second module.

Data-owned modules: create(map, config?)

  • They add the GeoJSON sources, layers and sprite images they need, and own them for their whole lifetime. Every id has a per-instance suffix.
  • A map can have many of them. create() builds a new, independent module every time, for example one set of places per search or one route per plan.

Per-module reference

ModuleKindWhat it draws or controls
BaseMapModuleStyle-ownedWhich base-map layer groups and road parts show, the events on them, and how hovered, clicked and coloured 3D buildings look
POIsModuleStyle-ownedThe style’s POIs: visibility, category and id filters, size, labels, category icons
TrafficFlowModuleStyle-ownedThe live traffic flow tiles
TrafficIncidentsModuleStyle-ownedThe live traffic incident tiles
TerrainModuleStyle-ownedHillshade shading and the 3D surface
StylingFoundationsModuleStyle-ownedSizes, map colours, projection and sky across the whole map
PlacesModuleData-ownedPlaces you give it, as pins, circles or base-map-looking icons
RoutingModuleData-ownedRoutes, waypoints and route sections
GeometriesModuleData-ownedPolygons and lines, such as administrative areas
ReachableRangesModuleData-ownedThe bands calculateReachableRanges returns
CustomGeoJSONModuleData-ownedYour own GeoJSON, with your own MapLibre layer specs
TrafficIncidentDetailsModuleData-ownedIncidents you fetched with trafficIncidentDetails
TrafficAreaAnalyticsModuleData-ownedArea analytics as a hexgrid, square grid or heatmap

Who owns what

Everything visible on the map has exactly one owner, whoever owns its layers. Every module has knobs of its own. Each style-owned module decides whether and how its part of the loaded style shows. The Styling Foundations module sets the foundations that reach across every part: sizes, the map colours, projection and sky. Each data-owned instance decides everything about the layers it adds itself. In the diagram, the dashed line marks the only place a knob reaches past its module. There, the data-owned modules read the accent as their default colour.

Style-owned modules: get(), one per mapStylingFoundationsModule: get(), one per mapData-owned modules: create(), many per mapMapLibre mapBaseMapModule · POIsModuleTrafficFlowModule · TrafficIncidentsModuleTerrainModuleTheir knobs: what is shown, and howvisible · filters · road partsPOI, traffic and hillshade looksIts knobs: the foundations of the whole mapsizes · map colours · projection · skycolors.accentPlacesModule · RoutingModule · GeometriesModuleReachableRangesModule · CustomGeoJSONModuleTrafficIncidentDetailsModule · TrafficAreaAnalyticsModuleEach instance's own knobscolor · label · width · markerType · …The loaded style's layersbase map · POIs · traffic tiles · hillshadeMap viewprojection · skySources and layers each instance adds(ids suffixed per instance) show, hide, filter, restylerestyle every partview.* knobs default colour, readdraw and style

In detail:

You want to change…OwnerHow
Whether something the loaded style draws is shown — a base-map layer group or road part, the traffic tiles, a POI category or a single POI, the hillshade, the 3D surfaceThe style-owned module for that partsetVisible, updateConfig({ filters }), setHillshadeVisible, setElevationVisible, setKnob
How one part looks — POI size and label colours, traffic colours and widths, hillshade lightingThe style-owned module for that part: POIs, traffic flow, traffic incidents, terrainsetKnob, updateConfig
The foundations across every part — label, icon and road sizes, the 10 map colours, projection and skyThe Styling Foundations modulesetKnob, setMapColors
A named bundle of looks across those modulesapplyMapPresetapplyMapPreset(map, id)
Anything a data-owned module draws itself — routes, places, geometries, your GeoJSON, fetched traffic incidents, area analyticsThat module, through its own configurationcreate(map, config), applyConfig / updateConfig, setKnob and setVisible
The map’s colour identity — the accent routes, places and geometries default toThe Styling Foundations module publishes it; each data-owned module reads itsetMapColors, the colors.accent knob; a colour set on the module always wins
A look a data-owned module borrows from the style, such as POI-looking places or the colours of fetched traffic incidentsThe module whose knob restyles it sets it on the style; the data-owned module reads it and redraws its own layersThe knobs that restyle what it borrows; a setting given to the module always wins

Two consequences:

  • The rows don’t cross. Knobs on the loaded style never write a data-owned module’s layers, and a data-owned module never restyles the base map under it. You recolour a route in the RoutingModule configuration, and the roads it runs on with colors.roadMajor. The accent and the borrowed looks are read, not written.
  • The foundations and a part’s own look meet on the same layers, and compose. One engine per map applies every style knob, whichever module holds it. So labels.sizeFactor and the POIs’ sizeFactor multiply on the POI labels, and all of them land on top after a style switch.

Within a style-owned module, the finer settings only narrow what its coarser ones show. A road part or the POI micro markers never show while their layer group or the POIs are hidden. Showing those again keeps a part’s false. The POIs’ zoomShift rewrites the same layer filters that filters.categories and filters.ids narrow, in either order.

To find the layers a module owns, read its sourceAndLayerIDs: the MapLibre source id and layer ids of each of its sources. Every module has it, style-owned or data-owned. Use it when your own code writes MapLibre layer properties and should leave a module’s layers alone. On the base map, getLayerIds(group) narrows the list to one layer group. A road part, such as the arrows, has no layer list of its own. The Styling Foundations module owns no layers, so its list is empty.

const pois = await POIsModule.get(map);
pois.sourceAndLayerIDs.pois.layerIDs; // the POI layers, micro markers included

Read it again after a style switch or a configuration change, since a data-owned module can add or remove layers, such as a route’s section layers.

Each module guide opens with a What this module owns line that applies this rule.

Writing to a module’s layers yourself

Changing a module’s layers with map.mapLibreMap is a fallback for visual tweaks no knob offers. It doesn’t combine cleanly with the modules, so expect to set your values again:

  • A style switch drops everything you wrote. The knobs land again on the new style, and your writes don’t.
  • A knob never builds on your value. It works its value out from the style’s or the module’s own, as How knobs work explains.
  • A knob, or any other change to a module’s configuration, replaces your value only on the layers and properties it changes, and leaves the rest. Changing a geometries module’s line.color keeps the fill opacity and label size you set. The Styling Foundations knobs do the same on the base-map and POI layers they reach. For a custom GeoJSON module, a change replaces the properties your new layer specs set differently.
  • A layer a data-owned module removes and adds back loses what you wrote on it. For example, the traffic incident details outline is removed by highlight: false.
  • Visibility belongs to the module:
    • The traffic, terrain and data-owned modules set it on all their layers at every configuration change, so a layer you hid shows again.
    • The base map sets it only on the layer groups and road parts a change toggles.
    • The POIs module reads it back from its layers. If you hide all of them yourself, the module counts as hidden, and its next change shows them again.
    • The Styling Foundations module never sets visibility.

Changing a setting

A module takes its settings in two ways, and which one you use depends on where the values come from:

  • The configuration methods are for settings your code writes. applyConfig(config) replaces the whole configuration, and updateConfig(partial) changes the top-level properties you give it. They take every setting, typed, including the ones no knob covers, such as layer specs, callbacks and MapLibre expressions.
  • The knob functions are for settings held as data, an id and a value from a control, storage, a URL or a language model. setKnob sets one setting by its catalogue id, and setKnobs sets several in one change. They cover only the plain-valued settings in the module’s catalogue.

Both write the same configuration, which getConfig() reads back. A knob id is the setting’s path in it, so setKnob(placesModule, placesKnobCatalogue, 'label.color', '#c2185b') changes the label.color that updateConfig({ label: { color: '#c2185b' } }) writes:

Your codesettings it writes, typedSettings held as dataa control · storage · a URL · a language modelConfiguration methodsget / create(map, config)applyConfig(config)updateConfig(partial)Knob functionssetKnob(module, catalogue, id, value)setKnobs(module, catalogue, values)The module's knob cataloguean entry per plain-valued settingits id is the setting's pathRangeErrornothing changes, not even the valid onesThe module's configurationone object, read with getConfig()What the module drawsSettings with a knobvisible · color · label.color · widthFactor …Settings only code can writelayer specs · callbacks · MapLibre expressions checks each value a value refused any settingunchecked at run time at each id's paththe rest keptredraw, and config-change
Configuration methodsKnob functions
A value of the wrong typeCaught by TypeScript, not at run timeRefused at run time, with a RangeError
A value out of rangeApplied as givenRefused, and nothing changes
A nested settingupdateConfig replaces the nested object you give itSet by its path, keeping the settings beside it

Note that the configuration methods don’t check values at run time. A value from outside your code, such as JSON.parse output or a model’s answer, can reach the map unchecked, so pass it to the knob functions instead.

updateConfig merges one level deep. A nested object you give it replaces the current one. To change one nested field, spread the current part or set its knob:

import { placesKnobCatalogue, setKnob, setKnobs } from '@tomtom-org/maps-sdk/map';
// Settings your code writes: typed, and any setting the module takes
placesModule.updateConfig({ label: { ...placesModule.getConfig()?.label, color: '#c2185b' } });
// Settings held as data: checked against the catalogue, set by path
setKnob(placesModule, placesKnobCatalogue, 'label.color', '#c2185b');
setKnobs(placesModule, placesKnobCatalogue, { 'label.color': '#c2185b', 'label.size': 14 });
  • Named setters are for visibility, such as setVisible / isVisible and those of the parts that hide on their own (see Visibility under Appearance vocabulary). The only others are TrafficAreaAnalyticsModule’s per-metric setPalette, setColorStops, setHeight and setFilters. A named setter is always set<Setting>.

Saving and replaying a configuration

getConfig() exports a configuration and applyConfig() imports it. A configuration that went through JSON and back into applyConfig holds the same settings and draws the same layers. Keep one to restore a user’s map, attach it to a support report, or replay it in a test.

localStorage.setItem('places', JSON.stringify(placesModule.getConfig()));
// Later, on the same module or a new one
placesModule.applyConfig(JSON.parse(localStorage.getItem('places')));

applyConfig doesn’t check what it reads back. If the saved settings can come from anywhere other than your own getConfig(), for example an older release or a user’s edit, save knob values by id instead and restore them with setKnobs. It checks each value against its catalogue entry and sets none if one is refused:

import { placesKnobCatalogue, setKnobs } from '@tomtom-org/maps-sdk/map';
localStorage.setItem('places', JSON.stringify({ 'label.color': '#c2185b', 'label.size': 14 }));
setKnobs(placesModule, placesKnobCatalogue, JSON.parse(localStorage.getItem('places'))); // RangeError if one is refused

The map effects playground saves its panel this way.

Most module configurations, styling knobs included, are fully JSON. Six modules also take functions or image elements, which JSON can’t carry. Each has a type for the part that survives, detailed on its reference page. When you replay, add the rest back in code:

ModuleSerializable partLeft out
PlacesModulePlacesModuleSerializableConfiglabel.title as a function, connections.label.title, icon.mapping, extraFeatureProps functions, image elements in icon
RoutingModuleRoutingModuleSerializableConfigwaypoints.icon.mapping, waypoints.label.title as a function, image elements in waypoints.icon
GeometriesModuleGeometriesModuleSerializableConfigtransformFeaturesForDisplay
ReachableRangesModuleReachableRangesModuleSerializableConfiglineLabel.title
CustomGeoJSONModuleCustomGeoJSONModuleSerializableConfigimages
POIsModulePOIsModuleSerializableConfigimage elements in icon.categoryIcons

JSON.stringify silently drops a function, but turns an image element into {}, which doesn’t replay. To keep the whole configuration serializable, give icon images as URLs, data URIs or SVG text, and a place or waypoint title as a MapLibre expression.

const state = JSON.parse(saved); // PlacesModuleSerializableConfig
placesModule.applyConfig({
...state,
connections: { ...state.connections, label: { ...state.connections?.label, title: (connection) => connection.name } },
});

The configuration is what a module draws with, not the data it shows, so replay show() with the data too.

Appearance vocabulary

A concept has the same name on every module that has it. The table lists the shared appearance terms, the rule each follows, and the exact properties that carry it. A module missing from a row doesn’t have that concept.

ConceptThe ruleModules and properties
The module’s colourA top-level color is the colour of what the module draws. If unset, it is the map’s accent (colors.accent, published as map.mapColors.accent), then the module’s own default. A part-level colour overrides it.RoutingModule: color, under layers.* paint overrides · GeometriesModule: color, under fill.palette, fill.color, line.color and a feature’s color property (order) · PlacesModule: color, under icon.default.style.fillColor, label.color and layers.*
LabelsOne label shape, LabelConfig: size, color, haloColor, haloWidth, opacity, font, typeface, customTypeface. Each module adds the label’s content and its placement: a distance from the icon, or an offset as [x, y]; FeatureLabelConfig adds a title, a function or a MapLibre expression.PlacesModule: label (PlaceLabelConfig, adds title, and distance as one number of ems away from the icon) · RoutingModule: waypoints.label (WaypointLabelConfig, adds title and visible), and summaryBubbles.label (SummaryBubbleLabelConfig: size, color, opacity, the typeface fields and title, with no halo, since the bubble is the text’s background) · GeometriesModule: label (GeometryLabelConfig, adds title, a string or expression that defaults to the feature’s own title), and lineLabel (GeometryLineLabelConfig, the same title plus minZoom, symbolSpacing, and offset as [x, y] ems) · ReachableRangesModule: lineLabel (ReachableRangeLineLabelConfig, adds a title function)
TypefaceA label’s typeface is one of the style’s faces, mapTypefaces (sans, sans-italic, serif, serif-italic), and each label keeps its weight. A customTypeface of your own font files wins over it, and font, MapLibre’s list of faces, wins over both. Leave both out and a module’s labels follow the map’s typeface.Map-wide: the Styling Foundations knob labels.typeface, and labels.customTypeface · PlacesModule: label.typeface, label.customTypeface · RoutingModule: waypoints.label.typeface, waypoints.label.customTypeface, and the same under summaryBubbles.label · GeometriesModule: label.* and lineLabel.* · ReachableRangesModule: lineLabel.*
MultipliersA *Factor multiplies a default and is clamped to its catalogue entry’s range, which knobEntryOf(catalogue, id) reads. Where a size also has presets ('s', 'm', 'l'), a *Preset picks the base and the factor multiplies it.RoutingModule: widthPreset and widthFactor (0.5 to 2), waypoints.sizePreset and waypoints.sizeFactor (0.5 to 2), sections.<type>.widthPreset and sections.<type>.widthFactor, sections.<type>.icon.sizeFactor (0.25 to 2), highlight.outline.widthFactor (1 to 1.25), highlight.section.outline.widthFactor (0.5 to 2), waypoints.highlight.sizeFactor (1 to 1.5) · GeometriesModule: highlight.fill.opacityFactor (1 to 4) and highlight.line.widthFactor (1 to 3) · ReachableRangesModule: fill.outermostOpacityFactor (0 to 1), stepped down band by band · TrafficIncidentDetailsModule: highlight.line.widthFactor (1 to 1.8), highlight.unfocusedOpacityFactor (0 to 1) on the incidents outside the focus · POIsModule: sizeFactor (0.5 to 1.5) · TrafficFlowModule and TrafficIncidentsModule: widthFactor (0.5 to 2), opacityFactor (0 to 1) · Styling Foundations knobs: labels.sizeFactor, symbols.sizeFactor, roads.widthFactor (0.5 to 1.5)
Hovered and clicked lookA feature a handler covers, or one setEventState puts a state on, draws one look whether hovered or clicked. highlight holds the factors that look multiplies by; a factor of 1 draws the feature as any other. A MapLibre layer you give in place of the default draws as given. A 3D building tells the two apart: hover and click each hold the colour it turns towards and how far, its intensity.RoutingModule: highlight.outline.widthFactor, waypoints.highlight.sizeFactor, and highlight.section.outline.color and highlight.section.outline.widthFactor on the sections setSectionFocus marks · GeometriesModule: highlight.fill.opacityFactor, highlight.line.widthFactor · TrafficIncidentDetailsModule: highlight.outline.color, highlight.line.widthFactor, also drawn on the incidents setFocus marks, highlight: false to turn it off · PlacesModule: layers.selected · BaseMapModule: buildings3D.hover.color, buildings3D.click.intensity · Landmarks 3D plugin: Buildings3D and Landmarks3D hover.color, click.intensity
Absolute unitsA value that mirrors a MapLibre property keeps MapLibre’s name, unless the SDK uses that word for another concept, and is in pixels. Any other unit is in the name. Opacities run from 0 to 1, label offsets are in ems.Pixels: LabelConfig size and haloWidth, GeometriesModule line.width and lineLabel.symbolSpacing, PlacesModule cluster.badge.outlineWidth and cluster.badge.radius · Metres: TrafficAreaAnalyticsModule height.maxMeters, height.minMeters and, per unit of the metric, height.metersPerUnit · Minutes: TrafficIncidentsModule filters.delays.minMinutes · Strengths from 0 to 1: TerrainModule hillshade.intensity, which raises nothing; its elevation.exaggeration scales the raised surface instead
Marker type, fill style, map themeTheme means only the map-wide look. How one module draws its own features has a name of its own.PlacesModule: markerType (PlacesMarkerType; placesMarkerTypes lists pin, circle-icon, base-map, pin-clustered) · GeometriesModule: fill.style (GeometryFillStyle; geometryFillStyles lists filled, outline, inverted), per feature properties.fillStyle · ReachableRangesModule: fill.style, the same values · TrafficAreaAnalyticsModule: regionPolygon.fill.style, filled or inverted · Map theme: StylingFoundationsModule.setMapColors, fed by the Map Theme plugin’s deriveMapColors, deriveMapColorsFromCss, deriveMapColorsFromImage and mapColorsLightDark
Fill colour or paletteA colour field takes a colour or a MapLibre expression, never a palette name. A palette is its own field: on geometries and reachable ranges a list of your own CSS colours, which the features or bands take one after another, or, with fill.paletteMode 'ramp', blended from the first to the last; on area analytics a name, ramped over the metric’s value; on the Landmarks 3D plugin’s buildings, their roofs and landmarks a list of your own CSS colours or map colour ids (colors.accent), which each building, roof or landmark takes one of with paletteMode 'pick', or a mix of two neighbouring ones with 'blend'. Its paletteIntensity sets how far they move to their palette colour, and variation shades each one apart.GeometriesModule: fill.color, fill.palette, fill.paletteMode (GeometryPaletteMode; geometryPaletteModes lists cycle, ramp), unset drawing one colour, the accent · ReachableRangesModule: fill.palette, fill.paletteMode, unset ramping from the accent toward the map’s land colour · TrafficAreaAnalyticsModule: metrics.<metric>.palette (AreaAnalyticsPalette; areaAnalyticsPalettes lists the names), and metrics.<metric>.colorStops, which wins over it · Landmarks 3D plugin: Buildings3D walls.palette, walls.paletteMode (PaletteMode; paletteModes lists pick, blend), walls.paletteIntensity, walls.variation, and roofs.palette, roofs.paletteMode, roofs.paletteIntensity · Landmarks3D palette, paletteMode, paletteIntensity, variation
Line patternA line’s dashes are its pattern, one of linePatterns: solid, dashed or dotted (LinePattern). The dashes scale with the line’s width.RoutingModule: sections.<type>.pattern · GeometriesModule and ReachableRangesModule: line.pattern
Zoom thresholdsminZoom and maxZoom.PlacesModule: entryPoints.minZoom · GeometriesModule: lineLabel.minZoom · RoutingModule: sections.<type>.sign.minZoom, countryCrossings.minZoom, summaryBubbles.minZoom and summaryBubbles.maxZoom · POIsModule: minZoom · TerrainModule: hillshade.maxZoom
Borrowed looksA part drawn to look like the style follows the knobs that restyle what it borrows. A look set on the module wins.PlacesModule with markerType base-map, circle-icon or pin-clustered · RoutingModule sections.traffic and summaryBubbles · TrafficIncidentDetailsModule line colours. The knobs each one follows: Borrowed looks
Visibilityvisible in the config, setVisible(visible) to change it, isVisible() to read it back. isVisible() returns the setting, the same value as the module’s visible knob. On a data-owned module, hiding keeps the data, show() and clear() leave it hidden, and getShown() returns what is shown. On a style-owned module that nothing has set, isVisible() reads what the style draws, and the traffic modules are hidden until shown; getRenderedFeatures() returns what its tiles render in view. A part that hides on its own has its own visible.All three on PlacesModule, RoutingModule, GeometriesModule, ReachableRangesModule, CustomGeoJSONModule, TrafficIncidentDetailsModule, TrafficAreaAnalyticsModule, POIsModule, TrafficFlowModule and TrafficIncidentsModule (plus icons.visible with setIconsVisible / isIconsVisible) · BaseMapModule: visible, groups.<group>.visible, setVisible and isVisible with { layerGroups } · RoutingModule per part: summaryBubbles.visible, countryCrossings.visible, sections.<type>.visible · TerrainModule: hillshade.visible with setHillshadeVisible / isHillshadeVisible, elevation.visible with setElevationVisible / isElevationVisible · Styling Foundations knobs: view.sky.visible
Layer positionbeforeLayerConfig takes 'top' or a named style layer such as 'lowestLabel' (BeforeLayerConfig) for all of a module’s layers. A module drawing several parts also takes a record keyed by its part names, all covering the parts it leaves out (PartsBeforeLayerConfig).GeometriesModule and ReachableRangesModule: GeometryBeforeLayerConfig, parts fill, line · RoutingModule: RoutingBeforeLayerConfig, parts mainLines, instructionLines, icons · PlacesModule: PlacesBeforeLayerConfig, parts places, connections · TrafficAreaAnalyticsModule: AreaAnalyticsBeforeLayerConfig, one part per display mode · TrafficIncidentDetailsModule: BeforeLayerConfig alone · CustomGeoJSONModule: CustomGeoJSONBeforeLayerConfig, for all its layers and on each layer, which also takes { layerID } to go below a layer outside the style
Value filtersOne filter shape, ValuesFilter: { show, values }, where show is one of filterShowModes, 'only' (just the values) or 'all-except' (everything but them).POIsModule: filters.categories and filters.ids · TrafficFlowModule and TrafficIncidentsModule: filters fields such as roadCategories and, on incidents, magnitudes · BaseMapModule: the layerGroups that setVisible, isVisible and events.where take

Every setting as data

Each module publishes its display settings as a knob catalogue, static data you can read with no map loaded. A control panel builds its controls from it, and an agent checks values against it. An entry’s id is the setting’s path in the module’s configuration, and never points into a list. A list is one knob of kind colors, enums or offset, or no knob. The kind says which value the entry takes and which fields come with it. The entry type is KnobEntry, and the kinds are KnobKind:

KindValueFields
toggletrue or false
factora multiplier over the default, the style’s or the module’s own, 1 keeping itrange
numbera numberrange
offsetan [x, y] displacement, x to the right and y down, in the unit the description namesrange, for x and y each
colora colour in hex, rgb(), hsl() or a colour name, the syntaxes a map style paints
enumone of the optionsoptions
enumsa list of the options; the description says when their order mattersoptions
colorsa list of colours, as a color knob takes them, or of the names in optionsoptions, where there are names
imagethe id of an image in the style’s sprite
textany string
  • range is the span a control offers, with the step a slider uses. Its bounds say which ends a value must keep to:

    boundsA value must beFor example
    hardbetween min and maxan opacity, a *Factor
    hard-minat least min; above max it still appliesa height in metres
    softany numberan offset
  • default is present where one value holds everywhere. Otherwise, the description says what decides, such as the style, the accent or the global configuration.

  • A setting that takes a MapLibre expression, a callback or a structured object stays in the configuration. If a setting also takes an expression, its entry holds the plain-value alternatives, which the module’s …KnobValueOf<ID> type names.

  • The styling catalogue and the map effects plugin catalogue use the same kinds.

Setting a knob by its id

These functions work with a knob by its catalogue id on every module, including the Styling Foundations module and the map effects plugin’s MapEffects:

  • setKnob(module, catalogue, id, value) - Sets one setting and keeps every other one. A value its entry refuses changes nothing.

  • setKnobs(module, catalogue, values) - Sets several settings, given by id, in one change and one config-change event. It checks every value first, so if its entry refuses one, none is set.

  • getKnob(module, catalogue, id) - Reads the value in force: the value you set, otherwise what the module knows it to be (a look knob of a style-owned module reads the loaded style), otherwise the entry’s default.

  • resetKnob(module, catalogue, id) - Unsets one setting and drops the objects it leaves empty, so a knob you set and then reset leaves the configuration as it was. resetConfig() unsets them all.

  • knobEntryOf(catalogue, id) - Reads one entry: kind, range or options, default and description.

  • validateKnobValue(entry, value) - Runs the check alone, for a value from a form or a language model.

  • validateKnobValue, setKnob and setKnobs throw a RangeError naming the knob and what it expects. The functions that take an id throw an Error for an id the catalogue lacks.

  • A literal id types the value it takes. An id held as any string, as in a panel looping over a catalogue, takes any value and is checked when set.

The path is the same for every module, and a knob only ever redraws what its own module draws:

One catalogue per modulestatic data, no map neededA valuefrom a control, saved settings or an agentSet knobs by idvalidateKnobValueevery value against its entryRangeErrornothing changesThat module's configurationthe settings at their paths changed, the rest keptWhat that module draws, and nothing elseevents: 'config-change'placesKnobCatalogueroutingKnobCataloguetrafficFlowKnobCatalogue…stylingFoundationsKnobCatalogueeffectKnobCatalogue (map effects plugin)Each entry: id · kind · range or options · defaultkinds shared by every cataloguesetKnob(module, catalogue, id, value)setKnobs(module, catalogue, values) the entry for the id invalidvalidredraw
import { getKnob, knobEntryOf, resetKnob, setKnob, trafficFlowKnobCatalogue, validateKnobValue } from '@tomtom-org/maps-sdk/map';
setKnob(trafficFlow, trafficFlowKnobCatalogue, 'filters.roadCategories.values', ['motorway', 'trunk']);
getKnob(trafficFlow, trafficFlowKnobCatalogue, 'visible'); // false until set: the entry's default
resetKnob(trafficFlow, trafficFlowKnobCatalogue, 'filters.roadCategories.values');
const knob = knobEntryOf(trafficFlowKnobCatalogue, 'filters.roadCategories.values'); // kind, range or options, default
validateKnobValue(knob, ['motorway', 'cart track']); // RangeError: … 'cart track' is not

The traffic config playground sets every flow and incidents knob this way, with controls built from the two catalogues.