exploreda 0.0.6 → 0.1.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.
- package/README.md +144 -0
- package/dist/ExplorEda.cjs +4608 -11288
- package/dist/ExplorEda.cjs.map +1 -1
- package/dist/ExplorEda.css +2282 -1689
- package/dist/ExplorEda.css.map +1 -1
- package/dist/ExplorEda.d.cts +124 -278
- package/dist/ExplorEda.d.ts +124 -278
- package/dist/ExplorEda.js +4479 -11166
- package/dist/ExplorEda.js.map +1 -1
- package/dist/calculations.cjs +18 -0
- package/dist/calculations.cjs.map +1 -0
- package/dist/calculations.d.cts +63 -0
- package/dist/calculations.d.ts +63 -0
- package/dist/calculations.js +3 -0
- package/dist/calculations.js.map +1 -0
- package/dist/charts/bar.cjs +27 -0
- package/dist/charts/bar.cjs.map +1 -0
- package/dist/charts/bar.d.cts +2 -0
- package/dist/charts/bar.d.ts +2 -0
- package/dist/charts/bar.js +18 -0
- package/dist/charts/bar.js.map +1 -0
- package/dist/charts/box-plot.cjs +26 -0
- package/dist/charts/box-plot.cjs.map +1 -0
- package/dist/charts/box-plot.d.cts +2 -0
- package/dist/charts/box-plot.d.ts +2 -0
- package/dist/charts/box-plot.js +17 -0
- package/dist/charts/box-plot.js.map +1 -0
- package/dist/charts/color-legend.cjs +22 -0
- package/dist/charts/color-legend.cjs.map +1 -0
- package/dist/charts/color-legend.d.cts +2 -0
- package/dist/charts/color-legend.d.ts +2 -0
- package/dist/charts/color-legend.js +13 -0
- package/dist/charts/color-legend.js.map +1 -0
- package/dist/charts/data-table.cjs +22 -0
- package/dist/charts/data-table.cjs.map +1 -0
- package/dist/charts/data-table.d.cts +2 -0
- package/dist/charts/data-table.d.ts +2 -0
- package/dist/charts/data-table.js +13 -0
- package/dist/charts/data-table.js.map +1 -0
- package/dist/charts/line.cjs +30 -0
- package/dist/charts/line.cjs.map +1 -0
- package/dist/charts/line.d.cts +2 -0
- package/dist/charts/line.d.ts +2 -0
- package/dist/charts/line.js +17 -0
- package/dist/charts/line.js.map +1 -0
- package/dist/charts/markdown.cjs +16 -0
- package/dist/charts/markdown.cjs.map +1 -0
- package/dist/charts/markdown.css +77 -0
- package/dist/charts/markdown.css.map +1 -0
- package/dist/charts/markdown.d.cts +2 -0
- package/dist/charts/markdown.d.ts +2 -0
- package/dist/charts/markdown.js +7 -0
- package/dist/charts/markdown.js.map +1 -0
- package/dist/charts/pivot-table.cjs +23 -0
- package/dist/charts/pivot-table.cjs.map +1 -0
- package/dist/charts/pivot-table.d.cts +2 -0
- package/dist/charts/pivot-table.d.ts +2 -0
- package/dist/charts/pivot-table.js +14 -0
- package/dist/charts/pivot-table.js.map +1 -0
- package/dist/charts/row.cjs +27 -0
- package/dist/charts/row.cjs.map +1 -0
- package/dist/charts/row.d.cts +6 -0
- package/dist/charts/row.d.ts +6 -0
- package/dist/charts/row.js +18 -0
- package/dist/charts/row.js.map +1 -0
- package/dist/charts/scatter.cjs +24 -0
- package/dist/charts/scatter.cjs.map +1 -0
- package/dist/charts/scatter.d.cts +2 -0
- package/dist/charts/scatter.d.ts +2 -0
- package/dist/charts/scatter.js +15 -0
- package/dist/charts/scatter.js.map +1 -0
- package/dist/charts/summary-table.cjs +19 -0
- package/dist/charts/summary-table.cjs.map +1 -0
- package/dist/charts/summary-table.d.cts +2 -0
- package/dist/charts/summary-table.d.ts +2 -0
- package/dist/charts/summary-table.js +10 -0
- package/dist/charts/summary-table.js.map +1 -0
- package/dist/charts/three-d-scatter.cjs +24 -0
- package/dist/charts/three-d-scatter.cjs.map +1 -0
- package/dist/charts/three-d-scatter.d.cts +6 -0
- package/dist/charts/three-d-scatter.d.ts +6 -0
- package/dist/charts/three-d-scatter.js +15 -0
- package/dist/charts/three-d-scatter.js.map +1 -0
- package/dist/chunk-3PGYFLE3.cjs +499 -0
- package/dist/chunk-3PGYFLE3.cjs.map +1 -0
- package/dist/chunk-4HNDKMWF.js +167 -0
- package/dist/chunk-4HNDKMWF.js.map +1 -0
- package/dist/chunk-4QNENKTV.cjs +1214 -0
- package/dist/chunk-4QNENKTV.cjs.map +1 -0
- package/dist/chunk-54M32JJB.js +132 -0
- package/dist/chunk-54M32JJB.js.map +1 -0
- package/dist/chunk-5B23JVH3.cjs +2238 -0
- package/dist/chunk-5B23JVH3.cjs.map +1 -0
- package/dist/chunk-5LH6NSNL.js +456 -0
- package/dist/chunk-5LH6NSNL.js.map +1 -0
- package/dist/chunk-6DOKKCJ5.cjs +313 -0
- package/dist/chunk-6DOKKCJ5.cjs.map +1 -0
- package/dist/chunk-6HZX5CBT.cjs +1074 -0
- package/dist/chunk-6HZX5CBT.cjs.map +1 -0
- package/dist/chunk-6U5DOIQM.js +1071 -0
- package/dist/chunk-6U5DOIQM.js.map +1 -0
- package/dist/chunk-7GBZIK2R.cjs +80 -0
- package/dist/chunk-7GBZIK2R.cjs.map +1 -0
- package/dist/chunk-7PTJNIOD.js +520 -0
- package/dist/chunk-7PTJNIOD.js.map +1 -0
- package/dist/chunk-AHZYQ7FN.js +319 -0
- package/dist/chunk-AHZYQ7FN.js.map +1 -0
- package/dist/chunk-AOODAOL4.cjs +55 -0
- package/dist/chunk-AOODAOL4.cjs.map +1 -0
- package/dist/chunk-ASKFIRMC.cjs +165 -0
- package/dist/chunk-ASKFIRMC.cjs.map +1 -0
- package/dist/chunk-B7OQUBH4.cjs +171 -0
- package/dist/chunk-B7OQUBH4.cjs.map +1 -0
- package/dist/chunk-BIMEHDLB.js +72 -0
- package/dist/chunk-BIMEHDLB.js.map +1 -0
- package/dist/chunk-C62KHV7S.js +1225 -0
- package/dist/chunk-C62KHV7S.js.map +1 -0
- package/dist/chunk-C7GQT65O.cjs +1119 -0
- package/dist/chunk-C7GQT65O.cjs.map +1 -0
- package/dist/chunk-CGDWDV4Z.js +1211 -0
- package/dist/chunk-CGDWDV4Z.js.map +1 -0
- package/dist/chunk-CJQQFNEY.js +69 -0
- package/dist/chunk-CJQQFNEY.js.map +1 -0
- package/dist/chunk-DHYLSXNR.js +964 -0
- package/dist/chunk-DHYLSXNR.js.map +1 -0
- package/dist/chunk-DKFA4KOJ.cjs +87 -0
- package/dist/chunk-DKFA4KOJ.cjs.map +1 -0
- package/dist/chunk-DS5BS7PP.cjs +357 -0
- package/dist/chunk-DS5BS7PP.cjs.map +1 -0
- package/dist/chunk-EGMFQSGK.js +909 -0
- package/dist/chunk-EGMFQSGK.js.map +1 -0
- package/dist/chunk-EU5EFHO5.cjs +53 -0
- package/dist/chunk-EU5EFHO5.cjs.map +1 -0
- package/dist/chunk-FM46QSDM.js +837 -0
- package/dist/chunk-FM46QSDM.js.map +1 -0
- package/dist/chunk-GV2LRR32.cjs +843 -0
- package/dist/chunk-GV2LRR32.cjs.map +1 -0
- package/dist/chunk-H3XKFSA5.cjs +322 -0
- package/dist/chunk-H3XKFSA5.cjs.map +1 -0
- package/dist/chunk-H5AVMMCE.js +347 -0
- package/dist/chunk-H5AVMMCE.js.map +1 -0
- package/dist/chunk-JDMUN4VK.cjs +986 -0
- package/dist/chunk-JDMUN4VK.cjs.map +1 -0
- package/dist/chunk-JNO7OXCC.js +2171 -0
- package/dist/chunk-JNO7OXCC.js.map +1 -0
- package/dist/chunk-JQMG4ZR7.js +111 -0
- package/dist/chunk-JQMG4ZR7.js.map +1 -0
- package/dist/chunk-L2Q2R43U.cjs +118 -0
- package/dist/chunk-L2Q2R43U.cjs.map +1 -0
- package/dist/chunk-LBTZVERO.js +466 -0
- package/dist/chunk-LBTZVERO.js.map +1 -0
- package/dist/chunk-LUUGGTTK.cjs +1227 -0
- package/dist/chunk-LUUGGTTK.cjs.map +1 -0
- package/dist/chunk-MEEPH7ZC.cjs +911 -0
- package/dist/chunk-MEEPH7ZC.cjs.map +1 -0
- package/dist/chunk-MJPDJ5AS.js +184 -0
- package/dist/chunk-MJPDJ5AS.js.map +1 -0
- package/dist/chunk-MJROUIDZ.cjs +219 -0
- package/dist/chunk-MJROUIDZ.cjs.map +1 -0
- package/dist/chunk-MUWSBYJS.js +528 -0
- package/dist/chunk-MUWSBYJS.js.map +1 -0
- package/dist/chunk-NDF5LCST.js +1088 -0
- package/dist/chunk-NDF5LCST.js.map +1 -0
- package/dist/chunk-NGWTPED4.js +311 -0
- package/dist/chunk-NGWTPED4.js.map +1 -0
- package/dist/chunk-PP4VCONW.js +739 -0
- package/dist/chunk-PP4VCONW.js.map +1 -0
- package/dist/chunk-PRMC2A6P.cjs +488 -0
- package/dist/chunk-PRMC2A6P.cjs.map +1 -0
- package/dist/chunk-PST6UU6S.cjs +742 -0
- package/dist/chunk-PST6UU6S.cjs.map +1 -0
- package/dist/chunk-Q7LK2UWH.js +33 -0
- package/dist/chunk-Q7LK2UWH.js.map +1 -0
- package/dist/chunk-SFV5LZPD.js +162 -0
- package/dist/chunk-SFV5LZPD.js.map +1 -0
- package/dist/chunk-SKXGYJJG.cjs +370 -0
- package/dist/chunk-SKXGYJJG.cjs.map +1 -0
- package/dist/chunk-SWLNKY6R.js +477 -0
- package/dist/chunk-SWLNKY6R.js.map +1 -0
- package/dist/chunk-TGVLNHUB.cjs +483 -0
- package/dist/chunk-TGVLNHUB.cjs.map +1 -0
- package/dist/chunk-TLLRW6S3.js +74 -0
- package/dist/chunk-TLLRW6S3.js.map +1 -0
- package/dist/chunk-TRAIXZ6M.cjs +140 -0
- package/dist/chunk-TRAIXZ6M.cjs.map +1 -0
- package/dist/chunk-U74A5VK5.cjs +74 -0
- package/dist/chunk-U74A5VK5.cjs.map +1 -0
- package/dist/chunk-UAVDLBTA.cjs +74 -0
- package/dist/chunk-UAVDLBTA.cjs.map +1 -0
- package/dist/chunk-UJWS6TRV.js +354 -0
- package/dist/chunk-UJWS6TRV.js.map +1 -0
- package/dist/chunk-UUJMUPB3.cjs +531 -0
- package/dist/chunk-UUJMUPB3.cjs.map +1 -0
- package/dist/chunk-VTKHZIJB.cjs +549 -0
- package/dist/chunk-VTKHZIJB.cjs.map +1 -0
- package/dist/chunk-YXPAWUXO.js +51 -0
- package/dist/chunk-YXPAWUXO.js.map +1 -0
- package/dist/chunk-ZD64SCZB.js +80 -0
- package/dist/chunk-ZD64SCZB.js.map +1 -0
- package/dist/core.cjs +28 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +22 -0
- package/dist/core.d.ts +22 -0
- package/dist/core.js +3 -0
- package/dist/core.js.map +1 -0
- package/dist/dataLayerState-B4XmQjQN.d.cts +258 -0
- package/dist/dataLayerState-B4XmQjQN.d.ts +258 -0
- package/package.json +30 -52
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { categoryLabel, useDataLayer, detectColumnType, finiteNumber, finiteNumbers } from './chunk-JNO7OXCC.js';
|
|
2
|
+
import { schemeCategory10, interpolateViridis, interpolateCool, interpolateWarm, interpolatePlasma, interpolateMagma, interpolateInferno } from 'd3-scale-chromatic';
|
|
3
|
+
import { scaleSequential, scaleOrdinal } from 'd3-scale';
|
|
4
|
+
import { useMemo, useCallback } from 'react';
|
|
5
|
+
|
|
6
|
+
var numericalPalettes = {
|
|
7
|
+
Viridis: interpolateViridis,
|
|
8
|
+
Inferno: interpolateInferno,
|
|
9
|
+
Magma: interpolateMagma,
|
|
10
|
+
Plasma: interpolatePlasma,
|
|
11
|
+
Warm: interpolateWarm,
|
|
12
|
+
Cool: interpolateCool
|
|
13
|
+
};
|
|
14
|
+
var defaultCategoricalColors = schemeCategory10;
|
|
15
|
+
function makeD3ColorScale(scale) {
|
|
16
|
+
if (scale.type === "numerical") {
|
|
17
|
+
const interpolate = numericalPalettes[scale.palette] ?? interpolateViridis;
|
|
18
|
+
return scaleSequential(interpolate).domain([scale.min, scale.max]);
|
|
19
|
+
}
|
|
20
|
+
return scaleOrdinal().domain(Array.from(scale.mapping.keys())).range(scale.palette);
|
|
21
|
+
}
|
|
22
|
+
function makeColorScale(scale) {
|
|
23
|
+
const d3Scale = makeD3ColorScale(scale);
|
|
24
|
+
return (value) => scale.type === "numerical" ? d3Scale(Number(value)) : d3Scale(categoryLabel(value));
|
|
25
|
+
}
|
|
26
|
+
function planNumericalLegend(scale, width, breakpoints, formatValue, getColor) {
|
|
27
|
+
const count = scale.min === scale.max ? 1 : Math.max(2, Math.min(Math.round(breakpoints), Math.floor(width / 56)));
|
|
28
|
+
const stops = Array.from({ length: count }, (_, index) => {
|
|
29
|
+
const value = scale.min + (scale.max - scale.min) * index / Math.max(1, count - 1);
|
|
30
|
+
return { value, label: formatValue(value), color: getColor(value) };
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
width,
|
|
34
|
+
requestedBreakpoints: breakpoints,
|
|
35
|
+
widthPerStop: 56,
|
|
36
|
+
domain: [scale.min, scale.max],
|
|
37
|
+
stops,
|
|
38
|
+
background: count === 1 ? stops[0].color : `linear-gradient(to right, ${stops.map((stop) => stop.color).join(", ")})`
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function useColorScales() {
|
|
42
|
+
const colorScales = useDataLayer((state) => state.colorScales);
|
|
43
|
+
const addColorScale = useDataLayer((state) => state.addColorScale);
|
|
44
|
+
const removeColorScale = useDataLayer((state) => state.removeColorScale);
|
|
45
|
+
const updateColorScale = useDataLayer((state) => state.updateColorScale);
|
|
46
|
+
const getColumnData = useDataLayer((state) => state.getColumnData);
|
|
47
|
+
const fieldProfiles = useDataLayer((state) => state.fieldProfiles);
|
|
48
|
+
const charts = useDataLayer((state) => state.charts);
|
|
49
|
+
const d3Scales = useMemo(() => {
|
|
50
|
+
const scales = /* @__PURE__ */ new Map();
|
|
51
|
+
colorScales.forEach(
|
|
52
|
+
(scale) => scales.set(scale.id, makeD3ColorScale(scale))
|
|
53
|
+
);
|
|
54
|
+
return scales;
|
|
55
|
+
}, [colorScales]);
|
|
56
|
+
const getColorForValue = useCallback(
|
|
57
|
+
(scaleId, value, defaultColor = "#000000") => {
|
|
58
|
+
if (!scaleId) {
|
|
59
|
+
return defaultColor;
|
|
60
|
+
}
|
|
61
|
+
const scale = colorScales.find((s) => s.id === scaleId);
|
|
62
|
+
if (!scale) {
|
|
63
|
+
return "#000000";
|
|
64
|
+
}
|
|
65
|
+
const d3Scale = d3Scales.get(scaleId);
|
|
66
|
+
if (!d3Scale) {
|
|
67
|
+
return "#000000";
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
if (scale.type === "numerical") {
|
|
71
|
+
return d3Scale(Number(value));
|
|
72
|
+
}
|
|
73
|
+
return d3Scale(categoryLabel(value));
|
|
74
|
+
} catch {
|
|
75
|
+
return "#000000";
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
[colorScales, d3Scales]
|
|
79
|
+
);
|
|
80
|
+
const getScaleById = (id) => {
|
|
81
|
+
return colorScales.find((s) => s.id === id);
|
|
82
|
+
};
|
|
83
|
+
const createDefaultNumericalScale = (name, min, max, sourceField) => {
|
|
84
|
+
const scale = {
|
|
85
|
+
name,
|
|
86
|
+
type: "numerical",
|
|
87
|
+
palette: "Viridis",
|
|
88
|
+
min,
|
|
89
|
+
max,
|
|
90
|
+
sourceField
|
|
91
|
+
};
|
|
92
|
+
return addColorScale(scale);
|
|
93
|
+
};
|
|
94
|
+
const createDefaultCategoricalScale = (name, values, sourceField) => {
|
|
95
|
+
const defaultPalette = defaultCategoricalColors;
|
|
96
|
+
const mapping = /* @__PURE__ */ new Map();
|
|
97
|
+
values.forEach((value, i) => {
|
|
98
|
+
mapping.set(
|
|
99
|
+
value,
|
|
100
|
+
defaultPalette[i % defaultPalette.length] ?? "#000000"
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
const scale = {
|
|
104
|
+
name,
|
|
105
|
+
type: "categorical",
|
|
106
|
+
palette: Array.from(mapping.values()),
|
|
107
|
+
mapping,
|
|
108
|
+
sourceField
|
|
109
|
+
};
|
|
110
|
+
return addColorScale(scale);
|
|
111
|
+
};
|
|
112
|
+
const getD3Scale = (scaleId) => {
|
|
113
|
+
return d3Scales.get(scaleId) ?? scaleSequential(interpolateViridis).domain([0, 1]);
|
|
114
|
+
};
|
|
115
|
+
const getOrCreateScaleForField = (field, name) => {
|
|
116
|
+
const boundScaleIds = new Set(
|
|
117
|
+
charts.filter(
|
|
118
|
+
(chart) => chart.colorField === field && typeof chart.colorScaleId === "string"
|
|
119
|
+
).map((chart) => chart.colorScaleId)
|
|
120
|
+
);
|
|
121
|
+
if (boundScaleIds.size === 1) {
|
|
122
|
+
const [boundScaleId] = boundScaleIds;
|
|
123
|
+
if (boundScaleId && colorScales.some((scale) => scale.id === boundScaleId)) {
|
|
124
|
+
return boundScaleId;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const existingScale = colorScales.find((s) => s.sourceField === field);
|
|
128
|
+
if (existingScale) {
|
|
129
|
+
return existingScale.id;
|
|
130
|
+
}
|
|
131
|
+
const values = Object.values(getColumnData(field));
|
|
132
|
+
const cleanValues = values.filter((v) => v != null);
|
|
133
|
+
const profile = fieldProfiles.find((item) => item.name === field);
|
|
134
|
+
const isNumerical = (profile?.dataType ?? detectColumnType(getColumnData(field))) === "numeric" && cleanValues.some((value) => finiteNumber(value) !== void 0);
|
|
135
|
+
let newScale;
|
|
136
|
+
if (isNumerical) {
|
|
137
|
+
const numericValues = finiteNumbers(cleanValues);
|
|
138
|
+
const min = Math.min(...numericValues);
|
|
139
|
+
const max = Math.max(...numericValues);
|
|
140
|
+
newScale = createDefaultNumericalScale(name ?? field, min, max, field);
|
|
141
|
+
} else {
|
|
142
|
+
const uniqueValues = Array.from(new Set(values.map(categoryLabel)));
|
|
143
|
+
newScale = createDefaultCategoricalScale(
|
|
144
|
+
name ?? field,
|
|
145
|
+
uniqueValues,
|
|
146
|
+
field
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return newScale.id;
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
addColorScale,
|
|
153
|
+
removeColorScale,
|
|
154
|
+
updateColorScale,
|
|
155
|
+
getColorForValue,
|
|
156
|
+
getScaleById,
|
|
157
|
+
colorScales,
|
|
158
|
+
createDefaultNumericalScale,
|
|
159
|
+
createDefaultCategoricalScale,
|
|
160
|
+
getD3Scale,
|
|
161
|
+
getOrCreateScaleForField
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { makeColorScale, planNumericalLegend, useColorScales };
|
|
166
|
+
//# sourceMappingURL=chunk-4HNDKMWF.js.map
|
|
167
|
+
//# sourceMappingURL=chunk-4HNDKMWF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/colorScaleMath.ts","../src/hooks/useColorScales.ts"],"names":["scaleSequential","interpolateViridis"],"mappings":";;;;;AAeA,IAAM,iBAAoB,GAAA;AAAA,EACxB,OAAS,EAAA,kBAAA;AAAA,EACT,OAAS,EAAA,kBAAA;AAAA,EACT,KAAO,EAAA,gBAAA;AAAA,EACP,MAAQ,EAAA,iBAAA;AAAA,EACR,IAAM,EAAA,eAAA;AAAA,EACN,IAAM,EAAA;AACR,CAAA;AAEO,IAAM,wBAA2B,GAAA,gBAAA;AAEjC,SAAS,iBAAiB,KAAuB,EAAA;AACtD,EAAI,IAAA,KAAA,CAAM,SAAS,WAAa,EAAA;AAC9B,IAAA,MAAM,WACJ,GAAA,iBAAA,CAAkB,KAAM,CAAA,OAAyC,CACjE,IAAA,kBAAA;AACF,IAAO,OAAA,eAAA,CAAgB,WAAW,CAAE,CAAA,MAAA,CAAO,CAAC,KAAM,CAAA,GAAA,EAAK,KAAM,CAAA,GAAG,CAAC,CAAA;AAAA;AAEnE,EAAA,OAAO,YAAqB,EAAA,CACzB,MAAO,CAAA,KAAA,CAAM,IAAK,CAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,EAAM,CAAC,CACvC,CAAA,KAAA,CAAM,MAAM,OAAO,CAAA;AACxB;AAEO,SAAS,eAAe,KAAuB,EAAA;AACpD,EAAM,MAAA,OAAA,GAAU,iBAAiB,KAAK,CAAA;AACtC,EAAA,OAAO,CAAC,KAAA,KACN,KAAM,CAAA,IAAA,KAAS,WACV,GAAA,OAAA,CAAoC,MAAO,CAAA,KAAK,CAAC,CAAA,GACjD,OAAyC,CAAA,aAAA,CAAc,KAAK,CAAC,CAAA;AACtE;AAEO,SAAS,mBACd,CAAA,KAAA,EACA,KACA,EAAA,WAAA,EACA,aACA,QACA,EAAA;AACA,EAAM,MAAA,KAAA,GACJ,MAAM,GAAQ,KAAA,KAAA,CAAM,MAChB,CACA,GAAA,IAAA,CAAK,IAAI,CAAG,EAAA,IAAA,CAAK,IAAI,IAAK,CAAA,KAAA,CAAM,WAAW,CAAG,EAAA,IAAA,CAAK,MAAM,KAAQ,GAAA,EAAE,CAAC,CAAC,CAAA;AAC3E,EAAM,MAAA,KAAA,GAAQ,MAAM,IAAK,CAAA,EAAE,QAAQ,KAAM,EAAA,EAAG,CAAC,CAAA,EAAG,KAAU,KAAA;AACxD,IAAA,MAAM,KACJ,GAAA,KAAA,CAAM,GAAQ,GAAA,CAAA,KAAA,CAAM,GAAM,GAAA,KAAA,CAAM,GAAO,IAAA,KAAA,GAAS,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,KAAA,GAAQ,CAAC,CAAA;AACvE,IAAO,OAAA,EAAE,OAAO,KAAO,EAAA,WAAA,CAAY,KAAK,CAAG,EAAA,KAAA,EAAO,QAAS,CAAA,KAAK,CAAE,EAAA;AAAA,GACnE,CAAA;AACD,EAAO,OAAA;AAAA,IACL,KAAA;AAAA,IACA,oBAAsB,EAAA,WAAA;AAAA,IACtB,YAAc,EAAA,EAAA;AAAA,IACd,MAAQ,EAAA,CAAC,KAAM,CAAA,GAAA,EAAK,MAAM,GAAG,CAAA;AAAA,IAC7B,KAAA;AAAA,IACA,YACE,KAAU,KAAA,CAAA,GACN,KAAM,CAAA,CAAC,EAAG,KACV,GAAA,CAAA,0BAAA,EAA6B,KAAM,CAAA,GAAA,CAAI,CAAC,IAAS,KAAA,IAAA,CAAK,KAAK,CAAE,CAAA,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,GAC/E;AACF;ACpDO,SAAS,cAAuC,GAAA;AACrD,EAAA,MAAM,WAAc,GAAA,YAAA,CAAa,CAAC,KAAA,KAAU,MAAM,WAAW,CAAA;AAC7D,EAAA,MAAM,aAAgB,GAAA,YAAA,CAAa,CAAC,KAAA,KAAU,MAAM,aAAa,CAAA;AACjE,EAAA,MAAM,gBAAmB,GAAA,YAAA,CAAa,CAAC,KAAA,KAAU,MAAM,gBAAgB,CAAA;AACvE,EAAA,MAAM,gBAAmB,GAAA,YAAA,CAAa,CAAC,KAAA,KAAU,MAAM,gBAAgB,CAAA;AACvE,EAAA,MAAM,aAAgB,GAAA,YAAA,CAAa,CAAC,KAAA,KAAU,MAAM,aAAa,CAAA;AACjE,EAAA,MAAM,aAAgB,GAAA,YAAA,CAAa,CAAC,KAAA,KAAU,MAAM,aAAa,CAAA;AACjE,EAAA,MAAM,MAAS,GAAA,YAAA,CAAa,CAAC,KAAA,KAAU,MAAM,MAAM,CAAA;AAGnD,EAAM,MAAA,QAAA,GAAW,QAAQ,MAAM;AAC7B,IAAM,MAAA,MAAA,uBAAa,GAGjB,EAAA;AAEF,IAAY,WAAA,CAAA,OAAA;AAAA,MAAQ,CAAC,UACnB,MAAO,CAAA,GAAA,CAAI,MAAM,EAAI,EAAA,gBAAA,CAAiB,KAAK,CAAC;AAAA,KAC9C;AAEA,IAAO,OAAA,MAAA;AAAA,GACT,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,MAAM,gBAAmB,GAAA,WAAA;AAAA,IACvB,CACE,OAAA,EACA,KACA,EAAA,YAAA,GAAuB,SACZ,KAAA;AACX,MAAA,IAAI,CAAC,OAAS,EAAA;AACZ,QAAO,OAAA,YAAA;AAAA;AAGT,MAAA,MAAM,QAAQ,WAAY,CAAA,IAAA,CAAK,CAAC,CAAM,KAAA,CAAA,CAAE,OAAO,OAAO,CAAA;AACtD,MAAA,IAAI,CAAC,KAAO,EAAA;AAEV,QAAO,OAAA,SAAA;AAAA;AAGT,MAAM,MAAA,OAAA,GAAU,QAAS,CAAA,GAAA,CAAI,OAAO,CAAA;AACpC,MAAA,IAAI,CAAC,OAAS,EAAA;AACZ,QAAO,OAAA,SAAA;AAAA;AAGT,MAAI,IAAA;AACF,QAAI,IAAA,KAAA,CAAM,SAAS,WAAa,EAAA;AAC9B,UAAQ,OAAA,OAAA,CAAoC,MAAO,CAAA,KAAK,CAAC,CAAA;AAAA;AAE3D,QAAQ,OAAA,OAAA,CAAyC,aAAc,CAAA,KAAK,CAAC,CAAA;AAAA,OAC/D,CAAA,MAAA;AACN,QAAO,OAAA,SAAA;AAAA;AACT,KACF;AAAA,IACA,CAAC,aAAa,QAAQ;AAAA,GACxB;AAEA,EAAM,MAAA,YAAA,GAAe,CAAC,EAA2C,KAAA;AAC/D,IAAA,OAAO,YAAY,IAAK,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,OAAO,EAAE,CAAA;AAAA,GAC5C;AAEA,EAAA,MAAM,2BAA8B,GAAA,CAClC,IACA,EAAA,GAAA,EACA,KACA,WACmB,KAAA;AACnB,IAAA,MAAM,KAAyC,GAAA;AAAA,MAC7C,IAAA;AAAA,MACA,IAAM,EAAA,WAAA;AAAA,MACN,OAAS,EAAA,SAAA;AAAA,MACT,GAAA;AAAA,MACA,GAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,cAAc,KAAK,CAAA;AAAA,GAC5B;AAEA,EAAA,MAAM,6BAAgC,GAAA,CACpC,IACA,EAAA,MAAA,EACA,WACmB,KAAA;AACnB,IAAA,MAAM,cAAiB,GAAA,wBAAA;AACvB,IAAM,MAAA,OAAA,uBAAc,GAAoB,EAAA;AACxC,IAAO,MAAA,CAAA,OAAA,CAAQ,CAAC,KAAA,EAAO,CAAM,KAAA;AAC3B,MAAQ,OAAA,CAAA,GAAA;AAAA,QACN,KAAA;AAAA,QACA,cAAe,CAAA,CAAA,GAAI,cAAe,CAAA,MAAM,CAAK,IAAA;AAAA,OAC/C;AAAA,KACD,CAAA;AAED,IAAA,MAAM,KAA2C,GAAA;AAAA,MAC/C,IAAA;AAAA,MACA,IAAM,EAAA,aAAA;AAAA,MACN,OAAS,EAAA,KAAA,CAAM,IAAK,CAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,MACpC,OAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,cAAc,KAAK,CAAA;AAAA,GAC5B;AAEA,EAAM,MAAA,UAAA,GAAa,CAAC,OAAoB,KAAA;AACtC,IACE,OAAA,QAAA,CAAS,GAAI,CAAA,OAAO,CACpBA,IAAAA,eAAAA,CAAgBC,kBAAkB,CAAA,CAAE,MAAO,CAAA,CAAC,CAAG,EAAA,CAAC,CAAC,CAAA;AAAA,GAErD;AAEA,EAAM,MAAA,wBAAA,GAA2B,CAAC,KAAA,EAAe,IAA0B,KAAA;AAGzE,IAAA,MAAM,gBAAgB,IAAI,GAAA;AAAA,MACxB,MACG,CAAA,MAAA;AAAA,QACC,CAAC,KACC,KAAA,KAAA,CAAM,eAAe,KAAS,IAAA,OAAO,MAAM,YAAiB,KAAA;AAAA,OAE/D,CAAA,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,YAAsB;AAAA,KAChD;AACA,IAAI,IAAA,aAAA,CAAc,SAAS,CAAG,EAAA;AAC5B,MAAM,MAAA,CAAC,YAAY,CAAI,GAAA,aAAA;AACvB,MACE,IAAA,YAAA,IACA,YAAY,IAAK,CAAA,CAAC,UAAU,KAAM,CAAA,EAAA,KAAO,YAAY,CACrD,EAAA;AACA,QAAO,OAAA,YAAA;AAAA;AACT;AAIF,IAAA,MAAM,gBAAgB,WAAY,CAAA,IAAA,CAAK,CAAC,CAAM,KAAA,CAAA,CAAE,gBAAgB,KAAK,CAAA;AACrE,IAAA,IAAI,aAAe,EAAA;AACjB,MAAA,OAAO,aAAc,CAAA,EAAA;AAAA;AAIvB,IAAA,MAAM,MAAS,GAAA,MAAA,CAAO,MAAO,CAAA,aAAA,CAAc,KAAK,CAAC,CAAA;AAGjD,IAAA,MAAM,cAAc,MAAO,CAAA,MAAA,CAAO,CAAC,CAAA,KAA4B,KAAK,IAAI,CAAA;AAGxE,IAAA,MAAM,UAAU,aAAc,CAAA,IAAA,CAAK,CAAC,IAAS,KAAA,IAAA,CAAK,SAAS,KAAK,CAAA;AAChE,IAAA,MAAM,eACH,OAAS,EAAA,QAAA,IAAY,gBAAiB,CAAA,aAAA,CAAc,KAAK,CAAC,CAAA,MACzD,SACF,IAAA,WAAA,CAAY,KAAK,CAAC,KAAA,KAAU,YAAa,CAAA,KAAK,MAAM,MAAS,CAAA;AAE/D,IAAI,IAAA,QAAA;AACJ,IAAA,IAAI,WAAa,EAAA;AACf,MAAM,MAAA,aAAA,GAAgB,cAAc,WAAW,CAAA;AAC/C,MAAA,MAAM,GAAM,GAAA,IAAA,CAAK,GAAI,CAAA,GAAG,aAAa,CAAA;AACrC,MAAA,MAAM,GAAM,GAAA,IAAA,CAAK,GAAI,CAAA,GAAG,aAAa,CAAA;AACrC,MAAA,QAAA,GAAW,2BAA4B,CAAA,IAAA,IAAQ,KAAO,EAAA,GAAA,EAAK,KAAK,KAAK,CAAA;AAAA,KAChE,MAAA;AACL,MAAM,MAAA,YAAA,GAAe,MAAM,IAAK,CAAA,IAAI,IAAI,MAAO,CAAA,GAAA,CAAI,aAAa,CAAC,CAAC,CAAA;AAClE,MAAW,QAAA,GAAA,6BAAA;AAAA,QACT,IAAQ,IAAA,KAAA;AAAA,QACR,YAAA;AAAA,QACA;AAAA,OACF;AAAA;AAGF,IAAA,OAAO,QAAS,CAAA,EAAA;AAAA,GAClB;AAEA,EAAO,OAAA;AAAA,IACL,aAAA;AAAA,IACA,gBAAA;AAAA,IACA,gBAAA;AAAA,IACA,gBAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,2BAAA;AAAA,IACA,6BAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF","file":"chunk-4HNDKMWF.js","sourcesContent":["import { categoryLabel } from \"./categories\";\nimport type { datum } from \"@/types/ChartTypes\";\nimport type { ColorScaleType } from \"@/types/ColorScaleTypes\";\nimport { scaleOrdinal, scaleSequential } from \"d3-scale\";\nimport type { ScaleOrdinal, ScaleSequential } from \"d3-scale\";\nimport {\n interpolateCool,\n interpolateInferno,\n interpolateMagma,\n interpolatePlasma,\n interpolateViridis,\n interpolateWarm,\n schemeCategory10,\n} from \"d3-scale-chromatic\";\n\nconst numericalPalettes = {\n Viridis: interpolateViridis,\n Inferno: interpolateInferno,\n Magma: interpolateMagma,\n Plasma: interpolatePlasma,\n Warm: interpolateWarm,\n Cool: interpolateCool,\n};\n\nexport const defaultCategoricalColors = schemeCategory10;\n\nexport function makeD3ColorScale(scale: ColorScaleType) {\n if (scale.type === \"numerical\") {\n const interpolate =\n numericalPalettes[scale.palette as keyof typeof numericalPalettes] ??\n interpolateViridis;\n return scaleSequential(interpolate).domain([scale.min, scale.max]);\n }\n return scaleOrdinal<string>()\n .domain(Array.from(scale.mapping.keys()))\n .range(scale.palette);\n}\n\nexport function makeColorScale(scale: ColorScaleType) {\n const d3Scale = makeD3ColorScale(scale);\n return (value: datum) =>\n scale.type === \"numerical\"\n ? (d3Scale as ScaleSequential<string>)(Number(value))\n : (d3Scale as ScaleOrdinal<string, string>)(categoryLabel(value));\n}\n\nexport function planNumericalLegend(\n scale: Extract<ColorScaleType, { type: \"numerical\" }>,\n width: number,\n breakpoints: number,\n formatValue: (value: number) => string,\n getColor: (value: number) => string\n) {\n const count =\n scale.min === scale.max\n ? 1\n : Math.max(2, Math.min(Math.round(breakpoints), Math.floor(width / 56)));\n const stops = Array.from({ length: count }, (_, index) => {\n const value =\n scale.min + ((scale.max - scale.min) * index) / Math.max(1, count - 1);\n return { value, label: formatValue(value), color: getColor(value) };\n });\n return {\n width,\n requestedBreakpoints: breakpoints,\n widthPerStop: 56,\n domain: [scale.min, scale.max] as [number, number],\n stops,\n background:\n count === 1\n ? stops[0]!.color\n : `linear-gradient(to right, ${stops.map((stop) => stop.color).join(\", \")})`,\n };\n}\n","import { finiteNumber, finiteNumbers } from \"@/lib/numeric\";\nimport { categoryLabel } from \"@/lib/categories\";\nimport { detectColumnType } from \"@/components/SummaryTable/utils/dataTypeDetection\";\nimport { useDataLayer } from \"@/providers/DataLayerProvider\";\nimport {\n CategoricalColorScale,\n ColorScaleType,\n NumericalColorScale,\n UseColorScalesReturn,\n} from \"@/types/ColorScaleTypes\";\nimport type { datum } from \"@/types/ChartTypes\";\nimport { interpolateViridis } from \"d3-scale-chromatic\";\nimport { scaleSequential } from \"d3-scale\";\nimport type { ScaleOrdinal, ScaleSequential } from \"d3-scale\";\nimport {\n defaultCategoricalColors,\n makeD3ColorScale,\n} from \"@/lib/colorScaleMath\";\n\nimport { useCallback, useMemo } from \"react\";\n\nexport function useColorScales(): UseColorScalesReturn {\n const colorScales = useDataLayer((state) => state.colorScales);\n const addColorScale = useDataLayer((state) => state.addColorScale);\n const removeColorScale = useDataLayer((state) => state.removeColorScale);\n const updateColorScale = useDataLayer((state) => state.updateColorScale);\n const getColumnData = useDataLayer((state) => state.getColumnData);\n const fieldProfiles = useDataLayer((state) => state.fieldProfiles);\n const charts = useDataLayer((state) => state.charts);\n\n // Memoized d3 scale objects\n const d3Scales = useMemo(() => {\n const scales = new Map<\n string,\n ScaleSequential<string> | ScaleOrdinal<string, string>\n >();\n\n colorScales.forEach((scale) =>\n scales.set(scale.id, makeD3ColorScale(scale))\n );\n\n return scales;\n }, [colorScales]);\n\n const getColorForValue = useCallback(\n (\n scaleId: string | undefined,\n value: datum,\n defaultColor: string = \"#000000\"\n ): string => {\n if (!scaleId) {\n return defaultColor;\n }\n\n const scale = colorScales.find((s) => s.id === scaleId);\n if (!scale) {\n // console.warn(`Color scale ${scaleId} not found`);\n return \"#000000\";\n }\n\n const d3Scale = d3Scales.get(scaleId);\n if (!d3Scale) {\n return \"#000000\";\n }\n\n try {\n if (scale.type === \"numerical\") {\n return (d3Scale as ScaleSequential<string>)(Number(value));\n }\n return (d3Scale as ScaleOrdinal<string, string>)(categoryLabel(value));\n } catch {\n return \"#000000\";\n }\n },\n [colorScales, d3Scales]\n );\n\n const getScaleById = (id: string): ColorScaleType | undefined => {\n return colorScales.find((s) => s.id === id);\n };\n\n const createDefaultNumericalScale = (\n name: string,\n min: number,\n max: number,\n sourceField?: string\n ): ColorScaleType => {\n const scale: Omit<NumericalColorScale, \"id\"> = {\n name,\n type: \"numerical\",\n palette: \"Viridis\",\n min,\n max,\n sourceField,\n };\n return addColorScale(scale);\n };\n\n const createDefaultCategoricalScale = (\n name: string,\n values: string[],\n sourceField?: string\n ): ColorScaleType => {\n const defaultPalette = defaultCategoricalColors;\n const mapping = new Map<string, string>();\n values.forEach((value, i) => {\n mapping.set(\n value,\n defaultPalette[i % defaultPalette.length] ?? \"#000000\"\n );\n });\n\n const scale: Omit<CategoricalColorScale, \"id\"> = {\n name,\n type: \"categorical\",\n palette: Array.from(mapping.values()),\n mapping,\n sourceField,\n };\n return addColorScale(scale);\n };\n\n const getD3Scale = (scaleId: string) => {\n return (\n d3Scales.get(scaleId) ??\n scaleSequential(interpolateViridis).domain([0, 1])\n );\n };\n\n const getOrCreateScaleForField = (field: string, name?: string): string => {\n // Existing chart bindings are authoritative. Keep the exact ID instead of\n // matching display names.\n const boundScaleIds = new Set(\n charts\n .filter(\n (chart) =>\n chart.colorField === field && typeof chart.colorScaleId === \"string\"\n )\n .map((chart) => chart.colorScaleId as string)\n );\n if (boundScaleIds.size === 1) {\n const [boundScaleId] = boundScaleIds;\n if (\n boundScaleId &&\n colorScales.some((scale) => scale.id === boundScaleId)\n ) {\n return boundScaleId;\n }\n }\n\n // Otherwise reuse the explicitly bound source scale before creating one.\n const existingScale = colorScales.find((s) => s.sourceField === field);\n if (existingScale) {\n return existingScale.id;\n }\n\n // Get all values for the field\n const values = Object.values(getColumnData(field));\n\n // Filter out null and undefined\n const cleanValues = values.filter((v): v is string | number => v != null);\n\n // Check if values are numerical\n const profile = fieldProfiles.find((item) => item.name === field);\n const isNumerical =\n (profile?.dataType ?? detectColumnType(getColumnData(field))) ===\n \"numeric\" &&\n cleanValues.some((value) => finiteNumber(value) !== undefined);\n\n let newScale: ColorScaleType;\n if (isNumerical) {\n const numericValues = finiteNumbers(cleanValues);\n const min = Math.min(...numericValues);\n const max = Math.max(...numericValues);\n newScale = createDefaultNumericalScale(name ?? field, min, max, field);\n } else {\n const uniqueValues = Array.from(new Set(values.map(categoryLabel)));\n newScale = createDefaultCategoricalScale(\n name ?? field,\n uniqueValues,\n field\n );\n }\n\n return newScale.id;\n };\n\n return {\n addColorScale,\n removeColorScale,\n updateColorScale,\n getColorForValue,\n getScaleById,\n colorScales,\n createDefaultNumericalScale,\n createDefaultCategoricalScale,\n getD3Scale,\n getOrCreateScaleForField,\n };\n}\n"]}
|