@mapbox/mapbox-gl-style-spec 14.16.0-beta.1 → 14.16.0-beta.3

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.
@@ -266,6 +266,19 @@ CompoundExpression.register(expressions, {
266
266
  [],
267
267
  (ctx) => ctx.globals.worldview || ""
268
268
  ],
269
+ 'is-active-floor': [
270
+ BooleanType,
271
+ varargs(StringType),
272
+ (ctx, args) => {
273
+ const hasActiveFloors = ctx.globals.activeFloors && ctx.globals.activeFloors.size > 0;
274
+ if (!hasActiveFloors) { return false; }
275
+ const floorIds: Set<string> = ctx.globals.activeFloors;
276
+ return args.some(arg => {
277
+ const value = arg.evaluate(ctx) as string;
278
+ return floorIds.has(value);
279
+ });
280
+ }
281
+ ],
269
282
  'id': [
270
283
  ValueType,
271
284
  [],
@@ -0,0 +1,33 @@
1
+ import CompoundExpression from "./compound_expression";
2
+ import Config from "./definitions/config";
3
+
4
+ import type {Expression} from "./expression";
5
+
6
+ function getConfigDependencies(e: Expression): Set<string> {
7
+ if (e instanceof Config) {
8
+ const singleConfig = new Set([e.key]);
9
+ return singleConfig;
10
+ }
11
+
12
+ let result = new Set<string>();
13
+ e.eachChild(arg => {
14
+ result = new Set([...result, ...getConfigDependencies(arg)]);
15
+ });
16
+ return result;
17
+ }
18
+
19
+ function isIndoorDependent(e: Expression): boolean {
20
+ if (e instanceof CompoundExpression && e.name === 'is-active-floor') {
21
+ return true;
22
+ }
23
+
24
+ let result = false;
25
+ e.eachChild(arg => {
26
+ if (!result && isIndoorDependent(arg)) {
27
+ result = true;
28
+ }
29
+ });
30
+ return result;
31
+ }
32
+
33
+ export {getConfigDependencies, isIndoorDependent};
@@ -9,6 +9,7 @@ import Coalesce from './definitions/coalesce';
9
9
  import Let from './definitions/let';
10
10
  import definitions from './definitions/index';
11
11
  import * as isConstant from './is_constant';
12
+ import * as expressionDependencies from './expression_dependencies';
12
13
  import RuntimeError from './runtime_error';
13
14
  import {success, error} from '../util/result';
14
15
  import {
@@ -60,16 +61,17 @@ export interface GlobalProperties {
60
61
  accumulated?: Value;
61
62
  brightness?: number;
62
63
  worldview?: string;
64
+ activeFloors?: Set<string>;
63
65
  }
64
66
 
65
67
  export class StyleExpression {
66
68
  expression: Expression;
67
-
68
69
  _evaluator: EvaluationContext;
69
70
  _defaultValue: Value;
70
71
  _warningHistory: {[key: string]: boolean};
71
72
  _enumValues?: {[_: string]: unknown};
72
73
  configDependencies: Set<string>;
74
+ isIndoorDependent: boolean;
73
75
 
74
76
  constructor(expression: Expression, propertySpec?: StylePropertySpecification, scope?: string, options?: ConfigOptions, iconImageUseTheme?: string) {
75
77
  this.expression = expression;
@@ -77,7 +79,8 @@ export class StyleExpression {
77
79
  this._evaluator = new EvaluationContext(scope, options, iconImageUseTheme);
78
80
  this._defaultValue = propertySpec ? getDefaultValue(propertySpec) : null;
79
81
  this._enumValues = propertySpec && propertySpec.type === 'enum' ? propertySpec.values : null;
80
- this.configDependencies = isConstant.getConfigDependencies(expression);
82
+ this.configDependencies = expressionDependencies.getConfigDependencies(expression);
83
+ this.isIndoorDependent = expressionDependencies.isIndoorDependent(expression);
81
84
  }
82
85
 
83
86
  evaluateWithoutErrorHandling(
@@ -124,7 +127,6 @@ export class StyleExpression {
124
127
  this._evaluator.featureTileCoord = featureTileCoord || null;
125
128
  this._evaluator.featureDistanceData = featureDistanceData || null;
126
129
  this._evaluator.iconImageUseTheme = iconImageUseTheme || null;
127
-
128
130
  try {
129
131
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
130
132
  const val = this.expression.evaluate(this._evaluator);
@@ -190,6 +192,7 @@ export class ZoomConstantExpression<Kind extends EvaluationKind> {
190
192
  kind: Kind;
191
193
  isStateDependent: boolean;
192
194
  configDependencies: Set<string>;
195
+ isIndoorDependent: boolean;
193
196
  _styleExpression: StyleExpression;
194
197
  isLightConstant: boolean | null | undefined;
195
198
  isLineProgressConstant: boolean | null | undefined;
@@ -200,7 +203,8 @@ export class ZoomConstantExpression<Kind extends EvaluationKind> {
200
203
  this.isLightConstant = isLightConstant;
201
204
  this.isLineProgressConstant = isLineProgressConstant;
202
205
  this.isStateDependent = kind !== ('constant' as EvaluationKind) && !isConstant.isStateConstant(expression.expression);
203
- this.configDependencies = isConstant.getConfigDependencies(expression.expression);
206
+ this.configDependencies = expressionDependencies.getConfigDependencies(expression.expression);
207
+ this.isIndoorDependent = expressionDependencies.isIndoorDependent(expression.expression);
204
208
  }
205
209
 
206
210
  evaluateWithoutErrorHandling(
@@ -233,6 +237,7 @@ export class ZoomDependentExpression<Kind extends EvaluationKind> {
233
237
  kind: Kind;
234
238
  zoomStops: Array<number>;
235
239
  isStateDependent: boolean;
240
+ isIndoorDependent: boolean;
236
241
  isLightConstant: boolean | null | undefined;
237
242
  isLineProgressConstant: boolean | null | undefined;
238
243
  configDependencies: Set<string>;
@@ -245,9 +250,10 @@ export class ZoomDependentExpression<Kind extends EvaluationKind> {
245
250
  this.zoomStops = zoomStops;
246
251
  this._styleExpression = expression;
247
252
  this.isStateDependent = kind !== ('camera' as EvaluationKind) && !isConstant.isStateConstant(expression.expression);
253
+ this.isIndoorDependent = expressionDependencies.isIndoorDependent(expression.expression);
248
254
  this.isLightConstant = isLightConstant;
249
255
  this.isLineProgressConstant = isLineProgressConstant;
250
- this.configDependencies = isConstant.getConfigDependencies(expression.expression);
256
+ this.configDependencies = expressionDependencies.getConfigDependencies(expression.expression);
251
257
  this.interpolationType = interpolationType;
252
258
  }
253
259
 
@@ -287,6 +293,7 @@ export class ZoomDependentExpression<Kind extends EvaluationKind> {
287
293
  export type ConstantExpression = {
288
294
  kind: 'constant';
289
295
  configDependencies: Set<string>;
296
+ isIndoorDependent: boolean;
290
297
  readonly evaluate: <T = unknown>(
291
298
  globals: GlobalProperties,
292
299
  feature?: Feature,
@@ -301,6 +308,7 @@ export type ConstantExpression = {
301
308
  export type SourceExpression = {
302
309
  kind: 'source';
303
310
  isStateDependent: boolean;
311
+ isIndoorDependent: boolean;
304
312
  isLightConstant: boolean | null | undefined;
305
313
  isLineProgressConstant: boolean | null | undefined;
306
314
  configDependencies: Set<string>;
@@ -317,6 +325,7 @@ export type SourceExpression = {
317
325
  export type CameraExpression = {
318
326
  kind: 'camera';
319
327
  isStateDependent: boolean;
328
+ isIndoorDependent: boolean;
320
329
  configDependencies: Set<string>;
321
330
  readonly evaluate: <T = unknown>(
322
331
  globals: GlobalProperties,
@@ -333,6 +342,7 @@ export type CameraExpression = {
333
342
  export interface CompositeExpression {
334
343
  kind: 'composite';
335
344
  isStateDependent: boolean;
345
+ isIndoorDependent: boolean;
336
346
  isLightConstant: boolean | null | undefined;
337
347
  isLineProgressConstant: boolean | null | undefined;
338
348
  configDependencies: Set<string>;
@@ -484,6 +494,7 @@ export function normalizePropertyExpression<T>(
484
494
  return {
485
495
  kind: 'constant',
486
496
  configDependencies: new Set(),
497
+ isIndoorDependent: false,
487
498
  evaluate: () => constant
488
499
  } as ConstantExpression;
489
500
  }
@@ -56,19 +56,6 @@ function isStateConstant(e: Expression): boolean {
56
56
  return result;
57
57
  }
58
58
 
59
- function getConfigDependencies(e: Expression): Set<string> {
60
- if (e instanceof Config) {
61
- const singleConfig = new Set([e.key]);
62
- return singleConfig;
63
- }
64
-
65
- let result = new Set<string>();
66
- e.eachChild(arg => {
67
- result = new Set([...result, ...getConfigDependencies(arg)]);
68
- });
69
- return result;
70
- }
71
-
72
59
  function isGlobalPropertyConstant(e: Expression, properties: Array<string>): boolean {
73
60
  if (e instanceof CompoundExpression && properties.indexOf(e.name) >= 0) { return false; }
74
61
  let result = true;
@@ -78,4 +65,4 @@ function isGlobalPropertyConstant(e: Expression, properties: Array<string>): boo
78
65
  return result;
79
66
  }
80
67
 
81
- export {isFeatureConstant, isGlobalPropertyConstant, isStateConstant, getConfigDependencies};
68
+ export {isFeatureConstant, isGlobalPropertyConstant, isStateConstant};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapbox/mapbox-gl-style-spec",
3
- "version": "14.16.0-beta.1",
3
+ "version": "14.16.0-beta.3",
4
4
  "description": "a specification for mapbox gl styles",
5
5
  "author": "Mapbox",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",
@@ -21,7 +21,8 @@
21
21
  "exports": {
22
22
  ".": {
23
23
  "require": "./dist/index.cjs",
24
- "import": "./dist/index.es.js"
24
+ "import": "./dist/index.es.js",
25
+ "types": "./dist/index.d.ts"
25
26
  },
26
27
  "./": {
27
28
  "import": "./"
package/reference/v8.json CHANGED
@@ -125,6 +125,7 @@
125
125
  },
126
126
  "indoor": {
127
127
  "type": "indoor",
128
+ "private": true,
128
129
  "experimental": true,
129
130
  "doc": "Controls the behaviour of indoor features."
130
131
  },
@@ -5746,6 +5747,19 @@
5746
5747
  }
5747
5748
  }
5748
5749
  },
5750
+ "is-active-floor": {
5751
+ "doc": "Experimental. Returns `true` if the input floor id belongs to one of the active indoor floors, `false` otherwise. In case of array of strings, returns `true` if any of the input floor ids belongs to one of the active indoor floors, `false` otherwise. Only supported in filters.",
5752
+ "group": "Indoor",
5753
+ "experimental": true,
5754
+ "private": true,
5755
+ "sdk-support": {
5756
+ "basic functionality": {
5757
+ "js": "3.16.0",
5758
+ "android": "11.16.0",
5759
+ "ios": "11.16.0"
5760
+ }
5761
+ }
5762
+ },
5749
5763
  "random": {
5750
5764
  "doc": "Returns a random value in the specified range (first two input numbers) based on a supplied seed (third input). The seed can be an expression or a constant number or string value.",
5751
5765
  "group": "Math",
@@ -6574,26 +6588,29 @@
6574
6588
  }
6575
6589
  }
6576
6590
  },
6577
- "indoor": {
6578
- "floorplanFeaturesetId": {
6591
+ "indoor_source": {
6592
+ "sourceId": {
6579
6593
  "type": "string",
6580
- "doc": "An ID of a featureset to be used to query indoor floorplans.",
6594
+ "doc": "Source ID of a source to be used to retrieve indoor data.",
6581
6595
  "experimental": true,
6596
+ "private": true,
6582
6597
  "transition": false,
6583
- "property-type": "data-constant",
6584
- "expression": {
6585
- "interpolated": false
6586
- }
6598
+ "property-type": "data-constant"
6587
6599
  },
6588
- "buildingFeaturesetId": {
6589
- "type": "string",
6590
- "doc": "An ID of a featureset to be used to add interactivity for building selection.",
6600
+ "sourceLayers": {
6601
+ "type": "array",
6602
+ "value": "string",
6603
+ "doc": "An array of source layers to be used to retrieve indoor data.",
6591
6604
  "experimental": true,
6605
+ "private": true,
6592
6606
  "transition": false,
6593
- "property-type": "data-constant",
6594
- "expression": {
6595
- "interpolated": false
6596
- }
6607
+ "property-type": "data-constant"
6608
+ }
6609
+ },
6610
+ "indoor": {
6611
+ "*": {
6612
+ "type": "indoor_source",
6613
+ "doc": "Specification of an indoor source - sourceId and sourceLayer required for vector source, for GeoJSON sourceLayers should be omitted."
6597
6614
  }
6598
6615
  },
6599
6616
  "light": {
package/types.ts CHANGED
@@ -329,14 +329,18 @@ export type ImportSpecification = {
329
329
  };
330
330
 
331
331
  export type IndoorSpecification = {
332
+ [_: string]: IndoorSourceSpecification
333
+ };
334
+
335
+ export type IndoorSourceSpecification = {
332
336
  /**
333
337
  * @experimental This property is experimental and subject to change in future versions.
334
338
  */
335
- "floorplanFeaturesetId"?: ExpressionSpecification,
339
+ "sourceId"?: string,
336
340
  /**
337
341
  * @experimental This property is experimental and subject to change in future versions.
338
342
  */
339
- "buildingFeaturesetId"?: ExpressionSpecification
343
+ "sourceLayers"?: Array<string>
340
344
  };
341
345
 
342
346
  export type ConfigSpecification = {
@@ -7,6 +7,7 @@ import latest from '../reference/latest';
7
7
 
8
8
  import type {StyleSpecification, LayerSpecification, AppearanceSpecification} from '../types';
9
9
  import type {StyleReference} from '../reference/latest';
10
+ import type {StylePropertySpecification} from '../style-spec';
10
11
 
11
12
  export type AppearanceValidatorOptions = {
12
13
  key: string;
@@ -37,7 +38,7 @@ export default function validateAppearance(options: AppearanceValidatorOptions):
37
38
  }
38
39
  });
39
40
 
40
- if (name !== 'hidden' && !condition) {
41
+ if (name !== 'hidden' && condition === undefined) {
41
42
  errors.push(new ValidationError(options.key, 'name', `Appearance with name different than "hidden" must have a condition`));
42
43
  }
43
44
 
@@ -49,10 +50,8 @@ function validateProperties(options: AppearanceValidatorOptions): Array<Validati
49
50
 
50
51
  const {styleSpec, layer, layerType} = options;
51
52
 
52
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
53
- const paintProperties = styleSpec[`paint_${layerType}`];
54
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
55
- const layoutProperties = styleSpec[`layout_${layerType}`];
53
+ const paintProperties = styleSpec[`paint_${layerType}`] as Record<string, StylePropertySpecification> | undefined;
54
+ const layoutProperties = styleSpec[`layout_${layerType}`] as Record<string, StylePropertySpecification> | undefined;
56
55
  const properties = options.object[options.objectKey] as object;
57
56
 
58
57
  for (const propertyKey in properties) {
@@ -73,8 +72,7 @@ function validateProperties(options: AppearanceValidatorOptions): Array<Validati
73
72
  layer,
74
73
  layerType,
75
74
  value: properties[propertyKey] as unknown,
76
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
77
- valueSpec: (propertyType === 'paint' ? paintProperties[propertyKey] : layoutProperties[propertyKey]) as object,
75
+ valueSpec: (propertyType === 'paint' ? paintProperties[propertyKey] : layoutProperties[propertyKey]),
78
76
  });
79
77
 
80
78
  errors.push(...validateProperty(propertyValidationOptions, propertyType));
@@ -4,7 +4,7 @@ import {deepUnbundle} from '../util/unbundle_jsonlint';
4
4
  import {isStateConstant, isGlobalPropertyConstant, isFeatureConstant} from '../expression/is_constant';
5
5
  import CompoundExpression from '../expression/compound_expression';
6
6
 
7
- import type {StylePropertySpecification} from '../../style-spec/style-spec';
7
+ import type {StylePropertySpecification} from '../style-spec';
8
8
  import type {Expression} from '../expression/expression';
9
9
  import type {StyleReference} from '../reference/latest';
10
10
  import type {StyleSpecification} from '../types';
@@ -59,14 +59,12 @@ function validateNonExpressionFilter(options: FilterValidatorOptions): Validatio
59
59
  case '<':
60
60
  case '<=':
61
61
  case '>':
62
- // @ts-expect-error - falls through
63
62
  case '>=':
64
63
  if (value.length >= 2 && unbundle(value[1]) === '$type') {
65
64
  errors.push(new ValidationError(key, value, `"$type" cannot be use with operator "${value[0]}"`));
66
65
  }
67
66
  /* falls through */
68
67
  case '==':
69
- // @ts-expect-error - falls through
70
68
  case '!=':
71
69
  if (value.length !== 3) {
72
70
  errors.push(new ValidationError(key, value, `filter array for operator "${value[0]}" must have 3 elements`));
@@ -10,6 +10,7 @@ import validateSpec from './validate';
10
10
  import {isObject, isString} from '../util/get_type';
11
11
 
12
12
  import type {StyleReference} from '../reference/latest';
13
+ import type {PropertyValidatorOptions} from './validate_property';
13
14
  import type {StyleSpecification, LayerSpecification, GeoJSONSourceSpecification} from '../types';
14
15
 
15
16
  type LayerValidatorOptions = {
@@ -138,7 +139,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
138
139
  style: options.style,
139
140
  styleSpec: options.styleSpec,
140
141
  objectElementValidators: {
141
- '*'(options) {
142
+ '*'(options: PropertyValidatorOptions) {
142
143
  return validateLayoutProperty(Object.assign({layerType: type}, options));
143
144
  }
144
145
  }
@@ -153,7 +154,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
153
154
  style: options.style,
154
155
  styleSpec: options.styleSpec,
155
156
  objectElementValidators: {
156
- '*'(options) {
157
+ '*'(options: PropertyValidatorOptions) {
157
158
  return validatePaintProperty(Object.assign({layerType: type, layer}, options));
158
159
  }
159
160
  }
@@ -8,12 +8,13 @@ import {isGlobalPropertyConstant, isFeatureConstant, isStateConstant} from '../e
8
8
  import {createPropertyExpression, isExpression} from '../expression/index';
9
9
 
10
10
  import type {StyleReference} from '../reference/latest';
11
+ import type {StylePropertySpecification} from '../style-spec';
11
12
  import type {StyleSpecification, LayerSpecification} from '../types';
12
13
 
13
14
  export type PropertyValidatorOptions = {
14
15
  key: string;
15
16
  value: unknown;
16
- valueSpec?: unknown;
17
+ valueSpec?: StylePropertySpecification;
17
18
  style: Partial<StyleSpecification>;
18
19
  styleSpec: StyleReference;
19
20
  objectKey?: string;
@@ -28,29 +29,24 @@ export default function validateProperty(options: PropertyValidatorOptions, prop
28
29
  const styleSpec = options.styleSpec;
29
30
  const value = options.value;
30
31
  const propertyKey = options.objectKey;
31
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
32
- const layerSpec = styleSpec[`${propertyType}_${options.layerType}`];
32
+ const layerSpec = styleSpec[`${propertyType}_${options.layerType}`] as Record<string, StylePropertySpecification> | undefined;
33
33
 
34
34
  if (!layerSpec) return [];
35
35
 
36
36
  const useThemeMatch = propertyKey.match(/^(.*)-use-theme$/);
37
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
38
37
  if (useThemeMatch && layerSpec[useThemeMatch[1]]) {
39
- if (isExpression(value)) {
38
+ if (isExpression(deepUnbundle(value))) {
40
39
  const errors: ValidationError[] = [];
41
40
  return errors.concat(validate({
42
- key: options.key,
41
+ key,
43
42
  value,
44
43
  valueSpec: {
45
- "type": "string",
46
- "expression": {
47
- "interpolated": false,
48
- "parameters": [
49
- "zoom",
50
- "feature"
51
- ]
44
+ type: 'string',
45
+ expression: {
46
+ interpolated: false,
47
+ parameters: ['zoom', 'feature']
52
48
  },
53
- "property-type": "data-driven"
49
+ 'property-type': 'data-driven'
54
50
  },
55
51
  style,
56
52
  styleSpec,
@@ -59,6 +55,7 @@ export default function validateProperty(options: PropertyValidatorOptions, prop
59
55
  propertyKey
60
56
  }));
61
57
  }
58
+
62
59
  return validate({
63
60
  key,
64
61
  value,
@@ -69,7 +66,6 @@ export default function validateProperty(options: PropertyValidatorOptions, prop
69
66
  }
70
67
 
71
68
  const transitionMatch = propertyKey.match(/^(.*)-transition$/);
72
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
73
69
  if (propertyType === 'paint' && transitionMatch && layerSpec[transitionMatch[1]] && layerSpec[transitionMatch[1]].transition) {
74
70
  return validate({
75
71
  key,
@@ -81,14 +77,12 @@ export default function validateProperty(options: PropertyValidatorOptions, prop
81
77
  });
82
78
  }
83
79
 
84
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
85
80
  const valueSpec = options.valueSpec || layerSpec[propertyKey];
86
81
  if (!valueSpec) {
87
82
  return [new ValidationWarning(key, value, `unknown property "${propertyKey}"`)];
88
83
  }
89
84
 
90
85
  let tokenMatch: RegExpExecArray | undefined;
91
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
92
86
  if (isString(value) && supportsPropertyExpression(valueSpec) && !valueSpec.tokens && (tokenMatch = /^{([^}]+)}$/.exec(value))) {
93
87
  const example = `\`{ "type": "identity", "property": ${tokenMatch ? JSON.stringify(tokenMatch[1]) : '"_"'} }\``;
94
88
  return [new ValidationError(
@@ -107,10 +101,8 @@ export default function validateProperty(options: PropertyValidatorOptions, prop
107
101
  errors.push(new ValidationError(key, value, '"text-font" does not support identity functions'));
108
102
  }
109
103
  } else if (options.layerType === 'model' && propertyType === 'paint' && layer && layer.layout && layer.layout.hasOwnProperty('model-id')) {
110
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
111
104
  if (supportsPropertyExpression(valueSpec) && (supportsLightExpression(valueSpec) || supportsZoomExpression(valueSpec))) {
112
105
  // Performance related style spec limitation: zoom and light expressions are not allowed for e.g. trees.
113
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
114
106
  const expression = createPropertyExpression(deepUnbundle(value), valueSpec);
115
107
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
116
108
  const expressionObj = (expression.value as any).expression || (expression.value as any)._styleExpression.expression;
@@ -128,7 +120,6 @@ export default function validateProperty(options: PropertyValidatorOptions, prop
128
120
  return errors.concat(validate({
129
121
  key: options.key,
130
122
  value,
131
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
132
123
  valueSpec,
133
124
  style,
134
125
  styleSpec,