@flowmap.gl/data 8.0.0-alpha.18 → 8.0.0-alpha.21

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 (44) hide show
  1. package/dist/FlowmapAggregateAccessors.d.ts +3 -3
  2. package/dist/FlowmapAggregateAccessors.d.ts.map +1 -1
  3. package/dist/FlowmapAggregateAccessors.js +2 -2
  4. package/dist/FlowmapSelectors.d.ts +44 -33
  5. package/dist/FlowmapSelectors.d.ts.map +1 -1
  6. package/dist/FlowmapSelectors.js +50 -49
  7. package/dist/FlowmapState.d.ts +5 -5
  8. package/dist/FlowmapState.d.ts.map +1 -1
  9. package/dist/FlowmapState.js +1 -1
  10. package/dist/cluster/ClusterIndex.d.ts +3 -3
  11. package/dist/cluster/ClusterIndex.d.ts.map +1 -1
  12. package/dist/cluster/ClusterIndex.js +1 -1
  13. package/dist/cluster/cluster.d.ts.map +1 -1
  14. package/dist/cluster/cluster.js +64 -13
  15. package/dist/colors.d.ts +1 -1
  16. package/dist/colors.d.ts.map +1 -1
  17. package/dist/colors.js +3 -3
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +4 -1
  21. package/dist/provider/FlowmapDataProvider.d.ts +7 -2
  22. package/dist/provider/FlowmapDataProvider.d.ts.map +1 -1
  23. package/dist/provider/FlowmapDataProvider.js +1 -1
  24. package/dist/provider/LocalFlowmapDataProvider.d.ts +3 -2
  25. package/dist/provider/LocalFlowmapDataProvider.d.ts.map +1 -1
  26. package/dist/provider/LocalFlowmapDataProvider.js +6 -1
  27. package/dist/selector-functions.d.ts +4 -0
  28. package/dist/selector-functions.d.ts.map +1 -0
  29. package/dist/selector-functions.js +20 -0
  30. package/dist/types.d.ts +12 -11
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/types.js +1 -1
  33. package/package.json +2 -3
  34. package/src/FlowmapAggregateAccessors.ts +2 -2
  35. package/src/FlowmapSelectors.ts +171 -160
  36. package/src/FlowmapState.ts +5 -5
  37. package/src/cluster/ClusterIndex.ts +19 -12
  38. package/src/cluster/cluster.ts +71 -16
  39. package/src/colors.ts +7 -9
  40. package/src/index.ts +3 -0
  41. package/src/provider/FlowmapDataProvider.ts +13 -2
  42. package/src/provider/LocalFlowmapDataProvider.ts +10 -2
  43. package/src/selector-functions.ts +34 -0
  44. package/src/types.ts +12 -11
@@ -16,9 +16,8 @@
16
16
  *
17
17
  */
18
18
 
19
- import {WebMercatorViewport} from '@math.gl/web-mercator';
20
- import {ascending, rollup, descending, extent, min} from 'd3-array';
21
- import {ScaleLinear, scaleLinear, scaleSqrt} from 'd3-scale';
19
+ import {ascending, descending, extent, min, rollup} from 'd3-array';
20
+ import {ScaleLinear, scaleSqrt} from 'd3-scale';
22
21
  import KDBush from 'kdbush';
23
22
  import {
24
23
  createSelector,
@@ -32,6 +31,7 @@ import {
32
31
  buildIndex,
33
32
  ClusterIndex,
34
33
  findAppropriateZoomLevel,
34
+ LocationWeightGetter,
35
35
  makeLocationWeightGetter,
36
36
  } from './cluster/ClusterIndex';
37
37
  import getColors, {
@@ -45,6 +45,10 @@ import getColors, {
45
45
  } from './colors';
46
46
  import FlowmapAggregateAccessors from './FlowmapAggregateAccessors';
47
47
  import {FlowmapState} from './FlowmapState';
48
+ import {
49
+ getFlowThicknessScale,
50
+ getViewportBoundingBox,
51
+ } from './selector-functions';
48
52
  import {
49
53
  getTimeGranularityByKey,
50
54
  getTimeGranularityByOrder,
@@ -54,6 +58,7 @@ import {
54
58
  import {
55
59
  AggregateFlow,
56
60
  Cluster,
61
+ ClusterLevels,
57
62
  ClusterNode,
58
63
  CountByTime,
59
64
  FlowAccessors,
@@ -89,60 +94,65 @@ export default class FlowmapSelectors<L, F> {
89
94
  this.accessors = new FlowmapAggregateAccessors(accessors);
90
95
  }
91
96
 
92
- getFetchedFlows = (state: FlowmapState, props: FlowmapData<L, F>) =>
97
+ getFlowsFromProps = (state: FlowmapState, props: FlowmapData<L, F>) =>
93
98
  props.flows;
94
- getFetchedLocations = (state: FlowmapState, props: FlowmapData<L, F>) =>
99
+ getLocationsFromProps = (state: FlowmapState, props: FlowmapData<L, F>) =>
95
100
  props.locations;
101
+ getClusterLevelsFromProps = (
102
+ state: FlowmapState,
103
+ props: FlowmapData<L, F>,
104
+ ) => {
105
+ return props.clusterLevels;
106
+ };
96
107
  getMaxTopFlowsDisplayNum = (state: FlowmapState, props: FlowmapData<L, F>) =>
97
- state.settingsState.maxTopFlowsDisplayNum;
108
+ state.settings.maxTopFlowsDisplayNum;
98
109
  getSelectedLocations = (state: FlowmapState, props: FlowmapData<L, F>) =>
99
- state.filterState.selectedLocations;
110
+ state.filter?.selectedLocations;
100
111
  getLocationFilterMode = (state: FlowmapState, props: FlowmapData<L, F>) =>
101
- state.filterState.locationFilterMode;
112
+ state.filter?.locationFilterMode;
102
113
  getClusteringEnabled = (state: FlowmapState, props: FlowmapData<L, F>) =>
103
- state.settingsState.clusteringEnabled;
114
+ state.settings.clusteringEnabled;
104
115
  getLocationTotalsEnabled = (state: FlowmapState, props: FlowmapData<L, F>) =>
105
- state.settingsState.locationTotalsEnabled;
116
+ state.settings.locationTotalsEnabled;
106
117
  getZoom = (state: FlowmapState, props: FlowmapData<L, F>) =>
107
118
  state.viewport.zoom;
108
119
  getViewport = (state: FlowmapState, props: FlowmapData<L, F>) =>
109
120
  state.viewport;
110
121
  getSelectedTimeRange = (state: FlowmapState, props: FlowmapData<L, F>) =>
111
- state.filterState.selectedTimeRange;
122
+ state.filter?.selectedTimeRange;
112
123
 
113
124
  getColorScheme: Selector<L, F, string | string[] | undefined> = (
114
125
  state: FlowmapState,
115
126
  props: FlowmapData<L, F>,
116
- ) => state.settingsState.colorScheme;
127
+ ) => state.settings.colorScheme;
117
128
 
118
129
  getDarkMode: Selector<L, F, boolean> = (
119
130
  state: FlowmapState,
120
131
  props: FlowmapData<L, F>,
121
- ) => state.settingsState.darkMode;
132
+ ) => state.settings.darkMode;
122
133
 
123
134
  getFadeEnabled: Selector<L, F, boolean> = (
124
135
  state: FlowmapState,
125
136
  props: FlowmapData<L, F>,
126
- ) => state.settingsState.fadeEnabled;
137
+ ) => state.settings.fadeEnabled;
127
138
 
128
139
  getFadeOpacityEnabled: Selector<L, F, boolean> = (
129
140
  state: FlowmapState,
130
141
  props: FlowmapData<L, F>,
131
- ) => state.settingsState.fadeOpacityEnabled;
142
+ ) => state.settings.fadeOpacityEnabled;
132
143
 
133
144
  getFadeAmount: Selector<L, F, number> = (
134
145
  state: FlowmapState,
135
146
  props: FlowmapData<L, F>,
136
- ) => state.settingsState.fadeAmount;
147
+ ) => state.settings.fadeAmount;
137
148
 
138
149
  getAnimate: Selector<L, F, boolean> = (
139
150
  state: FlowmapState,
140
151
  props: FlowmapData<L, F>,
141
- ) => state.settingsState.animationEnabled;
152
+ ) => state.settings.animationEnabled;
142
153
 
143
- getInvalidLocationIds: Selector<L, F, string[] | undefined> = createSelector(
144
- this.getFetchedLocations,
145
- (locations) => {
154
+ getInvalidLocationIds: Selector<L, F, (string | number)[] | undefined> =
155
+ createSelector(this.getLocationsFromProps, (locations) => {
146
156
  if (!locations) return undefined;
147
157
  const invalid = [];
148
158
  for (const location of locations) {
@@ -154,11 +164,10 @@ export default class FlowmapSelectors<L, F> {
154
164
  }
155
165
  }
156
166
  return invalid.length > 0 ? invalid : undefined;
157
- },
158
- );
167
+ });
159
168
 
160
169
  getLocations: Selector<L, F, Iterable<L> | undefined> = createSelector(
161
- this.getFetchedLocations,
170
+ this.getLocationsFromProps,
162
171
  this.getInvalidLocationIds,
163
172
  (locations, invalidIds) => {
164
173
  if (!locations) return undefined;
@@ -175,17 +184,15 @@ export default class FlowmapSelectors<L, F> {
175
184
  },
176
185
  );
177
186
 
178
- getLocationIds: Selector<L, F, Set<string> | undefined> = createSelector(
179
- this.getLocations,
180
- (locations) => {
187
+ getLocationIds: Selector<L, F, Set<string | number> | undefined> =
188
+ createSelector(this.getLocations, (locations) => {
181
189
  if (!locations) return undefined;
182
- const ids = new Set<string>();
190
+ const ids = new Set<string | number>();
183
191
  for (const id of locations) {
184
192
  ids.add(this.accessors.getLocationId(id));
185
193
  }
186
194
  return ids;
187
- },
188
- );
195
+ });
189
196
 
190
197
  getSelectedLocationsSet: Selector<L, F, Set<string> | undefined> =
191
198
  createSelector(this.getSelectedLocations, (ids) =>
@@ -193,23 +200,27 @@ export default class FlowmapSelectors<L, F> {
193
200
  );
194
201
 
195
202
  getSortedFlowsForKnownLocations: Selector<L, F, F[] | undefined> =
196
- createSelector(this.getFetchedFlows, this.getLocationIds, (flows, ids) => {
197
- if (!ids || !flows) return undefined;
198
- const filtered = [];
199
- for (const flow of flows) {
200
- const srcId = this.accessors.getFlowOriginId(flow);
201
- const dstId = this.accessors.getFlowDestId(flow);
202
- if (ids.has(srcId) && ids.has(dstId)) {
203
- filtered.push(flow);
203
+ createSelector(
204
+ this.getFlowsFromProps,
205
+ this.getLocationIds,
206
+ (flows, ids) => {
207
+ if (!ids || !flows) return undefined;
208
+ const filtered = [];
209
+ for (const flow of flows) {
210
+ const srcId = this.accessors.getFlowOriginId(flow);
211
+ const dstId = this.accessors.getFlowDestId(flow);
212
+ if (ids.has(srcId) && ids.has(dstId)) {
213
+ filtered.push(flow);
214
+ }
204
215
  }
205
- }
206
- return filtered.sort((a: F, b: F) =>
207
- descending(
208
- Math.abs(this.accessors.getFlowMagnitude(a)),
209
- Math.abs(this.accessors.getFlowMagnitude(b)),
210
- ),
211
- );
212
- });
216
+ return filtered.sort((a: F, b: F) =>
217
+ descending(
218
+ Math.abs(this.accessors.getFlowMagnitude(a)),
219
+ Math.abs(this.accessors.getFlowMagnitude(b)),
220
+ ),
221
+ );
222
+ },
223
+ );
213
224
 
214
225
  getActualTimeExtent: Selector<L, F, [Date, Date] | undefined> =
215
226
  createSelector(this.getSortedFlowsForKnownLocations, (flows) => {
@@ -302,29 +313,33 @@ export default class FlowmapSelectors<L, F> {
302
313
  },
303
314
  );
304
315
 
305
- getLocationsById: Selector<L, F, Map<string, L> | undefined> = createSelector(
306
- this.getLocationsHavingFlows,
307
- (locations) => {
316
+ getLocationsById: Selector<L, F, Map<string | number, L> | undefined> =
317
+ createSelector(this.getLocationsHavingFlows, (locations) => {
308
318
  if (!locations) return undefined;
309
- const locationsById = new Map<string, L>();
319
+ const locationsById = new Map<string | number, L>();
310
320
  for (const location of locations) {
311
321
  locationsById.set(this.accessors.getLocationId(location), location);
312
322
  }
313
323
  return locationsById;
314
- },
315
- );
316
-
317
- getClusterIndex: Selector<L, F, ClusterIndex<F> | undefined> = createSelector(
318
- this.getLocationsHavingFlows,
319
- this.getLocationsById,
320
- this.getSortedFlowsForKnownLocations,
321
- (locations, locationsById, flows) => {
322
- if (!locations || !locationsById || !flows) return undefined;
324
+ });
323
325
 
326
+ getLocationWeightGetter: Selector<L, F, LocationWeightGetter | undefined> =
327
+ createSelector(this.getSortedFlowsForKnownLocations, (flows) => {
328
+ if (!flows) return undefined;
324
329
  const getLocationWeight = makeLocationWeightGetter(
325
330
  flows,
326
331
  this.accessors.getFlowmapDataAccessors(),
327
332
  );
333
+ return getLocationWeight;
334
+ });
335
+
336
+ getClusterLevels: Selector<L, F, ClusterLevels | undefined> = createSelector(
337
+ this.getClusterLevelsFromProps,
338
+ this.getLocationsHavingFlows,
339
+ this.getLocationWeightGetter,
340
+ (clusterLevelsFromProps, locations, getLocationWeight) => {
341
+ if (clusterLevelsFromProps) return clusterLevelsFromProps;
342
+ if (!locations || !getLocationWeight) return undefined;
328
343
  const clusterLevels = clusterLocations(
329
344
  locations,
330
345
  this.accessors.getFlowmapDataAccessors(),
@@ -333,12 +348,24 @@ export default class FlowmapSelectors<L, F> {
333
348
  maxZoom: MAX_CLUSTER_ZOOM_LEVEL,
334
349
  },
335
350
  );
351
+ return clusterLevels;
352
+ },
353
+ );
354
+
355
+ getClusterIndex: Selector<L, F, ClusterIndex<F> | undefined> = createSelector(
356
+ this.getLocationsById,
357
+ this.getLocationWeightGetter,
358
+ this.getClusterLevels,
359
+ (locationsById, getLocationWeight, clusterLevels) => {
360
+ if (!locationsById || !getLocationWeight || !clusterLevels)
361
+ return undefined;
362
+
336
363
  const clusterIndex = buildIndex<F>(clusterLevels);
337
364
  const {getLocationName, getLocationClusterName} =
338
365
  this.accessors.getFlowmapDataAccessors();
339
366
 
340
367
  // Adding meaningful names
341
- const getName = (id: string) => {
368
+ const getName = (id: string | number) => {
342
369
  const loc = locationsById.get(id);
343
370
  if (loc) {
344
371
  return getLocationName
@@ -418,7 +445,7 @@ export default class FlowmapSelectors<L, F> {
418
445
  this.getAvailableClusterZoomLevels,
419
446
  (clusterIndex, mapZoom, availableClusterZoomLevels) => {
420
447
  if (!clusterIndex) return undefined;
421
- if (!availableClusterZoomLevels) {
448
+ if (!availableClusterZoomLevels || mapZoom == null) {
422
449
  return undefined;
423
450
  }
424
451
 
@@ -431,12 +458,12 @@ export default class FlowmapSelectors<L, F> {
431
458
  );
432
459
 
433
460
  getClusterZoom = (state: FlowmapState, props: FlowmapData<L, F>) => {
434
- const {settingsState} = state;
435
- if (!settingsState.clusteringEnabled) return undefined;
436
- if (settingsState.clusteringAuto || settingsState.clusteringLevel == null) {
461
+ const {settings} = state;
462
+ if (!settings.clusteringEnabled) return undefined;
463
+ if (settings.clusteringAuto || settings.clusteringLevel == null) {
437
464
  return this._getClusterZoom(state, props);
438
465
  }
439
- return settingsState.clusteringLevel;
466
+ return settings.clusteringLevel;
440
467
  };
441
468
 
442
469
  getLocationsForSearchBox: Selector<L, F, (L | Cluster)[] | undefined> =
@@ -489,7 +516,7 @@ export default class FlowmapSelectors<L, F> {
489
516
  );
490
517
 
491
518
  getDiffMode: Selector<L, F, boolean> = createSelector(
492
- this.getFetchedFlows,
519
+ this.getFlowsFromProps,
493
520
  (flows) => {
494
521
  if (flows) {
495
522
  for (const f of flows) {
@@ -522,27 +549,28 @@ export default class FlowmapSelectors<L, F> {
522
549
  },
523
550
  );
524
551
 
525
- getUnknownLocations: Selector<L, F, Set<string> | undefined> = createSelector(
526
- this.getLocationIds,
527
- this.getFetchedFlows,
528
- this.getSortedFlowsForKnownLocations,
529
- (ids, flows, flowsForKnownLocations) => {
530
- if (!ids || !flows) return undefined;
531
- if (
532
- flowsForKnownLocations
533
- // && flows.length === flowsForKnownLocations.length
534
- )
535
- return undefined;
536
- const missing = new Set<string>();
537
- for (const flow of flows) {
538
- if (!ids.has(this.accessors.getFlowOriginId(flow)))
539
- missing.add(this.accessors.getFlowOriginId(flow));
540
- if (!ids.has(this.accessors.getFlowDestId(flow)))
541
- missing.add(this.accessors.getFlowDestId(flow));
542
- }
543
- return missing;
544
- },
545
- );
552
+ getUnknownLocations: Selector<L, F, Set<string | number> | undefined> =
553
+ createSelector(
554
+ this.getLocationIds,
555
+ this.getFlowsFromProps,
556
+ this.getSortedFlowsForKnownLocations,
557
+ (ids, flows, flowsForKnownLocations) => {
558
+ if (!ids || !flows) return undefined;
559
+ if (
560
+ flowsForKnownLocations
561
+ // && flows.length === flowsForKnownLocations.length
562
+ )
563
+ return undefined;
564
+ const missing = new Set<string | number>();
565
+ for (const flow of flows) {
566
+ if (!ids.has(this.accessors.getFlowOriginId(flow)))
567
+ missing.add(this.accessors.getFlowOriginId(flow));
568
+ if (!ids.has(this.accessors.getFlowDestId(flow)))
569
+ missing.add(this.accessors.getFlowDestId(flow));
570
+ }
571
+ return missing;
572
+ },
573
+ );
546
574
 
547
575
  getSortedAggregatedFilteredFlows: Selector<
548
576
  L,
@@ -662,15 +690,7 @@ export default class FlowmapSelectors<L, F> {
662
690
  createSelector(
663
691
  this.getViewport,
664
692
  this.getMaxLocationCircleSize,
665
- (viewport, maxLocationCircleSize) => {
666
- const pad = maxLocationCircleSize;
667
- const bounds = new WebMercatorViewport({
668
- ...viewport,
669
- width: viewport.width + pad * 2,
670
- height: viewport.height + pad * 2,
671
- }).getBounds();
672
- return [bounds[0][0], bounds[0][1], bounds[1][0], bounds[1][1]];
673
- },
693
+ getViewportBoundingBox,
674
694
  );
675
695
 
676
696
  getLocationsForZoom: Selector<L, F, Iterable<L> | ClusterNode[] | undefined> =
@@ -688,47 +708,50 @@ export default class FlowmapSelectors<L, F> {
688
708
  },
689
709
  );
690
710
 
691
- getLocationTotals: Selector<L, F, Map<string, LocationTotals> | undefined> =
692
- createSelector(
693
- this.getLocationsForZoom,
694
- this.getSortedAggregatedFilteredFlows,
695
- this.getSelectedLocationsSet,
696
- this.getLocationFilterMode,
697
- (locations, flows, selectedLocationsSet, locationFilterMode) => {
698
- if (!flows) return undefined;
699
- const totals = new Map<string, LocationTotals>();
700
- const add = (
701
- id: string,
702
- d: Partial<LocationTotals>,
703
- ): LocationTotals => {
704
- const rv = totals.get(id) ?? {
705
- incomingCount: 0,
706
- outgoingCount: 0,
707
- internalCount: 0,
708
- };
709
- if (d.incomingCount != null) rv.incomingCount += d.incomingCount;
710
- if (d.outgoingCount != null) rv.outgoingCount += d.outgoingCount;
711
- if (d.internalCount != null) rv.internalCount += d.internalCount;
712
- return rv;
711
+ getLocationTotals: Selector<
712
+ L,
713
+ F,
714
+ Map<string | number, LocationTotals> | undefined
715
+ > = createSelector(
716
+ this.getLocationsForZoom,
717
+ this.getSortedAggregatedFilteredFlows,
718
+ this.getSelectedLocationsSet,
719
+ this.getLocationFilterMode,
720
+ (locations, flows, selectedLocationsSet, locationFilterMode) => {
721
+ if (!flows) return undefined;
722
+ const totals = new Map<string | number, LocationTotals>();
723
+ const add = (
724
+ id: string | number,
725
+ d: Partial<LocationTotals>,
726
+ ): LocationTotals => {
727
+ const rv = totals.get(id) ?? {
728
+ incomingCount: 0,
729
+ outgoingCount: 0,
730
+ internalCount: 0,
713
731
  };
714
- for (const f of flows) {
715
- if (
716
- this.isFlowInSelection(f, selectedLocationsSet, locationFilterMode)
717
- ) {
718
- const originId = this.accessors.getFlowOriginId(f);
719
- const destId = this.accessors.getFlowDestId(f);
720
- const count = this.accessors.getFlowMagnitude(f);
721
- if (originId === destId) {
722
- totals.set(originId, add(originId, {internalCount: count}));
723
- } else {
724
- totals.set(originId, add(originId, {outgoingCount: count}));
725
- totals.set(destId, add(destId, {incomingCount: count}));
726
- }
732
+ if (d.incomingCount != null) rv.incomingCount += d.incomingCount;
733
+ if (d.outgoingCount != null) rv.outgoingCount += d.outgoingCount;
734
+ if (d.internalCount != null) rv.internalCount += d.internalCount;
735
+ return rv;
736
+ };
737
+ for (const f of flows) {
738
+ if (
739
+ this.isFlowInSelection(f, selectedLocationsSet, locationFilterMode)
740
+ ) {
741
+ const originId = this.accessors.getFlowOriginId(f);
742
+ const destId = this.accessors.getFlowDestId(f);
743
+ const count = this.accessors.getFlowMagnitude(f);
744
+ if (originId === destId) {
745
+ totals.set(originId, add(originId, {internalCount: count}));
746
+ } else {
747
+ totals.set(originId, add(originId, {outgoingCount: count}));
748
+ totals.set(destId, add(destId, {incomingCount: count}));
727
749
  }
728
750
  }
729
- return totals;
730
- },
731
- );
751
+ }
752
+ return totals;
753
+ },
754
+ );
732
755
 
733
756
  getLocationsTree: Selector<L, F, KDBushTree> = createSelector(
734
757
  this.getLocationsForZoom,
@@ -762,7 +785,7 @@ export default class FlowmapSelectors<L, F> {
762
785
  },
763
786
  );
764
787
 
765
- getLocationIdsInViewport: Selector<L, F, Set<string> | undefined> =
788
+ getLocationIdsInViewport: Selector<L, F, Set<string | number> | undefined> =
766
789
  createSelectorCreator(
767
790
  defaultMemoize,
768
791
  // @ts-ignore
@@ -834,7 +857,7 @@ export default class FlowmapSelectors<L, F> {
834
857
  state: FlowmapState,
835
858
  props: FlowmapData<L, F>,
836
859
  ): [number, number] | undefined => {
837
- if (state.settingsState.adaptiveScalesEnabled) {
860
+ if (state.settings.adaptiveScalesEnabled) {
838
861
  return this._getLocationTotalsForViewportExtent(state, props);
839
862
  } else {
840
863
  return this._getLocationTotalsExtent(state, props);
@@ -929,7 +952,7 @@ export default class FlowmapSelectors<L, F> {
929
952
  state: FlowmapState,
930
953
  props: FlowmapData<L, F>,
931
954
  ): [number, number] | undefined => {
932
- if (state.settingsState.adaptiveScalesEnabled) {
955
+ if (state.settings.adaptiveScalesEnabled) {
933
956
  return this._getAdaptiveFlowMagnitudeExtent(state, props);
934
957
  } else {
935
958
  return this._getFlowMagnitudeExtent(state, props);
@@ -952,19 +975,7 @@ export default class FlowmapSelectors<L, F> {
952
975
 
953
976
  getFlowThicknessScale = createSelector(
954
977
  this.getFlowMagnitudeExtent,
955
- (magnitudeExtent) => {
956
- if (!magnitudeExtent) return undefined;
957
- return scaleLinear()
958
- .range([0.025, 0.5])
959
- .domain([
960
- 0,
961
- // should support diff mode too
962
- Math.max.apply(
963
- null,
964
- magnitudeExtent.map((x: number | undefined) => Math.abs(x || 0)),
965
- ),
966
- ]);
967
- },
978
+ getFlowThicknessScale,
968
979
  );
969
980
 
970
981
  getCircleSizeScale = createSelector(
@@ -995,7 +1006,7 @@ export default class FlowmapSelectors<L, F> {
995
1006
  this.getCircleSizeScale,
996
1007
  this.getLocationTotals,
997
1008
  (circleSizeScale, locationTotals) => {
998
- return (locationId: string) => {
1009
+ return (locationId: string | number) => {
999
1010
  const total = locationTotals?.get(locationId);
1000
1011
  if (total && circleSizeScale) {
1001
1012
  return (
@@ -1013,7 +1024,7 @@ export default class FlowmapSelectors<L, F> {
1013
1024
  this.getCircleSizeScale,
1014
1025
  this.getLocationTotals,
1015
1026
  (circleSizeScale, locationTotals) => {
1016
- return (locationId: string) => {
1027
+ return (locationId: string | number) => {
1017
1028
  const total = locationTotals?.get(locationId);
1018
1029
  if (total && circleSizeScale) {
1019
1030
  return (
@@ -1141,7 +1152,7 @@ export default class FlowmapSelectors<L, F> {
1141
1152
  getInCircleSize,
1142
1153
  getOutCircleSize,
1143
1154
  flowThicknessScale,
1144
- state.settingsState.animationEnabled,
1155
+ state.settings.animationEnabled,
1145
1156
  );
1146
1157
  }
1147
1158
 
@@ -1149,10 +1160,10 @@ export default class FlowmapSelectors<L, F> {
1149
1160
  locations: (L | ClusterNode)[] | undefined,
1150
1161
  flows: (F | AggregateFlow)[] | undefined,
1151
1162
  flowmapColors: DiffColorsRGBA | ColorsRGBA,
1152
- locationsById: Map<string, L | ClusterNode> | undefined,
1153
- locationIdsInViewport: Set<string> | undefined,
1154
- getInCircleSize: (locationId: string) => number,
1155
- getOutCircleSize: (locationId: string) => number,
1163
+ locationsById: Map<string | number, L | ClusterNode> | undefined,
1164
+ locationIdsInViewport: Set<string | number> | undefined,
1165
+ getInCircleSize: (locationId: string | number) => number,
1166
+ getOutCircleSize: (locationId: string | number) => number,
1156
1167
  flowThicknessScale: ScaleLinear<number, number, never> | undefined,
1157
1168
  animationEnabled: boolean,
1158
1169
  ): LayersData {
@@ -1326,8 +1337,8 @@ export default class FlowmapSelectors<L, F> {
1326
1337
 
1327
1338
  isFlowInSelection(
1328
1339
  flow: F | AggregateFlow,
1329
- selectedLocationsSet: Set<string> | undefined,
1330
- locationFilterMode: LocationFilterMode,
1340
+ selectedLocationsSet: Set<string | number> | undefined,
1341
+ locationFilterMode?: LocationFilterMode,
1331
1342
  ) {
1332
1343
  const origin = this.accessors.getFlowOriginId(flow);
1333
1344
  const dest = this.accessors.getFlowDestId(flow);
@@ -1373,8 +1384,8 @@ export default class FlowmapSelectors<L, F> {
1373
1384
  }
1374
1385
 
1375
1386
  function calcLocationTotalsExtent(
1376
- locationTotals: Map<string, LocationTotals> | undefined,
1377
- locationIdsInViewport: Set<string> | undefined,
1387
+ locationTotals: Map<string | number, LocationTotals> | undefined,
1388
+ locationIdsInViewport: Set<string | number> | undefined,
1378
1389
  ) {
1379
1390
  if (!locationTotals) return undefined;
1380
1391
  let rv: [number, number] | undefined = undefined;
@@ -1,9 +1,9 @@
1
1
  import {LocationFilterMode, ViewportProps} from './types';
2
2
 
3
3
  export interface FilterState {
4
- selectedLocations: string[] | undefined;
5
- selectedTimeRange: [Date, Date] | undefined;
6
- locationFilterMode: LocationFilterMode;
4
+ selectedLocations?: string[];
5
+ locationFilterMode?: LocationFilterMode;
6
+ selectedTimeRange?: [Date, Date];
7
7
  }
8
8
 
9
9
  export interface SettingsState {
@@ -23,7 +23,7 @@ export interface SettingsState {
23
23
  }
24
24
 
25
25
  export interface FlowmapState {
26
- filterState: FilterState;
27
- settingsState: SettingsState;
26
+ filter?: FilterState;
27
+ settings: SettingsState;
28
28
  viewport: ViewportProps;
29
29
  }