@flowmap.gl/layers 8.0.0-alpha.9 → 8.0.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 (54) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-dev.log +26 -0
  3. package/LICENSE +2 -2
  4. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.d.ts.map +1 -1
  5. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.js +16 -22
  6. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.d.ts.map +1 -1
  7. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.js +4 -16
  8. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.d.ts.map +1 -1
  9. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.js +4 -16
  10. package/dist/AnimatedFlowLinesLayer/index.d.ts.map +1 -1
  11. package/dist/AnimatedFlowLinesLayer/index.js +6 -1
  12. package/dist/FlowCirclesLayer/FlowCirclesLayer.d.ts +1 -1
  13. package/dist/FlowCirclesLayer/FlowCirclesLayer.d.ts.map +1 -1
  14. package/dist/FlowCirclesLayer/FlowCirclesLayer.js +9 -18
  15. package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.d.ts +1 -1
  16. package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.d.ts.map +1 -1
  17. package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.js +5 -16
  18. package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.d.ts.map +1 -1
  19. package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.js +4 -16
  20. package/dist/FlowCirclesLayer/index.d.ts.map +1 -1
  21. package/dist/FlowCirclesLayer/index.js +6 -1
  22. package/dist/FlowLinesLayer/FlowLinesLayer.d.ts.map +1 -1
  23. package/dist/FlowLinesLayer/FlowLinesLayer.js +79 -73
  24. package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.d.ts.map +1 -1
  25. package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.js +4 -16
  26. package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.d.ts +1 -1
  27. package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.d.ts.map +1 -1
  28. package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.js +5 -21
  29. package/dist/FlowLinesLayer/index.d.ts.map +1 -1
  30. package/dist/FlowLinesLayer/index.js +6 -1
  31. package/dist/FlowmapLayer.d.ts +17 -9
  32. package/dist/FlowmapLayer.d.ts.map +1 -1
  33. package/dist/FlowmapLayer.js +241 -141
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +6 -1
  36. package/dist/types.d.ts +12 -7
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/types.js +6 -1
  39. package/package.json +7 -3
  40. package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.ts +7 -19
  41. package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.ts +3 -15
  42. package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.ts +3 -15
  43. package/src/AnimatedFlowLinesLayer/index.ts +6 -0
  44. package/src/FlowCirclesLayer/FlowCirclesLayer.ts +3 -15
  45. package/src/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.ts +4 -15
  46. package/src/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.ts +3 -15
  47. package/src/FlowCirclesLayer/index.ts +6 -0
  48. package/src/FlowLinesLayer/FlowLinesLayer.ts +74 -80
  49. package/src/FlowLinesLayer/FlowLinesLayerFragment.glsl.ts +3 -15
  50. package/src/FlowLinesLayer/FlowLinesLayerVertex.glsl.ts +4 -20
  51. package/src/FlowLinesLayer/index.ts +6 -0
  52. package/src/FlowmapLayer.ts +164 -78
  53. package/src/index.ts +6 -0
  54. package/src/types.ts +17 -4
@@ -1,38 +1,27 @@
1
1
  /*
2
- * Copyright 2022 FlowmapBlue
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- *
2
+ * Copyright (c) Flowmap.gl contributors
3
+ * Copyright (c) 2018-2020 Teralytics
4
+ * SPDX-License-Identifier: Apache-2.0
16
5
  */
17
6
  import {CompositeLayer} from '@deck.gl/core';
18
- import {ScatterplotLayer} from '@deck.gl/layers';
7
+ import {ScatterplotLayer, TextLayer} from '@deck.gl/layers';
19
8
  import {
20
- colorAsRgba,
9
+ FilterState,
21
10
  FlowLinesLayerAttributes,
11
+ FlowmapAggregateAccessors,
22
12
  FlowmapData,
23
13
  FlowmapDataAccessors,
24
14
  FlowmapDataProvider,
15
+ LayersData,
16
+ LocalFlowmapDataProvider,
17
+ ViewportProps,
18
+ colorAsRgba,
25
19
  getFlowLineAttributesByIndex,
26
20
  getFlowmapColors,
27
- getOuterCircleRadiusByIndex,
28
21
  getLocationCoordsByIndex,
22
+ getOuterCircleRadiusByIndex,
29
23
  isFlowmapData,
30
24
  isFlowmapDataProvider,
31
- LayersData,
32
- LocalFlowmapDataProvider,
33
- LocationFilterMode,
34
- ViewportProps,
35
- FlowmapAggregateAccessors,
36
25
  } from '@flowmap.gl/data';
37
26
  import AnimatedFlowLinesLayer from './AnimatedFlowLinesLayer';
38
27
  import FlowCirclesLayer from './FlowCirclesLayer';
@@ -44,10 +33,16 @@ import {
44
33
  PickingType,
45
34
  } from './types';
46
35
 
47
- export type FlowmapLayerProps<L, F> = {
36
+ export type FlowmapLayerProps<
37
+ L extends Record<string, any>,
38
+ F extends Record<string, any>,
39
+ > = {
48
40
  data?: FlowmapData<L, F>;
49
41
  dataProvider?: FlowmapDataProvider<L, F>;
42
+ filter?: FilterState;
43
+ locationsEnabled?: boolean;
50
44
  locationTotalsEnabled?: boolean;
45
+ locationLabelsEnabled?: boolean;
51
46
  adaptiveScalesEnabled?: boolean;
52
47
  animationEnabled?: boolean;
53
48
  clusteringEnabled?: boolean;
@@ -68,6 +63,25 @@ export type FlowmapLayerProps<L, F> = {
68
63
  } & Partial<FlowmapDataAccessors<L, F>> &
69
64
  LayerProps;
70
65
 
66
+ const PROPS_TO_CAUSE_LAYER_DATA_UPDATE: string[] = [
67
+ 'filter',
68
+ 'locationsEnabled',
69
+ 'locationTotalsEnabled',
70
+ 'locationLabelsEnabled',
71
+ 'adaptiveScalesEnabled',
72
+ 'animationEnabled',
73
+ 'clusteringEnabled',
74
+ 'clusteringLevel',
75
+ 'fadeEnabled',
76
+ 'fadeOpacityEnabled',
77
+ 'clusteringAuto',
78
+ 'darkMode',
79
+ 'fadeAmount',
80
+ 'colorScheme',
81
+ 'highlightColor',
82
+ 'maxTopFlowsDisplayNum',
83
+ ];
84
+
71
85
  enum HighlightType {
72
86
  LOCATION = 'location',
73
87
  FLOW = 'flow',
@@ -86,20 +100,28 @@ type HighlightedFlowObject = {
86
100
 
87
101
  type HighlightedObject = HighlightedLocationObject | HighlightedFlowObject;
88
102
 
89
- type State<L, F> = {
103
+ type State<L extends Record<string, any>, F extends Record<string, any>> = {
90
104
  accessors: FlowmapAggregateAccessors<L, F>;
91
105
  dataProvider: FlowmapDataProvider<L, F>;
92
106
  layersData: LayersData | undefined;
93
107
  highlightedObject: HighlightedObject | undefined;
108
+ pickingInfo: FlowmapLayerPickingInfo<L, F> | undefined;
109
+ lastHoverTime: number | undefined;
110
+ lastClickTime: number | undefined;
94
111
  };
95
112
 
96
113
  export type SourceEvent = {srcEvent: MouseEvent};
97
114
 
98
- export default class FlowmapLayer<L, F> extends CompositeLayer {
115
+ export default class FlowmapLayer<
116
+ L extends Record<string, any>,
117
+ F extends Record<string, any>,
118
+ > extends CompositeLayer {
99
119
  static defaultProps = {
100
120
  darkMode: true,
101
121
  fadeAmount: 50,
122
+ locationsEnabled: true,
102
123
  locationTotalsEnabled: true,
124
+ locationLabelsEnabled: false,
103
125
  animationEnabled: false,
104
126
  clusteringEnabled: true,
105
127
  fadeEnabled: true,
@@ -116,29 +138,40 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
116
138
  public constructor(props: FlowmapLayerProps<L, F>) {
117
139
  super({
118
140
  ...props,
119
- dataProvider: {
120
- // To avoid deck.gl props diffing on comlink worker proxy causing an exception
121
- dataProvider: props.dataProvider,
122
- },
123
141
  onHover: (info: PickingInfo<any>, event: SourceEvent) => {
124
- // TODO: if (lastHoverEventStartTimeRef > startTime) {
125
- // // Skipping, because this is not the latest hover event
126
- // return;
127
- // }
128
- this.setState({highlightedObject: this._getHighlightedObject(info)});
142
+ const startTime = Date.now();
143
+ this.setState({
144
+ highlightedObject: this._getHighlightedObject(info),
145
+ lastHoverTime: startTime,
146
+ });
147
+
129
148
  const {onHover} = props;
130
149
  if (onHover) {
131
- this._getFlowmapLayerPickingInfo(info).then((info) =>
132
- onHover(info, event),
133
- );
150
+ this._getFlowmapLayerPickingInfo(info).then((info) => {
151
+ if ((this.state?.lastHoverTime ?? 0) <= startTime) {
152
+ this.setState({pickingInfo: info});
153
+ onHover(info, event);
154
+ } else {
155
+ // Skipping, because this is not the latest hover event
156
+ }
157
+ });
134
158
  }
135
159
  },
136
160
  onClick: (info: PickingInfo<any>, event: SourceEvent) => {
137
161
  const {onClick} = props;
162
+ const startTime = Date.now();
163
+ this.setState({
164
+ lastClickTime: startTime,
165
+ });
138
166
  if (onClick) {
139
167
  this._getFlowmapLayerPickingInfo(info).then((info) => {
140
- if (info) {
141
- onClick(info, event);
168
+ if ((this.state?.lastClickTime ?? 0) <= startTime) {
169
+ this.setState({pickingInfo: info});
170
+ if (info) {
171
+ onClick(info, event);
172
+ }
173
+ } else {
174
+ // Skipping, because this is not the latest hover event
142
175
  }
143
176
  });
144
177
  }
@@ -152,18 +185,36 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
152
185
  dataProvider: this._getOrMakeDataProvider(),
153
186
  layersData: undefined,
154
187
  highlightedObject: undefined,
188
+ pickingInfo: undefined,
189
+ lastHoverTime: undefined,
190
+ lastClickTime: undefined,
155
191
  };
156
192
  }
157
193
 
158
- private _updateAccessors() {
159
- this.state?.dataProvider?.setAccessors(this.props);
160
- this.setState({accessors: new FlowmapAggregateAccessors(this.props)});
194
+ getPickingInfo({info}: Record<string, any>) {
195
+ // This is for onHover event handlers set on the <DeckGL> component
196
+ if (!info.object) {
197
+ const object = this.state?.pickingInfo?.object;
198
+ if (object) {
199
+ return {
200
+ ...info,
201
+ object,
202
+ picked: true,
203
+ };
204
+ }
205
+ }
206
+ return info;
161
207
  }
162
208
 
209
+ // private _updateAccessors() {
210
+ // this.state?.dataProvider?.setAccessors(this.props);
211
+ // this.setState({accessors: new FlowmapAggregateAccessors(this.props)});
212
+ // }
213
+
163
214
  private _getOrMakeDataProvider() {
164
215
  const {data, dataProvider} = this.props;
165
- if (isFlowmapDataProvider<L, F>(dataProvider?.dataProvider)) {
166
- return dataProvider.dataProvider;
216
+ if (isFlowmapDataProvider<L, F>(dataProvider)) {
217
+ return dataProvider;
167
218
  } else if (isFlowmapData<L, F>(data)) {
168
219
  const dataProvider = new LocalFlowmapDataProvider<L, F>(this.props);
169
220
  dataProvider.setFlowmapData(data);
@@ -192,11 +243,6 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
192
243
  }
193
244
 
194
245
  updateState({oldProps, props, changeFlags}: Record<string, any>): void {
195
- const {dataProvider, highlightedObject} = this.state || {};
196
- if (!dataProvider) {
197
- return;
198
- }
199
-
200
246
  if (changeFlags.propsChanged) {
201
247
  // this._updateAccessors();
202
248
  }
@@ -204,26 +250,32 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
204
250
  this._updateDataProvider();
205
251
  }
206
252
  if (changeFlags.viewportChanged || changeFlags.dataChanged) {
207
- this.setState({
208
- highlightedObject: undefined,
209
- });
253
+ this.setState({highlightedObject: undefined});
210
254
  }
211
255
 
212
256
  if (
213
257
  changeFlags.viewportChanged ||
214
- changeFlags.propsOrDataChanged // TODO can we ignore accessor props changes?
258
+ changeFlags.dataChanged ||
259
+ (changeFlags.propsChanged &&
260
+ PROPS_TO_CAUSE_LAYER_DATA_UPDATE.some(
261
+ (prop) => oldProps[prop] !== props[prop],
262
+ ))
215
263
  ) {
216
- dataProvider.setFlowmapState(this._getFlowmapState());
217
- (async () => {
218
- const layersData = await dataProvider.getLayersData();
219
- this.setState({layersData});
220
- })();
264
+ const {dataProvider} = this.state || {};
265
+ if (dataProvider) {
266
+ dataProvider.setFlowmapState(this._getFlowmapState());
267
+ dataProvider.updateLayersData((layersData: LayersData | undefined) => {
268
+ this.setState({layersData, highlightedObject: undefined});
269
+ }, changeFlags);
270
+ }
221
271
  }
222
272
  }
223
273
 
224
274
  private _getSettingsState() {
225
275
  const {
276
+ locationsEnabled,
226
277
  locationTotalsEnabled,
278
+ locationLabelsEnabled,
227
279
  adaptiveScalesEnabled,
228
280
  animationEnabled,
229
281
  clusteringEnabled,
@@ -238,7 +290,9 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
238
290
  maxTopFlowsDisplayNum,
239
291
  } = this.props;
240
292
  return {
293
+ locationsEnabled,
241
294
  locationTotalsEnabled,
295
+ locationLabelsEnabled,
242
296
  adaptiveScalesEnabled,
243
297
  animationEnabled,
244
298
  clusteringEnabled,
@@ -257,12 +311,8 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
257
311
  private _getFlowmapState() {
258
312
  return {
259
313
  viewport: pickViewportProps(this.context.viewport),
260
- filterState: {
261
- selectedLocations: undefined,
262
- locationFilterMode: LocationFilterMode.ALL,
263
- selectedTimeRange: undefined,
264
- },
265
- settingsState: this._getSettingsState(),
314
+ filter: this.props.filter,
315
+ settings: this._getSettingsState(),
266
316
  };
267
317
  }
268
318
 
@@ -275,12 +325,14 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
275
325
  return undefined;
276
326
  }
277
327
  const commonInfo = {
278
- // ...info,
328
+ ...info,
329
+ picked: info.picked,
279
330
  layer: info.layer,
280
331
  index: info.index,
281
332
  x: info.x,
282
333
  y: info.y,
283
334
  coordinate: info.coordinate,
335
+ event: info.event,
284
336
  };
285
337
  if (
286
338
  sourceLayer instanceof FlowLinesLayer ||
@@ -298,11 +350,13 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
298
350
  if (origin && dest) {
299
351
  return {
300
352
  ...commonInfo,
301
- type: PickingType.FLOW,
302
- object: flow,
303
- origin: origin,
304
- dest: dest,
305
- count: accessors.getFlowMagnitude(flow),
353
+ object: {
354
+ type: PickingType.FLOW,
355
+ flow,
356
+ origin: origin,
357
+ dest: dest,
358
+ count: accessors.getFlowMagnitude(flow),
359
+ },
306
360
  };
307
361
  }
308
362
  }
@@ -322,13 +376,14 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
322
376
  );
323
377
  return {
324
378
  ...commonInfo,
325
- type: PickingType.LOCATION,
326
- object: location,
327
- id,
328
- name,
329
- totals,
330
- circleRadius: circleRadius,
331
- event: undefined,
379
+ object: {
380
+ type: PickingType.LOCATION,
381
+ location,
382
+ id,
383
+ name,
384
+ totals,
385
+ circleRadius: circleRadius,
386
+ },
332
387
  };
333
388
  }
334
389
  }
@@ -386,7 +441,8 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
386
441
  const layers = [];
387
442
  if (this.state?.layersData) {
388
443
  const {layersData, highlightedObject} = this.state;
389
- const {circleAttributes, lineAttributes} = layersData || {};
444
+ const {circleAttributes, lineAttributes, locationLabels} =
445
+ layersData || {};
390
446
  if (circleAttributes && lineAttributes) {
391
447
  const flowmapColors = getFlowmapColors(this._getSettingsState());
392
448
  const outlineColor = colorAsRgba(
@@ -468,6 +524,9 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
468
524
  pickable: false,
469
525
  outlineColor: colorAsRgba(this.props.highlightColor),
470
526
  outlineThickness: 1,
527
+ parameters: {
528
+ depthTest: false,
529
+ },
471
530
  }),
472
531
  }),
473
532
  );
@@ -475,6 +534,33 @@ export default class FlowmapLayer<L, F> extends CompositeLayer {
475
534
  }
476
535
  }
477
536
  }
537
+ if (locationLabels) {
538
+ layers.push(
539
+ new TextLayer(
540
+ this.getSubLayerProps({
541
+ id: 'location-labels',
542
+ data: locationLabels,
543
+ maxWidth: 1000,
544
+ pickable: false,
545
+ fontFamily: 'Helvetica',
546
+ getPixelOffset: (d: string, {index}: {index: number}) => {
547
+ const r = getOuterCircleRadiusByIndex(circleAttributes, index);
548
+ return [0, r + 5];
549
+ },
550
+ getPosition: (d: string, {index}: {index: number}) => {
551
+ const pos = getLocationCoordsByIndex(circleAttributes, index);
552
+ return pos;
553
+ },
554
+ getText: (d: string) => d,
555
+ getSize: 10,
556
+ getColor: [255, 255, 255, 255],
557
+ getAngle: 0,
558
+ getTextAnchor: 'middle',
559
+ getAlignmentBaseline: 'top',
560
+ }),
561
+ ),
562
+ );
563
+ }
478
564
  }
479
565
 
480
566
  return layers;
package/src/index.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /*
2
+ * Copyright (c) Flowmap.gl contributors
3
+ * Copyright (c) 2018-2020 Teralytics
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
1
7
  export {default as AnimatedFlowLinesLayer} from './AnimatedFlowLinesLayer';
2
8
  export {default as FlowLinesLayer} from './FlowLinesLayer';
3
9
  export {default as FlowCirclesLayer} from './FlowCirclesLayer';
package/src/types.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /*
2
+ * Copyright (c) Flowmap.gl contributors
3
+ * Copyright (c) 2018-2020 Teralytics
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
1
7
  import {
2
8
  AggregateFlow,
3
9
  Cluster,
@@ -18,28 +24,35 @@ export type DeckGLLayer = Record<string, any>;
18
24
  export interface PickingInfo<T> {
19
25
  layer: DeckGLLayer;
20
26
  index: number;
27
+ picked: boolean;
21
28
  object: T | undefined;
22
29
  x: number;
23
30
  y: number;
24
31
  coordinate: [number, number];
32
+ event: MouseEvent | undefined;
25
33
  }
26
34
 
27
- export interface LocationPickingInfo<L> extends PickingInfo<L | ClusterNode> {
35
+ export interface LocationPickingInfoObject<L> {
36
+ id: string | number;
28
37
  type: PickingType.LOCATION;
29
- id: string;
38
+ location: L | ClusterNode;
30
39
  name: string;
31
40
  totals: LocationTotals;
32
41
  circleRadius: number;
33
- event: MouseEvent | undefined;
34
42
  }
35
43
 
36
- export interface FlowPickingInfo<L, F> extends PickingInfo<F | AggregateFlow> {
44
+ export type LocationPickingInfo<L> = PickingInfo<LocationPickingInfoObject<L>>;
45
+
46
+ export interface FlowPickingInfoObject<L, F> {
37
47
  type: PickingType.FLOW;
48
+ flow: F | AggregateFlow;
38
49
  origin: L | ClusterNode;
39
50
  dest: L | ClusterNode;
40
51
  count: number;
41
52
  }
42
53
 
54
+ export type FlowPickingInfo<L, F> = PickingInfo<FlowPickingInfoObject<L, F>>;
55
+
43
56
  // export interface LocationAreaPickingInfo extends PickingInfo<PickingInfoData> {
44
57
  // type: PickingType.LOCATION_AREA;
45
58
  // object: FlowLocation;