From aa2fbe61fc2b54536d2d0c8c51a64abde35eb104 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Mon, 18 Nov 2024 16:43:14 -0500 Subject: [PATCH 1/5] Add interfaces to allow custom MVT sources to style the map layers and provied a custom legend --- .../mvt_vector_layer/mvt_vector_layer.tsx | 5 ++++ .../sources/vector_source/vector_source.tsx | 25 ++++++++++++++++--- .../classes/styles/vector/vector_style.tsx | 7 +++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx index 29b0f90802833..1958c1365d2dc 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx @@ -426,6 +426,11 @@ export class MvtVectorLayer extends AbstractVectorLayer { this._setMbPointsProperties(mbMap, sourceData.tileSourceLayer); this._setMbLinePolygonProperties(mbMap, sourceData.tileSourceLayer); this._syncTooManyFeaturesProperties(mbMap); + const myLayers = mbMap.getStyle().layers.filter((mbLayer:any) => { + return this.ownsMbLayerId(mbLayer.id) + }); + const layerIds = myLayers.map(layer=>layer.id) + this.getSource().syncSourceStyle(mbMap,layerIds) } // TODO ES MVT specific - move to es_tiled_vector_layer implementation diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index aeffc6f6c167d..b6e23bd2cf6d5 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { ReactElement } from 'react'; import { FeatureCollection, GeoJsonProperties, @@ -17,7 +17,7 @@ import { import type { KibanaExecutionContext } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import type { Query } from '@kbn/data-plugin/common'; -import type { MapGeoJSONFeature } from '@kbn/mapbox-gl'; +import type { MapGeoJSONFeature, Map as MbMap, } from '@kbn/mapbox-gl'; import { Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; @@ -36,6 +36,7 @@ import { } from '../../../../common/descriptor_types'; import { DataRequest } from '../../util/data_request'; import { FeatureGeometryFilterForm } from '../../../connected_components/mb_map/tooltip_control/features_tooltip'; +import { IVectorStyle } from '../../styles/vector/vector_style'; export function hasVectorSourceMethod( source: ISource, @@ -145,9 +146,27 @@ export interface IVectorSource extends ISource { * Provide unique ids for managing source requests in Inspector */ getInspectorRequestIds(): string[]; + + /** + * Syncs source specific styling with mbMap this allows custom sources to further style the map layers/filters + */ + syncSourceStyle(mbMap:MbMap,layers:string[]):void + + /** + * specifies if a source provides its own legend details or if the default vector_style is used if the source has this method it must also implement renderLegendDetails + */ + hasLegendDetails?(): Promise + /** + * specifies if a source provides its own legend details or if the default vector_style is used + */ + renderLegendDetails?(vectorStyle:IVectorStyle): ReactElement | null } export class AbstractVectorSource extends AbstractSource implements IVectorSource { + + syncSourceStyle(mbMap: MbMap, layers: string[]): void { + //Nothing internal currently implements this + } isMvt() { return false; } @@ -199,7 +218,7 @@ export class AbstractVectorSource extends AbstractSource implements IVectorSourc // Allow source to filter and format feature properties before displaying to user async getTooltipProperties( - properties: GeoJsonProperties, + properties: any, executionContext: KibanaExecutionContext ): Promise { const tooltipProperties: ITooltipProperty[] = []; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 31c06728d8112..c2807222b7745 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -721,13 +721,18 @@ export class VectorStyle implements IVectorStyle { }; async hasLegendDetails() { + if(this._source.hasLegendDetails){ + return await this._source.hasLegendDetails() + } return this._getLegendDetailStyleProperties().length > 0; } renderLegendDetails() { const symbolId = this._getSymbolId(); const svg = symbolId ? this.getIconSvg(symbolId) : undefined; - + if(this._source.renderLegendDetails){ + return this._source.renderLegendDetails(this) || <> + } return ( Date: Mon, 18 Nov 2024 17:02:18 -0500 Subject: [PATCH 2/5] Fix typing for getTooltioProperties --- .../maps/public/classes/sources/vector_source/vector_source.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index b6e23bd2cf6d5..705b9d13776c2 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -218,7 +218,7 @@ export class AbstractVectorSource extends AbstractSource implements IVectorSourc // Allow source to filter and format feature properties before displaying to user async getTooltipProperties( - properties: any, + properties: GeoJsonProperties, executionContext: KibanaExecutionContext ): Promise { const tooltipProperties: ITooltipProperty[] = []; From b71f9f7d952c6ed5a5ec974f8e4fc0a37337d3dd Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Wed, 20 Nov 2024 13:43:18 -0500 Subject: [PATCH 3/5] Implement recommended changes and lint --- .../mvt_vector_layer/mvt_vector_layer.tsx | 11 ++++++----- .../sources/vector_source/vector_source.tsx | 12 ++++-------- .../classes/styles/vector/vector_style.tsx | 16 +++++++--------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx index 1958c1365d2dc..5f25ce2750707 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx @@ -426,11 +426,12 @@ export class MvtVectorLayer extends AbstractVectorLayer { this._setMbPointsProperties(mbMap, sourceData.tileSourceLayer); this._setMbLinePolygonProperties(mbMap, sourceData.tileSourceLayer); this._syncTooManyFeaturesProperties(mbMap); - const myLayers = mbMap.getStyle().layers.filter((mbLayer:any) => { - return this.ownsMbLayerId(mbLayer.id) - }); - const layerIds = myLayers.map(layer=>layer.id) - this.getSource().syncSourceStyle(mbMap,layerIds) + this.getSource().syncSourceStyle?.(mbMap, () => + mbMap + .getStyle() + .layers.filter((mbLayer) => this.ownsMbLayerId(mbLayer.id)) + .map((layer) => layer.id) + ); } // TODO ES MVT specific - move to es_tiled_vector_layer implementation diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index 705b9d13776c2..717f3a0e5a25f 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -17,7 +17,7 @@ import { import type { KibanaExecutionContext } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import type { Query } from '@kbn/data-plugin/common'; -import type { MapGeoJSONFeature, Map as MbMap, } from '@kbn/mapbox-gl'; +import type { MapGeoJSONFeature, Map as MbMap } from '@kbn/mapbox-gl'; import { Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; @@ -150,23 +150,19 @@ export interface IVectorSource extends ISource { /** * Syncs source specific styling with mbMap this allows custom sources to further style the map layers/filters */ - syncSourceStyle(mbMap:MbMap,layers:string[]):void + syncSourceStyle?(mbMap: MbMap, getLayerIds: () => string[]): void; /** * specifies if a source provides its own legend details or if the default vector_style is used if the source has this method it must also implement renderLegendDetails */ - hasLegendDetails?(): Promise + hasLegendDetails?(): Promise; /** * specifies if a source provides its own legend details or if the default vector_style is used */ - renderLegendDetails?(vectorStyle:IVectorStyle): ReactElement | null + renderLegendDetails?(vectorStyle: IVectorStyle): ReactElement | null; } export class AbstractVectorSource extends AbstractSource implements IVectorSource { - - syncSourceStyle(mbMap: MbMap, layers: string[]): void { - //Nothing internal currently implements this - } isMvt() { return false; } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index c2807222b7745..b935ee276f6cd 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -110,7 +110,7 @@ export interface IVectorStyle extends IStyle { getIconSvg(symbolId: string): string | undefined; isUsingCustomIcon(symbolId: string): boolean; hasLegendDetails: () => Promise; - renderLegendDetails: () => ReactElement; + renderLegendDetails: () => ReactElement | null; clearFeatureState: (featureCollection: FeatureCollection, mbMap: MbMap, sourceId: string) => void; setFeatureStateAndStyleProps: ( featureCollection: FeatureCollection, @@ -721,19 +721,17 @@ export class VectorStyle implements IVectorStyle { }; async hasLegendDetails() { - if(this._source.hasLegendDetails){ - return await this._source.hasLegendDetails() - } - return this._getLegendDetailStyleProperties().length > 0; + return this._source.hasLegendDetails + ? await this._source.hasLegendDetails() + : this._getLegendDetailStyleProperties().length > 0; } renderLegendDetails() { const symbolId = this._getSymbolId(); const svg = symbolId ? this.getIconSvg(symbolId) : undefined; - if(this._source.renderLegendDetails){ - return this._source.renderLegendDetails(this) || <> - } - return ( + return this._source.renderLegendDetails ? ( + this._source.renderLegendDetails(this) + ) : ( Date: Thu, 21 Nov 2024 14:18:41 -0500 Subject: [PATCH 4/5] Move everything to mvt interface --- .../mvt_vector_layer/mvt_vector_layer.tsx | 2 +- .../vector_source/mvt_vector_source.ts | 17 ++++++++++++++ .../sources/vector_source/vector_source.tsx | 19 ++-------------- .../classes/styles/vector/vector_style.tsx | 22 ++++++++++++++----- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx index 5f25ce2750707..78e7c18fe43fa 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx @@ -426,7 +426,7 @@ export class MvtVectorLayer extends AbstractVectorLayer { this._setMbPointsProperties(mbMap, sourceData.tileSourceLayer); this._setMbLinePolygonProperties(mbMap, sourceData.tileSourceLayer); this._syncTooManyFeaturesProperties(mbMap); - this.getSource().syncSourceStyle?.(mbMap, () => + (this.getSource() as IMvtVectorSource).syncSourceStyle?.(mbMap, () => mbMap .getStyle() .layers.filter((mbLayer) => this.ownsMbLayerId(mbLayer.id)) diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts b/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts index 829afe5917cd5..01118a99cb1bc 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts @@ -5,8 +5,11 @@ * 2.0. */ +import type { Map as MbMap } from '@kbn/mapbox-gl'; +import { ReactElement } from 'react'; import { VectorSourceRequestMeta } from '../../../../common/descriptor_types'; import { IVectorSource } from '.'; +import { IVectorStyle } from '../../styles/vector/vector_style'; export interface IMvtVectorSource extends IVectorSource { /* @@ -25,4 +28,18 @@ export interface IMvtVectorSource extends IVectorSource { * Use getTileSourceLayer to specify the displayed source layer. */ getTileSourceLayer(): string; + + /** + * Syncs source specific styling with mbMap this allows custom sources to further style the map layers/filters + */ + syncSourceStyle?(mbMap: MbMap, getLayerIds: () => string[]): void; + + /** + * specifies if a source provides its own legend details or if the default vector_style is used if the source has this method it must also implement renderLegendDetails + */ + hasLegendDetails?(): Promise; + /** + * specifies if a source provides its own legend details or if the default vector_style is used + */ + renderLegendDetails?(vectorStyle: IVectorStyle): ReactElement | null; } diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index 717f3a0e5a25f..aeffc6f6c167d 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { ReactElement } from 'react'; +import React from 'react'; import { FeatureCollection, GeoJsonProperties, @@ -17,7 +17,7 @@ import { import type { KibanaExecutionContext } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import type { Query } from '@kbn/data-plugin/common'; -import type { MapGeoJSONFeature, Map as MbMap } from '@kbn/mapbox-gl'; +import type { MapGeoJSONFeature } from '@kbn/mapbox-gl'; import { Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; @@ -36,7 +36,6 @@ import { } from '../../../../common/descriptor_types'; import { DataRequest } from '../../util/data_request'; import { FeatureGeometryFilterForm } from '../../../connected_components/mb_map/tooltip_control/features_tooltip'; -import { IVectorStyle } from '../../styles/vector/vector_style'; export function hasVectorSourceMethod( source: ISource, @@ -146,20 +145,6 @@ export interface IVectorSource extends ISource { * Provide unique ids for managing source requests in Inspector */ getInspectorRequestIds(): string[]; - - /** - * Syncs source specific styling with mbMap this allows custom sources to further style the map layers/filters - */ - syncSourceStyle?(mbMap: MbMap, getLayerIds: () => string[]): void; - - /** - * specifies if a source provides its own legend details or if the default vector_style is used if the source has this method it must also implement renderLegendDetails - */ - hasLegendDetails?(): Promise; - /** - * specifies if a source provides its own legend details or if the default vector_style is used - */ - renderLegendDetails?(vectorStyle: IVectorStyle): ReactElement | null; } export class AbstractVectorSource extends AbstractSource implements IVectorSource { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index b935ee276f6cd..dee0a072e8681 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -75,7 +75,7 @@ import { IStyle } from '../style'; import { IStyleProperty } from './properties/style_property'; import { IField } from '../../fields/field'; import { IVectorLayer } from '../../layers/vector_layer'; -import { IVectorSource } from '../../sources/vector_source'; +import { IMvtVectorSource, IVectorSource } from '../../sources/vector_source'; import { createStyleFieldsHelper, StyleFieldsHelper } from './style_fields_helper'; import { IESAggField } from '../../fields/agg'; @@ -721,17 +721,20 @@ export class VectorStyle implements IVectorStyle { }; async hasLegendDetails() { - return this._source.hasLegendDetails - ? await this._source.hasLegendDetails() + if (!this._source.isMvt()) { + return this._getLegendDetailStyleProperties().length > 0; + } + const source = this._source as IMvtVectorSource; + + return source.hasLegendDetails && source.renderLegendDetails + ? await source.hasLegendDetails() : this._getLegendDetailStyleProperties().length > 0; } renderLegendDetails() { const symbolId = this._getSymbolId(); const svg = symbolId ? this.getIconSvg(symbolId) : undefined; - return this._source.renderLegendDetails ? ( - this._source.renderLegendDetails(this) - ) : ( + const VectorLegend = ( ); + + if (!this._source.isMvt()) { + return VectorLegend; + } + + const source = this._source as IMvtVectorSource; + return source.renderLegendDetails ? source.renderLegendDetails(this) : VectorLegend; } clearFeatureState(featureCollection: FeatureCollection, mbMap: MbMap, sourceId: string) { From d3acdeda8242cdcf57cc6091106e303f3d470517 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Mon, 25 Nov 2024 14:03:36 -0500 Subject: [PATCH 5/5] Move only syncSourceStyle to MVT Vector --- .../vector_source/mvt_vector_source.ts | 11 --------- .../sources/vector_source/vector_source.tsx | 12 +++++++++- .../classes/styles/vector/vector_style.tsx | 23 ++++++------------- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts b/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts index 01118a99cb1bc..3f76befda67e5 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts @@ -6,10 +6,8 @@ */ import type { Map as MbMap } from '@kbn/mapbox-gl'; -import { ReactElement } from 'react'; import { VectorSourceRequestMeta } from '../../../../common/descriptor_types'; import { IVectorSource } from '.'; -import { IVectorStyle } from '../../styles/vector/vector_style'; export interface IMvtVectorSource extends IVectorSource { /* @@ -33,13 +31,4 @@ export interface IMvtVectorSource extends IVectorSource { * Syncs source specific styling with mbMap this allows custom sources to further style the map layers/filters */ syncSourceStyle?(mbMap: MbMap, getLayerIds: () => string[]): void; - - /** - * specifies if a source provides its own legend details or if the default vector_style is used if the source has this method it must also implement renderLegendDetails - */ - hasLegendDetails?(): Promise; - /** - * specifies if a source provides its own legend details or if the default vector_style is used - */ - renderLegendDetails?(vectorStyle: IVectorStyle): ReactElement | null; } diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index aeffc6f6c167d..a3b2b494827b2 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { ReactElement } from 'react'; import { FeatureCollection, GeoJsonProperties, @@ -22,6 +22,7 @@ import { Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { ActionExecutionContext, Action } from '@kbn/ui-actions-plugin/public'; +import { IVectorStyle } from '../../styles/vector/vector_style'; import { GEO_JSON_TYPE, VECTOR_SHAPE_TYPE } from '../../../../common/constants'; import { TooltipFeatureAction } from '../../../../common/descriptor_types'; import { ITooltipProperty, TooltipProperty } from '../../tooltips/tooltip_property'; @@ -145,6 +146,15 @@ export interface IVectorSource extends ISource { * Provide unique ids for managing source requests in Inspector */ getInspectorRequestIds(): string[]; + + /** + * specifies if a source provides its own legend details or if the default vector_style is used if the source has this method it must also implement renderLegendDetails + */ + hasLegendDetails?(): Promise; + /** + * specifies if a source provides its own legend details or if the default vector_style is used + */ + renderLegendDetails?(vectorStyle: IVectorStyle): ReactElement | null; } export class AbstractVectorSource extends AbstractSource implements IVectorSource { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index dee0a072e8681..0ec1a21fe56ff 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -75,7 +75,7 @@ import { IStyle } from '../style'; import { IStyleProperty } from './properties/style_property'; import { IField } from '../../fields/field'; import { IVectorLayer } from '../../layers/vector_layer'; -import { IMvtVectorSource, IVectorSource } from '../../sources/vector_source'; +import { IVectorSource } from '../../sources/vector_source'; import { createStyleFieldsHelper, StyleFieldsHelper } from './style_fields_helper'; import { IESAggField } from '../../fields/agg'; @@ -721,20 +721,18 @@ export class VectorStyle implements IVectorStyle { }; async hasLegendDetails() { - if (!this._source.isMvt()) { - return this._getLegendDetailStyleProperties().length > 0; - } - const source = this._source as IMvtVectorSource; - - return source.hasLegendDetails && source.renderLegendDetails - ? await source.hasLegendDetails() + return this._source.hasLegendDetails && this._source.renderLegendDetails + ? await this._source.hasLegendDetails() : this._getLegendDetailStyleProperties().length > 0; } renderLegendDetails() { const symbolId = this._getSymbolId(); const svg = symbolId ? this.getIconSvg(symbolId) : undefined; - const VectorLegend = ( + + return this._source.renderLegendDetails ? ( + this._source.renderLegendDetails(this) + ) : ( ); - - if (!this._source.isMvt()) { - return VectorLegend; - } - - const source = this._source as IMvtVectorSource; - return source.renderLegendDetails ? source.renderLegendDetails(this) : VectorLegend; } clearFeatureState(featureCollection: FeatureCollection, mbMap: MbMap, sourceId: string) {