@carto/api-client 0.5.1 → 0.5.2-alpha.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 (65) hide show
  1. package/build/api-client.cjs +194 -84
  2. package/build/api-client.cjs.map +1 -1
  3. package/build/api-client.d.cts +28 -1
  4. package/build/api-client.d.ts +28 -1
  5. package/build/api-client.js +186 -83
  6. package/build/api-client.js.map +1 -1
  7. package/build/worker.js +30 -19
  8. package/build/worker.js.map +1 -1
  9. package/package.json +5 -3
  10. package/src/api/carto-api-error.ts +1 -1
  11. package/src/api/endpoints.ts +1 -1
  12. package/src/api/index.ts +2 -2
  13. package/src/api/query.ts +1 -1
  14. package/src/api/request-with-parameters.ts +2 -2
  15. package/src/deck/get-data-filter-extension-props.ts +3 -3
  16. package/src/fetch-map/basemap-styles.ts +2 -2
  17. package/src/fetch-map/basemap.ts +2 -2
  18. package/src/fetch-map/fetch-map.ts +3 -3
  19. package/src/fetch-map/layer-map.ts +81 -5
  20. package/src/fetch-map/parse-map.ts +71 -7
  21. package/src/fetch-map/source.ts +10 -10
  22. package/src/fetch-map/types.ts +7 -3
  23. package/src/filters/Filter.ts +4 -4
  24. package/src/filters/FilterTypes.ts +1 -1
  25. package/src/filters/geosjonFeatures.ts +3 -3
  26. package/src/filters/tileFeatures.ts +8 -3
  27. package/src/filters/tileFeaturesGeometries.ts +5 -5
  28. package/src/filters/tileFeaturesRaster.ts +3 -3
  29. package/src/filters/tileFeaturesSpatialIndex.ts +4 -4
  30. package/src/filters.ts +38 -3
  31. package/src/geo.ts +1 -1
  32. package/src/index.ts +3 -3
  33. package/src/models/model.ts +6 -3
  34. package/src/operations/aggregation.ts +14 -4
  35. package/src/operations/applySorting.ts +2 -2
  36. package/src/operations/groupBy.ts +2 -2
  37. package/src/operations/groupByDate.ts +2 -2
  38. package/src/operations/histogram.ts +2 -2
  39. package/src/operations/scatterPlot.ts +2 -2
  40. package/src/sources/base-source.ts +2 -2
  41. package/src/sources/boundary-query-source.ts +1 -1
  42. package/src/sources/h3-query-source.ts +1 -1
  43. package/src/sources/h3-table-source.ts +1 -1
  44. package/src/sources/h3-tileset-source.ts +1 -1
  45. package/src/sources/quadbin-query-source.ts +1 -1
  46. package/src/sources/quadbin-table-source.ts +1 -1
  47. package/src/sources/quadbin-tileset-source.ts +1 -1
  48. package/src/sources/raster-source.ts +1 -1
  49. package/src/sources/types.ts +2 -2
  50. package/src/sources/vector-query-source.ts +1 -1
  51. package/src/sources/vector-table-source.ts +1 -1
  52. package/src/sources/vector-tileset-source.ts +1 -1
  53. package/src/utils/getTileFormat.ts +1 -1
  54. package/src/utils/makeIntervalComplete.ts +1 -1
  55. package/src/utils/transformTileCoordsToWGS84.ts +1 -1
  56. package/src/utils/transformToTileCoords.ts +1 -1
  57. package/src/utils.ts +1 -1
  58. package/src/widget-sources/types.ts +5 -2
  59. package/src/widget-sources/widget-query-source.ts +4 -4
  60. package/src/widget-sources/widget-raster-source.ts +2 -2
  61. package/src/widget-sources/widget-remote-source.ts +6 -5
  62. package/src/widget-sources/widget-source.ts +3 -3
  63. package/src/widget-sources/widget-table-source.ts +4 -4
  64. package/src/widget-sources/widget-tileset-source-impl.ts +8 -11
  65. package/src/widget-sources/widget-tileset-source.ts +7 -7
package/package.json CHANGED
@@ -8,11 +8,12 @@
8
8
  "homepage": "https://github.com/CartoDB/carto-api-client#readme",
9
9
  "author": "Don McCurdy <donmccurdy@carto.com>",
10
10
  "packageManager": "yarn@4.3.1",
11
- "version": "0.5.1",
11
+ "version": "0.5.2-alpha.1",
12
12
  "license": "MIT",
13
13
  "publishConfig": {
14
14
  "access": "public"
15
15
  },
16
+ "main": "./build/api-client.cjs",
16
17
  "type": "module",
17
18
  "sideEffects": false,
18
19
  "exports": {
@@ -39,7 +40,7 @@
39
40
  "scripts": {
40
41
  "build": "tsup",
41
42
  "build:watch": "tsup --watch",
42
- "dev": "yarn build && concurrently --names tsup,vite \"yarn build:watch\" \"vite --config examples/vite.config.ts --open\"",
43
+ "dev": "yarn build && concurrently \"yarn build:watch\" \"vite --config examples/vite.config.ts --open\"",
43
44
  "test": "vitest run --typecheck",
44
45
  "test:watch": "vitest watch --typecheck",
45
46
  "coverage": "vitest run --coverage.enabled --coverage.all false",
@@ -127,5 +128,6 @@
127
128
  "resolutions": {
128
129
  "@carto/api-client": "portal:./",
129
130
  "rollup": "^4.20.0"
130
- }
131
+ },
132
+ "stableVersion": "0.5.1"
131
133
  }
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {MapType} from '../types.js';
5
+ import type {MapType} from '../types.js';
6
6
 
7
7
  export type APIRequestType =
8
8
  | 'Map data'
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {MapType} from '../types.js';
5
+ import type {MapType} from '../types.js';
6
6
 
7
7
  export type V3Endpoint = 'maps' | 'stats' | 'sql';
8
8
 
package/src/api/index.ts CHANGED
@@ -4,8 +4,8 @@
4
4
 
5
5
  export {
6
6
  CartoAPIError,
7
- APIErrorContext,
8
- APIRequestType,
7
+ type APIErrorContext,
8
+ type APIRequestType,
9
9
  } from './carto-api-error.js';
10
10
  // Internal, but required for fetchMap().
11
11
  export {buildPublicMapUrl, buildStatsUrl} from './endpoints.js';
package/src/api/query.ts CHANGED
@@ -10,7 +10,7 @@ import type {
10
10
  } from '../sources/types.js';
11
11
  import {buildQueryUrl} from './endpoints.js';
12
12
  import {requestWithParameters} from './request-with-parameters.js';
13
- import {APIErrorContext} from './carto-api-error.js';
13
+ import type {APIErrorContext} from './carto-api-error.js';
14
14
  import {getClient} from '../client.js';
15
15
 
16
16
  export type QueryOptions = SourceOptions & QuerySourceOptions;
@@ -3,11 +3,11 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {isPureObject} from '../utils.js';
6
- import {CartoAPIError, APIErrorContext} from './carto-api-error.js';
6
+ import {CartoAPIError, type APIErrorContext} from './carto-api-error.js';
7
7
  import {V3_MINOR_VERSION} from '../constants-internal.js';
8
8
  import {DEFAULT_MAX_LENGTH_URL} from '../constants-internal.js';
9
9
  import {getClient} from '../client.js';
10
- import {LocalCacheOptions} from '../sources/types.js';
10
+ import type {LocalCacheOptions} from '../sources/types.js';
11
11
 
12
12
  const DEFAULT_HEADERS = {
13
13
  Accept: 'application/json',
@@ -1,8 +1,8 @@
1
- import {Feature} from 'geojson';
2
- import {FilterLogicalOperator, Filters} from '../types.js';
1
+ import type {Feature} from 'geojson';
2
+ import type {FilterLogicalOperator, Filters} from '../types.js';
3
3
  import {FilterType} from '../constants.js';
4
4
  import {_buildFeatureFilter} from '../filters/index.js';
5
- import {FeatureData} from '../types-internal.js';
5
+ import type {FeatureData} from '../types-internal.js';
6
6
 
7
7
  type TimeFilter = Filters['string'][FilterType.TIME] & {
8
8
  params?: {offsetBy?: number};
@@ -1,5 +1,5 @@
1
- import {CartoAPIError, APIErrorContext} from '../api/index.js';
2
- import {GoogleBasemapProps} from './types.js';
1
+ import {CartoAPIError, type APIErrorContext} from '../api/index.js';
2
+ import type {GoogleBasemapProps} from './types.js';
3
3
 
4
4
  const cartoStyleUrlTemplate =
5
5
  'https://basemaps.cartocdn.com/gl/{basemap}-gl-style/style.json';
@@ -6,8 +6,8 @@ import {
6
6
  getStyleUrl,
7
7
  someLayerGroupsDisabled,
8
8
  } from './basemap-styles.js';
9
- import {Basemap, KeplerMapConfig, MapLibreBasemapProps} from './types.js';
10
- import {APIErrorContext} from '../api/index.js';
9
+ import type {Basemap, KeplerMapConfig, MapLibreBasemapProps} from './types.js';
10
+ import type {APIErrorContext} from '../api/index.js';
11
11
 
12
12
  const CUSTOM_STYLE_ID_PREFIX = 'custom:';
13
13
  const DEFAULT_CARTO_STYLE = 'positron';
@@ -1,19 +1,19 @@
1
1
  import {DEFAULT_API_BASE_URL} from '../constants.js';
2
2
 
3
3
  import {
4
- APIErrorContext,
4
+ type APIErrorContext,
5
5
  CartoAPIError,
6
6
  buildPublicMapUrl,
7
7
  buildStatsUrl,
8
8
  requestWithParameters,
9
9
  } from '../api/index.js';
10
10
 
11
- import {ParseMapResult, parseMap} from './parse-map.js';
11
+ import {type ParseMapResult, parseMap} from './parse-map.js';
12
12
  import {assert} from '../utils.js';
13
13
  import type {Basemap, Dataset, KeplerMapConfig} from './types.js';
14
14
  import {fetchBasemapProps} from './basemap.js';
15
15
  import {configureSource} from './source.js';
16
- import {Filters} from '../types.js';
16
+ import type {Filters} from '../types.js';
17
17
  import {isRemoteCalculationSupported} from './utils.js';
18
18
 
19
19
  /* global clearInterval, setInterval, URL */
@@ -23,7 +23,7 @@ export type LayerType =
23
23
  | 'tileset';
24
24
 
25
25
  import {createBinaryProxy, scaleIdentity} from './utils.js';
26
- import {
26
+ import type {
27
27
  CustomMarkersRange,
28
28
  Dataset,
29
29
  MapLayerConfig,
@@ -31,6 +31,8 @@ import {
31
31
  VisualChannelField,
32
32
  VisualChannels,
33
33
  } from './types.js';
34
+ import type {ProviderType} from '../types.js';
35
+ import {DEFAULT_AGGREGATION_EXP_ALIAS} from '../constants-internal.js';
34
36
 
35
37
  const SCALE_FUNCS: Record<string, () => any> = {
36
38
  linear: scaleLinear,
@@ -118,7 +120,8 @@ const customMarkersPropsMap = {
118
120
  const heatmapTilePropsMap = {
119
121
  visConfig: {
120
122
  colorRange: (x: any) => ({colorRange: x.colors.map(hexToRGBA)}),
121
- radius: 'radiusPixels',
123
+ radius: (radius: number) => ({radiusPixels: 20 + radius}),
124
+ opacity: 'opacity',
122
125
  },
123
126
  };
124
127
 
@@ -146,6 +149,17 @@ const deprecatedLayerTypes = [
146
149
  'point',
147
150
  ];
148
151
 
152
+ /** @privateRemarks Source: Builder */
153
+ export const TEXT_LABEL_INDEX = 0;
154
+
155
+ /** @privateRemarks Source: Builder */
156
+ export const TEXT_OUTLINE_OPACITY = 64;
157
+
158
+ export const TEXT_NUMBER_FORMATTER = new Intl.NumberFormat('en-US', {
159
+ maximumFractionDigits: 2,
160
+ notation: 'compact',
161
+ });
162
+
149
163
  export function getLayerProps(
150
164
  type: LayerType,
151
165
  config: MapLayerConfig,
@@ -272,9 +286,9 @@ function findAccessorKey(keys: string[], properties: any): string[] {
272
286
  }
273
287
  }
274
288
 
275
- throw new Error(
276
- `Could not find property for any accessor key: ${keys.join(', ')}`
277
- );
289
+ // If data doesn't contain any valid keys, return all keys to run search
290
+ // on next feature
291
+ return keys;
278
292
  }
279
293
 
280
294
  export function getColorValueAccessor(
@@ -459,3 +473,65 @@ export function getTextAccessor({name, type}: VisualChannelField, data: any) {
459
473
  }
460
474
 
461
475
  export {domainFromValues as _domainFromValues};
476
+
477
+ /** @privateRemarks Source: Builder */
478
+ export function calculateClusterRadius(
479
+ properties: {[column: string]: number},
480
+ stats: Record<string, {min: number; max: number}>,
481
+ radiusRange: [number, number],
482
+ column: string
483
+ ): number {
484
+ const {min, max} = stats[column];
485
+ const value = properties[column];
486
+
487
+ // When there's a single cluster on the screen, min and max are equivalent, so we should return the maximum radius
488
+ if (min === max) return radiusRange[1];
489
+
490
+ const normalizedValue = (value - min) / (max - min);
491
+ return radiusRange[0] + normalizedValue * (radiusRange[1] - radiusRange[0]);
492
+ }
493
+
494
+ /** @privateRemarks Source: Builder */
495
+ export function getDefaultAggregationExpColumnAliasForLayerType(
496
+ layerType: LayerType,
497
+ provider: ProviderType,
498
+ columns: string[]
499
+ ): string {
500
+ if (columns && layerType === 'clusterTile') {
501
+ return getColumnAliasForAggregationExp(
502
+ getDefaultColumnFromSchemaForAggregationExp(columns),
503
+ 'count',
504
+ provider
505
+ );
506
+ } else {
507
+ return DEFAULT_AGGREGATION_EXP_ALIAS;
508
+ }
509
+ }
510
+
511
+ /** @privateRemarks Source: Builder */
512
+ function getColumnAliasForAggregationExp(
513
+ name: string,
514
+ aggregation: string,
515
+ provider: ProviderType
516
+ ) {
517
+ const columnAlias = `${name}_${aggregation}`;
518
+ return provider === 'snowflake' ? columnAlias.toUpperCase() : columnAlias;
519
+ }
520
+
521
+ /** @privateRemarks Source: Builder */
522
+ function getDefaultColumnFromSchemaForAggregationExp(
523
+ columns: string[]
524
+ ): string {
525
+ return columns ? columns[0] : '';
526
+ }
527
+
528
+ /** @privateRemarks Source: Builder */
529
+ export function calculateClusterTextFontSize(radius: number): number {
530
+ if (radius >= 80) return 24;
531
+ if (radius >= 72) return 24;
532
+ if (radius >= 56) return 20;
533
+ if (radius >= 40) return 16;
534
+ if (radius >= 24) return 13;
535
+ if (radius >= 8) return 11;
536
+ return 11;
537
+ }
@@ -1,22 +1,28 @@
1
1
  import type {ColorParameters} from '@luma.gl/core';
2
2
  import {
3
- AGGREGATION,
3
+ calculateClusterRadius,
4
+ calculateClusterTextFontSize,
5
+ getDefaultAggregationExpColumnAliasForLayerType,
4
6
  getLayerProps,
5
7
  getColorAccessor,
6
8
  getColorValueAccessor,
7
9
  getSizeAccessor,
8
10
  getTextAccessor,
9
- OPACITY_MAP,
10
11
  opacityToAlpha,
11
12
  getIconUrlAccessor,
12
13
  negateAccessor,
13
14
  getMaxMarkerSize,
14
- LayerType,
15
+ type LayerType,
16
+ AGGREGATION,
17
+ OPACITY_MAP,
18
+ TEXT_NUMBER_FORMATTER,
19
+ TEXT_LABEL_INDEX,
20
+ TEXT_OUTLINE_OPACITY,
15
21
  } from './layer-map.js';
16
22
 
17
23
  import {assert, isEmptyObject} from '../utils.js';
18
- import {Filters} from '../types.js';
19
- import {
24
+ import type {Filters} from '../types.js';
25
+ import type {
20
26
  KeplerMapConfig,
21
27
  MapLayerConfig,
22
28
  VisualChannels,
@@ -100,7 +106,14 @@ export function parseMap(json: any) {
100
106
  ...defaultProps,
101
107
  ...createInteractionProps(interactionConfig),
102
108
  ...styleProps,
103
- ...createChannelProps(id, type, config, visualChannels, data), // Must come after style
109
+ ...createChannelProps(
110
+ id,
111
+ type,
112
+ config,
113
+ visualChannels,
114
+ data,
115
+ dataset
116
+ ), // Must come after style
104
117
  ...createParametersProp(
105
118
  layerBlending,
106
119
  styleProps.parameters || {}
@@ -197,7 +210,8 @@ function createChannelProps(
197
210
  type: string,
198
211
  config: MapLayerConfig,
199
212
  visualChannels: VisualChannels,
200
- data: any
213
+ data: any,
214
+ dataset: Dataset
201
215
  ) {
202
216
  const {
203
217
  colorField,
@@ -261,6 +275,56 @@ function createChannelProps(
261
275
  }
262
276
  }
263
277
 
278
+ if (type === 'clusterTile') {
279
+ const aggregationExpAlias = getDefaultAggregationExpColumnAliasForLayerType(
280
+ type,
281
+ dataset.providerId,
282
+ dataset.columns
283
+ );
284
+
285
+ result.pointType = visConfig.isTextVisible ? 'circle+text' : 'circle';
286
+ result.clusterLevel = visConfig.clusterLevel;
287
+
288
+ result.getWeight = (d: any) => {
289
+ return d.properties[aggregationExpAlias];
290
+ };
291
+
292
+ result.getPointRadius = (d: any, info: any) => {
293
+ return calculateClusterRadius(
294
+ d.properties,
295
+ info.data.attributes.stats,
296
+ visConfig.radiusRange as [number, number],
297
+ aggregationExpAlias
298
+ );
299
+ };
300
+
301
+ result.textCharacterSet = 'auto';
302
+ result.textFontFamily = 'Inter, sans';
303
+ result.textFontSettings = {sdf: true};
304
+ result.textFontWeight = 600;
305
+
306
+ result.getText = (d: any) =>
307
+ TEXT_NUMBER_FORMATTER.format(d.properties[aggregationExpAlias]);
308
+
309
+ result.getTextColor = config.textLabel[TEXT_LABEL_INDEX].color;
310
+ result.textOutlineColor = [
311
+ ...(config.textLabel[TEXT_LABEL_INDEX].outlineColor as number[]),
312
+ TEXT_OUTLINE_OPACITY,
313
+ ];
314
+ result.textOutlineWidth = 5;
315
+ result.textSizeUnits = 'pixels';
316
+
317
+ result.getTextSize = (d: any, info: any) => {
318
+ const radius = calculateClusterRadius(
319
+ d.properties,
320
+ info.data.attributes.stats,
321
+ visConfig.radiusRange as [number, number],
322
+ aggregationExpAlias
323
+ );
324
+ return calculateClusterTextFontSize(radius);
325
+ };
326
+ }
327
+
264
328
  if (radiusField || sizeField) {
265
329
  result.getPointRadius = getSizeAccessor(
266
330
  // @ts-ignore
@@ -1,6 +1,6 @@
1
- import {Dataset} from './types.js';
1
+ import type {Dataset} from './types.js';
2
2
  import {SpatialIndex, SpatialIndexColumn} from '../constants.js';
3
- import {
3
+ import type {
4
4
  QuerySourceOptions,
5
5
  TableSourceOptions,
6
6
  TilejsonResult,
@@ -15,22 +15,22 @@ import {
15
15
  } from '../constants-internal.js';
16
16
  import {
17
17
  h3QuerySource,
18
- H3QuerySourceOptions,
18
+ type H3QuerySourceOptions,
19
19
  h3TableSource,
20
- H3TableSourceOptions,
20
+ type H3TableSourceOptions,
21
21
  quadbinQuerySource,
22
- QuadbinQuerySourceOptions,
22
+ type QuadbinQuerySourceOptions,
23
23
  quadbinTableSource,
24
- QuadbinTableSourceOptions,
24
+ type QuadbinTableSourceOptions,
25
25
  rasterSource,
26
26
  vectorQuerySource,
27
- VectorQuerySourceOptions,
27
+ type VectorQuerySourceOptions,
28
28
  vectorTableSource,
29
- VectorTableSourceOptions,
29
+ type VectorTableSourceOptions,
30
30
  vectorTilesetSource,
31
- VectorTilesetSourceOptions,
31
+ type VectorTilesetSourceOptions,
32
32
  } from '../sources/index.js';
33
- import {Filter} from '../types.js';
33
+ import type {Filter} from '../types.js';
34
34
 
35
35
  type FetchDatasetOptions = {
36
36
  accessToken: string;
@@ -1,6 +1,6 @@
1
- import {LayerType, SCALE_TYPE} from './layer-map.js';
2
- import {Format, MapType, ProviderType, QueryParameters} from '../types.js';
3
- import {TilejsonResult} from '../sources/types.js';
1
+ import type {LayerType, SCALE_TYPE} from './layer-map.js';
2
+ import type {Format, MapType, ProviderType, QueryParameters} from '../types.js';
3
+ import type {TilejsonResult} from '../sources/types.js';
4
4
 
5
5
  export type VisualChannelField = {
6
6
  name: string;
@@ -75,6 +75,10 @@ export type VisConfig = {
75
75
  heightAggregation?: any;
76
76
 
77
77
  weightAggregation?: any;
78
+
79
+ // type = clusterTile
80
+ clusterLevel?: number;
81
+ isTextVisible?: boolean;
78
82
  };
79
83
 
80
84
  export type TextLabel = {
@@ -1,9 +1,9 @@
1
1
  import {filterFunctions} from './FilterTypes.js';
2
- import {Filter, FilterLogicalOperator, Filters} from '../types.js';
3
- import {Feature} from 'geojson';
2
+ import type {Filter, FilterLogicalOperator, Filters} from '../types.js';
3
+ import type {Feature} from 'geojson';
4
4
  import {FilterType} from '../constants.js';
5
- import {FeatureData} from '../types-internal.js';
6
- import {BinaryFeature} from '@loaders.gl/schema';
5
+ import type {FeatureData} from '../types-internal.js';
6
+ import type {BinaryFeature} from '@loaders.gl/schema';
7
7
 
8
8
  const LOGICAL_OPERATOR_METHODS: Record<
9
9
  FilterLogicalOperator,
@@ -1,5 +1,5 @@
1
1
  import {FilterType} from '../constants.js';
2
- import {FilterInterval, StringSearchOptions} from '../types.js';
2
+ import type {FilterInterval, StringSearchOptions} from '../types.js';
3
3
  import {makeIntervalComplete} from '../utils/makeIntervalComplete.js';
4
4
 
5
5
  export type FilterFunction = (
@@ -1,7 +1,7 @@
1
1
  import intersects from '@turf/boolean-intersects';
2
- import {FeatureCollection} from 'geojson';
3
- import {FeatureData} from '../types-internal.js';
4
- import {SpatialFilter} from '../types.js';
2
+ import type {FeatureCollection} from 'geojson';
3
+ import type {FeatureData} from '../types-internal.js';
4
+ import type {SpatialFilter} from '../types.js';
5
5
 
6
6
  export function geojsonFeatures({
7
7
  geojson,
@@ -1,10 +1,15 @@
1
- import {RasterTile, SpatialFilter, SpatialIndexTile, Tile} from '../types.js';
1
+ import type {
2
+ RasterTile,
3
+ SpatialFilter,
4
+ SpatialIndexTile,
5
+ Tile,
6
+ } from '../types.js';
2
7
  import {tileFeaturesGeometries} from './tileFeaturesGeometries.js';
3
8
  import {tileFeaturesSpatialIndex} from './tileFeaturesSpatialIndex.js';
4
9
  import {TileFormat} from '../constants.js';
5
10
  import {DEFAULT_GEO_COLUMN} from '../constants-internal.js';
6
- import {FeatureData} from '../types-internal.js';
7
- import {RasterMetadata, SpatialDataType} from '../sources/types.js';
11
+ import type {FeatureData} from '../types-internal.js';
12
+ import type {RasterMetadata, SpatialDataType} from '../sources/types.js';
8
13
  import {isRasterTile, tileFeaturesRaster} from './tileFeaturesRaster.js';
9
14
  import {assert} from '../utils.js';
10
15
 
@@ -5,7 +5,7 @@ import intersect from '@turf/intersect';
5
5
  import {transformToTileCoords} from '../utils/transformToTileCoords.js';
6
6
  import {transformTileCoordsToWGS84} from '../utils/transformTileCoordsToWGS84.js';
7
7
  import {TileFormat} from '../constants.js';
8
- import {
8
+ import type {
9
9
  BBox,
10
10
  Feature,
11
11
  Geometry,
@@ -15,11 +15,11 @@ import {
15
15
  Polygon,
16
16
  Position,
17
17
  } from 'geojson';
18
- import {SpatialFilter, Tile} from '../types.js';
19
- import {TileFeatureExtractOptions} from './tileFeatures.js';
18
+ import type {SpatialFilter, Tile} from '../types.js';
19
+ import type {TileFeatureExtractOptions} from './tileFeatures.js';
20
20
  import {featureCollection} from '@turf/helpers';
21
- import {FeatureData} from '../types-internal.js';
22
- import {
21
+ import type {FeatureData} from '../types-internal.js';
22
+ import type {
23
23
  BinaryAttribute,
24
24
  BinaryFeature,
25
25
  BinaryGeometryType,
@@ -4,9 +4,9 @@ import {
4
4
  geometryToCells,
5
5
  getResolution,
6
6
  } from 'quadbin';
7
- import {RasterTile, SpatialFilter, Tile} from '../types.js';
8
- import {FeatureData} from '../types-internal.js';
9
- import {
7
+ import type {RasterTile, SpatialFilter, Tile} from '../types.js';
8
+ import type {FeatureData} from '../types-internal.js';
9
+ import type {
10
10
  RasterMetadata,
11
11
  RasterMetadataBand,
12
12
  SpatialDataType,
@@ -1,11 +1,11 @@
1
1
  import {SpatialIndex} from '../constants.js';
2
2
  import {getResolution as quadbinGetResolution, geometryToCells} from 'quadbin';
3
3
  import bboxClip from '@turf/bbox-clip';
4
- import {SpatialFilter, SpatialIndexTile} from '../types.js';
5
- import {BBox, Feature} from 'geojson';
4
+ import type {SpatialFilter, SpatialIndexTile} from '../types.js';
5
+ import type {BBox, Feature} from 'geojson';
6
6
  import {getResolution as h3GetResolution, polygonToCells} from 'h3-js';
7
- import {FeatureData} from '../types-internal.js';
8
- import {SpatialDataType} from '../sources/types.js';
7
+ import type {FeatureData} from '../types-internal.js';
8
+ import type {SpatialDataType} from '../sources/types.js';
9
9
 
10
10
  export type TileFeaturesSpatialIndexOptions = {
11
11
  tiles: SpatialIndexTile[];
package/src/filters.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import {FilterType} from './constants.js';
2
- import {Filter} from './types.js';
2
+ import type {Filter} from './types.js';
3
3
  import {isEmptyObject} from './utils.js';
4
4
 
5
+ const FILTER_TYPES = new Set(Object.values(FilterType));
6
+ const isFilterType = (type: string): type is FilterType =>
7
+ FILTER_TYPES.has(type as FilterType);
8
+
5
9
  type FilterTypeOptions<T extends FilterType> = {
6
10
  type: T;
7
11
  column: string;
@@ -53,7 +57,7 @@ export function removeFilter(
53
57
  }
54
58
 
55
59
  if (owner) {
56
- for (const type of Object.values(FilterType)) {
60
+ for (const type of FILTER_TYPES) {
57
61
  if (owner === filter[type as FilterType]?.owner) {
58
62
  delete filter[type as FilterType];
59
63
  }
@@ -97,7 +101,7 @@ export function hasFilter(
97
101
  return true;
98
102
  }
99
103
 
100
- for (const type of Object.values(FilterType)) {
104
+ for (const type of FILTER_TYPES) {
101
105
  if (owner === filter[type as FilterType]?.owner) {
102
106
  return true;
103
107
  }
@@ -127,3 +131,34 @@ export function getFilter<T extends FilterType>(
127
131
 
128
132
  return null;
129
133
  }
134
+
135
+ /**
136
+ * Given all filters for a dataset, returns the subset of filters that are not
137
+ * attributable to the given owner. Typically used to allow filterable widgets
138
+ * to affect other widgets *without* filtering themselves.
139
+ *
140
+ * @privateRemarks Source: @carto/react-widgets
141
+ */
142
+ export function getApplicableFilters(
143
+ owner?: string,
144
+ filters?: Record<string, Filter>
145
+ ): Record<string, Filter> {
146
+ if (!filters) return {};
147
+
148
+ const applicableFilters: Record<string, Filter> = {};
149
+
150
+ for (const column in filters) {
151
+ for (const type in filters[column]) {
152
+ if (!isFilterType(type)) continue;
153
+
154
+ const filter = filters[column][type];
155
+ const isApplicable = !owner || !filter?.owner || filter?.owner !== owner;
156
+ if (filter && isApplicable) {
157
+ applicableFilters[column] ||= {};
158
+ (applicableFilters[column][type] as typeof filter) = filter;
159
+ }
160
+ }
161
+ }
162
+
163
+ return applicableFilters;
164
+ }
package/src/geo.ts CHANGED
@@ -4,7 +4,7 @@ import union from '@turf/union';
4
4
  import {getType} from '@turf/invariant';
5
5
  import {polygon, multiPolygon, feature, featureCollection} from '@turf/helpers';
6
6
  import type {BBox, Geometry, MultiPolygon, Polygon, Position} from 'geojson';
7
- import {SpatialFilter} from './types.js';
7
+ import type {SpatialFilter} from './types.js';
8
8
 
9
9
  /**
10
10
  * Returns a {@link SpatialFilter} for a given viewport, typically obtained
package/src/index.ts CHANGED
@@ -9,10 +9,10 @@ export * from './widget-sources/index.js';
9
9
  export * from './types.js';
10
10
 
11
11
  export {
12
- APIErrorContext,
13
- APIRequestType,
12
+ type APIErrorContext,
13
+ type APIRequestType,
14
14
  CartoAPIError,
15
- QueryOptions,
15
+ type QueryOptions,
16
16
  buildPublicMapUrl, // Internal, but required for fetchMap().
17
17
  buildStatsUrl, // Internal, but required for fetchMap().
18
18
  query,