@flowmap.gl/data 8.0.0-alpha.0

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 (56) hide show
  1. package/LICENSE +199 -0
  2. package/dist/FlowMapAggregateAccessors.d.ts +15 -0
  3. package/dist/FlowMapAggregateAccessors.d.ts.map +1 -0
  4. package/dist/FlowMapAggregateAccessors.js +43 -0
  5. package/dist/FlowMapSelectors.d.ts +156 -0
  6. package/dist/FlowMapSelectors.d.ts.map +1 -0
  7. package/dist/FlowMapSelectors.js +831 -0
  8. package/dist/FlowMapState.d.ts +24 -0
  9. package/dist/FlowMapState.d.ts.map +1 -0
  10. package/dist/FlowMapState.js +2 -0
  11. package/dist/cluster/ClusterIndex.d.ts +42 -0
  12. package/dist/cluster/ClusterIndex.d.ts.map +1 -0
  13. package/dist/cluster/ClusterIndex.js +178 -0
  14. package/dist/cluster/cluster.d.ts +31 -0
  15. package/dist/cluster/cluster.d.ts.map +1 -0
  16. package/dist/cluster/cluster.js +206 -0
  17. package/dist/colors.d.ts +103 -0
  18. package/dist/colors.d.ts.map +1 -0
  19. package/dist/colors.js +441 -0
  20. package/dist/getViewStateForLocations.d.ts +16 -0
  21. package/dist/getViewStateForLocations.d.ts.map +1 -0
  22. package/dist/getViewStateForLocations.js +30 -0
  23. package/dist/index.d.ts +11 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +10 -0
  26. package/dist/provider/FlowMapDataProvider.d.ts +16 -0
  27. package/dist/provider/FlowMapDataProvider.d.ts.map +1 -0
  28. package/dist/provider/FlowMapDataProvider.js +17 -0
  29. package/dist/provider/LocalFlowMapDataProvider.d.ts +20 -0
  30. package/dist/provider/LocalFlowMapDataProvider.d.ts.map +1 -0
  31. package/dist/provider/LocalFlowMapDataProvider.js +87 -0
  32. package/dist/time.d.ts +24 -0
  33. package/dist/time.d.ts.map +1 -0
  34. package/dist/time.js +126 -0
  35. package/dist/types.d.ts +116 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +23 -0
  38. package/dist/util.d.ts +2 -0
  39. package/dist/util.d.ts.map +1 -0
  40. package/dist/util.js +4 -0
  41. package/package.json +48 -0
  42. package/src/FlowMapAggregateAccessors.ts +60 -0
  43. package/src/FlowMapSelectors.ts +1407 -0
  44. package/src/FlowMapState.ts +26 -0
  45. package/src/cluster/ClusterIndex.ts +266 -0
  46. package/src/cluster/cluster.ts +299 -0
  47. package/src/colors.ts +723 -0
  48. package/src/getViewStateForLocations.ts +64 -0
  49. package/src/index.ts +10 -0
  50. package/src/provider/FlowMapDataProvider.ts +63 -0
  51. package/src/provider/LocalFlowMapDataProvider.ts +108 -0
  52. package/src/time.ts +160 -0
  53. package/src/types.ts +162 -0
  54. package/src/util.ts +3 -0
  55. package/tsconfig.json +11 -0
  56. package/typings.d.ts +1 -0
package/src/colors.ts ADDED
@@ -0,0 +1,723 @@
1
+ import {
2
+ interpolateCool,
3
+ interpolateInferno,
4
+ interpolateMagma,
5
+ interpolatePlasma,
6
+ interpolateViridis,
7
+ interpolateWarm,
8
+ schemeBlues,
9
+ schemeBuGn,
10
+ schemeBuPu,
11
+ schemeGnBu,
12
+ schemeGreens,
13
+ schemeGreys,
14
+ schemeOranges,
15
+ schemeOrRd,
16
+ schemePuBu,
17
+ schemePuBuGn,
18
+ schemePuRd,
19
+ schemePurples,
20
+ schemeRdPu,
21
+ schemeReds,
22
+ schemeYlGn,
23
+ schemeYlGnBu,
24
+ schemeYlOrBr,
25
+ schemeYlOrRd,
26
+ } from 'd3-scale-chromatic';
27
+ import {range} from 'd3-array';
28
+ import {scalePow, scaleSequential, scaleSequentialPow} from 'd3-scale';
29
+ import {interpolateRgbBasis} from 'd3-interpolate';
30
+ import {color as d3color, hcl} from 'd3-color';
31
+ import {SettingsState} from './FlowMapState';
32
+
33
+ const DEFAULT_OUTLINE_COLOR = '#fff';
34
+ const DEFAULT_DIMMED_OPACITY = 0.4;
35
+ const DEFAULT_FLOW_MIN_COLOR = 'rgba(240,240,240,0.5)';
36
+ const DEFAULT_FLOW_COLOR_SCHEME = [DEFAULT_FLOW_MIN_COLOR, '#137CBD'];
37
+ const DEFAULT_LOCATION_AREA_COLOR = 'rgba(220,220,220,0.5)';
38
+
39
+ const DEFAULT_FLOW_COLOR_SCHEME_POSITIVE = [DEFAULT_FLOW_MIN_COLOR, '#f6654e'];
40
+ const DEFAULT_FLOW_COLOR_SCHEME_NEGATIVE = [DEFAULT_FLOW_MIN_COLOR, '#00a9cc'];
41
+
42
+ export type ColorScale = (value: number) => RGBA;
43
+ export type RGBA = [number, number, number, number];
44
+
45
+ const FALLBACK_COLOR_RGBA: RGBA = [255, 255, 255, 255];
46
+
47
+ export function opacityFloatToInteger(opacity: number): number {
48
+ return Math.round(opacity * 255);
49
+ }
50
+
51
+ export function opacifyHex(hexCode: string, opacity: number): string {
52
+ const c = d3color(hexCode);
53
+ if (!c) {
54
+ console.warn('Invalid color: ', hexCode);
55
+ return `rgba(255, 255, 255, ${opacity})`;
56
+ }
57
+ const col = c.rgb();
58
+ return `rgba(${col.r}, ${col.g}, ${col.b}, ${opacity})`;
59
+ }
60
+
61
+ export function colorAsRgba(color: string): RGBA {
62
+ const col = d3color(color);
63
+ if (!col) {
64
+ console.warn('Invalid color: ', color);
65
+ return FALLBACK_COLOR_RGBA;
66
+ }
67
+ const rgbColor = col.rgb();
68
+ return [
69
+ Math.floor(rgbColor.r),
70
+ Math.floor(rgbColor.g),
71
+ Math.floor(rgbColor.b),
72
+ opacityFloatToInteger(col.opacity),
73
+ ];
74
+ }
75
+
76
+ function colorAsRgbaOr(
77
+ color: string | undefined,
78
+ defaultColor: RGBA | string,
79
+ ): RGBA {
80
+ if (color) {
81
+ return colorAsRgba(color);
82
+ }
83
+ if (typeof defaultColor === 'string') {
84
+ return colorAsRgba(defaultColor);
85
+ }
86
+ return defaultColor;
87
+ }
88
+
89
+ const asScheme = (scheme: ReadonlyArray<ReadonlyArray<string>>) =>
90
+ scheme[scheme.length - 1] as string[];
91
+
92
+ export enum ColorScheme {
93
+ primary = '#162d3c',
94
+ }
95
+
96
+ const SCALE_NUM_STEPS = 20;
97
+ const getColorSteps = (interpolate: (x: number) => string) =>
98
+ range(0, SCALE_NUM_STEPS + 1)
99
+ .map((i) => interpolate(i / SCALE_NUM_STEPS))
100
+ .reverse();
101
+
102
+ const FLOW_MIN_COLOR = 'rgba(240,240,240,0.5)';
103
+ export const BLUES_PALE = [FLOW_MIN_COLOR, ColorScheme.primary];
104
+ const schemeBluYl = [
105
+ '#f7feae',
106
+ '#b7e6a5',
107
+ '#7ccba2',
108
+ '#46aea0',
109
+ '#089099',
110
+ '#00718b',
111
+ '#045275',
112
+ ];
113
+
114
+ const schemeEmrld = [
115
+ '#d3f2a3',
116
+ '#97e196',
117
+ '#6cc08b',
118
+ '#4c9b82',
119
+ '#217a79',
120
+ '#105965',
121
+ '#074050',
122
+ ];
123
+
124
+ export const schemeTeal = [
125
+ '#d1eeea',
126
+ '#a8dbd9',
127
+ '#85c4c9',
128
+ '#68abb8',
129
+ '#4f90a6',
130
+ '#3b738f',
131
+ '#2a5674',
132
+ ];
133
+
134
+ export const DEFAULT_COLOR_SCHEME = schemeTeal;
135
+ export const COLOR_SCHEMES: {[key: string]: string[]} = {
136
+ Blues: asScheme(schemeBlues),
137
+ BluesPale: BLUES_PALE,
138
+ BluGrn: [
139
+ '#c4e6c3',
140
+ '#96d2a4',
141
+ '#6dbc90',
142
+ '#4da284',
143
+ '#36877a',
144
+ '#266b6e',
145
+ '#1d4f60',
146
+ ],
147
+ BluYl: schemeBluYl,
148
+ BrwnYl: [
149
+ '#ede5cf',
150
+ '#e0c2a2',
151
+ '#d39c83',
152
+ '#c1766f',
153
+ '#a65461',
154
+ '#813753',
155
+ '#541f3f',
156
+ ],
157
+ BuGn: asScheme(schemeBuGn),
158
+ BuPu: asScheme(schemeBuPu),
159
+ Burg: [
160
+ '#ffc6c4',
161
+ '#f4a3a8',
162
+ '#e38191',
163
+ '#cc607d',
164
+ '#ad466c',
165
+ '#8b3058',
166
+ '#672044',
167
+ ],
168
+ BurgYl: [
169
+ '#fbe6c5',
170
+ '#f5ba98',
171
+ '#ee8a82',
172
+ '#dc7176',
173
+ '#c8586c',
174
+ '#9c3f5d',
175
+ '#70284a',
176
+ ],
177
+ Cool: getColorSteps(interpolateCool),
178
+ DarkMint: [
179
+ '#d2fbd4',
180
+ '#a5dbc2',
181
+ '#7bbcb0',
182
+ '#559c9e',
183
+ '#3a7c89',
184
+ '#235d72',
185
+ '#123f5a',
186
+ ],
187
+ Emrld: schemeEmrld,
188
+ GnBu: asScheme(schemeGnBu),
189
+ Greens: asScheme(schemeGreens),
190
+ Greys: asScheme(schemeGreys),
191
+ Inferno: getColorSteps(interpolateInferno),
192
+ Magenta: [
193
+ '#f3cbd3',
194
+ '#eaa9bd',
195
+ '#dd88ac',
196
+ '#ca699d',
197
+ '#b14d8e',
198
+ '#91357d',
199
+ '#6c2167',
200
+ ],
201
+ Magma: getColorSteps(interpolateMagma),
202
+ Mint: [
203
+ '#e4f1e1',
204
+ '#b4d9cc',
205
+ '#89c0b6',
206
+ '#63a6a0',
207
+ '#448c8a',
208
+ '#287274',
209
+ '#0d585f',
210
+ ],
211
+ Oranges: asScheme(schemeOranges),
212
+ OrRd: asScheme(schemeOrRd),
213
+ OrYel: [
214
+ '#ecda9a',
215
+ '#efc47e',
216
+ '#f3ad6a',
217
+ '#f7945d',
218
+ '#f97b57',
219
+ '#f66356',
220
+ '#ee4d5a',
221
+ ],
222
+ Peach: [
223
+ '#fde0c5',
224
+ '#facba6',
225
+ '#f8b58b',
226
+ '#f59e72',
227
+ '#f2855d',
228
+ '#ef6a4c',
229
+ '#eb4a40',
230
+ ],
231
+ Plasma: getColorSteps(interpolatePlasma),
232
+ PinkYl: [
233
+ '#fef6b5',
234
+ '#ffdd9a',
235
+ '#ffc285',
236
+ '#ffa679',
237
+ '#fa8a76',
238
+ '#f16d7a',
239
+ '#e15383',
240
+ ],
241
+ PuBu: asScheme(schemePuBu),
242
+ PuBuGn: asScheme(schemePuBuGn),
243
+ PuRd: asScheme(schemePuRd),
244
+ Purp: [
245
+ '#f3e0f7',
246
+ '#e4c7f1',
247
+ '#d1afe8',
248
+ '#b998dd',
249
+ '#9f82ce',
250
+ '#826dba',
251
+ '#63589f',
252
+ ],
253
+ Purples: asScheme(schemePurples),
254
+ PurpOr: [
255
+ '#f9ddda',
256
+ '#f2b9c4',
257
+ '#e597b9',
258
+ '#ce78b3',
259
+ '#ad5fad',
260
+ '#834ba0',
261
+ '#573b88',
262
+ ],
263
+ RdPu: asScheme(schemeRdPu),
264
+ RedOr: [
265
+ '#f6d2a9',
266
+ '#f5b78e',
267
+ '#f19c7c',
268
+ '#ea8171',
269
+ '#dd686c',
270
+ '#ca5268',
271
+ '#b13f64',
272
+ ],
273
+ Reds: asScheme(schemeReds),
274
+ Sunset: [
275
+ '#f3e79b',
276
+ '#fac484',
277
+ '#f8a07e',
278
+ '#eb7f86',
279
+ '#ce6693',
280
+ '#a059a0',
281
+ '#5c53a5',
282
+ ],
283
+ SunsetDark: [
284
+ '#fcde9c',
285
+ '#faa476',
286
+ '#f0746e',
287
+ '#e34f6f',
288
+ '#dc3977',
289
+ '#b9257a',
290
+ '#7c1d6f',
291
+ ],
292
+ Teal: schemeTeal,
293
+ TealGrn: [
294
+ '#b0f2bc',
295
+ '#89e8ac',
296
+ '#67dba5',
297
+ '#4cc8a3',
298
+ '#38b2a3',
299
+ '#2c98a0',
300
+ '#257d98',
301
+ ],
302
+ Viridis: getColorSteps(interpolateViridis),
303
+ Warm: getColorSteps(interpolateWarm),
304
+ YlGn: asScheme(schemeYlGn),
305
+ YlGnBu: asScheme(schemeYlGnBu),
306
+ YlOrBr: asScheme(schemeYlOrBr),
307
+ YlOrRd: asScheme(schemeYlOrRd),
308
+ };
309
+
310
+ export const COLOR_SCHEME_KEYS = Object.keys(COLOR_SCHEMES);
311
+
312
+ const complementary = '#f52020';
313
+ const baseDiffColor = '#17a5be';
314
+
315
+ const diffColors: DiffColors = {
316
+ negative: {
317
+ flows: {
318
+ scheme: [FLOW_MIN_COLOR, baseDiffColor],
319
+ },
320
+ },
321
+ positive: {
322
+ flows: {
323
+ scheme: [FLOW_MIN_COLOR, complementary],
324
+ },
325
+ },
326
+ locationAreas: {
327
+ outline: 'rgba(92,112,128,0.5)',
328
+ normal: 'rgba(220,220,220,0.5)',
329
+ },
330
+ outlineColor: 'rgb(230,233,237)',
331
+ };
332
+
333
+ export function getFlowMapColors(
334
+ settingsState: SettingsState,
335
+ ): Colors | DiffColors {
336
+ return getColors(
337
+ false, // TODO: diffMode
338
+ settingsState.colorScheme,
339
+ settingsState.darkMode,
340
+ settingsState.fadeEnabled,
341
+ settingsState.fadeAmount,
342
+ settingsState.animationEnabled,
343
+ );
344
+ }
345
+
346
+ export function getColors(
347
+ diffMode: boolean,
348
+ schemeKey: string | undefined,
349
+ darkMode: boolean,
350
+ fadeEnabled: boolean,
351
+ fadeAmount: number,
352
+ animate: boolean,
353
+ ): Colors | DiffColors {
354
+ if (diffMode) {
355
+ return diffColors;
356
+ }
357
+
358
+ let scheme = (schemeKey && COLOR_SCHEMES[schemeKey]) || DEFAULT_COLOR_SCHEME;
359
+
360
+ if (darkMode) {
361
+ scheme = scheme.slice().reverse();
362
+ }
363
+ // if (animate)
364
+ // if (fadeAmount > 0)
365
+ {
366
+ const indices = range(0, Math.max(10, scheme.length));
367
+ const N = indices.length - 1;
368
+ const colorScale = scaleSequential(interpolateRgbBasis(scheme)).domain([
369
+ 0,
370
+ N,
371
+ ]);
372
+
373
+ if (!fadeEnabled || fadeAmount === 0) {
374
+ scheme = indices.map((c, i) => colorScale(i));
375
+ } else {
376
+ const amount = scalePow()
377
+ // .exponent(animate ? 1 : 1/2.5)
378
+ // .exponent(animate ? 100 : 50)
379
+ // .exponent(animate ? 20 : 5)
380
+ // .exponent(1/2.5)
381
+ .exponent(1.5)
382
+ .domain([N, 0])
383
+ // .range([fadeAmount/100*(animate?2:1), 0])
384
+ // .range([0, fadeAmount/100*(animate?2:1)])
385
+ // .range(darkMode ? [1-fadeAmount/100, 1] : [1, 1 - fadeAmount/100])
386
+ // .range(darkMode ? [1 - fadeAmount/100, 1] : [fadeAmount/100, 0])
387
+ // .range([1 - fadeAmount/100, 1])
388
+ .range([0, (2 * fadeAmount) / 100]);
389
+
390
+ scheme = indices.map(
391
+ (c, i) => {
392
+ const color = colorScale(i);
393
+ const alpha = amount(i);
394
+ if (color == null || alpha == null) return '#000';
395
+ const col = hcl(color);
396
+ col.l = darkMode
397
+ ? col.l - col.l * alpha
398
+ : col.l + (100 - col.l) * alpha;
399
+ col.c = col.c - col.c * (alpha / 4);
400
+ return col.toString();
401
+ },
402
+ // interpolateRgbBasis([colorScale(i), darkMode ? '#000' : '#fff'])(amount(i))
403
+ // interpolateHsl(colorScale(i), darkMode ? '#000' : '#fff')(amount(i)).toString()
404
+ );
405
+ }
406
+ }
407
+
408
+ return {
409
+ darkMode,
410
+ flows: {
411
+ scheme,
412
+ },
413
+ locationCircles: {
414
+ outgoing: darkMode ? '#000' : '#fff',
415
+ },
416
+ outlineColor: darkMode ? '#000' : 'rgba(255, 255, 255, 0.5)',
417
+ };
418
+ }
419
+
420
+ export function createFlowColorScale(
421
+ domain: [number, number],
422
+ scheme: string[],
423
+ animate: boolean | undefined,
424
+ ): ColorScale {
425
+ const scale = scaleSequentialPow(interpolateRgbBasis(scheme))
426
+ // @ts-ignore
427
+ .exponent(animate ? 1 / 2 : 1 / 3)
428
+ .domain(domain);
429
+ return (value: number) => colorAsRgba(scale(value));
430
+ }
431
+
432
+ export function getFlowColorScale(
433
+ colors: ColorsRGBA | DiffColorsRGBA,
434
+ magnitudeExtent: [number, number] | undefined,
435
+ animate: boolean | undefined,
436
+ ): (magnitude: number) => [number, number, number, number] {
437
+ const minMagnitude = magnitudeExtent ? magnitudeExtent[0] : 0;
438
+ const maxMagnitude = magnitudeExtent ? magnitudeExtent[1] : 0;
439
+ if (isDiffColorsRGBA(colors)) {
440
+ const posScale = createFlowColorScale(
441
+ [0, maxMagnitude],
442
+ colors.positive.flows.scheme,
443
+ animate,
444
+ );
445
+ const negScale = createFlowColorScale(
446
+ [0, minMagnitude],
447
+ colors.negative.flows.scheme,
448
+ animate,
449
+ );
450
+
451
+ return (magnitude: number) =>
452
+ magnitude >= 0 ? posScale(magnitude) : negScale(magnitude);
453
+ }
454
+
455
+ const scale = createFlowColorScale(
456
+ [0, maxMagnitude || 0],
457
+ colors.flows.scheme,
458
+ animate,
459
+ );
460
+ return (magnitude: number) => scale(magnitude);
461
+ }
462
+
463
+ export function isDiffColors(
464
+ colors: DiffColors | Colors,
465
+ ): colors is DiffColors {
466
+ return (colors as DiffColors).positive !== undefined;
467
+ }
468
+
469
+ export function isDiffColorsRGBA(
470
+ colors: DiffColorsRGBA | ColorsRGBA,
471
+ ): colors is DiffColorsRGBA {
472
+ return (colors as DiffColorsRGBA).positive !== undefined;
473
+ }
474
+
475
+ function getLocationAreaColorsRGBA(
476
+ colors: LocationAreaColors | undefined,
477
+ darkMode: boolean,
478
+ ): LocationAreaColorsRGBA {
479
+ const normalColor = (colors && colors.normal) || DEFAULT_LOCATION_AREA_COLOR;
480
+ const normalColorHcl = hcl(normalColor);
481
+ const locationAreasNormal = colorAsRgba(normalColor);
482
+ return {
483
+ normal: locationAreasNormal,
484
+ connected: colorAsRgbaOr(colors && colors.connected, locationAreasNormal),
485
+ highlighted: colorAsRgbaOr(
486
+ colors && colors.highlighted,
487
+ opacifyHex(
488
+ normalColorHcl[darkMode ? 'brighter' : 'darker'](1).toString(),
489
+ 0.5,
490
+ ),
491
+ ),
492
+ selected: colorAsRgbaOr(
493
+ colors && colors.selected,
494
+ opacifyHex(
495
+ normalColorHcl[darkMode ? 'brighter' : 'darker'](2).toString(),
496
+ 0.8,
497
+ ),
498
+ ),
499
+ outline: colorAsRgbaOr(
500
+ colors && colors.outline,
501
+ colorAsRgba(
502
+ normalColorHcl[darkMode ? 'brighter' : 'darker'](4).toString(),
503
+ ),
504
+ ),
505
+ };
506
+ }
507
+
508
+ export interface FlowColors {
509
+ scheme?: string[];
510
+ highlighted?: string;
511
+ }
512
+
513
+ export interface LocationCircleColors {
514
+ inner?: string;
515
+ outgoing?: string;
516
+ incoming?: string;
517
+ highlighted?: string;
518
+ empty?: string;
519
+ emptyOutline?: string;
520
+ }
521
+
522
+ export interface LocationAreaColors {
523
+ outline?: string;
524
+ normal?: string;
525
+ selected?: string;
526
+ highlighted?: string;
527
+ connected?: string;
528
+ }
529
+
530
+ export interface BaseColors {
531
+ darkMode?: boolean;
532
+ locationAreas?: LocationAreaColors;
533
+ dimmedOpacity?: number;
534
+ outlineColor?: string;
535
+ }
536
+
537
+ export interface Colors extends BaseColors {
538
+ flows?: FlowColors;
539
+ locationCircles?: LocationCircleColors;
540
+ }
541
+
542
+ export interface FlowAndCircleColors {
543
+ flows?: FlowColors;
544
+ locationCircles?: LocationCircleColors;
545
+ }
546
+
547
+ export interface DiffColors extends BaseColors {
548
+ positive?: FlowAndCircleColors;
549
+ negative?: FlowAndCircleColors;
550
+ }
551
+
552
+ // The xxxColorsRGBA objects are mirroring the input colors' objects,
553
+ // but converted to RGBA and with all the omitted ones set to defaults
554
+ // or derived.
555
+ export interface FlowColorsRGBA {
556
+ scheme: string[];
557
+ highlighted: RGBA;
558
+ }
559
+
560
+ export interface LocationCircleColorsRGBA {
561
+ inner: RGBA;
562
+ outgoing: RGBA;
563
+ incoming: RGBA;
564
+ highlighted: RGBA;
565
+ empty: RGBA;
566
+ emptyOutline: RGBA;
567
+ }
568
+
569
+ export interface LocationAreaColorsRGBA {
570
+ outline: RGBA;
571
+ normal: RGBA;
572
+ selected: RGBA;
573
+ highlighted: RGBA;
574
+ connected: RGBA;
575
+ }
576
+
577
+ export interface BaseColorsRGBA {
578
+ darkMode: boolean;
579
+ locationAreas: LocationAreaColorsRGBA;
580
+ dimmedOpacity: number;
581
+ outlineColor: RGBA;
582
+ }
583
+
584
+ export interface ColorsRGBA extends BaseColorsRGBA {
585
+ flows: FlowColorsRGBA;
586
+ locationCircles: LocationCircleColorsRGBA;
587
+ }
588
+
589
+ export interface FlowAndCircleColorsRGBA {
590
+ flows: FlowColorsRGBA;
591
+ locationCircles: LocationCircleColorsRGBA;
592
+ }
593
+
594
+ export interface DiffColorsRGBA extends BaseColorsRGBA {
595
+ positive: FlowAndCircleColorsRGBA;
596
+ negative: FlowAndCircleColorsRGBA;
597
+ }
598
+
599
+ function getFlowAndCircleColors(
600
+ inputColors: FlowAndCircleColors | undefined,
601
+ defaultFlowColorScheme: string[],
602
+ darkMode: boolean,
603
+ ): FlowAndCircleColorsRGBA {
604
+ const flowColorScheme =
605
+ (inputColors && inputColors.flows && inputColors.flows.scheme) ||
606
+ defaultFlowColorScheme;
607
+ const maxFlowColorHcl = hcl(flowColorScheme[flowColorScheme.length - 1]);
608
+ const flowColorHighlighted = colorAsRgbaOr(
609
+ inputColors && inputColors.flows && inputColors.flows.highlighted,
610
+ colorAsRgba(
611
+ maxFlowColorHcl[darkMode ? 'brighter' : 'darker'](0.7).toString(),
612
+ ),
613
+ );
614
+
615
+ const emptyColor = colorAsRgbaOr(
616
+ inputColors?.locationCircles?.empty,
617
+ darkMode ? '#000' : '#fff',
618
+ );
619
+ const innerColor = colorAsRgbaOr(
620
+ inputColors &&
621
+ inputColors.locationCircles &&
622
+ inputColors.locationCircles.inner,
623
+ maxFlowColorHcl.toString(),
624
+ );
625
+ return {
626
+ flows: {
627
+ scheme: flowColorScheme,
628
+ highlighted: flowColorHighlighted,
629
+ },
630
+ locationCircles: {
631
+ inner: innerColor,
632
+ outgoing: colorAsRgbaOr(
633
+ inputColors &&
634
+ inputColors.locationCircles &&
635
+ inputColors.locationCircles.outgoing,
636
+ darkMode ? '#000' : '#fff',
637
+ ),
638
+ incoming: colorAsRgbaOr(
639
+ inputColors &&
640
+ inputColors.locationCircles &&
641
+ inputColors.locationCircles.incoming,
642
+ maxFlowColorHcl[darkMode ? 'brighter' : 'darker'](1.25).toString(),
643
+ ),
644
+ highlighted: colorAsRgbaOr(
645
+ inputColors &&
646
+ inputColors.locationCircles &&
647
+ inputColors.locationCircles.highlighted,
648
+ flowColorHighlighted,
649
+ ),
650
+ empty: emptyColor,
651
+ emptyOutline: mixColorsRGBA(innerColor, emptyColor, 0.4),
652
+ },
653
+ };
654
+ }
655
+
656
+ function getBaseColorsRGBA(
657
+ colors: Colors | DiffColors | undefined,
658
+ ): BaseColorsRGBA {
659
+ const darkMode = colors && colors.darkMode ? true : false;
660
+ return {
661
+ darkMode,
662
+ locationAreas: getLocationAreaColorsRGBA(
663
+ colors && colors.locationAreas,
664
+ darkMode,
665
+ ),
666
+ outlineColor: colorAsRgba(
667
+ (colors && colors.outlineColor) || DEFAULT_OUTLINE_COLOR,
668
+ ),
669
+ dimmedOpacity:
670
+ colors && colors.dimmedOpacity != null
671
+ ? colors.dimmedOpacity
672
+ : DEFAULT_DIMMED_OPACITY,
673
+ };
674
+ }
675
+
676
+ export function getColorsRGBA(colors: Colors | undefined): ColorsRGBA {
677
+ const baseColorsRGBA = getBaseColorsRGBA(colors);
678
+ return {
679
+ ...baseColorsRGBA,
680
+ ...getFlowAndCircleColors(
681
+ colors,
682
+ DEFAULT_FLOW_COLOR_SCHEME,
683
+ baseColorsRGBA.darkMode,
684
+ ),
685
+ };
686
+ }
687
+
688
+ export function getDiffColorsRGBA(
689
+ colors: DiffColors | undefined,
690
+ ): DiffColorsRGBA {
691
+ const baseColorsRGBA = getBaseColorsRGBA(colors);
692
+ return {
693
+ ...baseColorsRGBA,
694
+ positive: getFlowAndCircleColors(
695
+ colors && colors.positive,
696
+ DEFAULT_FLOW_COLOR_SCHEME_POSITIVE,
697
+ baseColorsRGBA.darkMode,
698
+ ),
699
+ negative: getFlowAndCircleColors(
700
+ colors && colors.negative,
701
+ DEFAULT_FLOW_COLOR_SCHEME_NEGATIVE,
702
+ baseColorsRGBA.darkMode,
703
+ ),
704
+ };
705
+ }
706
+
707
+ export function rgbaAsString(color: RGBA): string {
708
+ return `rgba(${color.join(',')})`;
709
+ }
710
+
711
+ export function midpoint(a: number, b: number, zeroToOne: number): number {
712
+ return a + (b - a) * zeroToOne;
713
+ }
714
+
715
+ export function mixColorsRGBA(
716
+ color1: RGBA,
717
+ color2: RGBA,
718
+ zeroToOne: number,
719
+ ): RGBA {
720
+ return color1.map((v, i) => midpoint(v, color2[i], zeroToOne)) as RGBA;
721
+ }
722
+
723
+ export default getColors;