@telepix-lab/mapix
v0.1.0
Published
A mapbox-gl toolkit: AOI drawing (rectangle/polygon with self-intersection detection), a map compare slider, and geospatial file parsing (GeoJSON/KML/Shapefile).
Readme
@telepix-lab/mapix
A mapbox-gl toolkit for building area-of-interest (AOI) workflows:
- Draw modes for
@mapbox/mapbox-gl-draw: rectangle and freehand polygon with real-time self-intersection detection, plus adirect_selectvariant that validates edits. - Compare slider to swipe between two synchronized maps.
- File parsing for GeoJSON, KML, and Shapefile (
.zip) into a normalized polygonFeatureCollection, with automatic structural corrections. - Small helpers: area formatting, AOI style constants, source/layer cleanup.
Status:
0.x. The public API may change between minor versions until1.0.
Compatibility
| Feature | mapbox-gl v3 | MapLibre GL |
| --- | --- | --- |
| Draw modes | ✅ | ❌ not supported¹ |
| Compare slider | ✅ | ❌ (uses mapbox-gl types) |
| File parsing (parseFile, countVertices) | ✅ engine-agnostic | ✅ engine-agnostic |
¹ The draw modes build on @mapbox/mapbox-gl-draw, whose default theme uses a
line-dasharray literal that MapLibre rejects. Engine-neutral drawing is on the
1.0 roadmap. File parsing has no engine dependency and works anywhere.
Install
pnpm add @telepix-lab/mapix
# peer dependencies
pnpm add mapbox-gl @mapbox/mapbox-gl-drawPeer dependencies:
| Package | Range |
| --- | --- |
| mapbox-gl | ^3.0.0 |
| @mapbox/mapbox-gl-draw | ^1.4.0 |
Usage
Draw modes
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import {
DrawPolygon,
DrawRectangle,
DirectSelectWithIntersection,
} from '@telepix-lab/mapix';
const draw = new MapboxDraw({
displayControlsDefault: false,
modes: {
...MapboxDraw.modes,
draw_polygon: DrawPolygon,
draw_rectangle: DrawRectangle,
direct_select: DirectSelectWithIntersection,
},
});
map.addControl(draw);
// Optional vertex cap is injected per mode entry.
draw.changeMode('draw_polygon', { maxVertices: 1000 });Rectangle drawing supports modifier keys while dragging: Shift (square),
Alt/Option (draw from center), Space (move), and Ctrl/Cmd+Z /
Ctrl/Cmd+Shift+Z (undo / redo).
Compare slider
import { Compare } from '@telepix-lab/mapix';
const compare = new Compare(beforeMap, afterMap, '#comparison-container', {
orientation: 'vertical', // or 'horizontal'
minRatio: 0.2, // keep at least 20% for each side (default 0)
});
compare.on('slideend', (e) => {
console.log('slider position:', e.currentPosition);
});
// later
compare.remove();The divider is driven by Pointer Events, so mouse, touch and pen all work
through one path. The handle captures the pointer on press: the drag survives
the cursor leaving the handle, a second pointer can neither take it over nor end
it, and only a primary press starts one. The handle is given
touch-action: none inline so the browser does not claim touch drags for
panning.
remove() writes back the inline styles each map container had at construction
time and drops every listener the slider added, so a map reused elsewhere
(typically the "before" map) is left as it was found — even if removal happens
mid-drag. Resizing the container keeps the current split ratio rather than the
pixel offset, including across a resize to zero size (a hidden tab or panel).
File parsing
import {
parseFile,
countVertices,
SUPPORTED_FILE_ACCEPT, // ".geojson,.json,.kml,.shp,.zip"
} from '@telepix-lab/mapix';
const result = await parseFile(file);
if (result.success && result.data) {
// result.data is a GeoJSON FeatureCollection of Polygon / MultiPolygon
const vertexCount = countVertices(result.data);
// result.correction (optional) signals an applied structural fix
} else {
// result.errorCode is a stable machine code; map it to your own i18n.
console.error(result.errorCode, result.error);
}The library handles parsing and structural validation only. Upload policy
(file size, vertex limits, etc.) is the consumer's responsibility; use
countVertices to enforce your own limits.
Area formatting
import { formatArea } from '@telepix-lab/mapix';
formatArea(8500); // { value: '8,500', unit: 'm²' }
formatArea(12345); // { value: '0.01', unit: 'km²' }
formatArea(8500, { thresholdSquareMeters: 1000 }); // switch unit earlierAPI
- Draw modes:
DrawPolygon,DrawRectangle,DirectSelectWithIntersection - Compare:
Compare - File:
parseFile,getSupportedFileType,SUPPORTED_FILE_ACCEPT,countVertices - Geometry utils:
isRectangle,isRectangleGeometry,getPolygonInfo,getOppositeVertexIndex,scalePolygonFromVertex,constrainToRectangle - Formatting:
formatArea - Style constants:
AOI_FILL_COLOR,AOI_FILL_OPACITY,AOI_LINE_COLOR,AOI_LINE_WIDTH - Map helpers:
removeLayerIfExists,removeSourceIfExists
Types for all of the above are exported, including the GeoJSON types
(Feature, FeatureCollection, Polygon, MultiPolygon, Position, and the
PointFeature alias for Feature<Point>) re-exported for convenience.
License
MIT © TelePIX
