svelteplot 0.0.1-alpha.9 → 0.1.3-next.11
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/LICENSE.md +5 -0
- package/README.md +3 -36
- package/dist/Mark.svelte +292 -0
- package/dist/Mark.svelte.d.ts +22 -0
- package/dist/Plot.svelte +148 -156
- package/dist/Plot.svelte.d.ts +15 -15
- package/dist/constants.d.ts +15 -0
- package/dist/constants.js +110 -0
- package/dist/core/Facet.svelte +59 -0
- package/dist/core/Facet.svelte.d.ts +18 -0
- package/dist/core/FacetAxes.svelte +66 -0
- package/dist/core/FacetAxes.svelte.d.ts +4 -0
- package/dist/core/FacetGrid.svelte +86 -0
- package/dist/core/FacetGrid.svelte.d.ts +13 -0
- package/dist/core/Plot.svelte +568 -0
- package/dist/core/Plot.svelte.d.ts +14 -0
- package/dist/helpers/arrowPath.d.ts +14 -0
- package/dist/helpers/arrowPath.js +129 -0
- package/dist/helpers/autoProjection.d.ts +19 -0
- package/dist/helpers/autoProjection.js +87 -0
- package/dist/helpers/autoScales.d.ts +23 -0
- package/dist/helpers/autoScales.js +203 -0
- package/dist/helpers/autoTicks.d.ts +3 -0
- package/dist/helpers/autoTicks.js +40 -0
- package/dist/helpers/autoTimeFormat.d.ts +2 -2
- package/dist/helpers/autoTimeFormat.js +34 -5
- package/dist/helpers/callWithProps.d.ts +8 -0
- package/dist/helpers/callWithProps.js +13 -0
- package/dist/helpers/colors.js +17 -2
- package/dist/helpers/curves.d.ts +3 -0
- package/dist/helpers/curves.js +42 -0
- package/dist/helpers/data.d.ts +9 -0
- package/dist/helpers/data.js +16 -0
- package/dist/helpers/facets.d.ts +12 -0
- package/dist/helpers/facets.js +49 -0
- package/dist/helpers/formats.d.ts +3 -0
- package/dist/helpers/formats.js +3 -0
- package/dist/helpers/getBaseStyles.d.ts +7 -2
- package/dist/helpers/getBaseStyles.js +34 -10
- package/dist/helpers/getLogTicks.js +5 -5
- package/dist/helpers/group.d.ts +6 -0
- package/dist/helpers/group.js +53 -0
- package/dist/helpers/index.d.ts +18 -0
- package/dist/helpers/index.js +55 -0
- package/dist/helpers/isRawValue.d.ts +2 -0
- package/dist/helpers/isRawValue.js +5 -0
- package/dist/helpers/isValid.d.ts +6 -0
- package/dist/helpers/isValid.js +6 -0
- package/dist/helpers/math.d.ts +19 -0
- package/dist/helpers/math.js +116 -0
- package/dist/helpers/mergeDeep.d.ts +1 -1
- package/dist/helpers/noise.d.ts +1 -0
- package/dist/helpers/noise.js +72 -0
- package/dist/helpers/projection.d.ts +33 -0
- package/dist/helpers/projection.js +100 -0
- package/dist/helpers/reduce.d.ts +10 -0
- package/dist/helpers/reduce.js +85 -0
- package/dist/helpers/regressionLoess.d.ts +12 -0
- package/dist/helpers/regressionLoess.js +47 -0
- package/dist/helpers/removeIdenticalLines.d.ts +8 -1
- package/dist/helpers/removeIdenticalLines.js +14 -7
- package/dist/helpers/resolve.d.ts +21 -0
- package/dist/helpers/resolve.js +156 -0
- package/dist/helpers/roundedRect.d.ts +9 -0
- package/dist/helpers/roundedRect.js +31 -0
- package/dist/helpers/scales.d.ts +42 -0
- package/dist/helpers/scales.js +309 -0
- package/dist/helpers/time.d.ts +6 -0
- package/dist/helpers/time.js +282 -0
- package/dist/helpers/typeChecks.d.ts +8 -5
- package/dist/helpers/typeChecks.js +27 -6
- package/dist/index.d.ts +49 -1
- package/dist/index.js +53 -2
- package/dist/marks/Area.svelte +146 -0
- package/dist/marks/Area.svelte.d.ts +30 -0
- package/dist/marks/AreaX.svelte +27 -0
- package/dist/marks/AreaX.svelte.d.ts +12 -0
- package/dist/marks/AreaY.svelte +38 -0
- package/dist/marks/AreaY.svelte.d.ts +19 -0
- package/dist/marks/Arrow.svelte +139 -0
- package/dist/marks/Arrow.svelte.d.ts +44 -0
- package/dist/marks/AxisX.svelte +198 -93
- package/dist/marks/AxisX.svelte.d.ts +17 -16
- package/dist/marks/AxisY.svelte +176 -62
- package/dist/marks/AxisY.svelte.d.ts +17 -14
- package/dist/marks/BarX.svelte +86 -0
- package/dist/marks/BarX.svelte.d.ts +4 -0
- package/dist/marks/BarY.svelte +98 -0
- package/dist/marks/BarY.svelte.d.ts +4 -0
- package/dist/marks/BollingerX.svelte +44 -0
- package/dist/marks/BollingerX.svelte.d.ts +18 -0
- package/dist/marks/BollingerY.svelte +39 -0
- package/dist/marks/BollingerY.svelte.d.ts +18 -0
- package/dist/marks/BoxX.svelte +89 -0
- package/dist/marks/BoxX.svelte.d.ts +4 -0
- package/dist/marks/BoxY.svelte +110 -0
- package/dist/marks/BoxY.svelte.d.ts +29 -0
- package/dist/marks/Cell.svelte +110 -0
- package/dist/marks/Cell.svelte.d.ts +16 -0
- package/dist/marks/CellX.svelte +24 -0
- package/dist/marks/CellX.svelte.d.ts +3 -0
- package/dist/marks/CellY.svelte +24 -0
- package/dist/marks/CellY.svelte.d.ts +3 -0
- package/dist/marks/ColorLegend.svelte +148 -27
- package/dist/marks/ColorLegend.svelte.d.ts +12 -13
- package/dist/marks/CustomMark.svelte +43 -0
- package/dist/marks/CustomMark.svelte.d.ts +16 -0
- package/dist/marks/CustomMarkHTML.svelte +103 -0
- package/dist/marks/CustomMarkHTML.svelte.d.ts +17 -0
- package/dist/marks/DifferenceY.svelte +144 -0
- package/dist/marks/DifferenceY.svelte.d.ts +30 -0
- package/dist/marks/Dot.svelte +128 -73
- package/dist/marks/Dot.svelte.d.ts +24 -14
- package/dist/marks/DotX.svelte +15 -3
- package/dist/marks/DotX.svelte.d.ts +8 -16
- package/dist/marks/DotY.svelte +8 -3
- package/dist/marks/DotY.svelte.d.ts +5 -17
- package/dist/marks/Frame.svelte +39 -31
- package/dist/marks/Frame.svelte.d.ts +7 -14
- package/dist/marks/Geo.svelte +102 -0
- package/dist/marks/Geo.svelte.d.ts +10 -0
- package/dist/marks/Graticule.svelte +28 -0
- package/dist/marks/Graticule.svelte.d.ts +9 -0
- package/dist/marks/GridX.svelte +67 -36
- package/dist/marks/GridX.svelte.d.ts +7 -18
- package/dist/marks/GridY.svelte +64 -25
- package/dist/marks/GridY.svelte.d.ts +7 -14
- package/dist/marks/HTMLTooltip.svelte +91 -0
- package/dist/marks/HTMLTooltip.svelte.d.ts +11 -0
- package/dist/marks/Line.svelte +219 -58
- package/dist/marks/Line.svelte.d.ts +30 -14
- package/dist/marks/LineX.svelte +8 -8
- package/dist/marks/LineX.svelte.d.ts +4 -17
- package/dist/marks/LineY.svelte +7 -8
- package/dist/marks/LineY.svelte.d.ts +4 -17
- package/dist/marks/Link.svelte +180 -0
- package/dist/marks/Link.svelte.d.ts +21 -0
- package/dist/marks/Pointer.svelte +126 -0
- package/dist/marks/Pointer.svelte.d.ts +23 -0
- package/dist/marks/Rect.svelte +103 -0
- package/dist/marks/Rect.svelte.d.ts +15 -0
- package/dist/marks/RectX.svelte +33 -0
- package/dist/marks/RectX.svelte.d.ts +15 -0
- package/dist/marks/RectY.svelte +33 -0
- package/dist/marks/RectY.svelte.d.ts +15 -0
- package/dist/marks/RegressionX.svelte +26 -0
- package/dist/marks/RegressionX.svelte.d.ts +4 -0
- package/dist/marks/RegressionY.svelte +26 -0
- package/dist/marks/RegressionY.svelte.d.ts +4 -0
- package/dist/marks/RuleX.svelte +52 -28
- package/dist/marks/RuleX.svelte.d.ts +14 -14
- package/dist/marks/RuleY.svelte +52 -28
- package/dist/marks/RuleY.svelte.d.ts +14 -14
- package/dist/marks/Sphere.svelte +8 -0
- package/dist/marks/Sphere.svelte.d.ts +51 -0
- package/dist/marks/Spike.svelte +15 -0
- package/dist/marks/Spike.svelte.d.ts +4 -0
- package/dist/marks/SymbolLegend.svelte +27 -12
- package/dist/marks/SymbolLegend.svelte.d.ts +8 -14
- package/dist/marks/Text.svelte +189 -0
- package/dist/marks/Text.svelte.d.ts +26 -0
- package/dist/marks/TickX.svelte +89 -0
- package/dist/marks/TickX.svelte.d.ts +22 -0
- package/dist/marks/TickY.svelte +90 -0
- package/dist/marks/TickY.svelte.d.ts +22 -0
- package/dist/marks/Vector.svelte +219 -0
- package/dist/marks/Vector.svelte.d.ts +31 -0
- package/dist/marks/helpers/BaseAxisX.svelte +210 -0
- package/dist/marks/helpers/BaseAxisX.svelte.d.ts +24 -0
- package/dist/marks/helpers/BaseAxisY.svelte +187 -0
- package/dist/marks/helpers/BaseAxisY.svelte.d.ts +23 -0
- package/dist/marks/helpers/CanvasLayer.svelte +38 -0
- package/dist/marks/helpers/CanvasLayer.svelte.d.ts +13 -0
- package/dist/marks/helpers/DotCanvas.svelte +184 -0
- package/dist/marks/helpers/DotCanvas.svelte.d.ts +11 -0
- package/dist/marks/helpers/GeoCanvas.svelte +165 -0
- package/dist/marks/helpers/GeoCanvas.svelte.d.ts +13 -0
- package/dist/marks/helpers/GroupMultiple.svelte +17 -0
- package/dist/marks/helpers/GroupMultiple.svelte.d.ts +9 -0
- package/dist/marks/helpers/Marker.svelte +93 -0
- package/dist/marks/helpers/Marker.svelte.d.ts +10 -0
- package/dist/marks/helpers/MarkerPath.svelte +141 -0
- package/dist/marks/helpers/MarkerPath.svelte.d.ts +44 -0
- package/dist/marks/helpers/Regression.svelte +174 -0
- package/dist/marks/helpers/Regression.svelte.d.ts +26 -0
- package/dist/marks/helpers/events.d.ts +8 -0
- package/dist/marks/helpers/events.js +74 -0
- package/dist/transforms/bin.d.ts +51 -0
- package/dist/transforms/bin.js +171 -0
- package/dist/transforms/bollinger.d.ts +21 -0
- package/dist/transforms/bollinger.js +53 -0
- package/dist/transforms/centroid.d.ts +9 -0
- package/dist/transforms/centroid.js +13 -0
- package/dist/transforms/facet.d.ts +1 -0
- package/dist/transforms/facet.js +1 -0
- package/dist/transforms/filter.d.ts +2 -0
- package/dist/transforms/filter.js +8 -0
- package/dist/transforms/group.d.ts +66 -0
- package/dist/transforms/group.js +109 -0
- package/dist/transforms/interval.d.ts +11 -0
- package/dist/transforms/interval.js +34 -0
- package/dist/transforms/jitter.d.ts +0 -0
- package/dist/transforms/jitter.js +1 -0
- package/dist/transforms/map.d.ts +10 -0
- package/dist/transforms/map.js +89 -0
- package/dist/transforms/normalize.d.ts +9 -0
- package/dist/transforms/normalize.js +86 -0
- package/dist/transforms/recordize.d.ts +14 -0
- package/dist/transforms/recordize.js +79 -0
- package/dist/transforms/rename.d.ts +14 -0
- package/dist/transforms/rename.js +42 -0
- package/dist/transforms/select.d.ts +35 -0
- package/dist/transforms/select.js +55 -0
- package/dist/transforms/shift.d.ts +13 -0
- package/dist/transforms/shift.js +45 -0
- package/dist/transforms/sort.d.ts +28 -0
- package/dist/transforms/sort.js +66 -0
- package/dist/transforms/stack.d.ts +10 -0
- package/dist/transforms/stack.js +110 -0
- package/dist/transforms/window.d.ts +22 -0
- package/dist/transforms/window.js +73 -0
- package/dist/types.d.ts +625 -188
- package/dist/ui/Checkbox.svelte +6 -0
- package/dist/ui/Checkbox.svelte.d.ts +13 -0
- package/dist/ui/RadioInput.svelte +27 -0
- package/dist/ui/RadioInput.svelte.d.ts +9 -0
- package/dist/ui/Select.svelte +27 -0
- package/dist/ui/Select.svelte.d.ts +9 -0
- package/dist/ui/Slider.svelte +47 -0
- package/dist/ui/Slider.svelte.d.ts +11 -0
- package/dist/ui/Spiral.svelte +46 -0
- package/dist/ui/Spiral.svelte.d.ts +15 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +4 -0
- package/package.json +81 -42
- package/LICENSE +0 -11
- package/dist/classes/Channel.svelte.js +0 -74
- package/dist/classes/Mark.svelte.js +0 -17
- package/dist/classes/Plot.svelte.js +0 -98
- package/dist/contants.d.ts +0 -3
- package/dist/contants.js +0 -40
- package/dist/helpers/GroupMultiple.svelte +0 -8
- package/dist/helpers/GroupMultiple.svelte.d.ts +0 -19
- package/dist/helpers/createScale.d.ts +0 -5
- package/dist/helpers/createScale.js +0 -57
- package/dist/helpers/resolveChannel.d.ts +0 -2
- package/dist/helpers/resolveChannel.js +0 -28
- package/dist/helpers/wrapArray.d.ts +0 -2
- package/dist/helpers/wrapArray.js +0 -4
- package/dist/marks/BaseMark.svelte +0 -22
- package/dist/marks/BaseMark.svelte.d.ts +0 -19
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type ReducerName } from '../helpers/reduce.js';
|
|
2
|
+
import type { DataRecord, DataRow, RawValue, TransformArg } from '../types.js';
|
|
3
|
+
type ReducerFunc = (group: DataRow[]) => RawValue;
|
|
4
|
+
type ReducerOption = ReducerName | ReducerFunc;
|
|
5
|
+
type GroupBaseOptions = {
|
|
6
|
+
domain?: [number, number];
|
|
7
|
+
thresholds?: NamedThresholdsGenerator | number | number[] | ThresholdCountGenerator;
|
|
8
|
+
interval?: number | string;
|
|
9
|
+
cumulative?: false | 1 | -1;
|
|
10
|
+
reverse?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* copy properties from the first element of each group
|
|
13
|
+
*/
|
|
14
|
+
copy?: string[];
|
|
15
|
+
};
|
|
16
|
+
type AdditionalOutputChannels = Partial<{
|
|
17
|
+
fill: ReducerOption;
|
|
18
|
+
stroke: ReducerOption;
|
|
19
|
+
r: ReducerOption;
|
|
20
|
+
opacity: ReducerOption;
|
|
21
|
+
fillOpacity: ReducerOption;
|
|
22
|
+
strokeOpacity: ReducerOption;
|
|
23
|
+
}>;
|
|
24
|
+
type GroupXOptions = GroupBaseOptions & AdditionalOutputChannels & Partial<{
|
|
25
|
+
y: ReducerOption;
|
|
26
|
+
y1: ReducerOption;
|
|
27
|
+
y2: ReducerOption;
|
|
28
|
+
xPropName: string;
|
|
29
|
+
}>;
|
|
30
|
+
type GroupYOptions = GroupBaseOptions & AdditionalOutputChannels & Partial<{
|
|
31
|
+
x: ReducerOption;
|
|
32
|
+
x1: ReducerOption;
|
|
33
|
+
x2: ReducerOption;
|
|
34
|
+
yPropName: string;
|
|
35
|
+
}>;
|
|
36
|
+
type GroupZOptions = GroupXOptions | GroupYOptions;
|
|
37
|
+
/**
|
|
38
|
+
* groups the dataset by x and y channel and optionally reduces the group items
|
|
39
|
+
* to output channels fill, stroke, r, opacity, fillOpacity, or strokeOpacity
|
|
40
|
+
*/
|
|
41
|
+
export declare function group({ data, ...channels }: TransformArg<T, DataRecord>, options?: GroupXOptions): {
|
|
42
|
+
data: DataRecord[];
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* groups the dataset by the x channel and optionally reduces the group items
|
|
46
|
+
* to output channels y, y1, y2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
|
|
47
|
+
*/
|
|
48
|
+
export declare function groupX(input: TransformArg<T, DataRecord>, options?: GroupXOptions): {
|
|
49
|
+
data: DataRecord[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* groups the dataset by the y channel and optionally reduces the group items
|
|
53
|
+
* to output channels x, x1, x2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
|
|
54
|
+
*/
|
|
55
|
+
export declare function groupY(input: TransformArg<T, DataRecord>, options?: GroupYOptions): {
|
|
56
|
+
data: DataRecord[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* groups the dataset by the z channel and optionally reduces the group items
|
|
60
|
+
* to output channels x, x1, x2, y, y1, y2, fill, stroke, r, opacity, fillOpacity,
|
|
61
|
+
* or strokeOpacity
|
|
62
|
+
*/
|
|
63
|
+
export declare function groupZ(input: TransformArg<T, DataRecord>, options?: GroupZOptions): {
|
|
64
|
+
data: DataRecord[];
|
|
65
|
+
};
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { groupFacetsAndZ } from '../helpers/group.js';
|
|
2
|
+
import { testFilter } from '../helpers/index.js';
|
|
3
|
+
import { reduceOutputs } from '../helpers/reduce.js';
|
|
4
|
+
import { resolveChannel } from '../helpers/resolve.js';
|
|
5
|
+
import { groups as d3Groups } from 'd3-array';
|
|
6
|
+
import { omit } from '../helpers';
|
|
7
|
+
import { maybeInterval } from '../helpers/autoTicks.js';
|
|
8
|
+
/**
|
|
9
|
+
* groups the dataset by x and y channel and optionally reduces the group items
|
|
10
|
+
* to output channels fill, stroke, r, opacity, fillOpacity, or strokeOpacity
|
|
11
|
+
*/
|
|
12
|
+
export function group({ data, ...channels }, options = {}) {
|
|
13
|
+
if (channels.x == null || channels.y == null)
|
|
14
|
+
throw new Error('you must provide an x and y channel to group on');
|
|
15
|
+
// group by x or y
|
|
16
|
+
const groups = d3Groups(data.filter((d) => testFilter(d, channels)), (d) => resolveChannel('x', d, channels), (d) => resolveChannel('y', d, channels));
|
|
17
|
+
const newData = [];
|
|
18
|
+
const xChannel = typeof channels.x === 'string' ? channels.x : '__x';
|
|
19
|
+
const yChannel = typeof channels.y === 'string' ? channels.y : '__y';
|
|
20
|
+
let newChannels = omit({ ...channels, x: xChannel, y: yChannel }, 'filter');
|
|
21
|
+
const outputs = ['fill', 'stroke', 'r', 'opacity', 'fillOpacity', 'strokeOpacity'];
|
|
22
|
+
groups.forEach(([xGroupKey, xGroups]) => {
|
|
23
|
+
xGroups.forEach(([yGroupKey, items]) => {
|
|
24
|
+
const baseRecord = { [xChannel]: xGroupKey, [yChannel]: yGroupKey }; // dim === 'z' ? {} : { [`__${dim}`]: groupKey };
|
|
25
|
+
// copy properties from first item of each group
|
|
26
|
+
options.copy?.forEach((prop) => {
|
|
27
|
+
baseRecord[prop] = items[0][prop];
|
|
28
|
+
});
|
|
29
|
+
const newGroupChannels = groupFacetsAndZ(items, channels, (items, itemGroupProps) => {
|
|
30
|
+
const item = { ...baseRecord, ...itemGroupProps };
|
|
31
|
+
reduceOutputs(item, items, options, outputs, channels, newChannels);
|
|
32
|
+
newData.push(item);
|
|
33
|
+
});
|
|
34
|
+
newChannels = { ...newChannels, ...newGroupChannels };
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
return { data: newData, ...newChannels };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* groups the dataset by the x channel and optionally reduces the group items
|
|
41
|
+
* to output channels y, y1, y2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
|
|
42
|
+
*/
|
|
43
|
+
export function groupX(input, options = {}) {
|
|
44
|
+
return groupXYZ('x', input, options);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* groups the dataset by the y channel and optionally reduces the group items
|
|
48
|
+
* to output channels x, x1, x2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
|
|
49
|
+
*/
|
|
50
|
+
export function groupY(input, options = {}) {
|
|
51
|
+
return groupXYZ('y', input, options);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* groups the dataset by the z channel and optionally reduces the group items
|
|
55
|
+
* to output channels x, x1, x2, y, y1, y2, fill, stroke, r, opacity, fillOpacity,
|
|
56
|
+
* or strokeOpacity
|
|
57
|
+
*/
|
|
58
|
+
export function groupZ(input, options = {}) {
|
|
59
|
+
return groupXYZ('z', input, options);
|
|
60
|
+
}
|
|
61
|
+
function groupXYZ(dim, { data, ...channels }, options = {}) {
|
|
62
|
+
if ((dim === 'z' ? channels.z || channels.fill || channels.stroke : channels[dim]) == null)
|
|
63
|
+
throw new Error('you must provide a channel to group on ' + dim);
|
|
64
|
+
const propName = options[`${dim}PropName`] != null
|
|
65
|
+
? options[`${dim}PropName`]
|
|
66
|
+
: typeof channels[dim] === 'string' && !options.interval
|
|
67
|
+
? channels[dim]
|
|
68
|
+
: `__${dim}`;
|
|
69
|
+
const interval = options.interval ? maybeInterval(options.interval) : null;
|
|
70
|
+
// group by x or y
|
|
71
|
+
const groups = dim === 'z'
|
|
72
|
+
? [[null, data]]
|
|
73
|
+
: d3Groups(data.filter((d) => testFilter(d, channels)), (d) => {
|
|
74
|
+
const v = resolveChannel(dim, d, channels);
|
|
75
|
+
return interval ? interval.round(v) : v;
|
|
76
|
+
});
|
|
77
|
+
const newData = [];
|
|
78
|
+
let newChannels = omit({ ...channels }, 'filter');
|
|
79
|
+
if (dim !== 'z')
|
|
80
|
+
newChannels[dim] = propName;
|
|
81
|
+
const outputs = [
|
|
82
|
+
...(dim === 'x'
|
|
83
|
+
? ['y', 'y1', 'y2']
|
|
84
|
+
: dim === 'y'
|
|
85
|
+
? ['x', 'x1', 'x2']
|
|
86
|
+
: ['x', 'x1', 'x2', 'y', 'y1', 'y2']),
|
|
87
|
+
'fill',
|
|
88
|
+
'stroke',
|
|
89
|
+
'r',
|
|
90
|
+
'opacity',
|
|
91
|
+
'fillOpacity',
|
|
92
|
+
'strokeOpacity'
|
|
93
|
+
];
|
|
94
|
+
groups.forEach(([groupKey, items]) => {
|
|
95
|
+
const baseRecord = dim === 'z' ? {} : { [propName]: groupKey };
|
|
96
|
+
const newGroupChannels = groupFacetsAndZ(items, channels, (items, itemGroupProps) => {
|
|
97
|
+
const copiedProps = {};
|
|
98
|
+
// copy properties from first item of each group
|
|
99
|
+
options.copy?.forEach((prop) => {
|
|
100
|
+
copiedProps[prop] = items[0][prop];
|
|
101
|
+
});
|
|
102
|
+
const item = { ...baseRecord, ...copiedProps, ...itemGroupProps };
|
|
103
|
+
reduceOutputs(item, items, options, outputs, channels, newChannels);
|
|
104
|
+
newData.push(item);
|
|
105
|
+
});
|
|
106
|
+
newChannels = { ...newChannels, ...newGroupChannels };
|
|
107
|
+
});
|
|
108
|
+
return { data: newData, ...newChannels };
|
|
109
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PlotState, TransformArg } from '../types.js';
|
|
2
|
+
export declare function intervalX<T>(args: TransformArg<T>, { plot }: {
|
|
3
|
+
plot: PlotState;
|
|
4
|
+
}): {
|
|
5
|
+
data: T[];
|
|
6
|
+
};
|
|
7
|
+
export declare function intervalY<T>(args: TransformArg<T>, { plot }: {
|
|
8
|
+
plot: PlotState;
|
|
9
|
+
}): {
|
|
10
|
+
data: T[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { maybeInterval } from '../helpers/autoTicks.js';
|
|
2
|
+
import { resolveChannel } from '../helpers/resolve.js';
|
|
3
|
+
export function intervalX(args, { plot }) {
|
|
4
|
+
return interval('x', plot, args);
|
|
5
|
+
}
|
|
6
|
+
export function intervalY(args, { plot }) {
|
|
7
|
+
return interval('y', plot, args);
|
|
8
|
+
}
|
|
9
|
+
function interval(dim, plot, { data, ...options }) {
|
|
10
|
+
if (options.interval &&
|
|
11
|
+
options[dim] &&
|
|
12
|
+
options[`${dim}1`] == null &&
|
|
13
|
+
options[`${dim}2`] == null) {
|
|
14
|
+
// derive x1 and x2 from x+interval
|
|
15
|
+
const interval = maybeInterval(options.interval, plot.scales[dim].type);
|
|
16
|
+
const newData = data.map((row) => {
|
|
17
|
+
const val = resolveChannel(dim, row, options);
|
|
18
|
+
return {
|
|
19
|
+
...row,
|
|
20
|
+
[`__${dim}1`]: interval.floor(val),
|
|
21
|
+
[`__${dim}2`]: interval.offset(interval.floor(val))
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
data: newData,
|
|
26
|
+
// set default inset
|
|
27
|
+
[`inset${dim === 'x' ? 'Right' : 'Bottom'}`]: 1,
|
|
28
|
+
...options,
|
|
29
|
+
[`${dim}1`]: `__${dim}1`,
|
|
30
|
+
[`${dim}2`]: `__${dim}2`
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return { data, ...options };
|
|
34
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TransformArg, MapOptions, MapMethod, DataRecord } from '../types.js';
|
|
2
|
+
export declare function map<T>(args: TransformArg<T>, options: MapOptions): {
|
|
3
|
+
data: DataRecord[];
|
|
4
|
+
};
|
|
5
|
+
export declare function mapX<T>(args: TransformArg<T>, mapper: MapMethod): {
|
|
6
|
+
data: DataRecord[];
|
|
7
|
+
};
|
|
8
|
+
export declare function mapY<T>(args: TransformArg<T>, mapper: MapMethod): {
|
|
9
|
+
data: DataRecord[];
|
|
10
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { identity } from '../helpers/index.js';
|
|
2
|
+
import { count, rank } from 'd3-array';
|
|
3
|
+
import { groupFacetsAndZ } from '../helpers/group.js';
|
|
4
|
+
import { resolveChannel } from '../helpers/resolve.js';
|
|
5
|
+
export function map(args, options) {
|
|
6
|
+
const { data, ...channels } = args;
|
|
7
|
+
const newChannels = {};
|
|
8
|
+
const newData = [];
|
|
9
|
+
groupFacetsAndZ(data, channels, (groupedData) => {
|
|
10
|
+
for (const [channel, map] of Object.entries(options)) {
|
|
11
|
+
const mapper = maybeMap(map);
|
|
12
|
+
const values = groupedData.map((d) => resolveChannel(channel, d, channels));
|
|
13
|
+
const indices = groupedData.map((d, i) => i);
|
|
14
|
+
const mappedValues = new Array(values.length);
|
|
15
|
+
mapper.mapIndex(indices, values, mappedValues);
|
|
16
|
+
newChannels[channel] = `__${channel}`;
|
|
17
|
+
for (let i = 0; i < values.length; ++i) {
|
|
18
|
+
const datum = { ...groupedData[i], [`__${channel}`]: mappedValues[i] };
|
|
19
|
+
newData.push(datum);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return { data: newData, ...channels, ...newChannels };
|
|
24
|
+
}
|
|
25
|
+
export function mapX(args, mapper) {
|
|
26
|
+
let { x, x1, x2 } = args;
|
|
27
|
+
if (x === undefined && x1 === undefined && x2 === undefined)
|
|
28
|
+
args = { ...args, x: identity };
|
|
29
|
+
const outputs = {};
|
|
30
|
+
if (x != null)
|
|
31
|
+
outputs.x = mapper;
|
|
32
|
+
if (x1 != null)
|
|
33
|
+
outputs.x1 = mapper;
|
|
34
|
+
if (x2 != null)
|
|
35
|
+
outputs.x2 = mapper;
|
|
36
|
+
return map(args, outputs);
|
|
37
|
+
}
|
|
38
|
+
export function mapY(args, mapper) {
|
|
39
|
+
let { y, y1, y2 } = args;
|
|
40
|
+
if (y === undefined && y1 === undefined && y2 === undefined)
|
|
41
|
+
args = { ...args, y: identity };
|
|
42
|
+
const outputs = {};
|
|
43
|
+
if (y != null)
|
|
44
|
+
outputs.y = mapper;
|
|
45
|
+
if (y1 != null)
|
|
46
|
+
outputs.y1 = mapper;
|
|
47
|
+
if (y2 != null)
|
|
48
|
+
outputs.y2 = mapper;
|
|
49
|
+
return map(args, outputs);
|
|
50
|
+
}
|
|
51
|
+
function maybeMap(map) {
|
|
52
|
+
if (map == null)
|
|
53
|
+
throw new Error('missing map');
|
|
54
|
+
if (typeof map === 'object' && typeof map.mapIndex === 'function')
|
|
55
|
+
return map;
|
|
56
|
+
if (typeof map === 'function')
|
|
57
|
+
return mapFunction(map);
|
|
58
|
+
switch (`${map}`.toLowerCase()) {
|
|
59
|
+
case 'cumsum':
|
|
60
|
+
return mapCumsum;
|
|
61
|
+
case 'rank':
|
|
62
|
+
return mapFunction((I, V) => rank(I, (i) => V[i]));
|
|
63
|
+
case 'quantile':
|
|
64
|
+
return mapFunction((I, V) => rankQuantile(I, (i) => V[i]));
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`invalid map: ${map}`);
|
|
67
|
+
}
|
|
68
|
+
function rankQuantile(I, f) {
|
|
69
|
+
const n = count(I, f) - 1;
|
|
70
|
+
return rank(I, f).map((r) => r / n);
|
|
71
|
+
}
|
|
72
|
+
function mapFunction(f) {
|
|
73
|
+
return {
|
|
74
|
+
mapIndex(I, S, T) {
|
|
75
|
+
const M = f(I, S);
|
|
76
|
+
if (M.length !== I.length)
|
|
77
|
+
throw new Error('map function returned a mismatched length');
|
|
78
|
+
for (let i = 0, n = I.length; i < n; ++i)
|
|
79
|
+
T[I[i]] = M[i];
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const mapCumsum = {
|
|
84
|
+
mapIndex(I, S, T) {
|
|
85
|
+
let sum = 0;
|
|
86
|
+
for (const i of I)
|
|
87
|
+
T[i] = sum += S[i];
|
|
88
|
+
}
|
|
89
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TransformArg, MapIndexObject } from '../types.js';
|
|
2
|
+
type NormalizeBasis = 'deviation' | 'first' | 'last' | 'min' | 'max' | 'mean' | 'median' | 'sum' | 'extent' | MapIndexObject;
|
|
3
|
+
export declare function normalizeX<T>(args: TransformArg<T>, basis: NormalizeBasis): {
|
|
4
|
+
data: import("../types.js").DataRecord[];
|
|
5
|
+
};
|
|
6
|
+
export declare function normalizeY<T>(args: TransformArg<T>, basis: NormalizeBasis): {
|
|
7
|
+
data: import("../types.js").DataRecord[];
|
|
8
|
+
};
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { mapX, mapY } from './map.js';
|
|
2
|
+
import { min, max, mean, median, sum, deviation, extent } from 'd3-array';
|
|
3
|
+
export function normalizeX(args, basis) {
|
|
4
|
+
return mapX(args, normalize(basis));
|
|
5
|
+
}
|
|
6
|
+
export function normalizeY(args, basis) {
|
|
7
|
+
return mapY(args, normalize(basis));
|
|
8
|
+
}
|
|
9
|
+
function normalize(basis) {
|
|
10
|
+
if (basis === undefined)
|
|
11
|
+
return normalizeFirst;
|
|
12
|
+
if (typeof basis === 'function')
|
|
13
|
+
return normalizeBasis(basis);
|
|
14
|
+
// if (/^p\d{2}$/i.test(basis)) return normalizeAccessor(percentile(basis));
|
|
15
|
+
switch (`${basis}`.toLowerCase()) {
|
|
16
|
+
case 'deviation':
|
|
17
|
+
return normalizeDeviation;
|
|
18
|
+
case 'first':
|
|
19
|
+
return normalizeFirst;
|
|
20
|
+
case 'last':
|
|
21
|
+
return normalizeLast;
|
|
22
|
+
case 'max':
|
|
23
|
+
return normalizeMax;
|
|
24
|
+
case 'mean':
|
|
25
|
+
return normalizeMean;
|
|
26
|
+
case 'median':
|
|
27
|
+
return normalizeMedian;
|
|
28
|
+
case 'min':
|
|
29
|
+
return normalizeMin;
|
|
30
|
+
case 'sum':
|
|
31
|
+
return normalizeSum;
|
|
32
|
+
case 'extent':
|
|
33
|
+
return normalizeExtent;
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`invalid basis: ${basis}`);
|
|
36
|
+
}
|
|
37
|
+
function normalizeBasis(basis) {
|
|
38
|
+
return {
|
|
39
|
+
mapIndex(I, S, T) {
|
|
40
|
+
const b = +basis(I, S);
|
|
41
|
+
for (const i of I) {
|
|
42
|
+
T[i] = S[i] === null ? NaN : S[i] / b;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function normalizeAccessor(f) {
|
|
48
|
+
return normalizeBasis((I, S) => f(I, (i) => S[i]));
|
|
49
|
+
}
|
|
50
|
+
const normalizeExtent = {
|
|
51
|
+
mapIndex(I, S, T) {
|
|
52
|
+
const [s1, s2] = extent(I, (i) => S[i]);
|
|
53
|
+
const d = s2 - s1;
|
|
54
|
+
for (const i of I) {
|
|
55
|
+
T[i] = S[i] === null ? NaN : (S[i] - s1) / d;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const normalizeFirst = normalizeBasis((I, S) => {
|
|
60
|
+
for (let i = 0; i < I.length; ++i) {
|
|
61
|
+
const s = S[I[i]];
|
|
62
|
+
if (s != null && isFinite(s))
|
|
63
|
+
return s;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const normalizeLast = normalizeBasis((I, S) => {
|
|
67
|
+
for (let i = I.length - 1; i >= 0; --i) {
|
|
68
|
+
const s = S[I[i]];
|
|
69
|
+
if (s != null && isFinite(s))
|
|
70
|
+
return s;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const normalizeDeviation = {
|
|
74
|
+
mapIndex(I, S, T) {
|
|
75
|
+
const m = mean(I, (i) => S[i]);
|
|
76
|
+
const d = deviation(I, (i) => S[i]);
|
|
77
|
+
for (const i of I) {
|
|
78
|
+
T[i] = S[i] === null ? NaN : d ? (S[i] - m) / d : 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const normalizeMax = normalizeAccessor(max);
|
|
83
|
+
const normalizeMean = normalizeAccessor(mean);
|
|
84
|
+
const normalizeMedian = normalizeAccessor(median);
|
|
85
|
+
const normalizeMin = normalizeAccessor(min);
|
|
86
|
+
const normalizeSum = normalizeAccessor(sum);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TransformArgsRow, TransformArgsRecord } from '../types.js';
|
|
2
|
+
export declare const RAW_VALUE: unique symbol;
|
|
3
|
+
export declare function recordizeX({ data, ...channels }: TransformArgsRow, { withIndex }?: {
|
|
4
|
+
withIndex: boolean;
|
|
5
|
+
}): TransformArgsRecord;
|
|
6
|
+
export declare function recordizeY({ data, ...channels }: TransformArgsRow, { withIndex }?: {
|
|
7
|
+
withIndex: boolean;
|
|
8
|
+
}): TransformArgsRecord;
|
|
9
|
+
/**
|
|
10
|
+
* This transform is used to allow users to pass an [[x0, y0], [x1, y1], ...] array
|
|
11
|
+
* as dataset to marks that support it. It transforms the arrays into records, so
|
|
12
|
+
* the rest of our code doesn't have to deal with this case anymore.
|
|
13
|
+
*/
|
|
14
|
+
export declare function recordizeXY({ data, ...channels }: TransformArgsRow): TransformArgsRecord;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import isDataRecord from '../helpers/isDataRecord.js';
|
|
2
|
+
export const RAW_VALUE = Symbol();
|
|
3
|
+
/*
|
|
4
|
+
* This transform takes an array of raw values as input and returns data records
|
|
5
|
+
* in which the values are interpreted as x channel and their index as y
|
|
6
|
+
*/
|
|
7
|
+
export function recordizeX({ data, ...channels }, { withIndex } = { withIndex: true }) {
|
|
8
|
+
const dataIsRawValueArray = !isDataRecord(data[0]) && !Array.isArray(data[0]) && channels.x == null;
|
|
9
|
+
if (dataIsRawValueArray) {
|
|
10
|
+
return {
|
|
11
|
+
data: data.map((value, index) => ({
|
|
12
|
+
__value: value,
|
|
13
|
+
...(withIndex ? { __index: index } : {}),
|
|
14
|
+
[RAW_VALUE]: value,
|
|
15
|
+
// TODO: remove ___orig___ references
|
|
16
|
+
___orig___: value
|
|
17
|
+
})),
|
|
18
|
+
...channels,
|
|
19
|
+
x: '__value',
|
|
20
|
+
...(withIndex ? { y: '__index' } : {})
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return { data: data, ...channels };
|
|
24
|
+
}
|
|
25
|
+
/*
|
|
26
|
+
* This transform takes an array of raw values as input and returns data records
|
|
27
|
+
* in which the values are interpreted as y channel and their index as yx
|
|
28
|
+
*/
|
|
29
|
+
export function recordizeY({ data, ...channels }, { withIndex } = { withIndex: true }) {
|
|
30
|
+
if (!data)
|
|
31
|
+
return { data, ...channels };
|
|
32
|
+
const dataIsRawValueArray = !isDataRecord(data[0]) && !Array.isArray(data[0]) && channels.y == null;
|
|
33
|
+
if (dataIsRawValueArray) {
|
|
34
|
+
return {
|
|
35
|
+
data: Array.from(data).map((value, index) => ({
|
|
36
|
+
__value: value,
|
|
37
|
+
...(withIndex ? { __index: index } : {}),
|
|
38
|
+
[RAW_VALUE]: value,
|
|
39
|
+
___orig___: value
|
|
40
|
+
})),
|
|
41
|
+
...channels,
|
|
42
|
+
...(withIndex ? { x: '__index' } : {}),
|
|
43
|
+
y: '__value'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
data: Array.from(data).map((d, index) => ({
|
|
48
|
+
...d,
|
|
49
|
+
...(withIndex ? { __index: index } : {})
|
|
50
|
+
})),
|
|
51
|
+
x: '__index',
|
|
52
|
+
...channels
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* This transform is used to allow users to pass an [[x0, y0], [x1, y1], ...] array
|
|
57
|
+
* as dataset to marks that support it. It transforms the arrays into records, so
|
|
58
|
+
* the rest of our code doesn't have to deal with this case anymore.
|
|
59
|
+
*/
|
|
60
|
+
export function recordizeXY({ data, ...channels }) {
|
|
61
|
+
if (!data)
|
|
62
|
+
return { data, ...channels };
|
|
63
|
+
if (!isDataRecord(data[0]) &&
|
|
64
|
+
Array.isArray(data[0]) &&
|
|
65
|
+
channels.x === undefined &&
|
|
66
|
+
channels.y === undefined) {
|
|
67
|
+
return {
|
|
68
|
+
data: data.map(([x, y, ...rest]) => ({
|
|
69
|
+
___orig___: [x, y, ...rest],
|
|
70
|
+
__x: x,
|
|
71
|
+
__y: y
|
|
72
|
+
})),
|
|
73
|
+
...channels,
|
|
74
|
+
x: '__x',
|
|
75
|
+
y: '__y'
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return { data, ...channels };
|
|
79
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DataRecord } from '../types.js';
|
|
2
|
+
import type { ScaledChannelName, TransformArg } from '../types.js';
|
|
3
|
+
type RenameChannelsOptions = Partial<Record<ScaledChannelName, ScaledChannelName>>;
|
|
4
|
+
type ReplaceChannelsOptions = Partial<Record<ScaledChannelName, ScaledChannelName[]>>;
|
|
5
|
+
/**
|
|
6
|
+
* renames a channel without modifying the data
|
|
7
|
+
*/
|
|
8
|
+
export declare function renameChannels<T>({ data, ...channels }: TransformArg<T, DataRecord>, options: RenameChannelsOptions): TransformArg<T, DataRecord>;
|
|
9
|
+
/**
|
|
10
|
+
* renames a channel and copy the data
|
|
11
|
+
*/
|
|
12
|
+
export declare function renameChannelsAndData<T>({ data, ...channels }: TransformArg<T, DataRecord>, options: RenameChannelsOptions): TransformArg<T, DataRecord>;
|
|
13
|
+
export declare function replaceChannels<T>({ data, ...channels }: TransformArg<T, DataRecord>, options: ReplaceChannelsOptions): TransformArg<T, DataRecord>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* renames a channel without modifying the data
|
|
3
|
+
*/
|
|
4
|
+
export function renameChannels({ data, ...channels }, options) {
|
|
5
|
+
const newChannels = channels;
|
|
6
|
+
for (const [from, to] of Object.entries(options)) {
|
|
7
|
+
if (newChannels[from] !== undefined) {
|
|
8
|
+
newChannels[to] = newChannels[from];
|
|
9
|
+
delete newChannels[from];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return { data, ...newChannels };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* renames a channel and copy the data
|
|
16
|
+
*/
|
|
17
|
+
export function renameChannelsAndData({ data, ...channels }, options) {
|
|
18
|
+
const newData = [];
|
|
19
|
+
for (const datum of data) {
|
|
20
|
+
const newDatum = { ...datum };
|
|
21
|
+
for (const [from, to] of Object.entries(options)) {
|
|
22
|
+
if (channels[from] !== undefined) {
|
|
23
|
+
newDatum[to] = newDatum[from];
|
|
24
|
+
delete newDatum[from];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
newData.push(newDatum);
|
|
28
|
+
}
|
|
29
|
+
return renameChannels({ data: newData, ...channels }, options);
|
|
30
|
+
}
|
|
31
|
+
export function replaceChannels({ data, ...channels }, options) {
|
|
32
|
+
const newChannels = { ...channels };
|
|
33
|
+
for (const [from, to] of Object.entries(options)) {
|
|
34
|
+
if (newChannels[from] !== undefined) {
|
|
35
|
+
for (const t of to) {
|
|
36
|
+
newChannels[t] = newChannels[from];
|
|
37
|
+
}
|
|
38
|
+
delete newChannels[from];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { data, ...newChannels };
|
|
42
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ChannelName, DataRecord, TransformArg } from '../types.js';
|
|
2
|
+
type AtLeastOne<T, U = {
|
|
3
|
+
[K in keyof T]: Pick<T, K>;
|
|
4
|
+
}> = Partial<T> & U[keyof U];
|
|
5
|
+
type SelectOptions = 'first' | 'last' | AtLeastOne<{
|
|
6
|
+
[k in ChannelName]: 'min' | 'max';
|
|
7
|
+
}>;
|
|
8
|
+
export declare function select({ data, ...channels }: TransformArg<DataRecord>, options: SelectOptions): {
|
|
9
|
+
data: DataRecord[];
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Keeps only the first item of each group
|
|
13
|
+
*/
|
|
14
|
+
export declare function selectFirst(args: TransformArg<DataRecord>): {
|
|
15
|
+
data: DataRecord[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Keeps only the last item of each group
|
|
19
|
+
*/
|
|
20
|
+
export declare function selectLast(args: TransformArg<DataRecord>): {
|
|
21
|
+
data: DataRecord[];
|
|
22
|
+
};
|
|
23
|
+
export declare function selectMinX(args: TransformArg<DataRecord>): {
|
|
24
|
+
data: DataRecord[];
|
|
25
|
+
};
|
|
26
|
+
export declare function selectMaxX(args: TransformArg<DataRecord>): {
|
|
27
|
+
data: DataRecord[];
|
|
28
|
+
};
|
|
29
|
+
export declare function selectMinY(args: TransformArg<DataRecord>): {
|
|
30
|
+
data: DataRecord[];
|
|
31
|
+
};
|
|
32
|
+
export declare function selectMaxY(args: TransformArg<DataRecord>): {
|
|
33
|
+
data: DataRecord[];
|
|
34
|
+
};
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { groupFacetsAndZ } from '../helpers/group.js';
|
|
2
|
+
import { resolveChannel } from '../helpers/resolve.js';
|
|
3
|
+
// let o: SelectOptions = { x: 'min'};
|
|
4
|
+
export function select({ data, ...channels }, options) {
|
|
5
|
+
const newData = [];
|
|
6
|
+
groupFacetsAndZ(data, channels, (items) => {
|
|
7
|
+
if (typeof options === 'string') {
|
|
8
|
+
if (options !== 'first' && options !== 'last')
|
|
9
|
+
throw new Error('unknown sort option: ' + options);
|
|
10
|
+
newData.push(options === 'first' ? items[0] : items.at(-1));
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const sortOptions = Object.entries(options);
|
|
14
|
+
if (!sortOptions.length)
|
|
15
|
+
throw new Error('must provide the channel to sort by');
|
|
16
|
+
if (sortOptions.length > 1)
|
|
17
|
+
throw new Error('cannot sort by more than one channel');
|
|
18
|
+
if (sortOptions[0][1] !== 'min' && sortOptions[0][1] !== 'max')
|
|
19
|
+
throw new Error('unknown sort option: ' + sortOptions[0][1]);
|
|
20
|
+
const selected = items
|
|
21
|
+
.map((item) => ({
|
|
22
|
+
...item,
|
|
23
|
+
__sortby: resolveChannel(sortOptions[0][0], item, channels)
|
|
24
|
+
}))
|
|
25
|
+
.sort((a, b) => (a.__sortby > b.__sortby ? 1 : a.__sortby < b.__sortby ? -1 : 0))
|
|
26
|
+
.at(sortOptions[0][1] === 'min' ? 0 : -1);
|
|
27
|
+
newData.push(selected);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return { data: newData, ...channels };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Keeps only the first item of each group
|
|
34
|
+
*/
|
|
35
|
+
export function selectFirst(args) {
|
|
36
|
+
return select(args, 'first');
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Keeps only the last item of each group
|
|
40
|
+
*/
|
|
41
|
+
export function selectLast(args) {
|
|
42
|
+
return select(args, 'last');
|
|
43
|
+
}
|
|
44
|
+
export function selectMinX(args) {
|
|
45
|
+
return select(args, { x: 'min' });
|
|
46
|
+
}
|
|
47
|
+
export function selectMaxX(args) {
|
|
48
|
+
return select(args, { x: 'max' });
|
|
49
|
+
}
|
|
50
|
+
export function selectMinY(args) {
|
|
51
|
+
return select(args, { y: 'min' });
|
|
52
|
+
}
|
|
53
|
+
export function selectMaxY(args) {
|
|
54
|
+
return select(args, { y: 'max' });
|
|
55
|
+
}
|