@deck.gl/carto 8.6.2 → 8.7.0-alpha.2

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/dist/dist.dev.js +24009 -380
  2. package/dist/es5/api/index.js +14 -8
  3. package/dist/es5/api/index.js.map +1 -1
  4. package/dist/es5/api/layer-map.js +244 -0
  5. package/dist/es5/api/layer-map.js.map +1 -0
  6. package/dist/es5/api/maps-api-common.js +9 -13
  7. package/dist/es5/api/maps-api-common.js.map +1 -1
  8. package/dist/es5/api/maps-client.js +98 -157
  9. package/dist/es5/api/maps-client.js.map +1 -1
  10. package/dist/es5/api/maps-v3-client.js +325 -304
  11. package/dist/es5/api/maps-v3-client.js.map +1 -1
  12. package/dist/es5/api/parseMap.js +210 -0
  13. package/dist/es5/api/parseMap.js.map +1 -0
  14. package/dist/es5/basemap.js +1 -1
  15. package/dist/es5/basemap.js.map +1 -1
  16. package/dist/es5/config.js +23 -39
  17. package/dist/es5/config.js.map +1 -1
  18. package/dist/es5/index.js +22 -16
  19. package/dist/es5/index.js.map +1 -1
  20. package/dist/es5/layers/carto-bqtiler-layer.js +6 -39
  21. package/dist/es5/layers/carto-bqtiler-layer.js.map +1 -1
  22. package/dist/es5/layers/carto-layer.js +130 -211
  23. package/dist/es5/layers/carto-layer.js.map +1 -1
  24. package/dist/es5/layers/carto-sql-layer.js +6 -39
  25. package/dist/es5/layers/carto-sql-layer.js.map +1 -1
  26. package/dist/es5/style/color-bins-style.js +14 -13
  27. package/dist/es5/style/color-bins-style.js.map +1 -1
  28. package/dist/es5/style/color-categories-style.js +16 -39
  29. package/dist/es5/style/color-categories-style.js.map +1 -1
  30. package/dist/es5/style/color-continuous-style.js +14 -13
  31. package/dist/es5/style/color-continuous-style.js.map +1 -1
  32. package/dist/es5/style/palette.js +15 -21
  33. package/dist/es5/style/palette.js.map +1 -1
  34. package/dist/es5/style/utils.js +6 -13
  35. package/dist/es5/style/utils.js.map +1 -1
  36. package/dist/esm/api/index.js +1 -1
  37. package/dist/esm/api/index.js.map +1 -1
  38. package/dist/esm/api/layer-map.js +219 -0
  39. package/dist/esm/api/layer-map.js.map +1 -0
  40. package/dist/esm/api/maps-client.js +1 -1
  41. package/dist/esm/api/maps-client.js.map +1 -1
  42. package/dist/esm/api/maps-v3-client.js +145 -16
  43. package/dist/esm/api/maps-v3-client.js.map +1 -1
  44. package/dist/esm/api/parseMap.js +194 -0
  45. package/dist/esm/api/parseMap.js.map +1 -0
  46. package/dist/esm/config.js +11 -26
  47. package/dist/esm/config.js.map +1 -1
  48. package/dist/esm/index.js +1 -1
  49. package/dist/esm/index.js.map +1 -1
  50. package/dist/esm/layers/carto-layer.js +7 -9
  51. package/dist/esm/layers/carto-layer.js.map +1 -1
  52. package/dist/esm/style/color-bins-style.js.map +1 -1
  53. package/dist/esm/style/color-continuous-style.js.map +1 -1
  54. package/dist.min.js +278 -1
  55. package/package.json +7 -3
  56. package/src/api/index.js +1 -1
  57. package/src/api/layer-map.js +194 -0
  58. package/src/api/maps-client.js +3 -7
  59. package/src/api/maps-v3-client.js +114 -11
  60. package/src/api/parseMap.js +182 -0
  61. package/src/config.js +8 -39
  62. package/src/index.js +1 -0
  63. package/src/layers/carto-layer.js +3 -5
  64. package/src/style/color-bins-style.js +1 -3
  65. package/src/style/color-continuous-style.js +1 -3
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@deck.gl/carto",
3
3
  "description": "CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.",
4
4
  "license": "MIT",
5
- "version": "8.6.2",
5
+ "version": "8.7.0-alpha.2",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
@@ -36,7 +36,11 @@
36
36
  "@loaders.gl/tiles": "^3.0.8",
37
37
  "@math.gl/web-mercator": "^3.5.4",
38
38
  "cartocolor": "^4.0.2",
39
- "d3-scale": "^3.2.3"
39
+ "d3-array": "^2.8.0",
40
+ "d3-color": "^2.0.0",
41
+ "d3-format": "^2.0.0",
42
+ "d3-scale": "^3.2.3",
43
+ "moment-timezone": "^0.5.33"
40
44
  },
41
45
  "peerDependencies": {
42
46
  "@deck.gl/core": "^8.0.0",
@@ -44,5 +48,5 @@
44
48
  "@deck.gl/layers": "^8.0.0",
45
49
  "@loaders.gl/core": "^3.0.0"
46
50
  },
47
- "gitHead": "8ee546f7a28f93ba0e661bdf7ba18b45f1c07704"
51
+ "gitHead": "67bc5fe69149ae933a5f203724ad58f58c4a1737"
48
52
  }
package/src/api/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export {FORMATS, MAP_TYPES, API_VERSIONS} from './maps-api-common';
2
2
  export {getDataV2, CONNECTIONS} from './maps-client';
3
- export {fetchLayerData, getData, mapInstantiation} from './maps-v3-client';
3
+ export {fetchLayerData, fetchMap, getData, mapInstantiation} from './maps-v3-client';
@@ -0,0 +1,194 @@
1
+ import {extent} from 'd3-array';
2
+ import {rgb} from 'd3-color';
3
+ import {
4
+ scaleLinear,
5
+ scaleOrdinal,
6
+ scaleLog,
7
+ scalePoint,
8
+ scaleQuantile,
9
+ scaleQuantize,
10
+ scaleSqrt
11
+ } from 'd3-scale';
12
+ import {format as d3Format} from 'd3-format';
13
+ import moment from 'moment-timezone';
14
+ import {H3HexagonLayer, MVTLayer} from '@deck.gl/geo-layers';
15
+ import {GeoJsonLayer} from '@deck.gl/layers';
16
+
17
+ const SCALE_FUNCS = {
18
+ linear: scaleLinear,
19
+ ordinal: scaleOrdinal,
20
+ log: scaleLog,
21
+ point: scalePoint,
22
+ quantile: scaleQuantile,
23
+ quantize: scaleQuantize,
24
+ sqrt: scaleSqrt
25
+ };
26
+
27
+ // Kepler -> Deck.gl
28
+ const sharedPropMap = {
29
+ color: 'getFillColor',
30
+ isVisible: 'visible',
31
+ textLabel: {
32
+ alignment: 'getTextAlignmentBaseline',
33
+ anchor: 'getTextAnchor',
34
+ color: 'getTextColor',
35
+ size: 'getTextSize'
36
+ },
37
+ visConfig: {
38
+ enable3d: 'extruded',
39
+ filled: 'filled',
40
+ opacity: 'opacity',
41
+ strokeColor: 'getLineColor',
42
+ stroked: 'stroked',
43
+ thickness: 'getLineWidth',
44
+ radius: 'getPointRadius',
45
+ wireframe: 'wireframe'
46
+ }
47
+ };
48
+
49
+ const RADIUS_DOWNSCALE = 0.2;
50
+
51
+ const defaultProps = {
52
+ lineMiterLimit: 2,
53
+ lineWidthUnits: 'pixels',
54
+ pointRadiusScale: RADIUS_DOWNSCALE,
55
+ pointRadiusUnits: 'pixels',
56
+ rounded: true,
57
+ wrapLongitude: false
58
+ };
59
+
60
+ function mergePropMaps(a, b) {
61
+ return {...a, ...b, visConfig: {...a.visConfig, ...b.visConfig}};
62
+ }
63
+
64
+ export const LAYER_MAP = {
65
+ point: {
66
+ Layer: GeoJsonLayer,
67
+ propMap: mergePropMaps(sharedPropMap, {
68
+ visConfig: {outline: 'stroked'}
69
+ }),
70
+ defaultProps
71
+ },
72
+ geojson: {
73
+ Layer: GeoJsonLayer,
74
+ propMap: sharedPropMap,
75
+ defaultProps: {...defaultProps, lineWidthScale: 2}
76
+ },
77
+ hexagonId: {
78
+ Layer: H3HexagonLayer,
79
+ propMap: mergePropMaps(sharedPropMap, {
80
+ visConfig: {coverage: 'coverage', elevationScale: 'elevationScale'}
81
+ }),
82
+ defaultProps: {...defaultProps, getHexagon: d => d.h3}
83
+ },
84
+ mvt: {
85
+ Layer: MVTLayer,
86
+ propMap: sharedPropMap,
87
+ defaultProps: {...defaultProps, pointRadiusScale: 0.3, lineWidthScale: 2}
88
+ }
89
+ };
90
+
91
+ function domainFromAttribute(attribute, scaleType) {
92
+ if (scaleType === 'ordinal' || scaleType === 'point') {
93
+ return attribute.categories.map(c => c.category).filter(c => c !== undefined && c !== null);
94
+ }
95
+
96
+ let {min} = attribute;
97
+ if (scaleType === 'log' && min === 0) {
98
+ min = 1e-5;
99
+ }
100
+ return [min, attribute.max];
101
+ }
102
+
103
+ function domainFromValues(values, scaleType) {
104
+ if (scaleType === 'ordinal') {
105
+ return [...new Set(values)].sort();
106
+ }
107
+ return extent(values);
108
+ }
109
+
110
+ function calculateDomain(data, name, scaleType) {
111
+ if (data.tilestats) {
112
+ // Tileset data type
113
+ const {attributes} = data.tilestats.layers[0];
114
+ const attribute = attributes.find(a => a.attribute === name);
115
+ return domainFromAttribute(attribute, scaleType);
116
+ } else if (data.features) {
117
+ // GeoJSON data type
118
+ const values = data.features.map(({properties}) => properties[name]);
119
+ return domainFromValues(values, scaleType);
120
+ } else if (Array.isArray(data) && data[0][name] !== undefined) {
121
+ // JSON data type
122
+ const values = data.map(properties => properties[name]);
123
+ return domainFromValues(values, scaleType);
124
+ }
125
+
126
+ return [0, 1];
127
+ }
128
+
129
+ function normalizeAccessor(accessor, data) {
130
+ if (data.features || data.tilestats) {
131
+ return ({properties}) => {
132
+ return accessor(properties);
133
+ };
134
+ }
135
+ return accessor;
136
+ }
137
+
138
+ export function getColorAccessor({name}, scaleType, {colors}, opacity, data) {
139
+ const scale = SCALE_FUNCS[scaleType]();
140
+ scale.domain(calculateDomain(data, name, scaleType));
141
+ scale.range(colors);
142
+ const alpha = opacity !== undefined ? Math.round(255 * Math.pow(opacity, 1 / 2.2)) : 255;
143
+
144
+ const accessor = properties => {
145
+ const rgba = rgb(scale(properties[name]));
146
+ return [rgba.r, rgba.g, rgba.b, alpha];
147
+ };
148
+ return normalizeAccessor(accessor, data);
149
+ }
150
+
151
+ export function getSizeAccessor({name}, scaleType, range, data) {
152
+ const scale = SCALE_FUNCS[scaleType]();
153
+ scale.domain(calculateDomain(data, name, scaleType));
154
+ scale.range(range);
155
+
156
+ const accessor = properties => {
157
+ return scale(properties[name]);
158
+ };
159
+ return normalizeAccessor(accessor, data);
160
+ }
161
+
162
+ const FORMATS = {
163
+ date: s => moment.utc(s).format('MM/DD/YY HH:mm:ssa'),
164
+ integer: d3Format('i'),
165
+ float: d3Format('.5f'),
166
+ timestamp: s => moment.utc(s).format('X'),
167
+ default: String
168
+ };
169
+
170
+ export function getTextAccessor({name, type}, data) {
171
+ const format = FORMATS[type] || FORMATS.default;
172
+ const accessor = properties => {
173
+ return format(properties[name]);
174
+ };
175
+ return normalizeAccessor(accessor, data);
176
+ }
177
+
178
+ export function getTextPixelOffsetAccessor({alignment, anchor, size}, radius) {
179
+ const padding = 20;
180
+ const signX = anchor === 'middle' ? 0 : anchor === 'start' ? 1 : -1;
181
+ const signY = alignment === 'center' ? 0 : alignment === 'bottom' ? 1 : -1;
182
+ const sizeOffset = alignment === 'center' ? 0 : size;
183
+
184
+ const calculateOffset = r => {
185
+ r = RADIUS_DOWNSCALE * r;
186
+ return [signX * (r + padding), signY * (r + padding + sizeOffset)];
187
+ };
188
+
189
+ return typeof radius === 'function'
190
+ ? d => {
191
+ return calculateOffset(radius(d));
192
+ }
193
+ : calculateOffset(radius);
194
+ }
@@ -56,7 +56,7 @@ export async function getDataV2({type, source, credentials}) {
56
56
 
57
57
  default:
58
58
  throw new Error(
59
- `Invalid maps API version. It shoud be ${API_VERSIONS.V1} or ${API_VERSIONS.V2}`
59
+ `Invalid maps API version. It should be ${API_VERSIONS.V1} or ${API_VERSIONS.V2}`
60
60
  );
61
61
  }
62
62
  }
@@ -95,15 +95,11 @@ function dealWithError({response, json, credentials}) {
95
95
  switch (response.status) {
96
96
  case 401:
97
97
  throw new Error(
98
- `Unauthorized access to Maps API: invalid combination of user ('${
99
- credentials.username
100
- }') and apiKey ('${credentials.apiKey}')`
98
+ `Unauthorized access to Maps API: invalid combination of user ('${credentials.username}') and apiKey ('${credentials.apiKey}')`
101
99
  );
102
100
  case 403:
103
101
  throw new Error(
104
- `Unauthorized access to dataset: the provided apiKey('${
105
- credentials.apiKey
106
- }') doesn't provide access to the requested data`
102
+ `Unauthorized access to dataset: the provided apiKey('${credentials.apiKey}') doesn't provide access to the requested data`
107
103
  );
108
104
 
109
105
  default:
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import {getDefaultCredentials, buildMapsUrlFromBase} from '../config';
5
5
  import {API_VERSIONS, encodeParameter, FORMATS, MAP_TYPES} from './maps-api-common';
6
+ import {parseMap} from './parseMap';
6
7
  import {log} from '@deck.gl/core';
7
8
 
8
9
  const MAX_GET_LENGTH = 2048;
@@ -126,7 +127,7 @@ function getUrlFromMetadata(metadata, format) {
126
127
  return null;
127
128
  }
128
129
 
129
- function checkGetLayerDataParameters({type, source, connection, localCreds}) {
130
+ function checkFetchLayerDataParameters({type, source, connection, localCreds}) {
130
131
  log.assert(connection, 'Must define connection');
131
132
  log.assert(type, 'Must define a type');
132
133
  log.assert(source, 'Must define a source');
@@ -145,6 +146,38 @@ export async function fetchLayerData({
145
146
  columns,
146
147
  format,
147
148
  schema
149
+ }) {
150
+ // Internally we split data fetching into two parts to allow us to
151
+ // conditionally fetch the actual data, depending on the metadata state
152
+ const {url, accessToken, mapFormat, metadata} = await _fetchDataUrl({
153
+ type,
154
+ source,
155
+ connection,
156
+ credentials,
157
+ geoColumn,
158
+ columns,
159
+ format,
160
+ schema
161
+ });
162
+
163
+ const data = await request({url, format: mapFormat, accessToken});
164
+ const result = {data, format: mapFormat};
165
+ if (schema) {
166
+ result.schema = metadata.schema;
167
+ }
168
+
169
+ return result;
170
+ }
171
+
172
+ async function _fetchDataUrl({
173
+ type,
174
+ source,
175
+ connection,
176
+ credentials,
177
+ geoColumn,
178
+ columns,
179
+ format,
180
+ schema
148
181
  }) {
149
182
  const defaultCredentials = getDefaultCredentials();
150
183
  // Only pick up default credentials if they have been defined for
@@ -153,7 +186,7 @@ export async function fetchLayerData({
153
186
  ...(defaultCredentials.apiVersion === API_VERSIONS.V3 && defaultCredentials),
154
187
  ...credentials
155
188
  };
156
- checkGetLayerDataParameters({type, source, connection, localCreds});
189
+ checkFetchLayerDataParameters({type, source, connection, localCreds});
157
190
 
158
191
  if (!localCreds.mapsUrl) {
159
192
  localCreds.mapsUrl = buildMapsUrlFromBase(localCreds.apiBaseUrl);
@@ -177,7 +210,7 @@ export async function fetchLayerData({
177
210
  log.assert(url, `Format ${format} not available`);
178
211
  } else {
179
212
  // guess map format
180
- const prioritizedFormats = [FORMATS.GEOJSON, FORMATS.NDJSON, FORMATS.TILEJSON];
213
+ const prioritizedFormats = [FORMATS.GEOJSON, FORMATS.JSON, FORMATS.NDJSON, FORMATS.TILEJSON];
181
214
  for (const f of prioritizedFormats) {
182
215
  url = getUrlFromMetadata(metadata, f);
183
216
  if (url) {
@@ -188,17 +221,11 @@ export async function fetchLayerData({
188
221
  }
189
222
 
190
223
  const {accessToken} = localCreds;
191
-
192
- const data = await request({url, format: mapFormat, accessToken});
193
- const result = {data, format: mapFormat};
194
- if (schema) {
195
- result.schema = metadata.schema;
196
- }
197
-
198
- return result;
224
+ return {url, accessToken, mapFormat, metadata};
199
225
  }
200
226
 
201
227
  export async function getData({type, source, connection, credentials, geoColumn, columns, format}) {
228
+ log.deprecated('getData', 'fetchLayerData')();
202
229
  const layerData = await fetchLayerData({
203
230
  type,
204
231
  source,
@@ -211,3 +238,79 @@ export async function getData({type, source, connection, credentials, geoColumn,
211
238
  });
212
239
  return layerData.data;
213
240
  }
241
+
242
+ /* global clearInterval, setInterval, URLSearchParams */
243
+ async function _fetchMapDataset(dataset, accessToken) {
244
+ // First fetch metadata
245
+ const {connectionName: connection, source, type} = dataset;
246
+ const {url, mapFormat} = await _fetchDataUrl({
247
+ credentials: {accessToken},
248
+ connection,
249
+ source,
250
+ type
251
+ });
252
+
253
+ // Extract the last time the data changed
254
+ const cache = parseInt(new URLSearchParams(url).get('cache'), 10);
255
+ if (cache && dataset.cache === cache) {
256
+ return false;
257
+ }
258
+ dataset.cache = cache;
259
+
260
+ // Only fetch if the data has changed
261
+ const data = await request({url, format: mapFormat, accessToken});
262
+ dataset.data = data;
263
+ return true;
264
+ }
265
+
266
+ async function fillInMapDatasets({datasets, publicToken}) {
267
+ const promises = datasets.map(dataset => _fetchMapDataset(dataset, publicToken));
268
+ return await Promise.all(promises);
269
+ }
270
+
271
+ export async function fetchMap({cartoMapId, credentials, autoRefresh, onNewData}) {
272
+ const defaultCredentials = getDefaultCredentials();
273
+ const localCreds = {
274
+ ...(defaultCredentials.apiVersion === API_VERSIONS.V3 && defaultCredentials),
275
+ ...credentials
276
+ };
277
+
278
+ log.assert(cartoMapId, `Must define CARTO map id: fetchMap({cartoMapId: 'XXXX-XXXX-XXXX'})`);
279
+
280
+ log.assert(localCreds.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
281
+ log.assert(localCreds.apiBaseUrl, 'Must define apiBaseUrl');
282
+ if (!localCreds.mapsUrl) {
283
+ localCreds.mapsUrl = buildMapsUrlFromBase(localCreds.apiBaseUrl);
284
+ }
285
+
286
+ if (autoRefresh || onNewData) {
287
+ log.assert(onNewData, 'Must define `onNewData` when using autoRefresh');
288
+ log.assert(typeof onNewData === 'function', '`onNewData` must be a function');
289
+ log.assert(autoRefresh > 0, '`autoRefresh` must be a positive number');
290
+ }
291
+
292
+ const url = `${localCreds.mapsUrl}/public/${cartoMapId}`;
293
+ const map = await request({url});
294
+
295
+ // Periodically check if the data has changed. Note that this
296
+ // will not update when a map is published.
297
+ let stopAutoRefresh;
298
+ if (autoRefresh) {
299
+ const intervalId = setInterval(async () => {
300
+ const changed = await fillInMapDatasets(map);
301
+ if (changed.some(v => v === true)) {
302
+ onNewData(parseMap(map));
303
+ }
304
+ }, autoRefresh * 1000);
305
+ stopAutoRefresh = () => {
306
+ clearInterval(intervalId);
307
+ };
308
+ }
309
+
310
+ // Mutates map.datasets so that dataset.data contains data
311
+ await fillInMapDatasets(map);
312
+ return {
313
+ ...parseMap(map),
314
+ ...{stopAutoRefresh}
315
+ };
316
+ }
@@ -0,0 +1,182 @@
1
+ import GL from '@luma.gl/constants';
2
+ import {
3
+ LAYER_MAP,
4
+ getColorAccessor,
5
+ getSizeAccessor,
6
+ getTextAccessor,
7
+ getTextPixelOffsetAccessor
8
+ } from './layer-map';
9
+ import {_flatten as flatten, log} from '@deck.gl/core';
10
+
11
+ export function parseMap(json) {
12
+ const {keplerMapConfig, datasets} = json;
13
+ log.assert(keplerMapConfig.version === 'v1', 'Only support Kepler v1');
14
+ const {mapState, mapStyle} = keplerMapConfig.config;
15
+ const {layers, layerBlending, interactionConfig} = keplerMapConfig.config.visState;
16
+
17
+ return {
18
+ id: json.id,
19
+ title: json.title,
20
+ description: json.description,
21
+ createdAt: json.createdAt,
22
+ updatedAt: json.updatedAt,
23
+ initialViewState: mapState,
24
+ mapStyle,
25
+ layers: extractTextLayers(layers.reverse()).map(({id, type, config, visualChannels}) => {
26
+ log.assert(type in LAYER_MAP, `Unsupported layer type: ${type}`);
27
+ const {Layer, propMap, defaultProps} = LAYER_MAP[type];
28
+
29
+ const {dataId} = config;
30
+ const dataset = datasets.find(d => d.id === dataId);
31
+ log.assert(dataset, `No dataset matching dataId: ${dataId}`);
32
+ const {data} = dataset;
33
+ log.assert(data, `No data loaded for dataId: ${dataId}`);
34
+ return new Layer({
35
+ id,
36
+ data,
37
+ ...defaultProps,
38
+ ...createBlendingProps(layerBlending),
39
+ ...(!config.textLabel && createInteractionProps(interactionConfig)),
40
+ ...createStyleProps(config, propMap),
41
+ ...createChannelProps(visualChannels, type, config, data) // Must come after style
42
+ });
43
+ })
44
+ };
45
+ }
46
+
47
+ function extractTextLayers(layers) {
48
+ return flatten(
49
+ layers.map(({id, config, ...rest}) => {
50
+ const {textLabel, ...configRest} = config;
51
+ return [
52
+ // Original layer without textLabel
53
+ {id, config: configRest, ...rest},
54
+
55
+ // One layer per valid text label, with full opacity
56
+ ...textLabel
57
+ .filter(t => t.field)
58
+ .map(t => {
59
+ return {
60
+ id: `${id}-label-${t.field.name}`,
61
+ config: {
62
+ textLabel: t,
63
+ ...configRest,
64
+ visConfig: {...configRest.visConfig, opacity: 1}
65
+ },
66
+ ...rest
67
+ };
68
+ })
69
+ ];
70
+ })
71
+ );
72
+ }
73
+
74
+ function createBlendingProps(layerBlending) {
75
+ if (layerBlending === 'additive') {
76
+ return {
77
+ parameters: {
78
+ blendFunc: [GL.SRC_ALPHA, GL.DST_ALPHA],
79
+ blendEquation: GL.FUNC_ADD
80
+ }
81
+ };
82
+ } else if (layerBlending === 'subtractive') {
83
+ return {
84
+ parameters: {
85
+ blendFunc: [GL.ONE, GL.ONE_MINUS_DST_COLOR, GL.SRC_ALPHA, GL.DST_ALPHA],
86
+ blendEquation: [GL.FUNC_SUBTRACT, GL.FUNC_ADD]
87
+ }
88
+ };
89
+ }
90
+
91
+ return {};
92
+ }
93
+
94
+ function createInteractionProps(interactionConfig) {
95
+ const pickable = interactionConfig && interactionConfig.tooltip.enabled;
96
+ return {
97
+ autoHighlight: pickable,
98
+ pickable
99
+ };
100
+ }
101
+
102
+ function mapProps(source, target, mapping) {
103
+ for (const sourceKey in mapping) {
104
+ const sourceValue = source[sourceKey];
105
+ const targetKey = mapping[sourceKey];
106
+ if (sourceValue === undefined) {
107
+ // eslint-disable-next-line no-continue
108
+ continue;
109
+ }
110
+ if (typeof targetKey === 'string') {
111
+ target[targetKey] = sourceValue;
112
+ } else if (typeof targetKey === 'object') {
113
+ // Nested definition, recurse down one level
114
+ mapProps(sourceValue, target, targetKey);
115
+ }
116
+ }
117
+ }
118
+
119
+ function createStyleProps(config, mapping) {
120
+ const result = {};
121
+ mapProps(config, result, mapping);
122
+ result.highlightColor = config.visConfig.enable3d ? [255, 255, 255, 60] : [252, 242, 26, 255];
123
+ return result;
124
+ }
125
+
126
+ /* eslint-disable complexity */
127
+ function createChannelProps(visualChannels, type, config, data) {
128
+ const {colorField, colorScale, sizeField, sizeScale, strokeColorField, strokeColorScale} =
129
+ visualChannels;
130
+ let {heightField, heightScale} = visualChannels;
131
+ if (type === 'hexagonId') {
132
+ heightField = sizeField;
133
+ heightScale = sizeScale;
134
+ }
135
+ const {textLabel, visConfig} = config;
136
+ const result = {};
137
+ const textLabelField = textLabel && textLabel.field;
138
+ if (colorField) {
139
+ result.getFillColor = getColorAccessor(
140
+ colorField,
141
+ colorScale,
142
+ visConfig.colorRange,
143
+ 1, // Rely on layer opacity
144
+ data
145
+ );
146
+ }
147
+ if (strokeColorField) {
148
+ const opacity =
149
+ visConfig.strokeOpacity !== undefined ? visConfig.strokeOpacity / visConfig.opacity : 1;
150
+ result.getLineColor = getColorAccessor(
151
+ strokeColorField,
152
+ strokeColorScale,
153
+ visConfig.colorRange,
154
+ opacity,
155
+ data
156
+ );
157
+ }
158
+ if (heightField) {
159
+ result.getElevation = getSizeAccessor(
160
+ heightField,
161
+ heightScale,
162
+ visConfig.heightRange || visConfig.sizeRange,
163
+ data
164
+ );
165
+ }
166
+ if (sizeField) {
167
+ result.getPointRadius = getSizeAccessor(
168
+ sizeField,
169
+ sizeScale,
170
+ visConfig.radiusRange || visConfig.sizeRange,
171
+ data
172
+ );
173
+ }
174
+ if (textLabelField) {
175
+ result.getText = getTextAccessor(textLabelField, data);
176
+ result.pointType = 'text';
177
+ const radius = result.getPointRadius || visConfig.radius;
178
+ result.getTextPixelOffset = getTextPixelOffsetAccessor(textLabel, radius);
179
+ }
180
+
181
+ return result;
182
+ }
package/src/config.js CHANGED
@@ -1,60 +1,29 @@
1
- import {API_VERSIONS, DEFAULT_MAPS_URL_FORMAT} from './api/maps-api-common';
1
+ import {API_VERSIONS} from './api/maps-api-common';
2
2
 
3
3
  export const defaultClassicCredentials = {
4
- username: 'public',
5
4
  apiKey: 'default_public',
6
5
  region: 'us',
7
- mapsUrl: null
6
+ username: 'public'
8
7
  };
9
8
 
10
- const defaultCloudNativeCredentials = {
11
- accessToken: null,
12
- apiBaseUrl: null,
13
- mapsUrl: null
9
+ export const defaultCloudNativeCredentials = {
10
+ apiBaseUrl: 'https://gcp-us-east1.api.carto.com'
14
11
  };
15
12
 
16
13
  let credentials = {};
17
14
 
18
15
  setDefaultCredentials({});
19
16
 
20
- export function setDefaultCredentials(opts) {
21
- const apiVersion = opts.apiVersion || API_VERSIONS.V2;
17
+ export function setDefaultCredentials({apiVersion, ...rest}) {
18
+ apiVersion = apiVersion || API_VERSIONS.V3;
22
19
 
23
20
  switch (apiVersion) {
24
21
  case API_VERSIONS.V1:
25
- opts.mapsUrl = opts.mapsUrl || DEFAULT_MAPS_URL_FORMAT[apiVersion];
26
- credentials = {
27
- apiVersion,
28
- ...defaultClassicCredentials,
29
- ...opts
30
- };
31
- break;
32
-
33
22
  case API_VERSIONS.V2:
34
- opts.mapsUrl = opts.mapsUrl || DEFAULT_MAPS_URL_FORMAT[apiVersion];
35
- credentials = {
36
- apiVersion,
37
- ...defaultClassicCredentials,
38
- ...opts
39
- };
40
-
23
+ credentials = {apiVersion, ...defaultClassicCredentials, ...rest};
41
24
  break;
42
25
  case API_VERSIONS.V3:
43
- if (!opts.apiBaseUrl) {
44
- throw new Error(
45
- `API version ${
46
- API_VERSIONS.V3
47
- } requires to define apiBaseUrl at credentials. Go to https://app.carto.com to get your apiBaseUrl.`
48
- );
49
- }
50
-
51
- const apiBaseUrl = opts.apiBaseUrl || defaultCloudNativeCredentials.apiBaseUrl;
52
- opts.mapsUrl = opts.mapsUrl || buildMapsUrlFromBase(apiBaseUrl);
53
- credentials = {
54
- apiVersion,
55
- ...defaultCloudNativeCredentials,
56
- ...opts
57
- };
26
+ credentials = {apiVersion, ...defaultCloudNativeCredentials, ...rest};
58
27
  break;
59
28
  default:
60
29
  throw new Error(`Invalid API version ${apiVersion}. Use API_VERSIONS enum.`);
package/src/index.js CHANGED
@@ -11,6 +11,7 @@ export {
11
11
  MAP_TYPES,
12
12
  API_VERSIONS,
13
13
  fetchLayerData,
14
+ fetchMap,
14
15
  getDataV2 as _getDataV2,
15
16
  getData,
16
17
  mapInstantiation as _mapInstantiation