@mapbox/mapbox-gl-style-spec 14.28.0 → 14.29.0-rc.1

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 +339 -238
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +75 -13
  6. package/dist/index.es.js +339 -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 +63 -5
  41. package/types/config_options.ts +1 -1
  42. package/types.ts +10 -5
  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
  },
@@ -9449,7 +9465,6 @@ var paint_symbol = {
9449
9465
  "default": 0,
9450
9466
  minimum: 0,
9451
9467
  transition: true,
9452
- experimental: true,
9453
9468
  appearance: true,
9454
9469
  "sdk-support": {
9455
9470
  "basic functionality": {
@@ -9503,7 +9518,7 @@ var paint_raster = {
9503
9518
  },
9504
9519
  "raster-color": {
9505
9520
  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`.",
9521
+ 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
9522
  "use-theme": true,
9508
9523
  transition: false,
9509
9524
  "sdk-support": {
@@ -9544,7 +9559,7 @@ var paint_raster = {
9544
9559
  "zoom"
9545
9560
  ]
9546
9561
  },
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.",
9562
+ 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
9563
  example: [
9549
9564
  0.2126,
9550
9565
  0.7152,
@@ -9574,7 +9589,7 @@ var paint_raster = {
9574
9589
  "zoom"
9575
9590
  ]
9576
9591
  },
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.",
9592
+ 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
9593
  example: [
9579
9594
  0.5,
9580
9595
  10
@@ -9587,6 +9602,37 @@ var paint_raster = {
9587
9602
  }
9588
9603
  }
9589
9604
  },
9605
+ "raster-color-scale": {
9606
+ type: "enum",
9607
+ doc: "When `raster-color` is active, specifies how raster values are distributed across the color ramp over the range specified by `raster-color-range`.",
9608
+ values: {
9609
+ linear: {
9610
+ doc: "Raster values are spaced evenly across the color ramp."
9611
+ },
9612
+ log: {
9613
+ 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."
9614
+ }
9615
+ },
9616
+ "default": "linear",
9617
+ requires: [
9618
+ "raster-color",
9619
+ {
9620
+ source: "raster-array"
9621
+ }
9622
+ ],
9623
+ expression: {
9624
+ interpolated: false,
9625
+ parameters: [
9626
+ ]
9627
+ },
9628
+ "property-type": "data-constant",
9629
+ experimental: true,
9630
+ "sdk-support": {
9631
+ "basic functionality": {
9632
+ js: "3.29.0"
9633
+ }
9634
+ }
9635
+ },
9590
9636
  "raster-hue-rotate": {
9591
9637
  type: "number",
9592
9638
  "default": 0,
@@ -9840,6 +9886,21 @@ var paint_raster = {
9840
9886
  interpolated: false
9841
9887
  },
9842
9888
  "property-type": "data-constant"
9889
+ },
9890
+ "raster-allow-draping": {
9891
+ type: "boolean",
9892
+ "default": true,
9893
+ experimental: true,
9894
+ 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.",
9895
+ transition: false,
9896
+ "property-type": "data-constant",
9897
+ "sdk-support": {
9898
+ "basic functionality": {
9899
+ js: "3.28.0",
9900
+ android: "11.28.0",
9901
+ ios: "11.28.0"
9902
+ }
9903
+ }
9843
9904
  }
9844
9905
  };
9845
9906
  var paint_hillshade = {
@@ -14875,6 +14936,189 @@ class TinyQueue {
14875
14936
 
14876
14937
  var EXTENT = 8192;
14877
14938
 
14939
+ const FQIDSeparator = "";
14940
+ function makeConfigFQID(id, ownScope, contextScope) {
14941
+ return [id, ownScope, contextScope].filter(Boolean).join(FQIDSeparator);
14942
+ }
14943
+ function coerceValue(type, value) {
14944
+ switch (type) {
14945
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
14946
+ case "string":
14947
+ return toString(value);
14948
+ case "number":
14949
+ return +value;
14950
+ case "boolean":
14951
+ return !!value;
14952
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
14953
+ case "color":
14954
+ return Color.parse(value);
14955
+ case "formatted": {
14956
+ return Formatted.fromString(toString(value));
14957
+ }
14958
+ case "resolvedImage": {
14959
+ return ResolvedImage.build(toString(value));
14960
+ }
14961
+ }
14962
+ return value;
14963
+ }
14964
+ function clampToAllowedNumber(value, min, max, step) {
14965
+ if (step !== void 0) {
14966
+ value = step * Math.round(value / step);
14967
+ }
14968
+ if (min !== void 0 && value < min) {
14969
+ value = min;
14970
+ }
14971
+ if (max !== void 0 && value > max) {
14972
+ value = max;
14973
+ }
14974
+ return value;
14975
+ }
14976
+ class Config {
14977
+ constructor(type, key, scope, featureConstant = false) {
14978
+ this.type = type;
14979
+ this.key = key;
14980
+ this.scope = scope;
14981
+ this.featureConstant = featureConstant;
14982
+ }
14983
+ static parse(args, context) {
14984
+ let type = context.expectedType;
14985
+ type ?? (type = ValueType);
14986
+ if (args.length < 2 || args.length > 3) {
14987
+ return context.error(`Invalid number of arguments for 'config' expression.`);
14988
+ }
14989
+ const configKey = context.parse(args[1], 1);
14990
+ if (!(configKey instanceof Literal)) {
14991
+ return context.error(`Key name of 'config' expression must be a string literal.`);
14992
+ }
14993
+ let featureConstant = true;
14994
+ let configScopeValue;
14995
+ const configKeyValue = toString(configKey.value);
14996
+ if (args.length >= 3) {
14997
+ const configScope = context.parse(args[2], 2);
14998
+ if (!(configScope instanceof Literal)) {
14999
+ return context.error(`Scope of 'config' expression must be a string literal.`);
15000
+ }
15001
+ configScopeValue = toString(configScope.value);
15002
+ }
15003
+ if (context.options) {
15004
+ const fqid = makeConfigFQID(configKeyValue, configScopeValue, context._scope);
15005
+ const config = context.options.get(fqid);
15006
+ if (config) {
15007
+ featureConstant = isFeatureConstant(config.value || config.default);
15008
+ }
15009
+ }
15010
+ return new Config(type, configKeyValue, configScopeValue, featureConstant);
15011
+ }
15012
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15013
+ evaluate(ctx) {
15014
+ const fqid = makeConfigFQID(this.key, this.scope, ctx.scope);
15015
+ const config = ctx.getConfig(fqid);
15016
+ if (!config) return null;
15017
+ const { type, value, values, minValue, maxValue, stepValue } = config;
15018
+ const defaultValue = config.default.evaluate(ctx);
15019
+ let result = defaultValue;
15020
+ if (value) {
15021
+ const originalScope = ctx.scope;
15022
+ ctx.scope = (originalScope || "").split(FQIDSeparator).slice(1).join(FQIDSeparator);
15023
+ result = value.evaluate(ctx);
15024
+ ctx.scope = originalScope;
15025
+ }
15026
+ if (type) {
15027
+ result = coerceValue(type, result);
15028
+ }
15029
+ if (result !== void 0 && (minValue !== void 0 || maxValue !== void 0 || stepValue !== void 0)) {
15030
+ if (typeof result === "number") {
15031
+ result = clampToAllowedNumber(result, minValue, maxValue, stepValue);
15032
+ } else if (Array.isArray(result)) {
15033
+ result = result.map((item) => typeof item === "number" ? clampToAllowedNumber(item, minValue, maxValue, stepValue) : item);
15034
+ }
15035
+ }
15036
+ if (value !== void 0 && result !== void 0 && values && !values.includes(result)) {
15037
+ result = defaultValue;
15038
+ if (type) {
15039
+ result = coerceValue(type, result);
15040
+ }
15041
+ }
15042
+ if (type && type !== this.type || result !== void 0 && !typeEquals(typeOf(result), this.type)) {
15043
+ result = coerceValue(this.type.kind, result);
15044
+ }
15045
+ return result;
15046
+ }
15047
+ eachChild() {
15048
+ }
15049
+ outputDefined() {
15050
+ return false;
15051
+ }
15052
+ serialize() {
15053
+ const res = ["config", this.key];
15054
+ if (this.scope) {
15055
+ res.concat(this.scope);
15056
+ }
15057
+ return res;
15058
+ }
15059
+ }
15060
+
15061
+ function isFeatureConstant(e) {
15062
+ if (e instanceof CompoundExpression) {
15063
+ if (e.name === "get" && e.args.length === 1) {
15064
+ return false;
15065
+ } else if (e.name === "feature-state") {
15066
+ return false;
15067
+ } else if (e.name === "has" && e.args.length === 1) {
15068
+ return false;
15069
+ } else if (e.name === "properties" || e.name === "geometry-type" || e.name === "id") {
15070
+ return false;
15071
+ } else if (e.name.startsWith("filter-")) {
15072
+ return false;
15073
+ }
15074
+ }
15075
+ if (e instanceof Within) {
15076
+ return false;
15077
+ }
15078
+ if (e instanceof Distance) {
15079
+ return false;
15080
+ }
15081
+ if (e instanceof Config) {
15082
+ return e.featureConstant;
15083
+ }
15084
+ let result = true;
15085
+ e.eachChild((arg) => {
15086
+ if (result && !isFeatureConstant(arg)) {
15087
+ result = false;
15088
+ }
15089
+ });
15090
+ return result;
15091
+ }
15092
+ function isStateConstant(e) {
15093
+ if (e instanceof CompoundExpression) {
15094
+ if (e.name === "feature-state") {
15095
+ return false;
15096
+ }
15097
+ }
15098
+ let result = true;
15099
+ e.eachChild((arg) => {
15100
+ if (result && !isStateConstant(arg)) {
15101
+ result = false;
15102
+ }
15103
+ });
15104
+ return result;
15105
+ }
15106
+ function isGlobalPropertyConstantSet(e, properties) {
15107
+ if (e instanceof CompoundExpression && properties.has(e.name)) {
15108
+ return false;
15109
+ }
15110
+ let result = true;
15111
+ e.eachChild((arg) => {
15112
+ if (result && !isGlobalPropertyConstantSet(arg, properties)) {
15113
+ result = false;
15114
+ }
15115
+ });
15116
+ return result;
15117
+ }
15118
+ function isGlobalPropertyConstant(e, properties) {
15119
+ return isGlobalPropertyConstantSet(e, new Set(properties));
15120
+ }
15121
+
14878
15122
  const RE = 6378.137;
14879
15123
  const FE = 1 / 298.257223563;
14880
15124
  const E2 = FE * (2 - FE);
@@ -15410,245 +15654,94 @@ function polygonsToGeometryDistance(originGeometry, canonical, geometry) {
15410
15654
  function isTypeValid(type) {
15411
15655
  return type === "Point" || type === "MultiPoint" || type === "LineString" || type === "MultiLineString" || type === "Polygon" || type === "MultiPolygon";
15412
15656
  }
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
- }
15657
+ function extractDistanceGeometry(value) {
15658
+ if (!isValue(value) || typeof value !== "object" || value === null || Array.isArray(value)) {
15460
15659
  return null;
15461
15660
  }
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;
15661
+ const geojson = value;
15662
+ if (geojson.type === "FeatureCollection") {
15663
+ if (geojson.features.length === 0) return null;
15664
+ const geometries = [];
15665
+ for (const feature of geojson.features) {
15666
+ if (!isTypeValid(feature.geometry.type)) return null;
15667
+ geometries.push(feature.geometry);
15484
15668
  }
15669
+ return geometries;
15485
15670
  }
15486
- if (e instanceof Within) {
15487
- return false;
15671
+ if (geojson.type === "Feature") {
15672
+ return isTypeValid(geojson.geometry.type) ? [geojson.geometry] : null;
15488
15673
  }
15489
- if (e instanceof Distance) {
15490
- return false;
15674
+ if (isTypeValid(geojson.type)) {
15675
+ return [geojson];
15491
15676
  }
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));
15551
- }
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);
15561
- }
15562
- if (min !== void 0 && value < min) {
15563
- value = min;
15564
- }
15565
- if (max !== void 0 && value > max) {
15566
- value = max;
15567
- }
15568
- return value;
15677
+ return null;
15569
15678
  }
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;
15679
+ class Distance {
15680
+ constructor(geojson) {
15681
+ this.type = NumberType;
15682
+ this.geojson = geojson;
15576
15683
  }
15577
15684
  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.`);
15685
+ if (args.length !== 2) {
15686
+ return context.error(`'distance' expression requires either one argument, but found ' ${args.length - 1} instead.`);
15586
15687
  }
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.`);
15688
+ const arg = args[1];
15689
+ const isBareGeoJSON = isValue(arg) && !Array.isArray(arg);
15690
+ const parsed = context.parse(isBareGeoJSON ? ["literal", arg] : arg, 1, ValueType);
15691
+ if (!parsed) return null;
15692
+ for (const [globalProperties, name] of [
15693
+ [["measure-light"], "brightness"],
15694
+ [["pitch"], "pitch"],
15695
+ [["distance-from-center"], "distance-from-center"]
15696
+ ]) {
15697
+ if (!isGlobalPropertyConstant(parsed, globalProperties)) {
15698
+ return context.error(`'distance' expression may not depend on ${name}.`);
15594
15699
  }
15595
- configScopeValue = toString(configScope.value);
15596
15700
  }
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
- }
15701
+ if (!isStateConstant(parsed)) {
15702
+ return context.error(`'distance' expression may not depend on feature-state.`);
15603
15703
  }
15604
- return new Config(type, configKeyValue, configScopeValue, featureConstant);
15704
+ if (parsed instanceof Literal && !extractDistanceGeometry(parsed.value)) {
15705
+ return context.error(
15706
+ "'distance' expression needs to be an array with format ['Distance', GeoJSONObj]."
15707
+ );
15708
+ }
15709
+ return new Distance(parsed);
15605
15710
  }
15606
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15607
15711
  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);
15712
+ const geometries = extractDistanceGeometry(this.geojson.evaluate(ctx));
15713
+ if (!geometries) {
15714
+ console.warn("Distance Expression: could not resolve a valid Point/LineString/Polygon GeoJSON geometry.");
15715
+ return null;
15622
15716
  }
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
- }
15717
+ const geometry = ctx.geometry();
15718
+ const canonical = ctx.canonicalID();
15719
+ if (geometry == null || canonical == null) {
15720
+ console.warn("Distance Expression: requires valid feature and canonical information.");
15721
+ return null;
15629
15722
  }
15630
- if (value !== void 0 && result !== void 0 && values && !values.includes(result)) {
15631
- result = defaultValue;
15632
- if (type) {
15633
- result = coerceValue(type, result);
15634
- }
15723
+ const geometryType = ctx.geometryType();
15724
+ const distanceTo = geometryType === "Point" ? pointsToGeometryDistance : geometryType === "LineString" ? linesToGeometryDistance : geometryType === "Polygon" ? polygonsToGeometryDistance : null;
15725
+ if (!distanceTo) {
15726
+ console.warn("Distance Expression: currently only evaluates valid Point/LineString/Polygon geometries.");
15727
+ return null;
15635
15728
  }
15636
- if (type && type !== this.type || result !== void 0 && !typeEquals(typeOf(result), this.type)) {
15637
- result = coerceValue(this.type.kind, result);
15729
+ let dist = Infinity;
15730
+ for (const g of geometries) {
15731
+ const tempDist = distanceTo(geometry, canonical, g);
15732
+ if (tempDist == null || isNaN(tempDist)) return tempDist;
15733
+ if ((dist = Math.min(dist, tempDist)) === 0) break;
15638
15734
  }
15639
- return result;
15735
+ return dist;
15640
15736
  }
15641
- eachChild() {
15737
+ eachChild(fn) {
15738
+ fn(this.geojson);
15642
15739
  }
15643
15740
  outputDefined() {
15644
- return false;
15741
+ return true;
15645
15742
  }
15646
15743
  serialize() {
15647
- const res = ["config", this.key];
15648
- if (this.scope) {
15649
- res.concat(this.scope);
15650
- }
15651
- return res;
15744
+ return ["distance", this.geojson.serialize()];
15652
15745
  }
15653
15746
  }
15654
15747
 
@@ -17886,7 +17979,7 @@ function createFunction(parameters, propertySpec) {
17886
17979
  kind: "composite",
17887
17980
  interpolationType,
17888
17981
  interpolationFactor: Interpolate.interpolationFactor.bind(void 0, interpolationType),
17889
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
17982
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
17890
17983
  zoomStops: featureFunctionStops.map((s) => s[0]),
17891
17984
  evaluate({ zoom }, properties) {
17892
17985
  return evaluateExponentialFunction({
@@ -18017,15 +18110,16 @@ class StyleExpression {
18017
18110
  this.isIndoorDependent = isIndoorDependent(expression);
18018
18111
  }
18019
18112
  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);
18113
+ const evaluator = this._evaluator;
18114
+ evaluator.globals = globals;
18115
+ evaluator.feature = feature;
18116
+ evaluator.featureState = featureState;
18117
+ evaluator.canonical = canonical || null;
18118
+ evaluator.availableImages = availableImages || null;
18119
+ evaluator.formattedSection = formattedSection;
18120
+ evaluator.featureTileCoord = featureTileCoord || null;
18121
+ evaluator.featureDistanceData = featureDistanceData || null;
18122
+ return this.expression.evaluate(evaluator);
18029
18123
  }
18030
18124
  evaluate(globals, feature, featureState, canonical, availableImages, formattedSection, featureTileCoord, featureDistanceData, iconImageUseTheme) {
18031
18125
  if (!this._evaluator) {
@@ -18243,7 +18337,8 @@ function getExpectedType(spec) {
18243
18337
  enum: StringType,
18244
18338
  boolean: BooleanType,
18245
18339
  formatted: FormattedType,
18246
- resolvedImage: ResolvedImageType
18340
+ resolvedImage: ResolvedImageType,
18341
+ object: ObjectType
18247
18342
  };
18248
18343
  if (spec.type === "array") {
18249
18344
  return array$1(types[spec.value] || ValueType, spec.length);
@@ -19507,17 +19602,23 @@ function validateOption(options) {
19507
19602
  const optionValue = options.value;
19508
19603
  const isArrayOption = isObject(optionValue) && unbundle(optionValue.array) === true;
19509
19604
  const declaredType = !isArrayOption && isObject(optionValue) ? unbundle(optionValue.type) : void 0;
19605
+ const validateDefault = (elementOptions) => {
19606
+ const defaultValue = elementOptions.value;
19607
+ if (isObject(defaultValue)) {
19608
+ return validate({ ...elementOptions, valueSpec: { ...elementOptions.valueSpec, type: "*", expression: void 0 } });
19609
+ }
19610
+ if (declaredType && Array.isArray(defaultValue)) {
19611
+ return validate({ ...elementOptions, valueSpec: { ...elementOptions.valueSpec, type: declaredType } });
19612
+ }
19613
+ return validate(elementOptions);
19614
+ };
19510
19615
  return validateObject({
19511
19616
  ...options,
19512
19617
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
19513
19618
  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
19619
+ objectElementValidators: {
19620
+ default: validateDefault
19621
+ }
19521
19622
  });
19522
19623
  }
19523
19624