@sqlrooms/deck 0.29.0-rc.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.
- package/README.md +357 -0
- package/dist/ColorScaleLegend.d.ts +8 -0
- package/dist/ColorScaleLegend.d.ts.map +1 -0
- package/dist/ColorScaleLegend.js +11 -0
- package/dist/ColorScaleLegend.js.map +1 -0
- package/dist/DeckMap.d.ts +4 -0
- package/dist/DeckMap.d.ts.map +1 -0
- package/dist/DeckMap.js +157 -0
- package/dist/DeckMap.js.map +1 -0
- package/dist/datasets/normalizeDatasets.d.ts +5 -0
- package/dist/datasets/normalizeDatasets.d.ts.map +1 -0
- package/dist/datasets/normalizeDatasets.js +57 -0
- package/dist/datasets/normalizeDatasets.js.map +1 -0
- package/dist/datasets/usePreparedDeckDatasets.d.ts +3 -0
- package/dist/datasets/usePreparedDeckDatasets.d.ts.map +1 -0
- package/dist/datasets/usePreparedDeckDatasets.js +61 -0
- package/dist/datasets/usePreparedDeckDatasets.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/json/compileColorScale.d.ts +35 -0
- package/dist/json/compileColorScale.d.ts.map +1 -0
- package/dist/json/compileColorScale.js +527 -0
- package/dist/json/compileColorScale.js.map +1 -0
- package/dist/json/compileGeoArrowAccessor.d.ts +11 -0
- package/dist/json/compileGeoArrowAccessor.d.ts.map +1 -0
- package/dist/json/compileGeoArrowAccessor.js +74 -0
- package/dist/json/compileGeoArrowAccessor.js.map +1 -0
- package/dist/json/createDeckJsonConfiguration.d.ts +9 -0
- package/dist/json/createDeckJsonConfiguration.d.ts.map +1 -0
- package/dist/json/createDeckJsonConfiguration.js +112 -0
- package/dist/json/createDeckJsonConfiguration.js.map +1 -0
- package/dist/json/defaultClasses.d.ts +24 -0
- package/dist/json/defaultClasses.d.ts.map +1 -0
- package/dist/json/defaultClasses.js +21 -0
- package/dist/json/defaultClasses.js.map +1 -0
- package/dist/json/extractColorScaleLegends.d.ts +8 -0
- package/dist/json/extractColorScaleLegends.d.ts.map +1 -0
- package/dist/json/extractColorScaleLegends.js +48 -0
- package/dist/json/extractColorScaleLegends.js.map +1 -0
- package/dist/json/layerCompatibility.d.ts +15 -0
- package/dist/json/layerCompatibility.d.ts.map +1 -0
- package/dist/json/layerCompatibility.js +38 -0
- package/dist/json/layerCompatibility.js.map +1 -0
- package/dist/json/layerConfig.d.ts +10 -0
- package/dist/json/layerConfig.d.ts.map +1 -0
- package/dist/json/layerConfig.js +43 -0
- package/dist/json/layerConfig.js.map +1 -0
- package/dist/json/rewriteGeoArrowAccessors.d.ts +7 -0
- package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -0
- package/dist/json/rewriteGeoArrowAccessors.js +53 -0
- package/dist/json/rewriteGeoArrowAccessors.js.map +1 -0
- package/dist/prepare/detectGeometryColumn.d.ts +10 -0
- package/dist/prepare/detectGeometryColumn.d.ts.map +1 -0
- package/dist/prepare/detectGeometryColumn.js +84 -0
- package/dist/prepare/detectGeometryColumn.js.map +1 -0
- package/dist/prepare/geoarrow.d.ts +18 -0
- package/dist/prepare/geoarrow.d.ts.map +1 -0
- package/dist/prepare/geoarrow.js +114 -0
- package/dist/prepare/geoarrow.js.map +1 -0
- package/dist/prepare/geometryDecoder.d.ts +9 -0
- package/dist/prepare/geometryDecoder.d.ts.map +1 -0
- package/dist/prepare/geometryDecoder.js +2 -0
- package/dist/prepare/geometryDecoder.js.map +1 -0
- package/dist/prepare/prepareDeckDataset.d.ts +11 -0
- package/dist/prepare/prepareDeckDataset.d.ts.map +1 -0
- package/dist/prepare/prepareDeckDataset.js +66 -0
- package/dist/prepare/prepareDeckDataset.js.map +1 -0
- package/dist/prepare/toGeoJsonBinary.d.ts +9 -0
- package/dist/prepare/toGeoJsonBinary.d.ts.map +1 -0
- package/dist/prepare/toGeoJsonBinary.js +25 -0
- package/dist/prepare/toGeoJsonBinary.js.map +1 -0
- package/dist/prepare/types.d.ts +25 -0
- package/dist/prepare/types.d.ts.map +1 -0
- package/dist/prepare/types.js +2 -0
- package/dist/prepare/types.js.map +1 -0
- package/dist/prepare/wkbDecoder.d.ts +3 -0
- package/dist/prepare/wkbDecoder.d.ts.map +1 -0
- package/dist/prepare/wkbDecoder.js +106 -0
- package/dist/prepare/wkbDecoder.js.map +1 -0
- package/dist/types.d.ts +115 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePreparedDeckDatasets.d.ts","sourceRoot":"","sources":["../../src/datasets/usePreparedDeckDatasets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,gBAAgB,EAAE,wBAAwB,EAAC,MAAM,UAAU,CAAC;AAIzE,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACzC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAqE1C"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useStoreWithDuckDb } from '@sqlrooms/duckdb';
|
|
3
|
+
import { resolveArrowTable } from './normalizeDatasets';
|
|
4
|
+
import { prepareDeckDataset } from '../prepare/prepareDeckDataset';
|
|
5
|
+
export function usePreparedDeckDatasets(datasets) {
|
|
6
|
+
const executeSql = useStoreWithDuckDb((state) => state.db.executeSql);
|
|
7
|
+
const [states, setStates] = useState({});
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
let cancelled = false;
|
|
10
|
+
setStates(Object.fromEntries(Object.entries(datasets).map(([datasetId, input]) => [
|
|
11
|
+
datasetId,
|
|
12
|
+
input.sqlQuery ? { status: 'loading' } : { status: 'loading' },
|
|
13
|
+
])));
|
|
14
|
+
for (const [datasetId, input] of Object.entries(datasets)) {
|
|
15
|
+
const run = async () => {
|
|
16
|
+
try {
|
|
17
|
+
let table = resolveArrowTable(input);
|
|
18
|
+
if (!table && input.sqlQuery) {
|
|
19
|
+
const queryHandle = await executeSql(input.sqlQuery);
|
|
20
|
+
if (!queryHandle) {
|
|
21
|
+
throw new Error(`Query for dataset "${datasetId}" was cancelled.`);
|
|
22
|
+
}
|
|
23
|
+
table = await queryHandle;
|
|
24
|
+
}
|
|
25
|
+
if (!table) {
|
|
26
|
+
throw new Error(`Dataset "${datasetId}" could not resolve an Arrow table.`);
|
|
27
|
+
}
|
|
28
|
+
const prepared = prepareDeckDataset({
|
|
29
|
+
datasetId,
|
|
30
|
+
table,
|
|
31
|
+
geometryColumn: input.geometryColumn,
|
|
32
|
+
geometryEncodingHint: input.geometryEncodingHint,
|
|
33
|
+
});
|
|
34
|
+
if (!cancelled) {
|
|
35
|
+
setStates((current) => ({
|
|
36
|
+
...current,
|
|
37
|
+
[datasetId]: { status: 'ready', prepared },
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (!cancelled) {
|
|
43
|
+
setStates((current) => ({
|
|
44
|
+
...current,
|
|
45
|
+
[datasetId]: {
|
|
46
|
+
status: 'error',
|
|
47
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
void run();
|
|
54
|
+
}
|
|
55
|
+
return () => {
|
|
56
|
+
cancelled = true;
|
|
57
|
+
};
|
|
58
|
+
}, [datasets, executeSql]);
|
|
59
|
+
return states;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=usePreparedDeckDatasets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePreparedDeckDatasets.js","sourceRoot":"","sources":["../../src/datasets/usePreparedDeckDatasets.ts"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useState} from 'react';\nimport {useStoreWithDuckDb} from '@sqlrooms/duckdb';\nimport type {DeckDatasetInput, PreparedDeckDatasetState} from '../types';\nimport {resolveArrowTable} from './normalizeDatasets';\nimport {prepareDeckDataset} from '../prepare/prepareDeckDataset';\n\nexport function usePreparedDeckDatasets(\n datasets: Record<string, DeckDatasetInput>,\n): Record<string, PreparedDeckDatasetState> {\n const executeSql = useStoreWithDuckDb((state) => state.db.executeSql);\n const [states, setStates] = useState<Record<string, PreparedDeckDatasetState>>(\n {},\n );\n\n useEffect(() => {\n let cancelled = false;\n\n setStates(\n Object.fromEntries(\n Object.entries(datasets).map(([datasetId, input]) => [\n datasetId,\n input.sqlQuery ? {status: 'loading'} : {status: 'loading'},\n ]),\n ),\n );\n\n for (const [datasetId, input] of Object.entries(datasets)) {\n const run = async () => {\n try {\n let table = resolveArrowTable(input);\n if (!table && input.sqlQuery) {\n const queryHandle = await executeSql(input.sqlQuery);\n if (!queryHandle) {\n throw new Error(`Query for dataset \"${datasetId}\" was cancelled.`);\n }\n table = await queryHandle;\n }\n\n if (!table) {\n throw new Error(`Dataset \"${datasetId}\" could not resolve an Arrow table.`);\n }\n\n const prepared = prepareDeckDataset({\n datasetId,\n table,\n geometryColumn: input.geometryColumn,\n geometryEncodingHint: input.geometryEncodingHint,\n });\n\n if (!cancelled) {\n setStates((current) => ({\n ...current,\n [datasetId]: {status: 'ready', prepared},\n }));\n }\n } catch (error) {\n if (!cancelled) {\n setStates((current) => ({\n ...current,\n [datasetId]: {\n status: 'error',\n error: error instanceof Error ? error : new Error(String(error)),\n },\n }));\n }\n }\n };\n\n void run();\n }\n\n return () => {\n cancelled = true;\n };\n }, [datasets, executeSql]);\n\n return states;\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@include ../README.md}
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
export { DeckMap } from './DeckMap';
|
|
6
|
+
export { ColorScaleLegend } from './ColorScaleLegend';
|
|
7
|
+
export { createDeckJsonConfiguration } from './json/createDeckJsonConfiguration';
|
|
8
|
+
export { prepareDeckDataset } from './prepare/prepareDeckDataset';
|
|
9
|
+
export type { DeckDatasetInput, DeckMapProps, DeckQueryResultLike, LayerColorLegendConfig, LayerColorScale, LayerColorScaleProp, LayerExtensionProps, PreparedDeckDatasetState, } from './types';
|
|
10
|
+
export type { GeometryEncodingHint, PreparedDeckDataset, PreparedGeoArrowLayerData, ResolvedGeometryColumn, ResolvedGeometryEncoding, } from './prepare/types';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,2BAA2B,EAAC,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC;AAEhE,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@include ../README.md}
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
export { DeckMap } from './DeckMap';
|
|
6
|
+
export { ColorScaleLegend } from './ColorScaleLegend';
|
|
7
|
+
export { createDeckJsonConfiguration } from './json/createDeckJsonConfiguration';
|
|
8
|
+
export { prepareDeckDataset } from './prepare/prepareDeckDataset';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,2BAA2B,EAAC,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {DeckMap} from './DeckMap';\nexport {ColorScaleLegend} from './ColorScaleLegend';\nexport {createDeckJsonConfiguration} from './json/createDeckJsonConfiguration';\nexport {prepareDeckDataset} from './prepare/prepareDeckDataset';\n\nexport type {\n DeckDatasetInput,\n DeckMapProps,\n DeckQueryResultLike,\n LayerColorLegendConfig,\n LayerColorScale,\n LayerColorScaleProp,\n LayerExtensionProps,\n PreparedDeckDatasetState,\n} from './types';\nexport type {\n GeometryEncodingHint,\n PreparedDeckDataset,\n PreparedGeoArrowLayerData,\n ResolvedGeometryColumn,\n ResolvedGeometryEncoding,\n} from './prepare/types';\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type * as arrow from 'apache-arrow';
|
|
2
|
+
import type { LayerColorScale } from '../types';
|
|
3
|
+
export type ResolvedColorLegend = {
|
|
4
|
+
type: 'continuous';
|
|
5
|
+
title: string;
|
|
6
|
+
gradient: string;
|
|
7
|
+
ticks: Array<{
|
|
8
|
+
label: string;
|
|
9
|
+
offset: number;
|
|
10
|
+
}>;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'stepped';
|
|
13
|
+
title: string;
|
|
14
|
+
items: Array<{
|
|
15
|
+
label: string;
|
|
16
|
+
color: [number, number, number, number];
|
|
17
|
+
}>;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'categorical';
|
|
20
|
+
title: string;
|
|
21
|
+
items: Array<{
|
|
22
|
+
label: string;
|
|
23
|
+
color: [number, number, number, number];
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
export declare function compileColorScale(options: {
|
|
27
|
+
table: arrow.Table;
|
|
28
|
+
colorScale: LayerColorScale;
|
|
29
|
+
}): (value: unknown) => [number, number, number, number];
|
|
30
|
+
export declare function buildColorScaleLegend(options: {
|
|
31
|
+
table: arrow.Table;
|
|
32
|
+
colorScale: LayerColorScale;
|
|
33
|
+
title?: string;
|
|
34
|
+
}): ResolvedColorLegend | null;
|
|
35
|
+
//# sourceMappingURL=compileColorScale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compileColorScale.d.ts","sourceRoot":"","sources":["../../src/json/compileColorScale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAW3C,OAAO,KAAK,EAKV,eAAe,EAChB,MAAM,UAAU,CAAC;AA+GlB,MAAM,MAAM,mBAAmB,GAC3B;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;CAC/C,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;KAAC,CAAC,CAAC;CACxE,GACD;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;KAAC,CAAC,CAAC;CACxE,CAAC;AA0SN,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IACnB,UAAU,EAAE,eAAe,CAAC;CAC7B,WAdgB,OAAO,sCAqKvB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IACnB,UAAU,EAAE,eAAe,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,GAAG,IAAI,CAgJ7B"}
|
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
import { rgb } from 'd3-color';
|
|
2
|
+
import { scaleDiverging, scaleOrdinal, scaleQuantile, scaleQuantize, scaleSequential, scaleThreshold, } from 'd3-scale';
|
|
3
|
+
import * as chromatic from 'd3-scale-chromatic';
|
|
4
|
+
const DEFAULT_NULL_COLOR = [0, 0, 0, 0];
|
|
5
|
+
const DEFAULT_UNKNOWN_COLOR = [
|
|
6
|
+
180, 180, 180, 180,
|
|
7
|
+
];
|
|
8
|
+
const DEFAULT_BIN_COUNT = 5;
|
|
9
|
+
const CONTINUOUS_SEQUENTIAL_SCHEMES = {
|
|
10
|
+
Blues: chromatic.interpolateBlues,
|
|
11
|
+
BuGn: chromatic.interpolateBuGn,
|
|
12
|
+
BuPu: chromatic.interpolateBuPu,
|
|
13
|
+
Cividis: chromatic.interpolateCividis,
|
|
14
|
+
Cool: chromatic.interpolateCool,
|
|
15
|
+
CubehelixDefault: chromatic.interpolateCubehelixDefault,
|
|
16
|
+
GnBu: chromatic.interpolateGnBu,
|
|
17
|
+
Greens: chromatic.interpolateGreens,
|
|
18
|
+
Greys: chromatic.interpolateGreys,
|
|
19
|
+
Inferno: chromatic.interpolateInferno,
|
|
20
|
+
Magma: chromatic.interpolateMagma,
|
|
21
|
+
OrRd: chromatic.interpolateOrRd,
|
|
22
|
+
Oranges: chromatic.interpolateOranges,
|
|
23
|
+
Plasma: chromatic.interpolatePlasma,
|
|
24
|
+
PuBu: chromatic.interpolatePuBu,
|
|
25
|
+
PuBuGn: chromatic.interpolatePuBuGn,
|
|
26
|
+
PuRd: chromatic.interpolatePuRd,
|
|
27
|
+
Purples: chromatic.interpolatePurples,
|
|
28
|
+
Rainbow: chromatic.interpolateRainbow,
|
|
29
|
+
RdPu: chromatic.interpolateRdPu,
|
|
30
|
+
Reds: chromatic.interpolateReds,
|
|
31
|
+
Sinebow: chromatic.interpolateSinebow,
|
|
32
|
+
Turbo: chromatic.interpolateTurbo,
|
|
33
|
+
Viridis: chromatic.interpolateViridis,
|
|
34
|
+
Warm: chromatic.interpolateWarm,
|
|
35
|
+
YlGn: chromatic.interpolateYlGn,
|
|
36
|
+
YlGnBu: chromatic.interpolateYlGnBu,
|
|
37
|
+
YlOrBr: chromatic.interpolateYlOrBr,
|
|
38
|
+
YlOrRd: chromatic.interpolateYlOrRd,
|
|
39
|
+
};
|
|
40
|
+
const CONTINUOUS_DIVERGING_SCHEMES = {
|
|
41
|
+
BrBG: chromatic.interpolateBrBG,
|
|
42
|
+
PRGn: chromatic.interpolatePRGn,
|
|
43
|
+
PiYG: chromatic.interpolatePiYG,
|
|
44
|
+
PuOr: chromatic.interpolatePuOr,
|
|
45
|
+
RdBu: chromatic.interpolateRdBu,
|
|
46
|
+
RdGy: chromatic.interpolateRdGy,
|
|
47
|
+
RdYlBu: chromatic.interpolateRdYlBu,
|
|
48
|
+
RdYlGn: chromatic.interpolateRdYlGn,
|
|
49
|
+
Spectral: chromatic.interpolateSpectral,
|
|
50
|
+
};
|
|
51
|
+
const DISCRETE_NUMERIC_SCHEMES = {
|
|
52
|
+
Blues: chromatic.schemeBlues,
|
|
53
|
+
BuGn: chromatic.schemeBuGn,
|
|
54
|
+
BuPu: chromatic.schemeBuPu,
|
|
55
|
+
GnBu: chromatic.schemeGnBu,
|
|
56
|
+
Greens: chromatic.schemeGreens,
|
|
57
|
+
Greys: chromatic.schemeGreys,
|
|
58
|
+
OrRd: chromatic.schemeOrRd,
|
|
59
|
+
Oranges: chromatic.schemeOranges,
|
|
60
|
+
PuBu: chromatic.schemePuBu,
|
|
61
|
+
PuBuGn: chromatic.schemePuBuGn,
|
|
62
|
+
PuRd: chromatic.schemePuRd,
|
|
63
|
+
Purples: chromatic.schemePurples,
|
|
64
|
+
RdPu: chromatic.schemeRdPu,
|
|
65
|
+
Reds: chromatic.schemeReds,
|
|
66
|
+
YlGn: chromatic.schemeYlGn,
|
|
67
|
+
YlGnBu: chromatic.schemeYlGnBu,
|
|
68
|
+
YlOrBr: chromatic.schemeYlOrBr,
|
|
69
|
+
YlOrRd: chromatic.schemeYlOrRd,
|
|
70
|
+
BrBG: chromatic.schemeBrBG,
|
|
71
|
+
PRGn: chromatic.schemePRGn,
|
|
72
|
+
PiYG: chromatic.schemePiYG,
|
|
73
|
+
PuOr: chromatic.schemePuOr,
|
|
74
|
+
RdBu: chromatic.schemeRdBu,
|
|
75
|
+
RdGy: chromatic.schemeRdGy,
|
|
76
|
+
RdYlBu: chromatic.schemeRdYlBu,
|
|
77
|
+
RdYlGn: chromatic.schemeRdYlGn,
|
|
78
|
+
Spectral: chromatic.schemeSpectral,
|
|
79
|
+
};
|
|
80
|
+
const CATEGORICAL_SCHEMES = {
|
|
81
|
+
Accent: chromatic.schemeAccent,
|
|
82
|
+
Category10: chromatic.schemeCategory10,
|
|
83
|
+
Dark2: chromatic.schemeDark2,
|
|
84
|
+
Observable10: chromatic.schemeObservable10,
|
|
85
|
+
Paired: chromatic.schemePaired,
|
|
86
|
+
Pastel1: chromatic.schemePastel1,
|
|
87
|
+
Pastel2: chromatic.schemePastel2,
|
|
88
|
+
Set1: chromatic.schemeSet1,
|
|
89
|
+
Set2: chromatic.schemeSet2,
|
|
90
|
+
Set3: chromatic.schemeSet3,
|
|
91
|
+
Tableau10: chromatic.schemeTableau10,
|
|
92
|
+
};
|
|
93
|
+
function createNullColorAccessor(nullColor) {
|
|
94
|
+
return () => nullColor;
|
|
95
|
+
}
|
|
96
|
+
function normalizeColor(color, fallback) {
|
|
97
|
+
if (!color) {
|
|
98
|
+
return fallback;
|
|
99
|
+
}
|
|
100
|
+
return [color[0], color[1], color[2], color[3] ?? 255];
|
|
101
|
+
}
|
|
102
|
+
function parseColorString(value, alpha = 255) {
|
|
103
|
+
const parsed = rgb(value);
|
|
104
|
+
return [parsed.r, parsed.g, parsed.b, alpha];
|
|
105
|
+
}
|
|
106
|
+
function formatLegendNumber(value) {
|
|
107
|
+
return new Intl.NumberFormat('en-US', {
|
|
108
|
+
maximumFractionDigits: Math.abs(value) >= 100 ? 0 : 2,
|
|
109
|
+
}).format(value);
|
|
110
|
+
}
|
|
111
|
+
function resolveFieldName(schemaOwner, requestedField) {
|
|
112
|
+
const exactMatch = schemaOwner.schema.fields.find((field) => field.name === requestedField)?.name;
|
|
113
|
+
if (exactMatch) {
|
|
114
|
+
return exactMatch;
|
|
115
|
+
}
|
|
116
|
+
const caseInsensitiveMatches = schemaOwner.schema.fields
|
|
117
|
+
.map((field) => field.name)
|
|
118
|
+
.filter((fieldName) => fieldName.toLowerCase() === requestedField.toLowerCase());
|
|
119
|
+
if (caseInsensitiveMatches.length === 1) {
|
|
120
|
+
return caseInsensitiveMatches[0];
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
function getColumn(table, field) {
|
|
125
|
+
const resolvedFieldName = resolveFieldName(table, field);
|
|
126
|
+
if (!resolvedFieldName) {
|
|
127
|
+
throw new Error(`Unknown colorScale field "${field}".`);
|
|
128
|
+
}
|
|
129
|
+
const vector = table.getChild(resolvedFieldName);
|
|
130
|
+
if (!vector) {
|
|
131
|
+
throw new Error(`Unable to read colorScale field "${resolvedFieldName}".`);
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
fieldName: resolvedFieldName,
|
|
135
|
+
vector,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function getRowValue(row, fieldName) {
|
|
139
|
+
if (!row || typeof row !== 'object') {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
const object = row;
|
|
143
|
+
const sources = [
|
|
144
|
+
object,
|
|
145
|
+
object.properties,
|
|
146
|
+
].filter((value) => Boolean(value && typeof value === 'object'));
|
|
147
|
+
for (const source of sources) {
|
|
148
|
+
if (fieldName in source) {
|
|
149
|
+
return source[fieldName];
|
|
150
|
+
}
|
|
151
|
+
const caseInsensitiveMatches = Object.keys(source).filter((key) => key.toLowerCase() === fieldName.toLowerCase());
|
|
152
|
+
if (caseInsensitiveMatches.length === 1) {
|
|
153
|
+
return source[caseInsensitiveMatches[0]];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
function toFiniteNumber(value) {
|
|
159
|
+
if (typeof value === 'number') {
|
|
160
|
+
return Number.isFinite(value) ? value : undefined;
|
|
161
|
+
}
|
|
162
|
+
if (typeof value === 'bigint') {
|
|
163
|
+
return Number(value);
|
|
164
|
+
}
|
|
165
|
+
if (typeof value === 'string' && value.trim() !== '') {
|
|
166
|
+
const parsed = Number(value);
|
|
167
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
168
|
+
}
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
function getNumericValues(vector) {
|
|
172
|
+
const values = [];
|
|
173
|
+
for (let index = 0; index < vector.length; index += 1) {
|
|
174
|
+
const numericValue = toFiniteNumber(vector.get(index));
|
|
175
|
+
if (numericValue !== undefined) {
|
|
176
|
+
values.push(numericValue);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return values;
|
|
180
|
+
}
|
|
181
|
+
function getSequentialDomain(values) {
|
|
182
|
+
const min = Math.min(...values);
|
|
183
|
+
const max = Math.max(...values);
|
|
184
|
+
if (min === max) {
|
|
185
|
+
return [min - 1, max + 1];
|
|
186
|
+
}
|
|
187
|
+
return [min, max];
|
|
188
|
+
}
|
|
189
|
+
function getDivergingDomain(values) {
|
|
190
|
+
const min = Math.min(...values);
|
|
191
|
+
const max = Math.max(...values);
|
|
192
|
+
if (min === max) {
|
|
193
|
+
return [min - 1, min, max + 1];
|
|
194
|
+
}
|
|
195
|
+
if (min < 0 && max > 0) {
|
|
196
|
+
return [min, 0, max];
|
|
197
|
+
}
|
|
198
|
+
return [min, (min + max) / 2, max];
|
|
199
|
+
}
|
|
200
|
+
function unique(values) {
|
|
201
|
+
return [...new Set(values)];
|
|
202
|
+
}
|
|
203
|
+
function clampBinCount(bins) {
|
|
204
|
+
return Math.max(2, Math.round(bins));
|
|
205
|
+
}
|
|
206
|
+
function sampleInterpolator(interpolator, bins) {
|
|
207
|
+
if (bins === 1) {
|
|
208
|
+
return [interpolator(0.5)];
|
|
209
|
+
}
|
|
210
|
+
return Array.from({ length: bins }, (_, index) => interpolator(index / (bins - 1)));
|
|
211
|
+
}
|
|
212
|
+
function getNumericInterpolator(scheme) {
|
|
213
|
+
const sequential = CONTINUOUS_SEQUENTIAL_SCHEMES[scheme];
|
|
214
|
+
if (sequential) {
|
|
215
|
+
return sequential;
|
|
216
|
+
}
|
|
217
|
+
return CONTINUOUS_DIVERGING_SCHEMES[scheme];
|
|
218
|
+
}
|
|
219
|
+
function getDiscreteNumericColors(options) {
|
|
220
|
+
const { scheme, reverse } = options;
|
|
221
|
+
const bins = clampBinCount(options.bins);
|
|
222
|
+
const discreteScheme = DISCRETE_NUMERIC_SCHEMES[scheme];
|
|
223
|
+
const directColors = discreteScheme[bins];
|
|
224
|
+
const colors = Array.isArray(directColors)
|
|
225
|
+
? [...directColors]
|
|
226
|
+
: sampleInterpolator(getNumericInterpolator(scheme) ??
|
|
227
|
+
(() => {
|
|
228
|
+
throw new Error(`Unsupported numeric colorScale scheme "${scheme}".`);
|
|
229
|
+
})(), bins);
|
|
230
|
+
return reverse ? colors.reverse() : colors;
|
|
231
|
+
}
|
|
232
|
+
function formatExtentLabel(extent) {
|
|
233
|
+
const start = toFiniteNumber(extent[0]);
|
|
234
|
+
const end = toFiniteNumber(extent[1]);
|
|
235
|
+
if (start === undefined && end === undefined) {
|
|
236
|
+
return 'unknown';
|
|
237
|
+
}
|
|
238
|
+
if (start === undefined && end !== undefined) {
|
|
239
|
+
return `< ${formatLegendNumber(end)}`;
|
|
240
|
+
}
|
|
241
|
+
if (start !== undefined && end === undefined) {
|
|
242
|
+
return `>= ${formatLegendNumber(start)}`;
|
|
243
|
+
}
|
|
244
|
+
return `${formatLegendNumber(start)} - ${formatLegendNumber(end)}`;
|
|
245
|
+
}
|
|
246
|
+
function buildSteppedLegendItems(scale, range) {
|
|
247
|
+
return range.map((color) => ({
|
|
248
|
+
label: formatExtentLabel(scale.invertExtent(color)),
|
|
249
|
+
color: parseColorString(color),
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
function buildGradient(interpolator) {
|
|
253
|
+
return `linear-gradient(to right, ${[0, 0.25, 0.5, 0.75, 1]
|
|
254
|
+
.map((offset) => `${interpolator(offset)} ${offset * 100}%`)
|
|
255
|
+
.join(', ')})`;
|
|
256
|
+
}
|
|
257
|
+
function getGeoArrowOrRowValue(options) {
|
|
258
|
+
const { value, fieldName, vector } = options;
|
|
259
|
+
if (value &&
|
|
260
|
+
typeof value === 'object' &&
|
|
261
|
+
'index' in value &&
|
|
262
|
+
typeof value.index === 'number') {
|
|
263
|
+
const objectInfo = value;
|
|
264
|
+
const batch = objectInfo.data?.data;
|
|
265
|
+
const batchFieldName = batch
|
|
266
|
+
? resolveFieldName(batch, fieldName)
|
|
267
|
+
: undefined;
|
|
268
|
+
if (batch && batchFieldName) {
|
|
269
|
+
return batch.getChild(batchFieldName)?.get(objectInfo.index);
|
|
270
|
+
}
|
|
271
|
+
return vector.get(objectInfo.index);
|
|
272
|
+
}
|
|
273
|
+
return getRowValue(value, fieldName);
|
|
274
|
+
}
|
|
275
|
+
function createContinuousAccessor(options) {
|
|
276
|
+
const { fieldName, vector, nullColor, colorForValue } = options;
|
|
277
|
+
return (value) => {
|
|
278
|
+
const rawValue = getGeoArrowOrRowValue({ value, fieldName, vector });
|
|
279
|
+
const numericValue = toFiniteNumber(rawValue);
|
|
280
|
+
if (numericValue === undefined) {
|
|
281
|
+
return nullColor;
|
|
282
|
+
}
|
|
283
|
+
return parseColorString(colorForValue(numericValue));
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
export function compileColorScale(options) {
|
|
287
|
+
const { table, colorScale } = options;
|
|
288
|
+
const { fieldName, vector } = getColumn(table, colorScale.field);
|
|
289
|
+
const nullColor = normalizeColor(colorScale.nullColor, DEFAULT_NULL_COLOR);
|
|
290
|
+
if (colorScale.type === 'categorical') {
|
|
291
|
+
const baseRange = CATEGORICAL_SCHEMES[colorScale.scheme];
|
|
292
|
+
if (!baseRange) {
|
|
293
|
+
throw new Error(`Unsupported categorical colorScale scheme "${colorScale.scheme}".`);
|
|
294
|
+
}
|
|
295
|
+
const range = colorScale.reverse
|
|
296
|
+
? [...baseRange].reverse()
|
|
297
|
+
: [...baseRange];
|
|
298
|
+
const scale = scaleOrdinal(range);
|
|
299
|
+
const unknownColor = normalizeColor(colorScale.unknownColor, DEFAULT_UNKNOWN_COLOR);
|
|
300
|
+
return (value) => {
|
|
301
|
+
const rawValue = getGeoArrowOrRowValue({ value, fieldName, vector });
|
|
302
|
+
if (rawValue == null) {
|
|
303
|
+
return nullColor;
|
|
304
|
+
}
|
|
305
|
+
if (typeof rawValue !== 'string' &&
|
|
306
|
+
typeof rawValue !== 'number' &&
|
|
307
|
+
typeof rawValue !== 'boolean') {
|
|
308
|
+
return unknownColor;
|
|
309
|
+
}
|
|
310
|
+
return parseColorString(scale(String(rawValue)));
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
const numericValues = getNumericValues(vector);
|
|
314
|
+
if (numericValues.length === 0) {
|
|
315
|
+
return createNullColorAccessor(nullColor);
|
|
316
|
+
}
|
|
317
|
+
if (colorScale.type === 'sequential') {
|
|
318
|
+
const interpolator = CONTINUOUS_SEQUENTIAL_SCHEMES[colorScale.scheme];
|
|
319
|
+
const domain = colorScale.domain === 'auto'
|
|
320
|
+
? getSequentialDomain(numericValues)
|
|
321
|
+
: colorScale.domain;
|
|
322
|
+
const colorInterpolator = colorScale.reverse
|
|
323
|
+
? (t) => interpolator(1 - t)
|
|
324
|
+
: interpolator;
|
|
325
|
+
const scale = scaleSequential(colorInterpolator).domain(domain);
|
|
326
|
+
if (colorScale.clamp) {
|
|
327
|
+
scale.clamp(true);
|
|
328
|
+
}
|
|
329
|
+
return createContinuousAccessor({
|
|
330
|
+
fieldName,
|
|
331
|
+
vector,
|
|
332
|
+
nullColor,
|
|
333
|
+
colorForValue: (value) => scale(value),
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
if (colorScale.type === 'diverging') {
|
|
337
|
+
const interpolator = CONTINUOUS_DIVERGING_SCHEMES[colorScale.scheme];
|
|
338
|
+
const domain = colorScale.domain === 'auto'
|
|
339
|
+
? getDivergingDomain(numericValues)
|
|
340
|
+
: colorScale.domain;
|
|
341
|
+
const colorInterpolator = colorScale.reverse
|
|
342
|
+
? (t) => interpolator(1 - t)
|
|
343
|
+
: interpolator;
|
|
344
|
+
const scale = scaleDiverging(colorInterpolator).domain(domain);
|
|
345
|
+
if (colorScale.clamp) {
|
|
346
|
+
scale.clamp(true);
|
|
347
|
+
}
|
|
348
|
+
return createContinuousAccessor({
|
|
349
|
+
fieldName,
|
|
350
|
+
vector,
|
|
351
|
+
nullColor,
|
|
352
|
+
colorForValue: (value) => scale(value),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
if (colorScale.type === 'quantize') {
|
|
356
|
+
const range = getDiscreteNumericColors({
|
|
357
|
+
scheme: colorScale.scheme,
|
|
358
|
+
bins: colorScale.bins ?? DEFAULT_BIN_COUNT,
|
|
359
|
+
reverse: colorScale.reverse,
|
|
360
|
+
});
|
|
361
|
+
const domain = colorScale.domain === 'auto'
|
|
362
|
+
? getSequentialDomain(numericValues)
|
|
363
|
+
: colorScale.domain;
|
|
364
|
+
const scale = scaleQuantize()
|
|
365
|
+
.domain(domain)
|
|
366
|
+
.range(range);
|
|
367
|
+
return createContinuousAccessor({
|
|
368
|
+
fieldName,
|
|
369
|
+
vector,
|
|
370
|
+
nullColor,
|
|
371
|
+
colorForValue: scale,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
if (colorScale.type === 'quantile') {
|
|
375
|
+
const range = getDiscreteNumericColors({
|
|
376
|
+
scheme: colorScale.scheme,
|
|
377
|
+
bins: colorScale.bins ?? DEFAULT_BIN_COUNT,
|
|
378
|
+
reverse: colorScale.reverse,
|
|
379
|
+
});
|
|
380
|
+
const scale = scaleQuantile()
|
|
381
|
+
.domain(numericValues)
|
|
382
|
+
.range(range);
|
|
383
|
+
return createContinuousAccessor({
|
|
384
|
+
fieldName,
|
|
385
|
+
vector,
|
|
386
|
+
nullColor,
|
|
387
|
+
colorForValue: scale,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
const thresholds = [...colorScale.thresholds].sort((left, right) => left - right);
|
|
391
|
+
if (!thresholds.length) {
|
|
392
|
+
throw new Error('Threshold colorScale requires at least one threshold.');
|
|
393
|
+
}
|
|
394
|
+
const range = getDiscreteNumericColors({
|
|
395
|
+
scheme: colorScale.scheme,
|
|
396
|
+
bins: thresholds.length + 1,
|
|
397
|
+
reverse: colorScale.reverse,
|
|
398
|
+
});
|
|
399
|
+
const scale = scaleThreshold()
|
|
400
|
+
.domain(thresholds)
|
|
401
|
+
.range(range);
|
|
402
|
+
return createContinuousAccessor({
|
|
403
|
+
fieldName,
|
|
404
|
+
vector,
|
|
405
|
+
nullColor,
|
|
406
|
+
colorForValue: (value) => scale(value),
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
export function buildColorScaleLegend(options) {
|
|
410
|
+
const { table, colorScale, title } = options;
|
|
411
|
+
const { fieldName, vector } = getColumn(table, colorScale.field);
|
|
412
|
+
const resolvedTitle = title && title.trim() ? title.trim() : fieldName;
|
|
413
|
+
if (colorScale.type === 'categorical') {
|
|
414
|
+
const baseRange = CATEGORICAL_SCHEMES[colorScale.scheme];
|
|
415
|
+
const range = colorScale.reverse
|
|
416
|
+
? [...baseRange].reverse()
|
|
417
|
+
: [...baseRange];
|
|
418
|
+
const values = unique(Array.from({ length: vector.length }, (_, index) => vector.get(index)).filter((value) => value != null &&
|
|
419
|
+
(typeof value === 'string' ||
|
|
420
|
+
typeof value === 'number' ||
|
|
421
|
+
typeof value === 'boolean')));
|
|
422
|
+
if (values.length === 0) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
type: 'categorical',
|
|
427
|
+
title: resolvedTitle,
|
|
428
|
+
items: values.map((value, index) => ({
|
|
429
|
+
label: String(value),
|
|
430
|
+
color: parseColorString(range[index % range.length]),
|
|
431
|
+
})),
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
const numericValues = getNumericValues(vector);
|
|
435
|
+
if (numericValues.length === 0) {
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
if (colorScale.type === 'sequential') {
|
|
439
|
+
const interpolator = CONTINUOUS_SEQUENTIAL_SCHEMES[colorScale.scheme];
|
|
440
|
+
const domain = colorScale.domain === 'auto'
|
|
441
|
+
? getSequentialDomain(numericValues)
|
|
442
|
+
: colorScale.domain;
|
|
443
|
+
const colorInterpolator = colorScale.reverse
|
|
444
|
+
? (t) => interpolator(1 - t)
|
|
445
|
+
: interpolator;
|
|
446
|
+
return {
|
|
447
|
+
type: 'continuous',
|
|
448
|
+
title: resolvedTitle,
|
|
449
|
+
gradient: buildGradient(colorInterpolator),
|
|
450
|
+
ticks: [
|
|
451
|
+
{ label: formatLegendNumber(domain[0]), offset: 0 },
|
|
452
|
+
{ label: formatLegendNumber((domain[0] + domain[1]) / 2), offset: 50 },
|
|
453
|
+
{ label: formatLegendNumber(domain[1]), offset: 100 },
|
|
454
|
+
],
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
if (colorScale.type === 'diverging') {
|
|
458
|
+
const interpolator = CONTINUOUS_DIVERGING_SCHEMES[colorScale.scheme];
|
|
459
|
+
const domain = colorScale.domain === 'auto'
|
|
460
|
+
? getDivergingDomain(numericValues)
|
|
461
|
+
: colorScale.domain;
|
|
462
|
+
const colorInterpolator = colorScale.reverse
|
|
463
|
+
? (t) => interpolator(1 - t)
|
|
464
|
+
: interpolator;
|
|
465
|
+
return {
|
|
466
|
+
type: 'continuous',
|
|
467
|
+
title: resolvedTitle,
|
|
468
|
+
gradient: buildGradient(colorInterpolator),
|
|
469
|
+
ticks: [
|
|
470
|
+
{ label: formatLegendNumber(domain[0]), offset: 0 },
|
|
471
|
+
{ label: formatLegendNumber(domain[1]), offset: 50 },
|
|
472
|
+
{ label: formatLegendNumber(domain[2]), offset: 100 },
|
|
473
|
+
],
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
if (colorScale.type === 'quantize') {
|
|
477
|
+
const range = getDiscreteNumericColors({
|
|
478
|
+
scheme: colorScale.scheme,
|
|
479
|
+
bins: colorScale.bins ?? DEFAULT_BIN_COUNT,
|
|
480
|
+
reverse: colorScale.reverse,
|
|
481
|
+
});
|
|
482
|
+
const domain = colorScale.domain === 'auto'
|
|
483
|
+
? getSequentialDomain(numericValues)
|
|
484
|
+
: colorScale.domain;
|
|
485
|
+
const scale = scaleQuantize()
|
|
486
|
+
.domain(domain)
|
|
487
|
+
.range(range);
|
|
488
|
+
return {
|
|
489
|
+
type: 'stepped',
|
|
490
|
+
title: resolvedTitle,
|
|
491
|
+
items: buildSteppedLegendItems(scale, range),
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
if (colorScale.type === 'quantile') {
|
|
495
|
+
const range = getDiscreteNumericColors({
|
|
496
|
+
scheme: colorScale.scheme,
|
|
497
|
+
bins: colorScale.bins ?? DEFAULT_BIN_COUNT,
|
|
498
|
+
reverse: colorScale.reverse,
|
|
499
|
+
});
|
|
500
|
+
const scale = scaleQuantile()
|
|
501
|
+
.domain(numericValues)
|
|
502
|
+
.range(range);
|
|
503
|
+
return {
|
|
504
|
+
type: 'stepped',
|
|
505
|
+
title: resolvedTitle,
|
|
506
|
+
items: buildSteppedLegendItems(scale, range),
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
const thresholds = [...colorScale.thresholds].sort((left, right) => left - right);
|
|
510
|
+
if (!thresholds.length) {
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
const range = getDiscreteNumericColors({
|
|
514
|
+
scheme: colorScale.scheme,
|
|
515
|
+
bins: thresholds.length + 1,
|
|
516
|
+
reverse: colorScale.reverse,
|
|
517
|
+
});
|
|
518
|
+
const scale = scaleThreshold()
|
|
519
|
+
.domain(thresholds)
|
|
520
|
+
.range(range);
|
|
521
|
+
return {
|
|
522
|
+
type: 'stepped',
|
|
523
|
+
title: resolvedTitle,
|
|
524
|
+
items: buildSteppedLegendItems(scale, range),
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
//# sourceMappingURL=compileColorScale.js.map
|