Specification and utilities for working with Mapbox GL styles including validation, migration, formatting, and expression evaluation
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Feature filtering system for creating efficient layer filters based on geometry properties and feature attributes. Enables selective rendering of map features using expression-based and legacy filter formats.
Creates optimized filter functions from filter specifications for efficient feature evaluation.
/**
* Creates a feature filter from a filter specification
* @param filter - Filter specification (expression or legacy format)
* @returns FeatureFilter object with evaluation function and metadata
*/
function featureFilter(filter: FilterSpecification): FeatureFilter;
interface FeatureFilter {
/** Main filter evaluation function */
filter: FilterExpression;
/** Optional dynamic filter for runtime properties */
dynamicFilter?: FilterExpression;
/** Whether filter requires feature geometry */
needGeometry: boolean;
/** Whether filter requires feature properties */
needFeature: boolean;
}
type FilterExpression = (
globals: EvaluationContext,
feature: any,
canonical?: any
) => boolean;Usage Examples:
import { featureFilter } from "@mapbox/mapbox-gl-style-spec";
// Expression-based filter
const filter1 = featureFilter([
'all',
['==', ['get', 'class'], 'primary'],
['>', ['get', 'population'], 50000]
]);
// Legacy format filter
const filter2 = featureFilter([
'all',
['==', 'class', 'primary'],
['>', 'population', 50000]
]);
// Test features against filter
const feature = {
properties: {
class: 'primary',
population: 75000
},
geometry: { /* ... */ }
};
const passes = filter1.filter({ zoom: 10 }, feature);
console.log(passes); // trueUtilities for identifying filter format and requirements.
/**
* Tests whether a filter uses expression syntax
* @param filter - Filter specification to test
* @returns True if filter uses expression format
*/
function isExpressionFilter(filter: FilterSpecification): boolean;Usage Examples:
import { isExpressionFilter } from "@mapbox/mapbox-gl-style-spec";
const expressionFilter = ['==', ['get', 'type'], 'restaurant'];
const legacyFilter = ['==', 'type', 'restaurant'];
console.log(isExpressionFilter(expressionFilter)); // true
console.log(isExpressionFilter(legacyFilter)); // falseConverts legacy filter formats to modern expression syntax.
/**
* Converts legacy filter format to expression syntax
* @param filter - Legacy filter specification
* @returns Expression-format filter specification
*/
function convertFilter(filter: FilterSpecification): ExpressionSpecification;Usage Examples:
import { convertFilter } from "@mapbox/mapbox-gl-style-spec";
// Convert legacy to expression format
const legacyFilter = ['all', ['==', 'class', 'primary'], ['>', 'rank', 5]];
const expressionFilter = convertFilter(legacyFilter);
console.log(expressionFilter);
// Result: ['all', ['==', ['get', 'class'], 'primary'], ['>', ['get', 'rank'], 5]]Modern filter format using expression syntax for maximum flexibility.
type FilterSpecification =
| ExpressionFilterSpecification
| LegacyFilterSpecification;
type ExpressionFilterSpecification =
| boolean
| ExpressionSpecification;
// Common expression filter patterns
type ComparisonFilter = [
'==' | '!=' | '<' | '<=' | '>' | '>=',
ExpressionSpecification,
ExpressionSpecification
];
type LogicalFilter =
| ['all', ...ExpressionSpecification[]]
| ['any', ...ExpressionSpecification[]]
| ['none', ...ExpressionSpecification[]];
type MembershipFilter =
| ['in', ExpressionSpecification, ExpressionSpecification]
| ['!in', ExpressionSpecification, ExpressionSpecification];
type ExistentialFilter =
| ['has', string | ExpressionSpecification]
| ['!has', string | ExpressionSpecification];Backward-compatible filter format for older styles.
type LegacyFilterSpecification =
| LegacyComparisonFilter
| LegacyLogicalFilter
| LegacyMembershipFilter
| LegacyExistentialFilter;
type LegacyComparisonFilter = [
'==' | '!=' | '<' | '<=' | '>' | '>=',
string,
string | number | boolean
];
type LegacyLogicalFilter =
| ['all', ...LegacyFilterSpecification[]]
| ['any', ...LegacyFilterSpecification[]]
| ['none', ...LegacyFilterSpecification[]];
type LegacyMembershipFilter =
| ['in', string, ...Array<string | number | boolean>]
| ['!in', string, ...Array<string | number | boolean>];
type LegacyExistentialFilter =
| ['has', string]
| ['!has', string];Filters based on feature geometry properties.
// Geometry type filters
type GeometryTypeFilter = ['==', ['geometry-type'], 'Point' | 'LineString' | 'Polygon'];
// Geometry ID filters
type GeometryIdFilter = ['==', ['id'], string | number];Usage Examples:
// Filter by geometry type
const pointFilter = featureFilter(['==', ['geometry-type'], 'Point']);
// Filter by feature ID
const idFilter = featureFilter(['==', ['id'], 123]);
// Complex geometric filter
const complexFilter = featureFilter([
'all',
['==', ['geometry-type'], 'Polygon'],
['>', ['get', 'area'], 1000000]
]);Filters using distance calculations for proximity-based rendering.
interface FeatureDistanceData {
center: [number, number];
bearing: [number, number];
scale: number;
}
// Distance filter example
type DistanceFilter = ['<', ['distance', ['literal', [lng, lat]]], number];Filters using feature state for dynamic styling.
// Feature state filters
type FeatureStateFilter = [
'==',
['feature-state', string],
string | number | boolean
];Usage Examples:
// Filter by feature state
const stateFilter = featureFilter([
'==',
['feature-state', 'hover'],
true
]);
// Combine with property filters
const combinedFilter = featureFilter([
'all',
['==', ['get', 'type'], 'building'],
['==', ['feature-state', 'selected'], true]
]);interface EvaluationContext {
zoom: number;
heatmapDensity?: number;
lineProgress?: number;
distanceFromCenter?: number;
}
type FilterExpression = (
globals: EvaluationContext,
feature: GeoJSONFeature,
canonical?: CanonicalTileID
) => boolean;
interface GeoJSONFeature {
type: 'Feature';
id?: string | number;
properties: { [key: string]: any };
geometry: GeoJSONGeometry;
}
type GeoJSONGeometry =
| { type: 'Point'; coordinates: [number, number] }
| { type: 'LineString'; coordinates: Array<[number, number]> }
| { type: 'Polygon'; coordinates: Array<Array<[number, number]>> }
| { type: 'MultiPoint'; coordinates: Array<[number, number]> }
| { type: 'MultiLineString'; coordinates: Array<Array<[number, number]>> }
| { type: 'MultiPolygon'; coordinates: Array<Array<Array<[number, number]>>> };