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,219 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type {
|
|
3
|
+
PlotContext,
|
|
4
|
+
DataRecord,
|
|
5
|
+
BaseMarkProps,
|
|
6
|
+
ConstantAccessor,
|
|
7
|
+
ChannelAccessor,
|
|
8
|
+
FacetContext
|
|
9
|
+
} from '../types.js';
|
|
10
|
+
|
|
11
|
+
type D3Path = ReturnType<typeof import('d3-path').path>;
|
|
12
|
+
|
|
13
|
+
export type ShapeRenderer = {
|
|
14
|
+
draw(context: D3Path, l: number, r: number): void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type VectorMarkProps = BaseMarkProps & {
|
|
18
|
+
data: DataRecord[];
|
|
19
|
+
x: ChannelAccessor;
|
|
20
|
+
y: ChannelAccessor;
|
|
21
|
+
r?: number;
|
|
22
|
+
length?: ChannelAccessor;
|
|
23
|
+
rotate?: ChannelAccessor;
|
|
24
|
+
fill?: ChannelAccessor;
|
|
25
|
+
stroke?: ChannelAccessor;
|
|
26
|
+
/**
|
|
27
|
+
* Controls where the vector is anchored in relation to the x, y position.
|
|
28
|
+
* If set to 'start', the arrow will start at the x, y position. If set to
|
|
29
|
+
* 'middle', the arrow will be centered at the x, y position. If set to
|
|
30
|
+
* 'end', the arrow will end at the x, y position.
|
|
31
|
+
*/
|
|
32
|
+
anchor: 'start' | 'middle' | 'end';
|
|
33
|
+
shape?: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer;
|
|
34
|
+
children?: Snippet;
|
|
35
|
+
dx?: ConstantAccessor<number>;
|
|
36
|
+
dy?: ConstantAccessor<number>;
|
|
37
|
+
canvas?: boolean;
|
|
38
|
+
};
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<script lang="ts">
|
|
42
|
+
import { getContext, type Snippet } from 'svelte';
|
|
43
|
+
import { pathRound as path } from 'd3-path';
|
|
44
|
+
|
|
45
|
+
import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
|
|
46
|
+
import { projectXY } from '../helpers/scales.js';
|
|
47
|
+
import { sort } from '../index.js';
|
|
48
|
+
import Mark from '../Mark.svelte';
|
|
49
|
+
//import DotCanvas from './helpers/DotCanvas.svelte';
|
|
50
|
+
import { maybeData, testFilter, isValid } from '../helpers/index.js';
|
|
51
|
+
import { addEventHandlers } from './helpers/events.js';
|
|
52
|
+
|
|
53
|
+
const defaultRadius = 3.5;
|
|
54
|
+
|
|
55
|
+
// The size of the arrowhead is proportional to its length, but we still allow
|
|
56
|
+
// the relative size of the head to be controlled via the mark’s width option;
|
|
57
|
+
// doubling the default radius will produce an arrowhead that is twice as big.
|
|
58
|
+
// That said, we’ll probably want a arrow with a fixed head size, too.
|
|
59
|
+
const wingRatio = defaultRadius * 5;
|
|
60
|
+
|
|
61
|
+
let {
|
|
62
|
+
data = [{}],
|
|
63
|
+
canvas,
|
|
64
|
+
shape = 'arrow',
|
|
65
|
+
anchor = 'middle',
|
|
66
|
+
r = defaultRadius,
|
|
67
|
+
...options
|
|
68
|
+
}: VectorMarkProps = $props();
|
|
69
|
+
|
|
70
|
+
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
71
|
+
const plot = $derived(getPlotState());
|
|
72
|
+
|
|
73
|
+
const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
|
|
74
|
+
const testFacet = $derived(getTestFacet());
|
|
75
|
+
|
|
76
|
+
const shapeArrow: ShapeRenderer = {
|
|
77
|
+
draw(context: D3Path, l: number, r: number) {
|
|
78
|
+
const wing = (l * r) / wingRatio;
|
|
79
|
+
context.moveTo(0, 0);
|
|
80
|
+
context.lineTo(0, -l);
|
|
81
|
+
context.moveTo(-wing, wing - l);
|
|
82
|
+
context.lineTo(0, -l);
|
|
83
|
+
context.lineTo(wing, wing - l);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const shapeSpike: ShapeRenderer = {
|
|
88
|
+
draw(context: D3Path, l: number, r: number) {
|
|
89
|
+
context.moveTo(-r, 0);
|
|
90
|
+
context.lineTo(0, -l);
|
|
91
|
+
context.lineTo(r, 0);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const shapeArrowFilled: ShapeRenderer = {
|
|
96
|
+
draw(context: D3Path, l: number, r: number) {
|
|
97
|
+
// const wing = (l * r) / wingRatio;
|
|
98
|
+
const headLength = Math.max(3, l * 0.3);
|
|
99
|
+
const headSpike = headLength * 0.2;
|
|
100
|
+
const headWidth = Math.max(2, l * 0.3);
|
|
101
|
+
const tailWidth = Math.max(2, l * 0.3) * 0.3;
|
|
102
|
+
|
|
103
|
+
context.moveTo(0, 0);
|
|
104
|
+
|
|
105
|
+
context.lineTo(tailWidth * 0.5, -l + headLength - headSpike);
|
|
106
|
+
context.lineTo(headWidth * 0.5, -l + headLength);
|
|
107
|
+
context.lineTo(0, -l);
|
|
108
|
+
context.lineTo(-headWidth * 0.5, -l + headLength);
|
|
109
|
+
context.lineTo(-tailWidth * 0.5, -l + headLength - headSpike);
|
|
110
|
+
|
|
111
|
+
context.closePath();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const shapes = new Map([
|
|
116
|
+
['arrow', shapeArrow],
|
|
117
|
+
['arrow-filled', shapeArrowFilled],
|
|
118
|
+
['spike', shapeSpike]
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
function isShapeObject(value: any): value is ShapeRenderer {
|
|
122
|
+
return value && typeof value.draw === 'function';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function maybeShape(shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer) {
|
|
126
|
+
if (isShapeObject(shape)) return shape;
|
|
127
|
+
const value = shapes.get(`${shape}`.toLowerCase());
|
|
128
|
+
if (value) return value;
|
|
129
|
+
throw new Error(`invalid shape: ${shape}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function shapePath(
|
|
133
|
+
shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer,
|
|
134
|
+
l: number,
|
|
135
|
+
r: number
|
|
136
|
+
) {
|
|
137
|
+
const context = path();
|
|
138
|
+
maybeShape(shape).draw(context, l, r);
|
|
139
|
+
return context.toString();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const args = $derived(
|
|
143
|
+
sort({
|
|
144
|
+
data: maybeData(data),
|
|
145
|
+
// sort by descending radius by default
|
|
146
|
+
...options
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
</script>
|
|
150
|
+
|
|
151
|
+
<Mark
|
|
152
|
+
type="vector"
|
|
153
|
+
required={['x', 'y']}
|
|
154
|
+
channels={[
|
|
155
|
+
'x',
|
|
156
|
+
'y',
|
|
157
|
+
'r',
|
|
158
|
+
'length',
|
|
159
|
+
'symbol',
|
|
160
|
+
'fill',
|
|
161
|
+
'opacity',
|
|
162
|
+
'stroke',
|
|
163
|
+
'fillOpacity',
|
|
164
|
+
'strokeOpacity'
|
|
165
|
+
]}
|
|
166
|
+
{...args}>
|
|
167
|
+
{#snippet children({ mark, scaledData, usedScales })}
|
|
168
|
+
<g class="vector" data-l={usedScales.length}>
|
|
169
|
+
{#if canvas}
|
|
170
|
+
<text x="30" y="30" style="color:red"
|
|
171
|
+
>implement canvas rendering for vector mark</text>
|
|
172
|
+
{:else}
|
|
173
|
+
{#each scaledData as d}
|
|
174
|
+
{@const r = resolveChannel('r', d.datum, { r: 3, ...args })}
|
|
175
|
+
{#if d.valid && isValid(r)}
|
|
176
|
+
{@const dx = +resolveProp(args.dx, d.datum, 0)}
|
|
177
|
+
{@const dy = +resolveProp(args.dx, d.datum, 0)}
|
|
178
|
+
{@const [style, styleClass] = resolveStyles(
|
|
179
|
+
plot,
|
|
180
|
+
d,
|
|
181
|
+
{
|
|
182
|
+
strokeWidth: 1.5,
|
|
183
|
+
strokeLinejoin: 'round',
|
|
184
|
+
strokeLinecap: 'round',
|
|
185
|
+
...args
|
|
186
|
+
},
|
|
187
|
+
shape === 'arrow-filled' ? 'fill' : 'stroke',
|
|
188
|
+
usedScales
|
|
189
|
+
)}
|
|
190
|
+
<path
|
|
191
|
+
d={shapePath(shape, d.length, r)}
|
|
192
|
+
transform="translate({d.x + dx}, {d.y + dy}) rotate({resolveProp(
|
|
193
|
+
args.rotate,
|
|
194
|
+
d.datum,
|
|
195
|
+
0
|
|
196
|
+
)}) {anchor === 'start'
|
|
197
|
+
? ''
|
|
198
|
+
: anchor === 'end'
|
|
199
|
+
? `translate(0, ${d.length})`
|
|
200
|
+
: `translate(0, ${d.length / 2})`}"
|
|
201
|
+
{style}
|
|
202
|
+
use:addEventHandlers={{
|
|
203
|
+
getPlotState,
|
|
204
|
+
options: args,
|
|
205
|
+
datum: d.datum
|
|
206
|
+
}}
|
|
207
|
+
class={[styleClass]} />
|
|
208
|
+
{/if}
|
|
209
|
+
{/each}
|
|
210
|
+
{/if}
|
|
211
|
+
</g>
|
|
212
|
+
{/snippet}
|
|
213
|
+
</Mark>
|
|
214
|
+
|
|
215
|
+
<style>
|
|
216
|
+
path {
|
|
217
|
+
stroke-width: 1.5px;
|
|
218
|
+
}
|
|
219
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DataRecord, BaseMarkProps, ConstantAccessor, ChannelAccessor } from '../types.js';
|
|
2
|
+
type D3Path = ReturnType<typeof import('d3-path').path>;
|
|
3
|
+
export type ShapeRenderer = {
|
|
4
|
+
draw(context: D3Path, l: number, r: number): void;
|
|
5
|
+
};
|
|
6
|
+
export type VectorMarkProps = BaseMarkProps & {
|
|
7
|
+
data: DataRecord[];
|
|
8
|
+
x: ChannelAccessor;
|
|
9
|
+
y: ChannelAccessor;
|
|
10
|
+
r?: number;
|
|
11
|
+
length?: ChannelAccessor;
|
|
12
|
+
rotate?: ChannelAccessor;
|
|
13
|
+
fill?: ChannelAccessor;
|
|
14
|
+
stroke?: ChannelAccessor;
|
|
15
|
+
/**
|
|
16
|
+
* Controls where the vector is anchored in relation to the x, y position.
|
|
17
|
+
* If set to 'start', the arrow will start at the x, y position. If set to
|
|
18
|
+
* 'middle', the arrow will be centered at the x, y position. If set to
|
|
19
|
+
* 'end', the arrow will end at the x, y position.
|
|
20
|
+
*/
|
|
21
|
+
anchor: 'start' | 'middle' | 'end';
|
|
22
|
+
shape?: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer;
|
|
23
|
+
children?: Snippet;
|
|
24
|
+
dx?: ConstantAccessor<number>;
|
|
25
|
+
dy?: ConstantAccessor<number>;
|
|
26
|
+
canvas?: boolean;
|
|
27
|
+
};
|
|
28
|
+
import { type Snippet } from 'svelte';
|
|
29
|
+
declare const Vector: import("svelte").Component<VectorMarkProps, {}, "">;
|
|
30
|
+
type Vector = ReturnType<typeof Vector>;
|
|
31
|
+
export default Vector;
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// this component only takes care of rendering the x axis so we can re-use it
|
|
3
|
+
// for the facet labels
|
|
4
|
+
import { getContext, untrack } from 'svelte';
|
|
5
|
+
import removeIdenticalLines from '../../helpers/removeIdenticalLines.js';
|
|
6
|
+
import type {
|
|
7
|
+
AutoMarginStores,
|
|
8
|
+
ChannelAccessor,
|
|
9
|
+
ConstantAccessor,
|
|
10
|
+
PlotState,
|
|
11
|
+
RawValue,
|
|
12
|
+
ScaleType
|
|
13
|
+
} from '../../types.js';
|
|
14
|
+
import { resolveScaledStyles, resolveProp } from '../../helpers/resolve.js';
|
|
15
|
+
import { max } from 'd3-array';
|
|
16
|
+
import { randomId, testFilter } from '../../helpers/index.js';
|
|
17
|
+
|
|
18
|
+
type BaseAxisXProps = {
|
|
19
|
+
scaleFn: (d: RawValue) => number;
|
|
20
|
+
scaleType: ScaleType;
|
|
21
|
+
ticks: RawValue[];
|
|
22
|
+
tickFormat: (d: RawValue, i: number) => string | string[];
|
|
23
|
+
anchor: 'top' | 'bottom';
|
|
24
|
+
tickSize: number;
|
|
25
|
+
tickPadding: number;
|
|
26
|
+
tickFontSize: ConstantAccessor<number>;
|
|
27
|
+
tickClass: ConstantAccessor<string>;
|
|
28
|
+
marginTop: number;
|
|
29
|
+
height: number;
|
|
30
|
+
title: string;
|
|
31
|
+
options: {
|
|
32
|
+
dx: ConstantAccessor<number>;
|
|
33
|
+
dy: ConstantAccessor<number>;
|
|
34
|
+
filter: ChannelAccessor;
|
|
35
|
+
};
|
|
36
|
+
plot: PlotState;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let {
|
|
40
|
+
scaleFn,
|
|
41
|
+
scaleType,
|
|
42
|
+
ticks,
|
|
43
|
+
tickFormat,
|
|
44
|
+
anchor,
|
|
45
|
+
tickSize,
|
|
46
|
+
tickPadding,
|
|
47
|
+
tickFontSize,
|
|
48
|
+
tickClass,
|
|
49
|
+
marginTop,
|
|
50
|
+
height,
|
|
51
|
+
options,
|
|
52
|
+
plot,
|
|
53
|
+
title
|
|
54
|
+
}: BaseAxisXProps = $props();
|
|
55
|
+
|
|
56
|
+
function splitTick(tick: string | string[]) {
|
|
57
|
+
return Array.isArray(tick) ? tick : [tick];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let tickRotate = $derived(plot.options.x.tickRotate || 0);
|
|
61
|
+
|
|
62
|
+
let tickY = $derived(anchor === 'bottom' ? marginTop + height : marginTop);
|
|
63
|
+
|
|
64
|
+
let isQuantitative = $derived(scaleType !== 'point' && scaleType !== 'band');
|
|
65
|
+
|
|
66
|
+
// generate id used for registering margins
|
|
67
|
+
const id = randomId();
|
|
68
|
+
|
|
69
|
+
const { autoMarginTop, autoMarginBottom } =
|
|
70
|
+
getContext<AutoMarginStores>('svelteplot/autoMargins');
|
|
71
|
+
|
|
72
|
+
let tickTextElements = $state([] as SVGTextElement[]);
|
|
73
|
+
|
|
74
|
+
const positionedTicks = $derived.by(() => {
|
|
75
|
+
let tickObjects = removeIdenticalLines(
|
|
76
|
+
ticks.map((tick, i) => {
|
|
77
|
+
return {
|
|
78
|
+
value: tick,
|
|
79
|
+
hidden: false,
|
|
80
|
+
dx: +resolveProp(options.dx, tick, 0),
|
|
81
|
+
dy: +resolveProp(options.dy, tick, 0),
|
|
82
|
+
x: scaleFn(tick) + (scaleType === 'band' ? scaleFn.bandwidth() * 0.5 : 0),
|
|
83
|
+
text: splitTick(tickFormat(tick, i)),
|
|
84
|
+
element: null as SVGTextElement | null
|
|
85
|
+
};
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
const T = tickObjects.length;
|
|
89
|
+
for (let i = 0; i < T; i++) {
|
|
90
|
+
let j = i;
|
|
91
|
+
// find the preceeding tick that was not hidden
|
|
92
|
+
do {
|
|
93
|
+
j--;
|
|
94
|
+
} while (j >= 0 && tickObjects[j].hidden);
|
|
95
|
+
if (j >= 0) {
|
|
96
|
+
const tickLabelSpace = Math.abs(tickObjects[i].x - tickObjects[j].x);
|
|
97
|
+
tickObjects[i].hidden = tickLabelSpace < 15;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return tickObjects;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
$effect(() => {
|
|
104
|
+
untrack(() => [$autoMarginTop, $autoMarginBottom]);
|
|
105
|
+
const outsideTextAnchor = anchor === 'top' ? 'end' : 'start';
|
|
106
|
+
// measure tick label heights
|
|
107
|
+
const maxLabelHeight =
|
|
108
|
+
Math.ceil(
|
|
109
|
+
max(
|
|
110
|
+
positionedTicks.map((tick, i) => {
|
|
111
|
+
if (
|
|
112
|
+
resolveProp(options.anchor, tick.value, outsideTextAnchor) !==
|
|
113
|
+
outsideTextAnchor
|
|
114
|
+
)
|
|
115
|
+
return 0;
|
|
116
|
+
if (tick.hidden || !testFilter(tick.value, options)) return 0;
|
|
117
|
+
if (tickTextElements[i])
|
|
118
|
+
return tickTextElements[i].getBoundingClientRect().height;
|
|
119
|
+
return 0;
|
|
120
|
+
}) as number[]
|
|
121
|
+
)
|
|
122
|
+
) +
|
|
123
|
+
Math.max(0, tickPadding + tickSize) +
|
|
124
|
+
(title ? 15 : 0);
|
|
125
|
+
|
|
126
|
+
if (!isNaN(maxLabelHeight)) {
|
|
127
|
+
if (anchor === 'top' && $autoMarginTop.get(id) !== maxLabelHeight) {
|
|
128
|
+
$autoMarginTop.set(id, maxLabelHeight);
|
|
129
|
+
} else if (anchor === 'bottom' && $autoMarginBottom.get(id) !== maxLabelHeight) {
|
|
130
|
+
$autoMarginBottom.set(id, maxLabelHeight);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
$effect(() => {
|
|
136
|
+
// clear margins on destroy
|
|
137
|
+
return () => {
|
|
138
|
+
if ($autoMarginBottom.has(id)) $autoMarginBottom.delete(id);
|
|
139
|
+
if ($autoMarginTop.has(id)) $autoMarginTop.delete(id);
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
</script>
|
|
143
|
+
|
|
144
|
+
<g class="axis-x">
|
|
145
|
+
{#each positionedTicks as tick, t}
|
|
146
|
+
{#if testFilter(tick.value, options) && !tick.hidden}
|
|
147
|
+
{@const textLines = tick.text}
|
|
148
|
+
{@const prevTextLines = t && positionedTicks[t - 1].text}
|
|
149
|
+
{@const fontSize = resolveProp(tickFontSize, tick)}
|
|
150
|
+
{@const tickClass_ = resolveProp(tickClass, tick.value)}
|
|
151
|
+
{@const estLabelWidth = max(textLines.map((t) => t.length)) * fontSize * 0.2}
|
|
152
|
+
{@const moveDown =
|
|
153
|
+
(tickSize + tickPadding + (tickRotate !== 0 ? tickFontSize * 0.35 : 0)) *
|
|
154
|
+
(anchor === 'bottom' ? 1 : -1)}
|
|
155
|
+
<g
|
|
156
|
+
class="tick {tickClass_ || ''}"
|
|
157
|
+
transform="translate({tick.x + tick.dx}, {tickY + tick.dy})"
|
|
158
|
+
text-anchor={tickRotate < 0 ? 'end' : tickRotate > 0 ? 'start' : 'middle'}>
|
|
159
|
+
{#if tickSize}
|
|
160
|
+
<line
|
|
161
|
+
style={resolveScaledStyles(tick, options, {}, plot, 'stroke')}
|
|
162
|
+
y2={anchor === 'bottom' ? tickSize : -tickSize} />
|
|
163
|
+
{/if}
|
|
164
|
+
|
|
165
|
+
<text
|
|
166
|
+
bind:this={tickTextElements[t]}
|
|
167
|
+
transform="translate(0, {moveDown}) rotate({tickRotate})"
|
|
168
|
+
style:font-variant={isQuantitative ? 'tabular-nums' : 'normal'}
|
|
169
|
+
style={resolveScaledStyles(
|
|
170
|
+
tick,
|
|
171
|
+
{ ...options, fontSize: tickFontSize, stroke: null },
|
|
172
|
+
{},
|
|
173
|
+
plot,
|
|
174
|
+
'fill'
|
|
175
|
+
)}
|
|
176
|
+
x={0}
|
|
177
|
+
y={0}
|
|
178
|
+
dominant-baseline={tickRotate !== 0
|
|
179
|
+
? 'central'
|
|
180
|
+
: anchor === 'bottom'
|
|
181
|
+
? 'hanging'
|
|
182
|
+
: 'auto'}>
|
|
183
|
+
{#if ticks.length > 0 || t === 0 || t === ticks.length - 1}
|
|
184
|
+
{#if textLines.length === 1}
|
|
185
|
+
{textLines[0]}
|
|
186
|
+
{:else}
|
|
187
|
+
{#each textLines as line, i}
|
|
188
|
+
<tspan x="0" dy={i ? 12 : 0}
|
|
189
|
+
>{!prevTextLines || prevTextLines[i] !== line
|
|
190
|
+
? line
|
|
191
|
+
: ''}</tspan>
|
|
192
|
+
{/each}
|
|
193
|
+
{/if}
|
|
194
|
+
{/if}
|
|
195
|
+
</text>
|
|
196
|
+
</g>
|
|
197
|
+
{/if}
|
|
198
|
+
{/each}
|
|
199
|
+
</g>
|
|
200
|
+
|
|
201
|
+
<style>
|
|
202
|
+
line {
|
|
203
|
+
stroke: currentColor;
|
|
204
|
+
}
|
|
205
|
+
text {
|
|
206
|
+
font-size: 11px;
|
|
207
|
+
opacity: 0.8;
|
|
208
|
+
fill: currentColor;
|
|
209
|
+
}
|
|
210
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ChannelAccessor, ConstantAccessor, PlotState, RawValue, ScaleType } from '../../types.js';
|
|
2
|
+
type BaseAxisXProps = {
|
|
3
|
+
scaleFn: (d: RawValue) => number;
|
|
4
|
+
scaleType: ScaleType;
|
|
5
|
+
ticks: RawValue[];
|
|
6
|
+
tickFormat: (d: RawValue, i: number) => string | string[];
|
|
7
|
+
anchor: 'top' | 'bottom';
|
|
8
|
+
tickSize: number;
|
|
9
|
+
tickPadding: number;
|
|
10
|
+
tickFontSize: ConstantAccessor<number>;
|
|
11
|
+
tickClass: ConstantAccessor<string>;
|
|
12
|
+
marginTop: number;
|
|
13
|
+
height: number;
|
|
14
|
+
title: string;
|
|
15
|
+
options: {
|
|
16
|
+
dx: ConstantAccessor<number>;
|
|
17
|
+
dy: ConstantAccessor<number>;
|
|
18
|
+
filter: ChannelAccessor;
|
|
19
|
+
};
|
|
20
|
+
plot: PlotState;
|
|
21
|
+
};
|
|
22
|
+
declare const BaseAxisX: import("svelte").Component<BaseAxisXProps, {}, "">;
|
|
23
|
+
type BaseAxisX = ReturnType<typeof BaseAxisX>;
|
|
24
|
+
export default BaseAxisX;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getContext, untrack } from 'svelte';
|
|
3
|
+
import { randomId, testFilter } from '../../helpers/index.js';
|
|
4
|
+
import { resolveProp, resolveScaledStyles } from '../../helpers/resolve.js';
|
|
5
|
+
import { max } from 'd3-array';
|
|
6
|
+
import type {
|
|
7
|
+
AutoMarginStores,
|
|
8
|
+
ConstantAccessor,
|
|
9
|
+
PlotState,
|
|
10
|
+
RawValue,
|
|
11
|
+
ScaleType
|
|
12
|
+
} from '../../types.js';
|
|
13
|
+
|
|
14
|
+
type BaseAxisYProps = {
|
|
15
|
+
scaleFn: (d: RawValue) => number;
|
|
16
|
+
scaleType: ScaleType;
|
|
17
|
+
ticks: RawValue[];
|
|
18
|
+
tickFormat: (d: RawValue) => string | string[];
|
|
19
|
+
anchor: 'left' | 'right';
|
|
20
|
+
lineAnchor: 'top' | 'center' | 'bottom';
|
|
21
|
+
tickSize: number;
|
|
22
|
+
tickPadding: number;
|
|
23
|
+
tickFontSize: ConstantAccessor<number>;
|
|
24
|
+
marginLeft: number;
|
|
25
|
+
width: number;
|
|
26
|
+
title: string | null;
|
|
27
|
+
options: {
|
|
28
|
+
dx: ConstantAccessor<number>;
|
|
29
|
+
dy: ConstantAccessor<number>;
|
|
30
|
+
};
|
|
31
|
+
plot: PlotState;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
let {
|
|
35
|
+
scaleFn,
|
|
36
|
+
scaleType,
|
|
37
|
+
ticks,
|
|
38
|
+
tickFormat,
|
|
39
|
+
anchor,
|
|
40
|
+
lineAnchor,
|
|
41
|
+
tickSize,
|
|
42
|
+
tickPadding,
|
|
43
|
+
tickFontSize,
|
|
44
|
+
tickClass,
|
|
45
|
+
marginLeft,
|
|
46
|
+
width,
|
|
47
|
+
title,
|
|
48
|
+
plot,
|
|
49
|
+
options
|
|
50
|
+
}: BaseAxisYProps = $props();
|
|
51
|
+
|
|
52
|
+
const LINE_ANCHOR = {
|
|
53
|
+
top: 'hanging',
|
|
54
|
+
center: 'middle',
|
|
55
|
+
bottom: 'auto'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const positionedTicks = $derived.by(() => {
|
|
59
|
+
let tickObjects = ticks.map((tick, i) => {
|
|
60
|
+
return {
|
|
61
|
+
value: tick,
|
|
62
|
+
hidden: false,
|
|
63
|
+
dx: +resolveProp(options.dx, tick, 0),
|
|
64
|
+
dy: +resolveProp(options.dy, tick, 0),
|
|
65
|
+
y: scaleFn(tick) + (scaleType === 'band' ? scaleFn.bandwidth() * 0.5 : 0),
|
|
66
|
+
text: tickFormat(tick),
|
|
67
|
+
element: null as SVGTextElement | null
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
const T = tickObjects.length;
|
|
71
|
+
for (let i = 0; i < T; i++) {
|
|
72
|
+
let j = i;
|
|
73
|
+
// find the preceeding tick that was not hidden
|
|
74
|
+
do {
|
|
75
|
+
j--;
|
|
76
|
+
} while (j >= 0 && tickObjects[j].hidden);
|
|
77
|
+
if (j >= 0) {
|
|
78
|
+
const tickLabelSpace = Math.abs(tickObjects[i].y - tickObjects[j].y);
|
|
79
|
+
tickObjects[i].hidden = tickLabelSpace < 15;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return tickObjects;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
let tickTexts = $state([] as SVGTextElement[]);
|
|
86
|
+
|
|
87
|
+
// generate id used for registering margins
|
|
88
|
+
const id = randomId();
|
|
89
|
+
|
|
90
|
+
const { autoMarginLeft, autoMarginRight, autoMarginTop } =
|
|
91
|
+
getContext<AutoMarginStores>('svelteplot/autoMargins');
|
|
92
|
+
|
|
93
|
+
$effect(() => {
|
|
94
|
+
untrack(() => [$autoMarginLeft, $autoMarginRight]);
|
|
95
|
+
const outsideTextAnchor = anchor === 'left' ? 'end' : 'start';
|
|
96
|
+
// measure tick label widths
|
|
97
|
+
const maxLabelWidth =
|
|
98
|
+
Math.ceil(
|
|
99
|
+
max(
|
|
100
|
+
positionedTicks.map((tick, i) => {
|
|
101
|
+
if (
|
|
102
|
+
resolveProp(options.textAnchor, tick.value, outsideTextAnchor) !==
|
|
103
|
+
outsideTextAnchor
|
|
104
|
+
)
|
|
105
|
+
return 0;
|
|
106
|
+
if (tick.hidden || !testFilter(tick.value, options)) return 0;
|
|
107
|
+
if (tickTexts[i]) return tickTexts[i].getBoundingClientRect().width;
|
|
108
|
+
return 0;
|
|
109
|
+
}) as number[]
|
|
110
|
+
)
|
|
111
|
+
) + Math.max(0, tickPadding + tickSize);
|
|
112
|
+
|
|
113
|
+
if (!isNaN(maxLabelWidth)) {
|
|
114
|
+
if (anchor === 'left' && $autoMarginLeft.get(id) !== maxLabelWidth) {
|
|
115
|
+
$autoMarginLeft.set(id, maxLabelWidth);
|
|
116
|
+
} else if (anchor === 'right' && $autoMarginRight.get(id) !== maxLabelWidth) {
|
|
117
|
+
$autoMarginRight.set(id, maxLabelWidth);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
$effect(() => {
|
|
123
|
+
untrack(() => [$autoMarginTop]);
|
|
124
|
+
if (title) {
|
|
125
|
+
// add margin top to make some space for title
|
|
126
|
+
$autoMarginTop.set(id, 20);
|
|
127
|
+
} else {
|
|
128
|
+
// no need for extra margin top
|
|
129
|
+
$autoMarginTop.delete(id);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
$effect(() => {
|
|
134
|
+
// clear margins on destroy
|
|
135
|
+
return () => {
|
|
136
|
+
if ($autoMarginLeft.has(id)) $autoMarginLeft.delete(id);
|
|
137
|
+
if ($autoMarginRight.has(id)) $autoMarginRight.delete(id);
|
|
138
|
+
if ($autoMarginTop.has(id)) $autoMarginTop.delete(id);
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
</script>
|
|
142
|
+
|
|
143
|
+
<g class="axis-y">
|
|
144
|
+
{#each positionedTicks as tick, t}
|
|
145
|
+
{#if testFilter(tick.value, options) && !tick.hidden}
|
|
146
|
+
{@const tickClass_ = resolveProp(tickClass, tick.value)}
|
|
147
|
+
<g
|
|
148
|
+
class="tick {tickClass_ || ''}"
|
|
149
|
+
transform="translate({tick.dx +
|
|
150
|
+
marginLeft +
|
|
151
|
+
(anchor === 'left' ? 0 : width)},{tick.y + tick.dy})">
|
|
152
|
+
{#if tickSize}
|
|
153
|
+
<line
|
|
154
|
+
style={resolveScaledStyles(tick.value, options, {}, plot, 'stroke')}
|
|
155
|
+
x2={anchor === 'left' ? -tickSize : tickSize} />
|
|
156
|
+
{/if}
|
|
157
|
+
<text
|
|
158
|
+
bind:this={tickTexts[t]}
|
|
159
|
+
class={{ 'is-left': anchor === 'left' }}
|
|
160
|
+
style={resolveScaledStyles(
|
|
161
|
+
tick.value,
|
|
162
|
+
{ ...options, fontSize: tickFontSize, stroke: null },
|
|
163
|
+
{},
|
|
164
|
+
plot,
|
|
165
|
+
'fill'
|
|
166
|
+
)}
|
|
167
|
+
x={(tickSize + tickPadding) * (anchor === 'left' ? -1 : 1)}
|
|
168
|
+
dominant-baseline={LINE_ANCHOR[lineAnchor]}
|
|
169
|
+
>{Array.isArray(tick.text) ? tick.text.join(' ') : tick.text}</text>
|
|
170
|
+
</g>
|
|
171
|
+
{/if}
|
|
172
|
+
{/each}
|
|
173
|
+
</g>
|
|
174
|
+
|
|
175
|
+
<style>
|
|
176
|
+
line {
|
|
177
|
+
stroke: currentColor;
|
|
178
|
+
}
|
|
179
|
+
text {
|
|
180
|
+
font-size: 11px;
|
|
181
|
+
opacity: 0.8;
|
|
182
|
+
fill: currentColor;
|
|
183
|
+
}
|
|
184
|
+
text.is-left {
|
|
185
|
+
text-anchor: end;
|
|
186
|
+
}
|
|
187
|
+
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ConstantAccessor, PlotState, RawValue, ScaleType } from '../../types.js';
|
|
2
|
+
type BaseAxisYProps = {
|
|
3
|
+
scaleFn: (d: RawValue) => number;
|
|
4
|
+
scaleType: ScaleType;
|
|
5
|
+
ticks: RawValue[];
|
|
6
|
+
tickFormat: (d: RawValue) => string | string[];
|
|
7
|
+
anchor: 'left' | 'right';
|
|
8
|
+
lineAnchor: 'top' | 'center' | 'bottom';
|
|
9
|
+
tickSize: number;
|
|
10
|
+
tickPadding: number;
|
|
11
|
+
tickFontSize: ConstantAccessor<number>;
|
|
12
|
+
marginLeft: number;
|
|
13
|
+
width: number;
|
|
14
|
+
title: string | null;
|
|
15
|
+
options: {
|
|
16
|
+
dx: ConstantAccessor<number>;
|
|
17
|
+
dy: ConstantAccessor<number>;
|
|
18
|
+
};
|
|
19
|
+
plot: PlotState;
|
|
20
|
+
};
|
|
21
|
+
declare const BaseAxisY: import("svelte").Component<BaseAxisYProps, {}, "">;
|
|
22
|
+
type BaseAxisY = ReturnType<typeof BaseAxisY>;
|
|
23
|
+
export default BaseAxisY;
|