svelteplot 0.0.1-alpha.9 → 0.1.3-next.12
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 -35
- 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 +311 -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 +93 -0
- package/dist/marks/BarX.svelte.d.ts +4 -0
- package/dist/marks/BarY.svelte +103 -0
- package/dist/marks/BarY.svelte.d.ts +25 -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 +1 -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 +15 -0
- package/dist/transforms/recordize.js +78 -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 +24 -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,141 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Helper component for paths with markers and optional text along the path.
|
|
4
|
+
-->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import Marker, { type MarkerShape } from './Marker.svelte';
|
|
7
|
+
import { isSnippet, randomId } from '../../helpers/index.js';
|
|
8
|
+
import { resolveProp } from '../../helpers/resolve.js';
|
|
9
|
+
import type {
|
|
10
|
+
BaseMarkProps,
|
|
11
|
+
ConstantAccessor,
|
|
12
|
+
DataRecord,
|
|
13
|
+
Mark,
|
|
14
|
+
PlotContext,
|
|
15
|
+
PlotScales
|
|
16
|
+
} from '../../types.js';
|
|
17
|
+
import { addEventHandlers } from './events.js';
|
|
18
|
+
import { getContext } from 'svelte';
|
|
19
|
+
|
|
20
|
+
type MarkerPathProps = BaseMarkProps & {
|
|
21
|
+
/**
|
|
22
|
+
* the datum associated with this path, usually the first
|
|
23
|
+
* element of the data array group
|
|
24
|
+
*/
|
|
25
|
+
datum: DataRecord;
|
|
26
|
+
/**
|
|
27
|
+
* the marker shape to use at the start of the path, defaults to
|
|
28
|
+
* cirlce
|
|
29
|
+
*/
|
|
30
|
+
markerStart?: boolean | MarkerShape;
|
|
31
|
+
/**
|
|
32
|
+
* the marker shape to use at the middle of the path, defaults to circle
|
|
33
|
+
*/
|
|
34
|
+
markerMid?: boolean | MarkerShape;
|
|
35
|
+
/**
|
|
36
|
+
* the marker shape to use at the end of the path, defaults to circle
|
|
37
|
+
*/
|
|
38
|
+
markerEnd?: boolean | MarkerShape;
|
|
39
|
+
/**
|
|
40
|
+
* shorthand for setting all markers
|
|
41
|
+
*/
|
|
42
|
+
marker?: boolean | MarkerShape;
|
|
43
|
+
/**
|
|
44
|
+
* path string
|
|
45
|
+
*/
|
|
46
|
+
d: string;
|
|
47
|
+
style: string;
|
|
48
|
+
startOffset: string;
|
|
49
|
+
textStyle: string;
|
|
50
|
+
textStyleClass?: string | null;
|
|
51
|
+
text: string;
|
|
52
|
+
transform: string;
|
|
53
|
+
color: string;
|
|
54
|
+
strokeWidth: ConstantAccessor<number>;
|
|
55
|
+
mark: Mark<BaseMarkProps>;
|
|
56
|
+
scales: PlotScales;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
let {
|
|
60
|
+
datum,
|
|
61
|
+
markerStart,
|
|
62
|
+
markerMid,
|
|
63
|
+
markerEnd,
|
|
64
|
+
marker,
|
|
65
|
+
d,
|
|
66
|
+
dInv,
|
|
67
|
+
style,
|
|
68
|
+
class: className = null,
|
|
69
|
+
textStyleClass = null,
|
|
70
|
+
startOffset,
|
|
71
|
+
textStyle,
|
|
72
|
+
text,
|
|
73
|
+
transform,
|
|
74
|
+
color,
|
|
75
|
+
strokeWidth,
|
|
76
|
+
mark
|
|
77
|
+
}: MarkerPathProps = $props();
|
|
78
|
+
|
|
79
|
+
const id = randomId();
|
|
80
|
+
|
|
81
|
+
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
82
|
+
|
|
83
|
+
const points = $derived(text && d != null ? d.split(/[LMC]/).slice(1) : []);
|
|
84
|
+
const hasPath = $derived(points.length > 0);
|
|
85
|
+
const firstPt = $derived(text && hasPath ? points.at(0).split(',').map(Number) : []);
|
|
86
|
+
const lastPt = $derived(text && hasPath ? points.at(-1).split(',').map(Number) : []);
|
|
87
|
+
const leftToRight = $derived(text && hasPath ? firstPt[0] < lastPt.at(-2) : true);
|
|
88
|
+
|
|
89
|
+
// use reversed path if the path is not left to right
|
|
90
|
+
const textPath = $derived(!text || leftToRight ? d : dInv);
|
|
91
|
+
const strokeWidth_ = $derived(resolveProp(strokeWidth, datum, 1.4));
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<g
|
|
95
|
+
{transform}
|
|
96
|
+
class={className}
|
|
97
|
+
stroke-width={strokeWidth_}
|
|
98
|
+
use:addEventHandlers={{ getPlotState, options: mark.options, datum }}>
|
|
99
|
+
{#each Object.entries( { start: markerStart, mid: markerMid, end: markerEnd, all: marker } ) as [key, marker]}
|
|
100
|
+
{@const markerId = `marker-${key === 'all' ? '' : `${key}-`}${id}`}
|
|
101
|
+
{#if isSnippet(marker)}
|
|
102
|
+
{@render marker(markerId, color)}
|
|
103
|
+
{:else if marker}
|
|
104
|
+
<Marker
|
|
105
|
+
id={markerId}
|
|
106
|
+
shape={marker === true ? 'circle' : resolveProp(marker, datum)}
|
|
107
|
+
{color} />
|
|
108
|
+
{/if}
|
|
109
|
+
{/each}
|
|
110
|
+
{#if mark.options.onmouseenter || mark.options.onclick}
|
|
111
|
+
<!-- add invisible path in bg for easier mouse access -->
|
|
112
|
+
<path
|
|
113
|
+
{d}
|
|
114
|
+
style="fill:none;stroke-width: {(strokeWidth || 1) +
|
|
115
|
+
10}; stroke: transparent; stroke-opacity:0" />
|
|
116
|
+
{/if}
|
|
117
|
+
<path
|
|
118
|
+
marker-start={markerStart || marker
|
|
119
|
+
? `url(#marker-${markerStart ? 'start-' : ''}${id})`
|
|
120
|
+
: null}
|
|
121
|
+
marker-mid={markerMid || marker ? `url(#marker-${markerMid ? 'mid-' : ''}${id})` : null}
|
|
122
|
+
marker-end={markerEnd || marker ? `url(#marker-${markerEnd ? 'end-' : ''}${id})` : null}
|
|
123
|
+
{d}
|
|
124
|
+
{style}
|
|
125
|
+
use:addEventHandlers={{ getPlotState, options: mark.options, datum }} />
|
|
126
|
+
{#if text}
|
|
127
|
+
<!-- since textPath.side is not yet supported, we have to use an invisible
|
|
128
|
+
path in order to keep the text from turning upside down -->
|
|
129
|
+
<path d={textPath} {id} stroke="none" fill="none" />
|
|
130
|
+
<text dy="-3" style={textStyle} class={textStyleClass}>
|
|
131
|
+
<textPath {startOffset} href="#{id}">{text}</textPath>
|
|
132
|
+
</text>
|
|
133
|
+
{/if}
|
|
134
|
+
</g>
|
|
135
|
+
|
|
136
|
+
<style>
|
|
137
|
+
text {
|
|
138
|
+
font-size: 12px;
|
|
139
|
+
paint-order: stroke fill;
|
|
140
|
+
}
|
|
141
|
+
</style>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type MarkerShape } from './Marker.svelte';
|
|
2
|
+
import type { BaseMarkProps, ConstantAccessor, DataRecord, Mark, PlotScales } from '../../types.js';
|
|
3
|
+
type MarkerPathProps = BaseMarkProps & {
|
|
4
|
+
/**
|
|
5
|
+
* the datum associated with this path, usually the first
|
|
6
|
+
* element of the data array group
|
|
7
|
+
*/
|
|
8
|
+
datum: DataRecord;
|
|
9
|
+
/**
|
|
10
|
+
* the marker shape to use at the start of the path, defaults to
|
|
11
|
+
* cirlce
|
|
12
|
+
*/
|
|
13
|
+
markerStart?: boolean | MarkerShape;
|
|
14
|
+
/**
|
|
15
|
+
* the marker shape to use at the middle of the path, defaults to circle
|
|
16
|
+
*/
|
|
17
|
+
markerMid?: boolean | MarkerShape;
|
|
18
|
+
/**
|
|
19
|
+
* the marker shape to use at the end of the path, defaults to circle
|
|
20
|
+
*/
|
|
21
|
+
markerEnd?: boolean | MarkerShape;
|
|
22
|
+
/**
|
|
23
|
+
* shorthand for setting all markers
|
|
24
|
+
*/
|
|
25
|
+
marker?: boolean | MarkerShape;
|
|
26
|
+
/**
|
|
27
|
+
* path string
|
|
28
|
+
*/
|
|
29
|
+
d: string;
|
|
30
|
+
style: string;
|
|
31
|
+
startOffset: string;
|
|
32
|
+
textStyle: string;
|
|
33
|
+
textStyleClass?: string | null;
|
|
34
|
+
text: string;
|
|
35
|
+
transform: string;
|
|
36
|
+
color: string;
|
|
37
|
+
strokeWidth: ConstantAccessor<number>;
|
|
38
|
+
mark: Mark<BaseMarkProps>;
|
|
39
|
+
scales: PlotScales;
|
|
40
|
+
};
|
|
41
|
+
/** Helper component for paths with markers and optional text along the path. */
|
|
42
|
+
declare const MarkerPath: import("svelte").Component<MarkerPathProps, {}, "">;
|
|
43
|
+
type MarkerPath = ReturnType<typeof MarkerPath>;
|
|
44
|
+
export default MarkerPath;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { BaseMarkProps, ChannelAccessor, FacetContext, PlotContext } from '../../types.js';
|
|
3
|
+
|
|
4
|
+
type RegressionType = 'linear' | 'quad' | 'poly' | 'exp' | 'log' | 'pow' | 'loess';
|
|
5
|
+
|
|
6
|
+
export type RegressionMarkProps = BaseMarkProps & {
|
|
7
|
+
x: ChannelAccessor;
|
|
8
|
+
y: ChannelAccessor;
|
|
9
|
+
type: RegressionType;
|
|
10
|
+
/**
|
|
11
|
+
* If order is specified, sets the regression's order to the specified number.
|
|
12
|
+
* For example, if order is set to 4, the regression generator will perform a
|
|
13
|
+
* fourth-degree polynomial regression. Likewise, if order is set to 2, the
|
|
14
|
+
* regression generator will perform a quadratic regression. Be careful about
|
|
15
|
+
* attempting to fit your data with higher order polynomials; though the
|
|
16
|
+
* regression line will fit your data with a high determination coefficient,
|
|
17
|
+
* it may have little predictive power for data outside of your domain.
|
|
18
|
+
*/
|
|
19
|
+
order: number;
|
|
20
|
+
// for log
|
|
21
|
+
base: number;
|
|
22
|
+
// for loess
|
|
23
|
+
span: number;
|
|
24
|
+
// for confidence bands
|
|
25
|
+
confidence: number;
|
|
26
|
+
};
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<script lang="ts">
|
|
30
|
+
import { getContext } from 'svelte';
|
|
31
|
+
import { Line, Area } from '../../index.js';
|
|
32
|
+
|
|
33
|
+
import {
|
|
34
|
+
regressionLinear,
|
|
35
|
+
regressionQuad,
|
|
36
|
+
regressionPoly,
|
|
37
|
+
regressionExp,
|
|
38
|
+
regressionLog,
|
|
39
|
+
regressionPow,
|
|
40
|
+
regressionLoess
|
|
41
|
+
} from 'd3-regression/dist/d3-regression.esm.js';
|
|
42
|
+
import { resolveChannel } from '../../helpers/resolve.js';
|
|
43
|
+
import { confidenceInterval } from '../../helpers/math.js';
|
|
44
|
+
import callWithProps from '../../helpers/callWithProps.js';
|
|
45
|
+
import { isDate } from '../../helpers/typeChecks';
|
|
46
|
+
|
|
47
|
+
const regressions = new Map<RegressionType, typeof regressionLinear>([
|
|
48
|
+
['linear', regressionLinear],
|
|
49
|
+
['quad', regressionQuad],
|
|
50
|
+
['poly', regressionPoly],
|
|
51
|
+
['exp', regressionExp],
|
|
52
|
+
['log', regressionLog],
|
|
53
|
+
['pow', regressionPow],
|
|
54
|
+
['loess', regressionLoess]
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
function maybeRegression(name: string) {
|
|
58
|
+
name = `${name}`.toLowerCase();
|
|
59
|
+
if (regressions.has(name)) return regressions.get(name);
|
|
60
|
+
throw new Error('unknown regression ' + name);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
64
|
+
let plot = $derived(getPlotState());
|
|
65
|
+
|
|
66
|
+
let {
|
|
67
|
+
data,
|
|
68
|
+
dependent,
|
|
69
|
+
type = 'linear',
|
|
70
|
+
order = 3,
|
|
71
|
+
base = 2.71828,
|
|
72
|
+
span = 0.3,
|
|
73
|
+
confidence = 0.99,
|
|
74
|
+
class: className = null,
|
|
75
|
+
...options
|
|
76
|
+
}: RegressionMarkProps & { dependent: 'x' | 'y' } = $props();
|
|
77
|
+
|
|
78
|
+
const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
|
|
79
|
+
let testFacet = $derived(getTestFacet());
|
|
80
|
+
|
|
81
|
+
let filteredData = $derived(data.filter((d) => testFacet(d, options)));
|
|
82
|
+
|
|
83
|
+
let independent: 'x' | 'y' = $derived(dependent === 'x' ? 'y' : 'x');
|
|
84
|
+
|
|
85
|
+
let regressionFn = $derived(maybeRegression(type));
|
|
86
|
+
|
|
87
|
+
let regression = $derived(
|
|
88
|
+
callWithProps(regressionFn, [], {
|
|
89
|
+
x: (d) => resolveChannel(independent, d, options),
|
|
90
|
+
y: (d) => resolveChannel(dependent, d, options),
|
|
91
|
+
...(type === 'poly' ? { order } : {}),
|
|
92
|
+
...(type === 'log' ? { base } : {}),
|
|
93
|
+
...(!type.startsWith('loess') ? { domain: plot.scales[independent].domain } : {}),
|
|
94
|
+
...(type === 'loess' ? { bandwidth: span } : {})
|
|
95
|
+
})(filteredData)
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
let regrPoints = $derived([
|
|
99
|
+
...new Set([
|
|
100
|
+
plot.scales[independent].domain[0],
|
|
101
|
+
...plot.scales[independent].fn.ticks(40),
|
|
102
|
+
plot.scales[independent].domain[1]
|
|
103
|
+
])
|
|
104
|
+
]);
|
|
105
|
+
|
|
106
|
+
let regrData = $derived(
|
|
107
|
+
regression.predictMany
|
|
108
|
+
? regression.predictMany(regrPoints).map((__y, i) => ({ __x: regrPoints[i], __y }))
|
|
109
|
+
: regression.predict
|
|
110
|
+
? regrPoints.map((__x) => {
|
|
111
|
+
// const __x = x;
|
|
112
|
+
const __y = regression.predict(__x);
|
|
113
|
+
return { __x, __y };
|
|
114
|
+
})
|
|
115
|
+
: regression.map(([__x, __y]) => ({
|
|
116
|
+
__x: plot.scales[independent].type === 'time' ? new Date(__x) : __x,
|
|
117
|
+
__y
|
|
118
|
+
}))
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
let stroke = $derived(
|
|
122
|
+
options.stroke != null ? resolveChannel('stroke', filteredData[0], options) : null
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
let confBandGen = $derived(
|
|
126
|
+
confidence !== false
|
|
127
|
+
? confidenceInterval(
|
|
128
|
+
data
|
|
129
|
+
.map((d) => ({
|
|
130
|
+
x: resolveChannel(independent, d, options),
|
|
131
|
+
y: resolveChannel(dependent, d, options)
|
|
132
|
+
}))
|
|
133
|
+
.filter(
|
|
134
|
+
({ x, y }) => (Number.isFinite(x) || isDate(x)) && Number.isFinite(y)
|
|
135
|
+
),
|
|
136
|
+
regression.predict,
|
|
137
|
+
1 - confidence
|
|
138
|
+
)
|
|
139
|
+
: null
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
let confBandData = $derived(
|
|
143
|
+
confidence !== false && regression.predict
|
|
144
|
+
? regrPoints.map((x) => {
|
|
145
|
+
const { x: __x, left, right } = confBandGen(x);
|
|
146
|
+
return { __x, __y1: left, __y2: right };
|
|
147
|
+
})
|
|
148
|
+
: []
|
|
149
|
+
);
|
|
150
|
+
</script>
|
|
151
|
+
|
|
152
|
+
{#if filteredData.length}
|
|
153
|
+
<g class="regression-{independent} {className || ''}">
|
|
154
|
+
<Line
|
|
155
|
+
data={regrData}
|
|
156
|
+
{...{
|
|
157
|
+
...options,
|
|
158
|
+
fx: null,
|
|
159
|
+
fy: null,
|
|
160
|
+
stroke,
|
|
161
|
+
x: dependent === 'y' ? '__x' : '__y',
|
|
162
|
+
y: dependent === 'y' ? '__y' : '__x'
|
|
163
|
+
}} />
|
|
164
|
+
{#if confBandData.length}
|
|
165
|
+
<Area
|
|
166
|
+
data={confBandData}
|
|
167
|
+
{...dependent === 'y'
|
|
168
|
+
? { x1: '__x', y1: '__y1', y2: '__y2' }
|
|
169
|
+
: { y1: '__x', x1: '__y1', x2: '__y2' }}
|
|
170
|
+
fill={stroke || 'currentColor'}
|
|
171
|
+
opacity={0.15} />
|
|
172
|
+
{/if}
|
|
173
|
+
</g>
|
|
174
|
+
{/if}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BaseMarkProps, ChannelAccessor } from '../../types.js';
|
|
2
|
+
type RegressionType = 'linear' | 'quad' | 'poly' | 'exp' | 'log' | 'pow' | 'loess';
|
|
3
|
+
export type RegressionMarkProps = BaseMarkProps & {
|
|
4
|
+
x: ChannelAccessor;
|
|
5
|
+
y: ChannelAccessor;
|
|
6
|
+
type: RegressionType;
|
|
7
|
+
/**
|
|
8
|
+
* If order is specified, sets the regression's order to the specified number.
|
|
9
|
+
* For example, if order is set to 4, the regression generator will perform a
|
|
10
|
+
* fourth-degree polynomial regression. Likewise, if order is set to 2, the
|
|
11
|
+
* regression generator will perform a quadratic regression. Be careful about
|
|
12
|
+
* attempting to fit your data with higher order polynomials; though the
|
|
13
|
+
* regression line will fit your data with a high determination coefficient,
|
|
14
|
+
* it may have little predictive power for data outside of your domain.
|
|
15
|
+
*/
|
|
16
|
+
order: number;
|
|
17
|
+
base: number;
|
|
18
|
+
span: number;
|
|
19
|
+
confidence: number;
|
|
20
|
+
};
|
|
21
|
+
type $$ComponentProps = RegressionMarkProps & {
|
|
22
|
+
dependent: 'x' | 'y';
|
|
23
|
+
};
|
|
24
|
+
declare const Regression: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
25
|
+
type Regression = ReturnType<typeof Regression>;
|
|
26
|
+
export default Regression;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BaseMarkProps, DataRecord, PlotState } from '../../types.js';
|
|
2
|
+
export declare function addEventHandlers(node: SVGElement, { options, datum, getPlotState }: {
|
|
3
|
+
options: BaseMarkProps;
|
|
4
|
+
datum: DataRecord;
|
|
5
|
+
getPlotState: () => PlotState;
|
|
6
|
+
}): {
|
|
7
|
+
destroy(): void;
|
|
8
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { invert, pick } from 'es-toolkit';
|
|
2
|
+
import { RAW_VALUE } from '../../transforms/recordize.js';
|
|
3
|
+
import { INDEX } from '../../constants.js';
|
|
4
|
+
export function addEventHandlers(node, { options, datum, getPlotState }) {
|
|
5
|
+
const events = pick(options, [
|
|
6
|
+
'onclick',
|
|
7
|
+
'oncontextmenu',
|
|
8
|
+
'ondblclick',
|
|
9
|
+
'ondrag',
|
|
10
|
+
'ondragend',
|
|
11
|
+
'ondragenter',
|
|
12
|
+
'ondragleave',
|
|
13
|
+
'ondragover',
|
|
14
|
+
'ondragstart',
|
|
15
|
+
'ondrop',
|
|
16
|
+
'onmousedown',
|
|
17
|
+
'onmouseenter',
|
|
18
|
+
'onmouseleave',
|
|
19
|
+
'onmousemove',
|
|
20
|
+
'onmouseout',
|
|
21
|
+
'onmouseup',
|
|
22
|
+
'onwheel',
|
|
23
|
+
'ontouchcancel',
|
|
24
|
+
'ontouchend',
|
|
25
|
+
'ontouchmove'
|
|
26
|
+
]);
|
|
27
|
+
const listeners = new Map();
|
|
28
|
+
// attach event handlers
|
|
29
|
+
for (const [eventName, eventHandler] of Object.entries(events)) {
|
|
30
|
+
if (eventHandler) {
|
|
31
|
+
const wrappedHandler = (origEvent) => {
|
|
32
|
+
const { scales } = getPlotState();
|
|
33
|
+
if (origEvent.layerX !== undefined) {
|
|
34
|
+
if (scales.projection) {
|
|
35
|
+
const [x, y] = scales.projection.invert([
|
|
36
|
+
origEvent.layerX,
|
|
37
|
+
origEvent.layerY
|
|
38
|
+
]);
|
|
39
|
+
origEvent.dataX = x;
|
|
40
|
+
origEvent.dataY = y;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
origEvent.dataX = invertScale(scales.x, origEvent.layerX);
|
|
44
|
+
origEvent.dataY = invertScale(scales.y, origEvent.layerY);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
eventHandler(origEvent, datum.hasOwnProperty(RAW_VALUE) ? datum[RAW_VALUE] : datum, datum[INDEX]);
|
|
48
|
+
};
|
|
49
|
+
listeners.set(eventName, wrappedHandler);
|
|
50
|
+
node.addEventListener(eventName.substring(2), wrappedHandler);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (events.onclick || events.onmousedown || events.onmouseup) {
|
|
54
|
+
// force role button
|
|
55
|
+
node.setAttribute('role', 'button');
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
destroy() {
|
|
59
|
+
for (const [eventName, handler] of listeners.entries()) {
|
|
60
|
+
node.removeEventListener(eventName.substring(2), handler);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function invertScale(scale, position) {
|
|
66
|
+
if (scale.type === 'band') {
|
|
67
|
+
// invert band scale since scaleBand doesn't have an invert function
|
|
68
|
+
const eachBand = scale.fn.step();
|
|
69
|
+
console.log({ eachBand, position });
|
|
70
|
+
const index = Math.floor(position / eachBand);
|
|
71
|
+
return scale.fn.domain()[index];
|
|
72
|
+
}
|
|
73
|
+
return scale.fn.invert ? scale.fn.invert(position) : undefined;
|
|
74
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { DataRecord, RawValue } from '../types.js';
|
|
2
|
+
import type { TransformArg } from '../types.js';
|
|
3
|
+
import { type ThresholdCountGenerator } from 'd3-array';
|
|
4
|
+
import { Reducer, type ReducerName } from '../helpers/reduce.js';
|
|
5
|
+
type NamedThresholdsGenerator = 'auto' | 'scott' | 'sturges' | 'freedman-diaconis';
|
|
6
|
+
type BinBaseOptions = {
|
|
7
|
+
domain?: [number, number];
|
|
8
|
+
thresholds?: NamedThresholdsGenerator | number | number[] | ThresholdCountGenerator;
|
|
9
|
+
interval?: number | string;
|
|
10
|
+
cumulative?: false | 1 | -1;
|
|
11
|
+
reverse?: boolean;
|
|
12
|
+
};
|
|
13
|
+
type ReducerOption = ReducerName | ((group: DataRecord[]) => RawValue);
|
|
14
|
+
type AdditionalOutputChannels = Partial<{
|
|
15
|
+
fill: ReducerOption;
|
|
16
|
+
stroke: ReducerOption;
|
|
17
|
+
r: ReducerOption;
|
|
18
|
+
opacity: ReducerOption;
|
|
19
|
+
fillOpacity: ReducerOption;
|
|
20
|
+
strokeOpacity: ReducerOption;
|
|
21
|
+
}>;
|
|
22
|
+
export type BinXOptions = BinBaseOptions & AdditionalOutputChannels & Partial<{
|
|
23
|
+
y: typeof Reducer;
|
|
24
|
+
y1: typeof Reducer;
|
|
25
|
+
y2: typeof Reducer;
|
|
26
|
+
}>;
|
|
27
|
+
export type BinYOptions = BinBaseOptions & AdditionalOutputChannels & Partial<{
|
|
28
|
+
x: typeof Reducer;
|
|
29
|
+
x1: typeof Reducer;
|
|
30
|
+
x2: typeof Reducer;
|
|
31
|
+
}>;
|
|
32
|
+
type BinOptions = BinBaseOptions & AdditionalOutputChannels;
|
|
33
|
+
/**
|
|
34
|
+
* Bins on x. Also groups on y and the first channel of z, fill, or stroke, if any.
|
|
35
|
+
*
|
|
36
|
+
* @param param0
|
|
37
|
+
* @param options
|
|
38
|
+
*/
|
|
39
|
+
export declare function binX<T>({ data, ...channels }: TransformArg<T, DataRecord>, options?: BinXOptions): TransformArg<T, DataRecord>;
|
|
40
|
+
/**
|
|
41
|
+
* Bins on y. Also groups on y and the first channel of z, fill, or stroke, if any.
|
|
42
|
+
*
|
|
43
|
+
* @param param0
|
|
44
|
+
* @param options
|
|
45
|
+
*/
|
|
46
|
+
export declare function binY<T>({ data, ...channels }: TransformArg<T, DataRecord>, options?: BinYOptions): TransformArg<T, DataRecord>;
|
|
47
|
+
/**
|
|
48
|
+
* for binning in x and y dimension simulatenously
|
|
49
|
+
*/
|
|
50
|
+
export declare function bin<T>({ data, ...channels }: TransformArg<T, DataRecord>, options?: BinOptions): TransformArg<T, DataRecord>;
|
|
51
|
+
export {};
|