Core utilities and theme for Classic Theme maps
npm install @classic-homes/maps-coreCore utilities, types, and themes for Classic Theme map components. This package provides the shared foundation for @classic-homes/maps-react and @classic-homes/maps-svelte.
``bash`
npm install @classic-homes/maps-core
- Theme System: Pre-configured light/dark themes with design token integration
- MapLibre Style Generation: Generate complete MapLibre GL styles from themes
- Type Definitions: Comprehensive TypeScript types for all map components
- Utility Functions: Bounds calculation, GeoJSON validation, coordinate formatting
- Style Helpers: Create hover, selection, and data-driven expressions
- Spatial Indexing: Grid-based and R-tree indexes for large datasets
- LOD Utilities: Level-of-detail management for 100k+ feature datasets
- Polygon Simplification: Douglas-Peucker algorithm for zoom-based simplification
`typescript
import {
lightTheme,
darkTheme,
lightBasicStyle,
darkBasicStyle,
THEME_LIGHT,
THEME_DARK,
} from '@classic-homes/maps-core';
// Use pre-generated MapLibre styles
const mapStyle = isDark ? darkBasicStyle : lightBasicStyle;
// Or access theme colors for custom styling
const highlightColor = lightTheme.colors.highlight;
`
`typescript
import {
createHoverExpression,
createSelectionExpression,
createInteractiveExpression,
createCategoricalColorExpression,
createContinuousColorExpression,
createLotFillStyle,
createLotOutlineStyle,
} from '@classic-homes/maps-core';
// Hover highlighting
const fillColor = createHoverExpression('#22c55e', '#3b82f6');
// Status-based coloring
const statusColor = createCategoricalColorExpression(
'status',
{
available: '#22c55e',
pending: '#f59e0b',
sold: '#ef4444',
},
'#888888'
);
// Lot fill with hover/selection support
const lotStyle = createLotFillStyle({
defaultColor: '#22c55e',
hoverColor: '#3b82f6',
selectedColor: '#f59e0b',
opacity: 0.7,
});
`
`typescript
import {
calculateBounds,
combineBounds,
loadGeoJSON,
validateGeoJSON,
calculateCentroid,
filterByGeometryType,
} from '@classic-homes/maps-core';
// Calculate bounds of a GeoJSON
const bounds = calculateBounds(featureCollection);
// Load and validate GeoJSON
const { data, error, success } = await loadGeoJSON('/api/features.geojson');
// Filter by geometry type
const polygonsOnly = filterByGeometryType(featureCollection, ['Polygon', 'MultiPolygon']);
`
`typescript
import {
buildSpatialIndex,
queryByBounds,
buildRTreeIndex,
queryRTreeByBounds,
createIdleViewportManager,
} from '@classic-homes/maps-core';
// Build a spatial index for fast viewport queries
const index = buildSpatialIndex(featureCollection, { targetCells: 100 });
// Query visible features in viewport
const visible = queryByBounds(index, viewportBounds, { buffer: 0.1 });
// For smooth panning, use the idle-aware viewport manager
const viewportManager = createIdleViewportManager(featureCollection, {
indexType: 'rtree',
bufferFraction: 0.2,
});
const result = viewportManager.query(viewportBounds);
`
`typescript
import {
generateLODData,
generateLODDataWithSimplification,
createDynamicLODManager,
DEFAULT_SIMPLIFICATION_THRESHOLDS,
} from '@classic-homes/maps-core';
// Generate LOD boundaries
const lod = generateLODData(lotsData, {
groupBy: 'community',
subGroupBy: 'filing',
useConvexHull: true,
});
// With polygon simplification for different zoom levels
const lodWithSimplification = generateLODDataWithSimplification(lotsData, {
groupBy: 'community',
simplificationThresholds: DEFAULT_SIMPLIFICATION_THRESHOLDS,
});
// Dynamic FPS-based LOD threshold adjustment
const lodManager = createDynamicLODManager({
baseThresholds: { groupMaxZoom: 12, subGroupMaxZoom: 14 },
targetFps: 50,
});
`
`typescript
import { createGeoJSONFingerprint, fingerprintEqual, geoJSONEqual } from '@classic-homes/maps-core';
// O(1) equality check instead of deep comparison
const prevFingerprint = createGeoJSONFingerprint(prevData);
const nextFingerprint = createGeoJSONFingerprint(nextData);
if (!fingerprintEqual(prevFingerprint, nextFingerprint)) {
// Data changed, update the map
updateSource(nextData);
}
`
The package exports comprehensive TypeScript types:
`typescript
import type {
// Coordinates
LngLat,
MapBounds,
BoundsArray,
MapViewport,
// GeoJSON
GeoJSONFeature,
GeoJSONFeatureCollection,
GeoJSONGeometry,
GeoJSONPolygon,
// Events
MapClickEventParams,
MapHoverEventParams,
FeatureClickEventParams,
FeatureHoverEventParams,
MarkerClickEventParams,
// Component Props
MapProps,
SourceProps,
FillLayerProps,
LineLayerProps,
CircleLayerProps,
MarkerProps,
PopupProps,
// Themes
MapTheme,
MapThemeColors,
MapStyleSpec,
} from '@classic-homes/maps-core';
`
| Function | Description |
| --------------------------- | ---------------------------- |
| generateLightTheme() | Generate light theme colors |generateDarkTheme()
| | Generate dark theme colors |generateBasicStyle(theme)
| | Generate MapLibre style spec |getTheme(name)
| | Get theme by name |
| Function | Description |
| ------------------------------------------------------ | ----------------------------------------- |
| createFillStyle(opts) | Create fill layer paint properties |createLineStyle(opts)
| | Create line layer paint/layout properties |createCircleStyle(opts)
| | Create circle layer paint properties |createHoverExpression(base, hover)
| | Feature-state based hover expression |createSelectionExpression(base, selected)
| | Feature-state based selection expression |createInteractiveExpression(base, hover, selected)
| | Combined hover + selection |createCategoricalColorExpression(prop, map, default)
| | Match expression for categories |createContinuousColorExpression(prop, stops, interp)
| | Interpolate expression |createZoomExpression(stops)
| | Zoom-based interpolation |
| Function | Description |
| --------------------------------- | ------------------------------- |
| loadGeoJSON(url, opts) | Fetch and validate GeoJSON |validateGeoJSON(data)
| | Validate GeoJSON structure |calculateCentroid(geojson)
| | Calculate centroid of features |countFeaturesByType(fc)
| | Count features by geometry type |filterByGeometryType(fc, types)
| | Filter by geometry types |
| Function | Description |
| ----------------------------- | ------------------------------ |
| calculateBounds(geojson) | Get bounding box of features |extendBounds(bounds, point)
| | Extend bounds to include point |combineBounds(a, b)
| | Merge two bounds |isValidBounds(bounds)
| | Validate bounds array |
| Function | Description |
| ------------------------------------------- | ------------------------------ |
| buildSpatialIndex(fc, opts) | Build grid-based spatial index |queryByBounds(index, bounds, opts)
| | Query features in viewport |buildRTreeIndex(fc, opts)
| | Build R-tree spatial index |queryRTreeByBounds(index, bounds, opts)
| | Query R-tree by bounds |createIdleViewportManager(fc, opts)
| | Smooth viewport querying |createPredictiveViewportManager(fc, opts)
| | Predictive pan loading |
| Function | Description |
| ------------------------------------------ | ------------------------------ |
| groupFeaturesByProperty(fc, opts) | Group features by property |generateLODData(fc, opts)
| | Generate LOD boundaries |generateConvexHull(features)
| | Generate convex hull polygon |simplifyPolygon(polygon, tolerance)
| | Douglas-Peucker simplification |simplifyFeatureCollection(fc, tolerance)
| | Simplify all features |createDynamicLODManager(opts)` | FPS-based threshold adjustment |
|
MIT