api reference
Map View API Reference
createMapView: a 3D MapLibre and deck.gl map of a grid’s rows, as points, columns, polygons and flowing routes, kept in step with the grid’s own filter, search and selection.
API reference › The map view
All 22 pages Everything on one page → Developer guide →
The map view
modules/mapview puts a 3D map beside the grid that shows the same rows geographically, and keeps the two in step: the map is always a picture of the grid's current state, not a separate report. Any row with a place - a latitude and a longitude, a GeoJSON geometry, or a path of coordinates - is drawn; a filter, a quick search or a grouping on the grid redraws the map on the grid's next frame; selecting a row flies the map to it; clicking a feature selects its row and scrolls the grid to it; and hovering shows the row's cells in the grid's own formatted text. For a telecoms team, the build schedule, premises list or fault log they already manage in the grid becomes a 3D map of their network with no extra integration.
import { createMapView } from '@toclocoinc/lattice-grid/modules/mapview';
const map = createMapView(grid, {
container: '#map', // or mode: 'split' | 'tab' | 'popout'
geometry: { lat: 'latitude', lng: 'longitude' }, // or { geojson: 'geom' } or { path: 'route' }
layer: 'column', // 'point' | 'column' | 'polygon' | 'path'
elevation: 'premisesPassed',
color: { field: 'status', map: { live: '#2e7d32', build: '#f9a825', planned: '#90a4ae' } },
buildings: true,
});
deck.gl and MapLibre stay yours. The module imports neither and ships no dependency. Load MapLibre GL and deck.gl on the page (their UMD builds set the globals maplibregl and deck), or pass them as libs: { deck, maplibregl }. The map is a MapLibre map, and the rows are deck.gl layers on it through deck's MapboxOverlay in interleaved mode, so deck's routes, areas, columns and points and MapLibre's 3D buildings share one depth buffer: a building in front of a route hides it at pitch 45 to 60. (deck.gl 9.1 reads the camera's depth planes under the names Mapbox GL uses, transform._nearZ and _farZ, and MapLibre GL 4.x names them nearZ and farZ; the module aliases them so the two agree. Looking straight down, at pitch 0, a roof is nearer the camera than anything under it, so a route under a building's footprint is hidden by its roof there too.) If either library is missing, mapview:libs warns, naming which one, and the map's box is left empty.
Where the rows are. geometry is { lat, lng } (or lon), { geojson } - a GeoJSON Geometry or Feature, as an object or its JSON text, or WKT or WKB - or { path }, an array of [lng, lat] pairs or its JSON text - or, for a network, { lat, lng, route: { by, order } } or { from: { lat, lng }, to: { lat, lng } } (see The network map). A row whose place is blank or cannot be read is skipped and counted: provenance() returns { drawn, skipped, matched, layers }, the rows drawn, the rows with no usable place, the rows the grid matched, and the count drawn by each layer kind.
How they look. A row is drawn by the layer for its geometry: a point is a marker (deck's ScatterplotLayer), or an extruded column (ColumnLayer) when an elevation is given; a polygon is an area (GeoJsonLayer), extruded when an elevation is given; a line is a route (PathLayer). layer picks the kind for the rows of its geometry, and setLayer() switches it live. elevation is a numeric column or one number, in metres, multiplied by elevationScale. color is one colour; { field, map }, a colour per value (any value not in map takes the next colour of the charts palette); or { field, scale: 'ramp', domain, colours, rampScale }, a number placed along a ramp by the charts module's own scale code, exactly as a heat map places it. Unset, rows take the grid theme's accent, and selected rows its focus colour. radius (a marker's, in metres) and width (a route's, in pixels) are a column or a number; a column layer draws every column at one radius, so only a number applies to it. flow: true (or { speed, trail }) animates a flow along the routes; it stops while the page is hidden and is drawn still for a reader who prefers reduced motion.
Which rows: the grid's. The map draws the rows the grid shows after its filters and quick search - and, when it is grouped, every leaf row of the grouped result, whether or not its group is collapsed, because collapsing a group hides its rows from the table, not from the data. It is the same row path as the deck.gl adapter: a paged pushdown grid's map draws the rows inside the map's view, asked of the engine, up to viewportCap. A burst of grid changes costs one redraw, on the next animation frame.
Selection, both ways. A grid selection draws the selected rows in the highlight colour and flies the map to them: to the row, or to the box of several. flyTo(key) or flyTo([keys]) does the same from code. A click on a feature selects its row in the grid (selection: 'single' or 'multiple'; a grid that cannot take it warns mapview:selection), opens any collapsed group the row sits in, and scrolls it into view. Hovering a feature shows the tooltip columns (default the first three visible columns that do not hold the place; false for none), each as the grid's own display text for that cell, so a formatted value reads identically on the map and in the grid.
The basemap and buildings. basemap is a MapLibre style URL or style object; the default is OpenFreeMap's keyless positron, or its dark style for a dark theme. buildings: true adds 3D buildings from the style's OpenMapTiles building layer (render_height, render_min_height), coloured for the light or dark theme; a style with no vector source warns mapview:buildings. The first view fits the drawn rows; view: { center, zoom, pitch, bearing } sets it instead. theme is light or dark, by default the grid's own.
Where the map goes. mode: 'container' (the default when container, an element or a selector, is given) fills that element. 'split' (the default without one) puts the map beside the grid in the grid's own host, with a divider a pointer drags and the arrow keys move. 'tab' shows the grid and the map as two tabs. 'popout' opens the map in a separate browser window that runs on this page's libraries; when the browser blocks the popup, it opens in a floating panel instead, moved by its title bar, resized from its corner and closed by its button. destroy() removes the map, its layers and every listener, and puts the grid back where it was.
Events. on(name, fn) returns the unsubscribe and off(name, fn) removes a listener: feature:click ({ key, row }, and for a route route and keys), feature:hover ({ key, row, lines }), draw ({ provenance }), load (the basemap style loaded) and close (the reader closed a popped-out map). update(options) changes options and redraws now; layers() returns the deck.gl layers last handed to the map.
The mapView key in a grid's own configuration is not offered: the grid has no means for a module to add a configuration key, so the map view is made by createMapView(grid, options) once the grid exists.
The network map: routes from rows, dashes, icons
A fibre, pipe or power network is usually not one row per line: it is a table of points, each row one vertex of a route, plus the cabinets and joints that sit on it. The map view draws that table as it is. The recipe below puts the routes, their vertex rows and the cabinet points in one view: routes assembled from the vertex rows, coloured and dashed by their status, cabinets as icons on badges, all readable in the 3D presentation among extruded buildings.
createMapView(grid, {
container: '#map',
geometry: { lat: 'lat', lng: 'lng', route: { by: 'routeId', order: 'seq' } },
color: { field: 'status', map: { live: '#2e9d4f', planned: '#1f6fd1', backbone: '#d62828', proposed: '#d62828' } },
dash: { field: 'status', map: { proposed: 'dashed', planned: 'dotted', live: 'solid' } },
width: 4,
icon: { field: 'kind', map: { cabinet: 'cabinet', splice: 'splice', exchange: 'exchange' }, size: 26, badge: 'diamond' },
legend: true,
buildings: true, // the default 3D presentation: pitched, with extruded buildings
});
Routes from rows. With route: { by, order }, every row that has a place and a non-blank by value is one vertex of the route that value names. Each route is one line through its vertices in order (numbers as numbers, anything else as text, a blank last; without order, the grid's row order). A route whose rows are given in any order is still drawn in sequence. The rule that tells a vertex from a point is the route id: a row belongs to a route only when it has a route id. A row with a blank route id (null or empty) is not a vertex; it stays a point - a cabinet, a splice - and is drawn as one, so vertex rows and cabinet rows share a grid. A vertex row is never also drawn as a point.
A route's colour, width, dash and elevation are route-level: the value in the route's first vertex row (in sequence order), or, with route: { aggregate }, the last, min or max across its rows. A route with fewer than two usable vertices (a vertex row with no usable place does not count) is skipped, and counted: provenance() adds routes, routesSkipped and routesRebuilt, and the skipped route's rows are in skipped, so drawn + skipped is every matched row. The segment form, { from: { lat, lng }, to: { lat, lng } }, draws each row as one line from its from to its to, with no route id; a row missing an end is skipped.
Live. A filter, an edit, an add or a delete of a vertex row assembles again only that route: every other route is reused as it was, and provenance().routesRebuilt says how many were assembled on the last draw. Clicking a route selects every one of its rows in the grid (the grid needs selection: 'multiple' to hold them all), and selecting any of a route's rows draws the route in the highlight colour. Hovering a route shows its route id first, then the tooltip columns of its first row, each in the grid's own formatted text.
Dashed lines. dash is 'dashed' or 'dotted' for every line, [dash, gap] in pixels, or { field, map } naming a pattern per value (a value not named is solid). The pattern is in pixels and keeps its length on screen as the camera zooms and pitches. Dashes are drawn by deck.gl's PathStyleExtension, which the page supplies with deck (the standalone deck.gl bundle exports it); without it mapview:dash warns and the lines are solid. legend: true draws the legend in the map's box. When the colour rule and the dash rule key on the same field (color: { field: 'status', map } and dash: { field: 'status', map: { proposed: 'dashed' } }) the legend has one entry per value, its sample a short line in that value's colour and dash pattern (a solid value is a solid line); a value drawn only as points is a square swatch. When they key on different fields the legend keeps two sections, each titled by its field's column header. legend() returns { sections, colours, dashes }: sections is what is drawn ({ field, title, merged, entries: [{ label, colour, dash, line }] }), colours and dashes are the two rules' own entries.
Icon markers. icon: { field, map, default, size, anchor, badge } draws point rows with deck's IconLayer instead of circles. A point's icon is map[value], else default; the glyphs are the grid's icon registry - the same one a network chart's node icons use - which now includes cabinet, splice, exchange, pole, chamber, premises and fault, or an SVG path, an icon definition, or an image URL. Registry glyphs are tinted by the color mapping, or, with badge: 'circle' | 'square' | 'diamond', drawn white on a badge of that colour with a white ring (the red diamonds of a network map); the badge is what picks, hovers and selects, as a point does. Every icon is packed once into one atlas at 64 pixels a glyph, sharp at 2x, and repacked only when a point asks for an icon the atlas does not hold. An unknown name warns mapview:icon:<name> and its point is a circle.
Readable in 3D. Routes are drawn in pixels, between 2 and 30 pixels wide whatever the width, so they stay clear at street level, and 2 m above the ground (points 4 m, when routes are in view) so a route does not z-fight the basemap at pitch 45 to 60. Icons are billboards that always face the camera and keep their pixel size; they are not depth-tested, so an icon is drawn whole over the ground, the routes and the extruded buildings - a cabinet inside a building's footprint is never hidden by it. The draw order is polygons, then routes (and their flow), then columns, then points, then icons: points over lines over areas.
A network map: routes assembled from vertex rows in sequence order, dashed by status, a route selecting all its rows, and an edit assembling one route again
const { createTestDom, flushFrames } = await import('../packages/dom/src/renderer/testdom.js');
const { createHeadlessGrid } = await import('../packages/core/src/index.js');
const { createMapView } = await import('../packages/modules/mapview/index.js');
const dom = createTestDom();
const el = dom.document.createElement('div');
dom.root.appendChild(el);
const grid = createHeadlessGrid({
rowKey: 'id',
selection: 'multiple',
columns: [{ field: 'id' }, { field: 'routeId' }, { field: 'seq', type: 'number' }, { field: 'status' }, { field: 'kind' },
{ field: 'lat', type: 'number' }, { field: 'lng', type: 'number' }],
rows: [
// Two routes, their vertex rows out of order, and a cabinet that is on no route.
{ id: 'a3', routeId: 'R1', seq: 3, status: 'live', lat: 51.884, lng: 0.904 },
{ id: 'a1', routeId: 'R1', seq: 1, status: 'live', lat: 51.880, lng: 0.900 },
{ id: 'a2', routeId: 'R1', seq: 2, status: 'live', lat: 51.882, lng: 0.901 },
{ id: 'b2', routeId: 'R2', seq: 2, status: 'proposed', lat: 51.889, lng: 0.909 },
{ id: 'b1', routeId: 'R2', seq: 1, status: 'proposed', lat: 51.885, lng: 0.905 },
{ id: 'c1', routeId: null, seq: null, status: 'live', kind: 'cabinet', lat: 51.882, lng: 0.901 },
],
});
// The icon atlas is drawn on a canvas, which a page has. This stand-in canvas just accepts the drawing.
const make = dom.document.createElement.bind(dom.document);
dom.document.createElement = (tag) => {
const el = make(tag);
if (tag === 'canvas') {
el.getContext = () => new Proxy({}, { get: () => () => {} });
el.toDataURL = () => 'data:image/png;base64,atlas';
}
return el;
};
globalThis.Path2D ??= class { constructor(d) { this.d = d; } };
// Stand-ins for the page's deck.gl and MapLibre, as above; PathStyleExtension is
// what draws the dashes, and the page's deck supplies it.
const layer = (kind) => class { constructor(props) { this.props = props; this.kind = kind; } };
const deck = {
ScatterplotLayer: layer('point'), ColumnLayer: layer('column'), GeoJsonLayer: layer('polygon'),
PathLayer: layer('path'), TripsLayer: layer('flow'), IconLayer: layer('icon'), PathStyleExtension: layer('dash'),
MapboxOverlay: class { constructor(p) { this.props = p; } setProps(p) { Object.assign(this.props, p); } },
};
const maplibregl = {
Map: class {
on() {} off() {} addControl() {} removeControl() {} remove() {} resize() {} setStyle() {}
getZoom() { return 12; } getBounds() { return null; } getStyle() { return { sources: {} }; }
getLayer() {} addLayer() {} jumpTo() {} fitBounds() {} flyTo() {}
},
};
const map = createMapView(grid, {
container: el,
libs: { deck, maplibregl },
geometry: { lat: 'lat', lng: 'lng', route: { by: 'routeId', order: 'seq' } },
color: { field: 'status', map: { live: '#2e9d4f', proposed: '#d62828' } },
dash: { field: 'status', map: { proposed: 'dashed', live: 'solid' } },
width: 4,
icon: { field: 'kind', map: { cabinet: 'cabinet' }, size: 26, badge: 'diamond' },
legend: true,
});
const routes = map.layers().find((l) => l.kind === 'path');
const r1 = routes.props.data.find((d) => d.item.route === 'R1');
const seen = [
`${map.provenance().routes} routes`,
routes.props.getPath(r1).map((p) => p[1]).join(','), // in seq order, not row order
map.legend().dashes.map((d) => `${d.label} ${d.dash ? d.dash.join('/') : 'solid'}`).join(' + '), // dash and gap, in pixels
map.layers().find((l) => l.kind === 'icon').props.data.map((d) => d.icon).join(), // the cabinet is an icon
];
map.overlay.props.onClick({ object: r1 }); // a route selects all its rows
seen.push(grid.selection.keys().sort().join());
grid.rows.apply({ update: [{ id: 'b1', lat: 51.8855 }] }); // an edit assembles one route again
flushFrames();
seen.push(map.provenance().routesRebuilt);
map.destroy();
return seen.join(' | ');
Rows to the map, a filter followed, a selection flown to, the grid's own text on hover, a click selecting, a layer switched, and destroy
const { createTestDom, flushFrames } = await import('../packages/dom/src/renderer/testdom.js');
const { createHeadlessGrid } = await import('../packages/core/src/index.js');
const { createMapView } = await import('../packages/modules/mapview/index.js');
const dom = createTestDom();
const el = dom.document.createElement('div');
dom.root.appendChild(el);
const grid = createHeadlessGrid({
rowKey: 'id',
selection: 'single',
columns: [{ field: 'id' }, { field: 'status' }, { field: 'passed', type: 'number' },
{ field: 'cost', type: 'number', format: { style: 'currency', decimals: 0 } },
{ field: 'lat', type: 'number' }, { field: 'lng', type: 'number' }],
rows: Array.from({ length: 30 }, (_, i) => ({
id: 'p' + i, status: ['planned', 'build', 'live'][i % 3], passed: (i % 10) + 1,
cost: 900 + i * 25, lat: 51.88 + (i % 6) * 0.002, lng: 0.89 + Math.floor(i / 6) * 0.003,
})),
});
// Stand-ins for the page's deck.gl and MapLibre: a layer keeps its props, the
// overlay keeps the layers, the map records its camera. On a page these are
// the UMD globals `deck` and `maplibregl`, and `libs` is not needed.
const layer = (kind) => class { constructor(props) { this.props = props; this.kind = kind; } };
const deck = {
ScatterplotLayer: layer('point'), ColumnLayer: layer('column'), GeoJsonLayer: layer('polygon'),
PathLayer: layer('path'), TripsLayer: layer('flow'),
MapboxOverlay: class { constructor(p) { this.props = p; } setProps(p) { Object.assign(this.props, p); } },
};
const camera = [];
const maplibregl = {
Map: class {
on() {} off() {} addControl() {} removeControl() {} remove() {} resize() {} setStyle() {}
getZoom() { return 12; } getBounds() { return null; } getStyle() { return { sources: {} }; }
getLayer() {} addLayer() {} jumpTo(o) { camera.push('jump ' + o.zoom); }
fitBounds() { camera.push('fit'); } flyTo(o) { camera.push('fly ' + o.center.join(',')); }
},
};
const map = createMapView(grid, {
container: el,
mode: 'container',
libs: { deck, maplibregl },
geometry: { lat: 'lat', lng: 'lng' },
layer: 'column',
elevation: 'passed',
elevationScale: 20,
radius: 15,
width: 3,
color: { field: 'status', map: { live: '#2e7d32', build: '#f9a825', planned: '#90a4ae' } },
flow: false, // routes only: an animated flow along them
buildings: true,
basemap: 'https://tiles.openfreemap.org/styles/positron',
theme: 'light',
tooltip: ['status', 'cost'],
viewportCap: 20000, // a paged pushdown grid: rows fetched for the view
});
const seen = [`${map.provenance().drawn} ${map.layers()[0].kind} ${camera.at(-1)}`];
grid.filters.set({ col: 'status', op: 'eq', value: 'live' });
flushFrames(); // the map redraws on the grid's next frame
seen.push(map.provenance().drawn);
grid.selection.set(['p5']); // a grid selection flies the map
seen.push(camera.at(-1));
const tips = [];
map.on('feature:hover', (e) => tips.push(e.lines.map((l) => l.text).join(' ')));
map.overlay.props.onHover({ object: map.layers()[0].props.data[0], x: 0, y: 0 });
seen.push(tips[0]); // the grid's own cell text
map.overlay.props.onClick({ object: map.layers()[0].props.data[2] });
seen.push(grid.selection.keys()[0]); // a click selects the row
map.setLayer('point');
seen.push(map.layers()[0].kind);
map.flyTo(['p2', 'p8']);
seen.push(camera.at(-1));
const draws = [];
const onDraw = (e) => draws.push(e.provenance.drawn);
map.on('draw', onDraw);
map.update({ view: { zoom: 14, pitch: 60 } });
map.off('draw', onDraw);
map.update({});
seen.push(`${camera.at(-1)} ${draws.join()}`);
map.destroy();
seen.push(el.children.length);
return seen.join(' | ');
Type reference
Generated from the type declarations, so it always matches the release. Each surface lists its properties, its methods and the events it raises as three tables; an option or value type lists its members once.
The map view
MapViewRoute
Routes assembled from ordinary rows: with `geometry: { lat, lng, route }` every row that has a place AND a non-blank value in the `by` column is one vertex of the route that value names, and each route is drawn as one line through its vertices in `order` (numbers as numbers, anything else as text; a blank last; rows with equal values in the order the grid shows them; no `order`: the grid's order). A row with a blank `by` is not a vertex: it stays a point (a cabinet, a splice) and is drawn as one. A vertex row is never also drawn as a point. A route's colour, width, dash and elevation are route-level: read from the route's first vertex row (in sequence order), or from `aggregate` across its rows.
| Property | Type | Description |
|---|---|---|
| by | string | The column holding each vertex row's route id. |
| order | string | The column holding each vertex's position in its route. (optional) |
| aggregate | 'first' | 'last' | 'min' | 'max' | How a route-level style column is read across the route's rows: `first` (default), `last`, or `min` / `max` (numbers as numbers, anything else as text). An unknown value warns `mapview:route`. (optional) |
MapViewOptions
What {@link createMapView} takes.
| Property | Type | Description |
|---|---|---|
| geometry | MapViewGeometry | Where each row is placed. A row whose place is blank or cannot be read is skipped and counted in `provenance().skipped`. A name that is not a column of the grid: nothing is drawn and `mapview:geometry` warns. |
| container | HTMLElement | string | The element (or a selector for it) the map fills. Given without a `mode`, the mode is `container`. (optional) |
| mode | 'container' | 'split' | 'tab' | 'popout' | Where the map goes: `container` (the `container` element); `split` (the default without a container: the map beside the grid in the grid's own host, with a divider a pointer drags and the arrow keys move); `tab` (the grid and the map as two tabs); `popout` (a separate browser window on this page's libraries, or a floating panel when the popup is blocked). `split`, `tab` and `popout` need a grid made by `createGrid`. (optional) |
| layer | MapViewLayer 'point' | 'column' | 'polygon' | 'path' | The layer for the rows of one geometry: `point` (markers) or `column` (extruded columns) for points, `polygon` (areas, extruded with an `elevation`) for polygons, `path` (routes) for lines. Rows of another geometry keep their default: a point is a marker, or a column when an `elevation` is given; a polygon an area; a line a route. (optional) |
| elevation | string | number | A numeric column (or one number) for the height of columns and extruded areas, in metres. (optional) |
| elevationScale | number | A multiplier on `elevation`. Default 1. (optional) |
| color | MapViewColour | How rows are coloured. Default the grid theme's accent. (optional) |
| radius | string | number | A marker's radius in metres: a numeric column or one number (default 30). A `column` layer draws every column at one radius, so only a number applies to it. (optional) |
| width | string | number | A route's width in pixels: a numeric column or one number. Default 3. A route is always drawn between 2 and 30 pixels wide whatever its width, wide enough to read at street level among extruded buildings, and drawn 2 m above the ground (4 m for points when routes are in view) so it does not z-fight the basemap at pitch. (optional) |
| dash | MapViewDash | Dash lines by value or all alike; see {@link MapViewDash}. The legend shows each pattern the map names. (optional) |
| icon | MapViewIcon | Icon markers for point rows; see {@link MapViewIcon}. (optional) |
| legend | boolean | Show a legend in the map's box: a swatch for each colour the `color` rule maps and a sample line for each pattern `dash` names. Default off; `legend()` returns the same entries as data. (optional) |
| flow | MapViewFlow | Animate a flow along the routes. Stops while the page is hidden, and is drawn still when the reader prefers reduced motion. (optional) |
| buildings | boolean | Add 3D buildings from the basemap's OpenMapTiles `building` layer (`render_height`, `render_min_height`), coloured for the light or dark theme. Off by default. A style with no vector source warns `mapview:buildings`. (optional) |
| basemap | string | Record<string, unknown> | A MapLibre style URL or style object. Default OpenFreeMap's keyless positron, or its dark style for a dark theme. (optional) |
| view | MapViewCamera | The initial camera. Default: fitted to the drawn rows. (optional) |
| theme | 'light' | 'dark' | 'auto' | `light` or `dark`; default the grid's own (`data-theme` above it, `auto` read from the reader's colour-scheme preference). (optional) |
| tooltip | string[] | false | The columns the hover tooltip shows, each as the grid's own formatted cell text. Default the grid's first three visible columns that do not hold the place; `false` for no tooltip. A route's tooltip leads with its route id and shows its first row's cells. (optional) |
| libs | { deck?: unknown; maplibregl?: unknown } | The page's deck.gl and MapLibre GL. Default the globals `deck` and `maplibregl` their UMD builds set. Either missing: the map is left empty and `mapview:libs` warns, naming which. (optional) |
| viewportCap | number | On a paged pushdown grid, the most rows fetched for the map's view; as {@link ChartSpec.viewportCap}, default 20,000. (optional) |
MapViewProvenance
What a map view drew.
| Property | Type | Description |
|---|---|---|
| drawn | number | The rows drawn (every vertex row of a drawn route counts). |
| skipped | number | The rows the grid shows that have no usable place, so were not drawn; with `route`, also the vertex rows of a route skipped for having fewer than two usable vertices, so `drawn + skipped` is every matched row. |
| matched | number | The rows the grid matched. |
| layers | Partial<Record<MapViewLayer | 'icon', number>> | The items drawn by each layer kind (a route is one path); `icon` counts the points drawn as icons, `point` the circles. |
| routes | number | With `geometry.route`: the routes drawn. (optional) |
| routesSkipped | number | With `geometry.route`: the routes skipped for having fewer than two usable vertices. (optional) |
| routesRebuilt | number | With `geometry.route`: the routes assembled from their rows on the last draw. A route none of whose vertex rows (or route-level style columns) changed is reused, so an edit, add, delete or filter of one vertex row assembles one route, not all of them. (optional) |
| computed | 'client' | 'engine' | `client` when the grid held the rows, `engine` when a paged source's engine answered for the view. |
MapViewEventPayloads
What each map view event carries.
| Property | Type | Description |
|---|---|---|
| feature:click | { key: string | number; row: Record<string, unknown> | null; route?: string; keys?: Array<string | number> } | A feature was clicked; its row is now selected in the grid. A route selects every one of its rows: `key` is its first row's key, `route` its id and `keys` all its rows' keys. |
| feature:hover | { key: string | number | null; row: Record<string, unknown> | null; lines: Array<{ column: string; title: string; text: string }> } | The pointer moved onto a feature (`key` null when it left one); `lines` are the tooltip's. |
| draw | { provenance: MapViewProvenance } | The layers were redrawn. |
| load | { map: unknown } | The basemap style loaded (at first, and after a basemap or theme change). |
| close | Record<string, never> | The reader closed a popped-out map. |
MapView
A live map view of a grid.
Properties
| Property | Type | Description |
|---|---|---|
| element | HTMLElement | null | The map view's own element. (read-only) |
| map | unknown | The MapLibre map; null when the map could not be built. (read-only) |
| overlay | unknown | deck.gl's `MapboxOverlay` on it; null when the map could not be built. (read-only) |
Methods
| Method | Signature | Parameters | Returns | Description |
|---|---|---|---|---|
| update | (options?: Partial<MapViewOptions>): void | options?: Partial<MapViewOptions> | void | Change options and redraw now: `basemap` and `theme` restyle the map, `buildings` adds or removes them, `view` moves the camera, and `geometry` re-reads every row's place. |
| flyTo | (keys: string | number | Array<string | number>): void | keys: string | number | Array<string | number> | void | Fly to one row, or fit the map to several. |
| setLayer | (layer: MapViewLayer): void | layer: MapViewLayer | void | Draw the rows of one geometry with this layer kind. |
| provenance | (): MapViewProvenance | - | MapViewProvenance | What the map drew last: rows drawn, skipped and matched, and per layer. |
| layers | (): unknown[] | - | unknown[] | The deck.gl layers last handed to the map, in draw order: areas, routes, columns, points, icons. |
| legend | (): { colours: Array<{ label: string; colour: number[] }>; dashes: Array<{ label: string; dash: [number, number] | null }>; sections: Array<{ field: string | null; title: string; merged: boolean; entries: Array<{ label: string; colour: number[] | null; dash: [number, number] | null; line: boolean }>; }>; } | - | { colours: Array<{ label: string; colour: number[] }>; dashes: Array<{ label: string; dash: [number, number] | null }>; sections: Array<{ field: string | null; title: string; merged: boolean; entries: Array<{ label: string; colour: number[] | null; dash: [number, number] | null; line: boolean }>; }>; } | What the legend shows, as data. `sections` is what is drawn: one merged section when the colour and dash rules key on the same field (an entry per value, `line` true for a value drawn as a line, its sample in that value's colour and `dash`; false for a point-only value, a square), else one section per rule titled by its field's header. `colours` and `dashes` are the two rules' own entries (`null` dash is solid). |
| on | (name: MapViewEventName, fn: (event: MapViewEventPayloads[MapViewEventName]) => void): () => void | name: MapViewEventNamefn: (event: MapViewEventPayloads[MapViewEventName]) => void | () => void | Listen for an event; returns the unsubscribe. An unknown name warns `mapview:event:<name>`. |
| off | (name: MapViewEventName, fn: (event: MapViewEventPayloads[MapViewEventName]) => void): void | name: MapViewEventNamefn: (event: MapViewEventPayloads[MapViewEventName]) => void | void | Stop listening for an event. |
| destroy | (): void | - | void | Remove the map, its layers and every listener, and put the grid back where it was. |
Events
| Event | When | Payload | Cancellable |
|---|---|---|---|
| feature:click | { key: string | number; row: Record<string, unknown> | null; route?: string; keys?: Array<string | number> } | - | |
| feature:hover | { key: string | number | null; row: Record<string, unknown> | null; lines: Array<{ column: string; title: string; text: string }> } | - | |
| draw | { provenance: MapViewProvenance } | no | |
| load | { map: unknown } | - | |
| close | Record<string, never> | - |