@mapbox/mapbox-gl-style-spec 14.28.0 → 14.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/composite.ts +5 -5
  2. package/diff.ts +38 -40
  3. package/dist/index.cjs +362 -238
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +101 -13
  6. package/dist/index.es.js +362 -238
  7. package/dist/index.es.js.map +1 -1
  8. package/expression/compound_expression.ts +6 -6
  9. package/expression/definitions/assertion.ts +9 -12
  10. package/expression/definitions/at.ts +1 -1
  11. package/expression/definitions/at_interpolated.ts +1 -1
  12. package/expression/definitions/case.ts +1 -2
  13. package/expression/definitions/coalesce.ts +1 -1
  14. package/expression/definitions/coercion.ts +10 -12
  15. package/expression/definitions/collator.ts +8 -8
  16. package/expression/definitions/comparison.ts +0 -1
  17. package/expression/definitions/distance.ts +135 -73
  18. package/expression/definitions/format.ts +10 -13
  19. package/expression/definitions/image.ts +8 -8
  20. package/expression/definitions/index.ts +92 -90
  21. package/expression/definitions/interpolate.ts +18 -19
  22. package/expression/definitions/let.ts +1 -2
  23. package/expression/definitions/literal.ts +1 -1
  24. package/expression/definitions/match.ts +7 -8
  25. package/expression/definitions/number_format.ts +7 -8
  26. package/expression/definitions/step.ts +11 -11
  27. package/expression/definitions/within.ts +23 -24
  28. package/expression/evaluation_context.ts +4 -4
  29. package/expression/expression.ts +1 -1
  30. package/expression/index.ts +43 -21
  31. package/expression/parsing_context.ts +2 -2
  32. package/expression/stops.ts +2 -2
  33. package/expression/values.ts +2 -2
  34. package/feature_filter/index.ts +3 -3
  35. package/function/convert.ts +8 -8
  36. package/function/index.ts +4 -2
  37. package/group_by_layout.ts +6 -4
  38. package/package.json +1 -1
  39. package/read_style.ts +2 -2
  40. package/reference/v8.json +86 -5
  41. package/types/config_options.ts +1 -1
  42. package/types.ts +16 -6
  43. package/util/properties.ts +1 -1
  44. package/validate/validate.ts +15 -5
  45. package/validate/validate_appearance.ts +7 -7
  46. package/validate/validate_array.ts +7 -7
  47. package/validate/validate_enum.ts +2 -3
  48. package/validate/validate_fog.ts +2 -2
  49. package/validate/validate_function.ts +14 -13
  50. package/validate/validate_layer.ts +10 -9
  51. package/validate/validate_light.ts +2 -2
  52. package/validate/validate_lights.ts +3 -3
  53. package/validate/validate_number.ts +10 -7
  54. package/validate/validate_object.ts +11 -10
  55. package/validate/validate_option.ts +24 -9
  56. package/validate/validate_property.ts +4 -4
  57. package/validate/validate_rain.ts +1 -1
  58. package/validate/validate_snow.ts +1 -1
  59. package/validate/validate_style.ts +2 -1
  60. package/validate/validate_terrain.ts +2 -2
  61. package/validate_mapbox_api_supported.ts +5 -6
  62. package/validate_style.min.ts +2 -1
  63. package/visit.ts +11 -10
package/dist/index.es.js CHANGED
@@ -369,6 +369,16 @@ var option = {
369
369
  },
370
370
  color: {
371
371
  doc: "The result will be coerced to a color."
372
+ },
373
+ object: {
374
+ doc: "The result will be coerced to an object.",
375
+ "sdk-support": {
376
+ "basic functionality": {
377
+ js: "3.29.0",
378
+ android: "11.29.0",
379
+ ios: "11.29.0"
380
+ }
381
+ }
372
382
  }
373
383
  }
374
384
  },
@@ -3000,6 +3010,7 @@ var layout_symbol = {
3000
3010
  experimental: true,
3001
3011
  "sdk-support": {
3002
3012
  "basic functionality": {
3013
+ js: "3.7.0",
3003
3014
  android: "11.9.0",
3004
3015
  ios: "11.9.0"
3005
3016
  }
@@ -5473,13 +5484,18 @@ var expression_name = {
5473
5484
  }
5474
5485
  },
5475
5486
  distance: {
5476
- doc: "Returns the shortest distance in meters between the evaluated feature and the input geometry. The input value can be a valid GeoJSON of type `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`, `Feature`, or `FeatureCollection`. Distance values returned may vary in precision due to loss in precision from encoding geometries, particularly below zoom level 13.",
5487
+ doc: "Returns the shortest distance in meters between the evaluated feature and the input geometry. The input value can be a valid GeoJSON of type `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`, `Feature`, or `FeatureCollection`, or expression that returns a valid GeoJSON. Distance values returned may vary in precision due to loss in precision from encoding geometries, particularly below zoom level 13.",
5477
5488
  group: "Math",
5478
5489
  "sdk-support": {
5479
5490
  "basic functionality": {
5480
5491
  js: "3.0.0",
5481
5492
  android: "9.2.0",
5482
5493
  ios: "5.9.0"
5494
+ },
5495
+ "expressions support": {
5496
+ js: "3.29.0",
5497
+ android: "11.29.0",
5498
+ ios: "11.29.0"
5483
5499
  }
5484
5500
  }
5485
5501
  },
@@ -8255,6 +8271,29 @@ var paint_line = {
8255
8271
  ]
8256
8272
  },
8257
8273
  "property-type": "data-constant"
8274
+ },
8275
+ "line-cutout-depth": {
8276
+ type: "number",
8277
+ "default": 0,
8278
+ minimum: 0,
8279
+ units: "meters",
8280
+ doc: "Depth offset along the camera, in meters. When set to a non-zero value, applied cutout opacity is 0.",
8281
+ experimental: true,
8282
+ "private": true,
8283
+ transition: true,
8284
+ "sdk-support": {
8285
+ "basic functionality": {
8286
+ android: "11.29.0",
8287
+ ios: "11.29.0"
8288
+ }
8289
+ },
8290
+ expression: {
8291
+ interpolated: true,
8292
+ parameters: [
8293
+ "zoom"
8294
+ ]
8295
+ },
8296
+ "property-type": "data-constant"
8258
8297
  }
8259
8298
  };
8260
8299
  var paint_circle = {
@@ -9449,7 +9488,6 @@ var paint_symbol = {
9449
9488
  "default": 0,
9450
9489
  minimum: 0,
9451
9490
  transition: true,
9452
- experimental: true,
9453
9491
  appearance: true,
9454
9492
  "sdk-support": {
9455
9493
  "basic functionality": {
@@ -9503,7 +9541,7 @@ var paint_raster = {
9503
9541
  },
9504
9542
  "raster-color": {
9505
9543
  type: "color",
9506
- doc: "Defines a color map by which to colorize a raster layer, parameterized by the `[\"raster-value\"]` expression and evaluated at 256 uniformly spaced steps over the range specified by `raster-color-range`.",
9544
+ doc: "Defines the color ramp used to colorize a raster layer, parameterized by the `[\"raster-value\"]` expression and evaluated over the range specified by `raster-color-range`. Raster values are spaced evenly across the range by default.",
9507
9545
  "use-theme": true,
9508
9546
  transition: false,
9509
9547
  "sdk-support": {
@@ -9544,7 +9582,7 @@ var paint_raster = {
9544
9582
  "zoom"
9545
9583
  ]
9546
9584
  },
9547
- doc: "When `raster-color` is active, specifies the combination of source RGB channels used to compute the raster value. Computed using the equation `mix.r * src.r + mix.g * src.g + mix.b * src.b + mix.a`. The first three components specify the mix of source red, green, and blue channels, respectively. The fourth component serves as a constant offset and is *not* multipled by source alpha. Source alpha is instead carried through and applied as opacity to the colorized result. Default value corresponds to RGB luminosity.",
9585
+ doc: "When `raster-color` is active, specifies how the raster value is computed from a non-`rasterarray` source's channels, using the equation `mix.r * src.r + mix.g * src.g + mix.b * src.b + mix.a`. The first three components weight the source's red, green, and blue channels; the fourth is a constant offset and is not multiplied by source alpha. Source alpha is carried through and applied as opacity to the colorized result. The default corresponds to RGB luminosity. `rasterarray` sources ignore this property, as their raster value is decoded directly from the source data.",
9548
9586
  example: [
9549
9587
  0.2126,
9550
9588
  0.7152,
@@ -9574,7 +9612,7 @@ var paint_raster = {
9574
9612
  "zoom"
9575
9613
  ]
9576
9614
  },
9577
- doc: "When `raster-color` is active, specifies the range over which `raster-color` is tabulated. Units correspond to the computed raster value via `raster-color-mix`. For `rasterarray` sources, if `raster-color-range` is unspecified, the source's stated data range is used.",
9615
+ doc: "When `raster-color` is active, specifies the range of raster values mapped onto the color ramp, from the start of the ramp (low bound) to its end (high bound). For `rasterarray` sources the raster value is the decoded source data in the source's own units, and the source's stated data range is used when this property is unspecified. For other raster sources the raster value is computed from the source's channels via `raster-color-mix`. Defaults to `[0, 1]` when no range is otherwise available.",
9578
9616
  example: [
9579
9617
  0.5,
9580
9618
  10
@@ -9587,6 +9625,37 @@ var paint_raster = {
9587
9625
  }
9588
9626
  }
9589
9627
  },
9628
+ "raster-color-scale": {
9629
+ type: "enum",
9630
+ doc: "When `raster-color` is active, specifies how raster values are distributed across the color ramp over the range specified by `raster-color-range`.",
9631
+ values: {
9632
+ linear: {
9633
+ doc: "Raster values are spaced evenly across the color ramp."
9634
+ },
9635
+ log: {
9636
+ doc: "Raster values are spaced logarithmically, giving more of the color ramp to smaller values. Useful for data concentrated near the low end of a wide range."
9637
+ }
9638
+ },
9639
+ "default": "linear",
9640
+ requires: [
9641
+ "raster-color",
9642
+ {
9643
+ source: "raster-array"
9644
+ }
9645
+ ],
9646
+ expression: {
9647
+ interpolated: false,
9648
+ parameters: [
9649
+ ]
9650
+ },
9651
+ "property-type": "data-constant",
9652
+ experimental: true,
9653
+ "sdk-support": {
9654
+ "basic functionality": {
9655
+ js: "3.29.0"
9656
+ }
9657
+ }
9658
+ },
9590
9659
  "raster-hue-rotate": {
9591
9660
  type: "number",
9592
9661
  "default": 0,
@@ -9840,6 +9909,21 @@ var paint_raster = {
9840
9909
  interpolated: false
9841
9910
  },
9842
9911
  "property-type": "data-constant"
9912
+ },
9913
+ "raster-allow-draping": {
9914
+ type: "boolean",
9915
+ "default": true,
9916
+ experimental: true,
9917
+ doc: "Whether the raster layer is allowed to drape over terrain and globe. When disabled, the layer is rendered after all draped layers, which can change its position in the layer order. Disabling draping has a performance cost, since the terrain/globe geometry must be rendered again for each such layer.",
9918
+ transition: false,
9919
+ "property-type": "data-constant",
9920
+ "sdk-support": {
9921
+ "basic functionality": {
9922
+ js: "3.28.0",
9923
+ android: "11.28.0",
9924
+ ios: "11.28.0"
9925
+ }
9926
+ }
9843
9927
  }
9844
9928
  };
9845
9929
  var paint_hillshade = {
@@ -14875,6 +14959,189 @@ class TinyQueue {
14875
14959
 
14876
14960
  var EXTENT = 8192;
14877
14961
 
14962
+ const FQIDSeparator = "";
14963
+ function makeConfigFQID(id, ownScope, contextScope) {
14964
+ return [id, ownScope, contextScope].filter(Boolean).join(FQIDSeparator);
14965
+ }
14966
+ function coerceValue(type, value) {
14967
+ switch (type) {
14968
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
14969
+ case "string":
14970
+ return toString(value);
14971
+ case "number":
14972
+ return +value;
14973
+ case "boolean":
14974
+ return !!value;
14975
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
14976
+ case "color":
14977
+ return Color.parse(value);
14978
+ case "formatted": {
14979
+ return Formatted.fromString(toString(value));
14980
+ }
14981
+ case "resolvedImage": {
14982
+ return ResolvedImage.build(toString(value));
14983
+ }
14984
+ }
14985
+ return value;
14986
+ }
14987
+ function clampToAllowedNumber(value, min, max, step) {
14988
+ if (step !== void 0) {
14989
+ value = step * Math.round(value / step);
14990
+ }
14991
+ if (min !== void 0 && value < min) {
14992
+ value = min;
14993
+ }
14994
+ if (max !== void 0 && value > max) {
14995
+ value = max;
14996
+ }
14997
+ return value;
14998
+ }
14999
+ class Config {
15000
+ constructor(type, key, scope, featureConstant = false) {
15001
+ this.type = type;
15002
+ this.key = key;
15003
+ this.scope = scope;
15004
+ this.featureConstant = featureConstant;
15005
+ }
15006
+ static parse(args, context) {
15007
+ let type = context.expectedType;
15008
+ type ?? (type = ValueType);
15009
+ if (args.length < 2 || args.length > 3) {
15010
+ return context.error(`Invalid number of arguments for 'config' expression.`);
15011
+ }
15012
+ const configKey = context.parse(args[1], 1);
15013
+ if (!(configKey instanceof Literal)) {
15014
+ return context.error(`Key name of 'config' expression must be a string literal.`);
15015
+ }
15016
+ let featureConstant = true;
15017
+ let configScopeValue;
15018
+ const configKeyValue = toString(configKey.value);
15019
+ if (args.length >= 3) {
15020
+ const configScope = context.parse(args[2], 2);
15021
+ if (!(configScope instanceof Literal)) {
15022
+ return context.error(`Scope of 'config' expression must be a string literal.`);
15023
+ }
15024
+ configScopeValue = toString(configScope.value);
15025
+ }
15026
+ if (context.options) {
15027
+ const fqid = makeConfigFQID(configKeyValue, configScopeValue, context._scope);
15028
+ const config = context.options.get(fqid);
15029
+ if (config) {
15030
+ featureConstant = isFeatureConstant(config.value || config.default);
15031
+ }
15032
+ }
15033
+ return new Config(type, configKeyValue, configScopeValue, featureConstant);
15034
+ }
15035
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15036
+ evaluate(ctx) {
15037
+ const fqid = makeConfigFQID(this.key, this.scope, ctx.scope);
15038
+ const config = ctx.getConfig(fqid);
15039
+ if (!config) return null;
15040
+ const { type, value, values, minValue, maxValue, stepValue } = config;
15041
+ const defaultValue = config.default.evaluate(ctx);
15042
+ let result = defaultValue;
15043
+ if (value) {
15044
+ const originalScope = ctx.scope;
15045
+ ctx.scope = (originalScope || "").split(FQIDSeparator).slice(1).join(FQIDSeparator);
15046
+ result = value.evaluate(ctx);
15047
+ ctx.scope = originalScope;
15048
+ }
15049
+ if (type) {
15050
+ result = coerceValue(type, result);
15051
+ }
15052
+ if (result !== void 0 && (minValue !== void 0 || maxValue !== void 0 || stepValue !== void 0)) {
15053
+ if (typeof result === "number") {
15054
+ result = clampToAllowedNumber(result, minValue, maxValue, stepValue);
15055
+ } else if (Array.isArray(result)) {
15056
+ result = result.map((item) => typeof item === "number" ? clampToAllowedNumber(item, minValue, maxValue, stepValue) : item);
15057
+ }
15058
+ }
15059
+ if (value !== void 0 && result !== void 0 && values && !values.includes(result)) {
15060
+ result = defaultValue;
15061
+ if (type) {
15062
+ result = coerceValue(type, result);
15063
+ }
15064
+ }
15065
+ if (type && type !== this.type || result !== void 0 && !typeEquals(typeOf(result), this.type)) {
15066
+ result = coerceValue(this.type.kind, result);
15067
+ }
15068
+ return result;
15069
+ }
15070
+ eachChild() {
15071
+ }
15072
+ outputDefined() {
15073
+ return false;
15074
+ }
15075
+ serialize() {
15076
+ const res = ["config", this.key];
15077
+ if (this.scope) {
15078
+ res.concat(this.scope);
15079
+ }
15080
+ return res;
15081
+ }
15082
+ }
15083
+
15084
+ function isFeatureConstant(e) {
15085
+ if (e instanceof CompoundExpression) {
15086
+ if (e.name === "get" && e.args.length === 1) {
15087
+ return false;
15088
+ } else if (e.name === "feature-state") {
15089
+ return false;
15090
+ } else if (e.name === "has" && e.args.length === 1) {
15091
+ return false;
15092
+ } else if (e.name === "properties" || e.name === "geometry-type" || e.name === "id") {
15093
+ return false;
15094
+ } else if (e.name.startsWith("filter-")) {
15095
+ return false;
15096
+ }
15097
+ }
15098
+ if (e instanceof Within) {
15099
+ return false;
15100
+ }
15101
+ if (e instanceof Distance) {
15102
+ return false;
15103
+ }
15104
+ if (e instanceof Config) {
15105
+ return e.featureConstant;
15106
+ }
15107
+ let result = true;
15108
+ e.eachChild((arg) => {
15109
+ if (result && !isFeatureConstant(arg)) {
15110
+ result = false;
15111
+ }
15112
+ });
15113
+ return result;
15114
+ }
15115
+ function isStateConstant(e) {
15116
+ if (e instanceof CompoundExpression) {
15117
+ if (e.name === "feature-state") {
15118
+ return false;
15119
+ }
15120
+ }
15121
+ let result = true;
15122
+ e.eachChild((arg) => {
15123
+ if (result && !isStateConstant(arg)) {
15124
+ result = false;
15125
+ }
15126
+ });
15127
+ return result;
15128
+ }
15129
+ function isGlobalPropertyConstantSet(e, properties) {
15130
+ if (e instanceof CompoundExpression && properties.has(e.name)) {
15131
+ return false;
15132
+ }
15133
+ let result = true;
15134
+ e.eachChild((arg) => {
15135
+ if (result && !isGlobalPropertyConstantSet(arg, properties)) {
15136
+ result = false;
15137
+ }
15138
+ });
15139
+ return result;
15140
+ }
15141
+ function isGlobalPropertyConstant(e, properties) {
15142
+ return isGlobalPropertyConstantSet(e, new Set(properties));
15143
+ }
15144
+
14878
15145
  const RE = 6378.137;
14879
15146
  const FE = 1 / 298.257223563;
14880
15147
  const E2 = FE * (2 - FE);
@@ -15410,245 +15677,94 @@ function polygonsToGeometryDistance(originGeometry, canonical, geometry) {
15410
15677
  function isTypeValid(type) {
15411
15678
  return type === "Point" || type === "MultiPoint" || type === "LineString" || type === "MultiLineString" || type === "Polygon" || type === "MultiPolygon";
15412
15679
  }
15413
- class Distance {
15414
- constructor(geojson, geometries) {
15415
- this.type = NumberType;
15416
- this.geojson = geojson;
15417
- this.geometries = geometries;
15418
- }
15419
- static parse(args, context) {
15420
- if (args.length !== 2) {
15421
- return context.error(`'distance' expression requires either one argument, but found ' ${args.length - 1} instead.`);
15422
- }
15423
- if (isValue(args[1])) {
15424
- const geojson = args[1];
15425
- if (geojson.type === "FeatureCollection") {
15426
- for (let i = 0; i < geojson.features.length; ++i) {
15427
- if (isTypeValid(geojson.features[i].geometry.type)) {
15428
- return new Distance(geojson, geojson.features[i].geometry);
15429
- }
15430
- }
15431
- } else if (geojson.type === "Feature") {
15432
- if (isTypeValid(geojson.geometry.type)) {
15433
- return new Distance(geojson, geojson.geometry);
15434
- }
15435
- } else if (isTypeValid(geojson.type)) {
15436
- return new Distance(geojson, geojson);
15437
- }
15438
- }
15439
- return context.error(
15440
- "'distance' expression needs to be an array with format ['Distance', GeoJSONObj]."
15441
- );
15442
- }
15443
- evaluate(ctx) {
15444
- const geometry = ctx.geometry();
15445
- const canonical = ctx.canonicalID();
15446
- if (geometry != null && canonical != null) {
15447
- if (ctx.geometryType() === "Point") {
15448
- return pointsToGeometryDistance(geometry, canonical, this.geometries);
15449
- }
15450
- if (ctx.geometryType() === "LineString") {
15451
- return linesToGeometryDistance(geometry, canonical, this.geometries);
15452
- }
15453
- if (ctx.geometryType() === "Polygon") {
15454
- return polygonsToGeometryDistance(geometry, canonical, this.geometries);
15455
- }
15456
- console.warn("Distance Expression: currently only evaluates valid Point/LineString/Polygon geometries.");
15457
- } else {
15458
- console.warn("Distance Expression: requires valid feature and canonical information.");
15459
- }
15680
+ function extractDistanceGeometry(value) {
15681
+ if (!isValue(value) || typeof value !== "object" || value === null || Array.isArray(value)) {
15460
15682
  return null;
15461
15683
  }
15462
- eachChild() {
15463
- }
15464
- outputDefined() {
15465
- return true;
15466
- }
15467
- serialize() {
15468
- return ["distance", this.geojson];
15469
- }
15470
- }
15471
-
15472
- function isFeatureConstant(e) {
15473
- if (e instanceof CompoundExpression) {
15474
- if (e.name === "get" && e.args.length === 1) {
15475
- return false;
15476
- } else if (e.name === "feature-state") {
15477
- return false;
15478
- } else if (e.name === "has" && e.args.length === 1) {
15479
- return false;
15480
- } else if (e.name === "properties" || e.name === "geometry-type" || e.name === "id") {
15481
- return false;
15482
- } else if (e.name.startsWith("filter-")) {
15483
- return false;
15484
- }
15485
- }
15486
- if (e instanceof Within) {
15487
- return false;
15488
- }
15489
- if (e instanceof Distance) {
15490
- return false;
15491
- }
15492
- if (e instanceof Config) {
15493
- return e.featureConstant;
15494
- }
15495
- let result = true;
15496
- e.eachChild((arg) => {
15497
- if (result && !isFeatureConstant(arg)) {
15498
- result = false;
15499
- }
15500
- });
15501
- return result;
15502
- }
15503
- function isStateConstant(e) {
15504
- if (e instanceof CompoundExpression) {
15505
- if (e.name === "feature-state") {
15506
- return false;
15507
- }
15508
- }
15509
- let result = true;
15510
- e.eachChild((arg) => {
15511
- if (result && !isStateConstant(arg)) {
15512
- result = false;
15513
- }
15514
- });
15515
- return result;
15516
- }
15517
- function isGlobalPropertyConstantSet(e, properties) {
15518
- if (e instanceof CompoundExpression && properties.has(e.name)) {
15519
- return false;
15520
- }
15521
- let result = true;
15522
- e.eachChild((arg) => {
15523
- if (result && !isGlobalPropertyConstantSet(arg, properties)) {
15524
- result = false;
15525
- }
15526
- });
15527
- return result;
15528
- }
15529
- function isGlobalPropertyConstant(e, properties) {
15530
- return isGlobalPropertyConstantSet(e, new Set(properties));
15531
- }
15532
-
15533
- const FQIDSeparator = "";
15534
- function makeConfigFQID(id, ownScope, contextScope) {
15535
- return [id, ownScope, contextScope].filter(Boolean).join(FQIDSeparator);
15536
- }
15537
- function coerceValue(type, value) {
15538
- switch (type) {
15539
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
15540
- case "string":
15541
- return toString(value);
15542
- case "number":
15543
- return +value;
15544
- case "boolean":
15545
- return !!value;
15546
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
15547
- case "color":
15548
- return Color.parse(value);
15549
- case "formatted": {
15550
- return Formatted.fromString(toString(value));
15684
+ const geojson = value;
15685
+ if (geojson.type === "FeatureCollection") {
15686
+ if (geojson.features.length === 0) return null;
15687
+ const geometries = [];
15688
+ for (const feature of geojson.features) {
15689
+ if (!isTypeValid(feature.geometry.type)) return null;
15690
+ geometries.push(feature.geometry);
15551
15691
  }
15552
- case "resolvedImage": {
15553
- return ResolvedImage.build(toString(value));
15554
- }
15555
- }
15556
- return value;
15557
- }
15558
- function clampToAllowedNumber(value, min, max, step) {
15559
- if (step !== void 0) {
15560
- value = step * Math.round(value / step);
15692
+ return geometries;
15561
15693
  }
15562
- if (min !== void 0 && value < min) {
15563
- value = min;
15694
+ if (geojson.type === "Feature") {
15695
+ return isTypeValid(geojson.geometry.type) ? [geojson.geometry] : null;
15564
15696
  }
15565
- if (max !== void 0 && value > max) {
15566
- value = max;
15697
+ if (isTypeValid(geojson.type)) {
15698
+ return [geojson];
15567
15699
  }
15568
- return value;
15700
+ return null;
15569
15701
  }
15570
- class Config {
15571
- constructor(type, key, scope, featureConstant = false) {
15572
- this.type = type;
15573
- this.key = key;
15574
- this.scope = scope;
15575
- this.featureConstant = featureConstant;
15702
+ class Distance {
15703
+ constructor(geojson) {
15704
+ this.type = NumberType;
15705
+ this.geojson = geojson;
15576
15706
  }
15577
15707
  static parse(args, context) {
15578
- let type = context.expectedType;
15579
- type ?? (type = ValueType);
15580
- if (args.length < 2 || args.length > 3) {
15581
- return context.error(`Invalid number of arguments for 'config' expression.`);
15582
- }
15583
- const configKey = context.parse(args[1], 1);
15584
- if (!(configKey instanceof Literal)) {
15585
- return context.error(`Key name of 'config' expression must be a string literal.`);
15708
+ if (args.length !== 2) {
15709
+ return context.error(`'distance' expression requires either one argument, but found ' ${args.length - 1} instead.`);
15586
15710
  }
15587
- let featureConstant = true;
15588
- let configScopeValue;
15589
- const configKeyValue = toString(configKey.value);
15590
- if (args.length >= 3) {
15591
- const configScope = context.parse(args[2], 2);
15592
- if (!(configScope instanceof Literal)) {
15593
- return context.error(`Scope of 'config' expression must be a string literal.`);
15711
+ const arg = args[1];
15712
+ const isBareGeoJSON = isValue(arg) && !Array.isArray(arg);
15713
+ const parsed = context.parse(isBareGeoJSON ? ["literal", arg] : arg, 1, ValueType);
15714
+ if (!parsed) return null;
15715
+ for (const [globalProperties, name] of [
15716
+ [["measure-light"], "brightness"],
15717
+ [["pitch"], "pitch"],
15718
+ [["distance-from-center"], "distance-from-center"]
15719
+ ]) {
15720
+ if (!isGlobalPropertyConstant(parsed, globalProperties)) {
15721
+ return context.error(`'distance' expression may not depend on ${name}.`);
15594
15722
  }
15595
- configScopeValue = toString(configScope.value);
15596
15723
  }
15597
- if (context.options) {
15598
- const fqid = makeConfigFQID(configKeyValue, configScopeValue, context._scope);
15599
- const config = context.options.get(fqid);
15600
- if (config) {
15601
- featureConstant = isFeatureConstant(config.value || config.default);
15602
- }
15724
+ if (!isStateConstant(parsed)) {
15725
+ return context.error(`'distance' expression may not depend on feature-state.`);
15603
15726
  }
15604
- return new Config(type, configKeyValue, configScopeValue, featureConstant);
15727
+ if (parsed instanceof Literal && !extractDistanceGeometry(parsed.value)) {
15728
+ return context.error(
15729
+ "'distance' expression needs to be an array with format ['Distance', GeoJSONObj]."
15730
+ );
15731
+ }
15732
+ return new Distance(parsed);
15605
15733
  }
15606
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15607
15734
  evaluate(ctx) {
15608
- const fqid = makeConfigFQID(this.key, this.scope, ctx.scope);
15609
- const config = ctx.getConfig(fqid);
15610
- if (!config) return null;
15611
- const { type, value, values, minValue, maxValue, stepValue } = config;
15612
- const defaultValue = config.default.evaluate(ctx);
15613
- let result = defaultValue;
15614
- if (value) {
15615
- const originalScope = ctx.scope;
15616
- ctx.scope = (originalScope || "").split(FQIDSeparator).slice(1).join(FQIDSeparator);
15617
- result = value.evaluate(ctx);
15618
- ctx.scope = originalScope;
15619
- }
15620
- if (type) {
15621
- result = coerceValue(type, result);
15735
+ const geometries = extractDistanceGeometry(this.geojson.evaluate(ctx));
15736
+ if (!geometries) {
15737
+ console.warn("Distance Expression: could not resolve a valid Point/LineString/Polygon GeoJSON geometry.");
15738
+ return null;
15622
15739
  }
15623
- if (result !== void 0 && (minValue !== void 0 || maxValue !== void 0 || stepValue !== void 0)) {
15624
- if (typeof result === "number") {
15625
- result = clampToAllowedNumber(result, minValue, maxValue, stepValue);
15626
- } else if (Array.isArray(result)) {
15627
- result = result.map((item) => typeof item === "number" ? clampToAllowedNumber(item, minValue, maxValue, stepValue) : item);
15628
- }
15740
+ const geometry = ctx.geometry();
15741
+ const canonical = ctx.canonicalID();
15742
+ if (geometry == null || canonical == null) {
15743
+ console.warn("Distance Expression: requires valid feature and canonical information.");
15744
+ return null;
15629
15745
  }
15630
- if (value !== void 0 && result !== void 0 && values && !values.includes(result)) {
15631
- result = defaultValue;
15632
- if (type) {
15633
- result = coerceValue(type, result);
15634
- }
15746
+ const geometryType = ctx.geometryType();
15747
+ const distanceTo = geometryType === "Point" ? pointsToGeometryDistance : geometryType === "LineString" ? linesToGeometryDistance : geometryType === "Polygon" ? polygonsToGeometryDistance : null;
15748
+ if (!distanceTo) {
15749
+ console.warn("Distance Expression: currently only evaluates valid Point/LineString/Polygon geometries.");
15750
+ return null;
15635
15751
  }
15636
- if (type && type !== this.type || result !== void 0 && !typeEquals(typeOf(result), this.type)) {
15637
- result = coerceValue(this.type.kind, result);
15752
+ let dist = Infinity;
15753
+ for (const g of geometries) {
15754
+ const tempDist = distanceTo(geometry, canonical, g);
15755
+ if (tempDist == null || isNaN(tempDist)) return tempDist;
15756
+ if ((dist = Math.min(dist, tempDist)) === 0) break;
15638
15757
  }
15639
- return result;
15758
+ return dist;
15640
15759
  }
15641
- eachChild() {
15760
+ eachChild(fn) {
15761
+ fn(this.geojson);
15642
15762
  }
15643
15763
  outputDefined() {
15644
- return false;
15764
+ return true;
15645
15765
  }
15646
15766
  serialize() {
15647
- const res = ["config", this.key];
15648
- if (this.scope) {
15649
- res.concat(this.scope);
15650
- }
15651
- return res;
15767
+ return ["distance", this.geojson.serialize()];
15652
15768
  }
15653
15769
  }
15654
15770
 
@@ -17886,7 +18002,7 @@ function createFunction(parameters, propertySpec) {
17886
18002
  kind: "composite",
17887
18003
  interpolationType,
17888
18004
  interpolationFactor: Interpolate.interpolationFactor.bind(void 0, interpolationType),
17889
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
18005
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
17890
18006
  zoomStops: featureFunctionStops.map((s) => s[0]),
17891
18007
  evaluate({ zoom }, properties) {
17892
18008
  return evaluateExponentialFunction({
@@ -18017,15 +18133,16 @@ class StyleExpression {
18017
18133
  this.isIndoorDependent = isIndoorDependent(expression);
18018
18134
  }
18019
18135
  evaluateWithoutErrorHandling(globals, feature, featureState, canonical, availableImages, formattedSection, featureTileCoord, featureDistanceData) {
18020
- this._evaluator.globals = globals;
18021
- this._evaluator.feature = feature;
18022
- this._evaluator.featureState = featureState;
18023
- this._evaluator.canonical = canonical || null;
18024
- this._evaluator.availableImages = availableImages || null;
18025
- this._evaluator.formattedSection = formattedSection;
18026
- this._evaluator.featureTileCoord = featureTileCoord || null;
18027
- this._evaluator.featureDistanceData = featureDistanceData || null;
18028
- return this.expression.evaluate(this._evaluator);
18136
+ const evaluator = this._evaluator;
18137
+ evaluator.globals = globals;
18138
+ evaluator.feature = feature;
18139
+ evaluator.featureState = featureState;
18140
+ evaluator.canonical = canonical || null;
18141
+ evaluator.availableImages = availableImages || null;
18142
+ evaluator.formattedSection = formattedSection;
18143
+ evaluator.featureTileCoord = featureTileCoord || null;
18144
+ evaluator.featureDistanceData = featureDistanceData || null;
18145
+ return this.expression.evaluate(evaluator);
18029
18146
  }
18030
18147
  evaluate(globals, feature, featureState, canonical, availableImages, formattedSection, featureTileCoord, featureDistanceData, iconImageUseTheme) {
18031
18148
  if (!this._evaluator) {
@@ -18243,7 +18360,8 @@ function getExpectedType(spec) {
18243
18360
  enum: StringType,
18244
18361
  boolean: BooleanType,
18245
18362
  formatted: FormattedType,
18246
- resolvedImage: ResolvedImageType
18363
+ resolvedImage: ResolvedImageType,
18364
+ object: ObjectType
18247
18365
  };
18248
18366
  if (spec.type === "array") {
18249
18367
  return array$1(types[spec.value] || ValueType, spec.length);
@@ -19507,17 +19625,23 @@ function validateOption(options) {
19507
19625
  const optionValue = options.value;
19508
19626
  const isArrayOption = isObject(optionValue) && unbundle(optionValue.array) === true;
19509
19627
  const declaredType = !isArrayOption && isObject(optionValue) ? unbundle(optionValue.type) : void 0;
19628
+ const validateDefault = (elementOptions) => {
19629
+ const defaultValue = elementOptions.value;
19630
+ if (isObject(defaultValue)) {
19631
+ return validate({ ...elementOptions, valueSpec: { ...elementOptions.valueSpec, type: "*", expression: void 0 } });
19632
+ }
19633
+ if (declaredType && Array.isArray(defaultValue)) {
19634
+ return validate({ ...elementOptions, valueSpec: { ...elementOptions.valueSpec, type: declaredType } });
19635
+ }
19636
+ return validate(elementOptions);
19637
+ };
19510
19638
  return validateObject({
19511
19639
  ...options,
19512
19640
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
19513
19641
  valueSpec: styleSpec.option,
19514
- objectElementValidators: declaredType ? {
19515
- // Only propagate the declared type when the default is an
19516
- // expression (array-form). Primitive defaults keep the previous
19517
- // permissive validation, mirroring the runtime parser's narrowing
19518
- // in style.ts/parser.cpp.
19519
- default: (elementOptions) => Array.isArray(elementOptions.value) ? validate({ ...elementOptions, valueSpec: { ...elementOptions.valueSpec, type: declaredType } }) : validate(elementOptions)
19520
- } : void 0
19642
+ objectElementValidators: {
19643
+ default: validateDefault
19644
+ }
19521
19645
  });
19522
19646
  }
19523
19647