layerchart 0.54.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Arc.svelte +170 -144
- package/dist/components/Area.svelte +96 -67
- package/dist/components/Area.svelte.d.ts +1 -0
- package/dist/components/Axis.svelte +205 -155
- package/dist/components/Bar.svelte +72 -45
- package/dist/components/Bars.svelte +45 -34
- package/dist/components/Blur.svelte +5 -3
- package/dist/components/Bounds.svelte +37 -21
- package/dist/components/Brush.svelte +269 -112
- package/dist/components/Brush.svelte.d.ts +7 -0
- package/dist/components/Calendar.svelte +51 -38
- package/dist/components/Chart.svelte +295 -74
- package/dist/components/Chart.svelte.d.ts +17 -17
- package/dist/components/ChartClipPath.svelte +8 -5
- package/dist/components/ChartContext.svelte +243 -93
- package/dist/components/ChartContext.svelte.d.ts +15 -23
- package/dist/components/Circle.svelte +25 -16
- package/dist/components/CircleClipPath.svelte +16 -10
- package/dist/components/ClipPath.svelte +11 -7
- package/dist/components/ColorRamp.svelte +12 -10
- package/dist/components/ForceSimulation.svelte +185 -116
- package/dist/components/Frame.svelte +10 -6
- package/dist/components/GeoCircle.svelte +15 -9
- package/dist/components/GeoContext.svelte +109 -62
- package/dist/components/GeoEdgeFade.svelte +20 -14
- package/dist/components/GeoPath.svelte +107 -69
- package/dist/components/GeoPoint.svelte +32 -18
- package/dist/components/GeoSpline.svelte +30 -22
- package/dist/components/GeoTile.svelte +40 -30
- package/dist/components/GeoVisible.svelte +10 -7
- package/dist/components/Graticule.svelte +14 -8
- package/dist/components/Grid.svelte +75 -48
- package/dist/components/Group.svelte +43 -31
- package/dist/components/Highlight.svelte +284 -243
- package/dist/components/HitCanvas.svelte +75 -42
- package/dist/components/Hull.svelte +40 -20
- package/dist/components/Labels.svelte +81 -70
- package/dist/components/Legend.svelte +105 -74
- package/dist/components/Legend.svelte.d.ts +1 -1
- package/dist/components/Line.svelte +65 -19
- package/dist/components/Line.svelte.d.ts +13 -1
- package/dist/components/LinearGradient.svelte +21 -15
- package/dist/components/Link.svelte +94 -22
- package/dist/components/Link.svelte.d.ts +17 -1
- package/dist/components/Marker.svelte +81 -0
- package/dist/components/Marker.svelte.d.ts +28 -0
- package/dist/components/MonthPath.svelte +23 -16
- package/dist/components/MotionPath.svelte +34 -25
- package/dist/components/Pack.svelte +21 -14
- package/dist/components/Partition.svelte +35 -20
- package/dist/components/Pattern.svelte +8 -6
- package/dist/components/Pie.svelte +76 -57
- package/dist/components/Point.svelte +11 -7
- package/dist/components/Points.svelte +178 -143
- package/dist/components/RadialGradient.svelte +25 -18
- package/dist/components/Rect.svelte +33 -19
- package/dist/components/RectClipPath.svelte +16 -11
- package/dist/components/Rule.svelte +50 -42
- package/dist/components/Sankey.svelte +55 -30
- package/dist/components/Spline.svelte +167 -96
- package/dist/components/Spline.svelte.d.ts +15 -0
- package/dist/components/Text.svelte +137 -104
- package/dist/components/Threshold.svelte +18 -7
- package/dist/components/TileImage.svelte +56 -50
- package/dist/components/TransformContext.svelte +235 -135
- package/dist/components/TransformControls.svelte +57 -29
- package/dist/components/TransformControls.svelte.d.ts +1 -1
- package/dist/components/Tree.svelte +33 -23
- package/dist/components/Treemap.svelte +69 -41
- package/dist/components/Voronoi.svelte +55 -28
- package/dist/components/charts/AreaChart.svelte +138 -87
- package/dist/components/charts/AreaChart.svelte.d.ts +4 -4
- package/dist/components/charts/BarChart.svelte +179 -114
- package/dist/components/charts/BarChart.svelte.d.ts +4 -4
- package/dist/components/charts/LineChart.svelte +97 -53
- package/dist/components/charts/LineChart.svelte.d.ts +4 -4
- package/dist/components/charts/PieChart.svelte +104 -54
- package/dist/components/charts/PieChart.svelte.d.ts +3 -3
- package/dist/components/charts/ScatterChart.svelte +83 -48
- package/dist/components/charts/ScatterChart.svelte.d.ts +4 -4
- package/dist/components/layout/Canvas.svelte +63 -43
- package/dist/components/layout/Html.svelte +28 -18
- package/dist/components/layout/Svg.svelte +47 -32
- package/dist/components/tooltip/Tooltip.svelte +137 -91
- package/dist/components/tooltip/Tooltip.svelte.d.ts +1 -1
- package/dist/components/tooltip/TooltipContext.svelte +315 -249
- package/dist/components/tooltip/TooltipHeader.svelte +9 -3
- package/dist/components/tooltip/TooltipItem.svelte +17 -9
- package/dist/components/tooltip/TooltipList.svelte +2 -1
- package/dist/components/tooltip/TooltipSeparator.svelte +3 -2
- package/dist/docs/Blockquote.svelte +4 -3
- package/dist/docs/Code.svelte +15 -8
- package/dist/docs/CurveMenuField.svelte +17 -12
- package/dist/docs/GeoDebug.svelte +13 -9
- package/dist/docs/Header1.svelte +2 -1
- package/dist/docs/Json.svelte +6 -4
- package/dist/docs/Layout.svelte +6 -6
- package/dist/docs/PathDataMenuField.svelte +52 -44
- package/dist/docs/Preview.svelte +39 -33
- package/dist/docs/TilesetField.svelte +80 -62
- package/dist/docs/TransformDebug.svelte +8 -5
- package/dist/docs/ViewSourceButton.svelte +13 -9
- package/dist/stores/motionStore.d.ts +1 -1
- package/dist/utils/scales.d.ts +3 -3
- package/package.json +29 -30
|
@@ -1,26 +1,42 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { scaleLinear } from 'd3-scale';
|
|
3
|
+
|
|
4
|
+
import { chartContext } from './ChartContext.svelte';
|
|
5
|
+
import { motionScale } from '../utils/scales.js';
|
|
6
|
+
|
|
7
|
+
const { width, height } = chartContext();
|
|
8
|
+
|
|
9
|
+
type Extents = Partial<{ x0: number; y0: number; x1: number; y1: number }>;
|
|
10
|
+
type ExtentsAcccessor = (dimensions: { width: number; height: number }) => Extents;
|
|
11
|
+
|
|
12
|
+
export let domain: Extents | ExtentsAcccessor | null | undefined = undefined;
|
|
13
|
+
export let range: Extents | ExtentsAcccessor | null | undefined = undefined;
|
|
14
|
+
export let spring: boolean | Parameters<typeof motionScale>[1]['spring'] = undefined;
|
|
15
|
+
export let tweened: boolean | Parameters<typeof motionScale>[1]['tweened'] = undefined;
|
|
16
|
+
|
|
17
|
+
function getExtents(
|
|
18
|
+
extents: Extents | ExtentsAcccessor | null | undefined,
|
|
19
|
+
axis: 'x' | 'y',
|
|
20
|
+
fallback: number
|
|
21
|
+
) {
|
|
22
|
+
const resolvedExtents =
|
|
23
|
+
typeof extents === 'function' ? extents({ width: $width, height: $height }) : extents;
|
|
24
|
+
|
|
11
25
|
return [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
// @ts-expect-error
|
|
27
|
+
resolvedExtents?.[axis + '0'] ?? 0, // x0 or y0
|
|
28
|
+
// @ts-expect-error
|
|
29
|
+
resolvedExtents?.[axis + '1'] ?? fallback, // x1 or y1, fallback as $width or $height
|
|
16
30
|
];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
$: xScale.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const xScale = motionScale(scaleLinear as any, { spring, tweened });
|
|
34
|
+
$: xScale.domain(getExtents(domain, 'x', $width));
|
|
35
|
+
$: xScale.range(getExtents(range, 'x', $width));
|
|
36
|
+
|
|
37
|
+
const yScale = motionScale(scaleLinear as any, { spring, tweened });
|
|
38
|
+
$: yScale.domain(getExtents(domain, 'y', $height));
|
|
39
|
+
$: yScale.range(getExtents(range, 'y', $height));
|
|
24
40
|
</script>
|
|
25
41
|
|
|
26
42
|
<slot xScale={$xScale} yScale={$yScale} />
|
|
@@ -1,135 +1,234 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
export let
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export let
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createEventDispatcher, type ComponentProps } from 'svelte';
|
|
3
|
+
import type { SVGAttributes } from 'svelte/elements';
|
|
4
|
+
import { extent, min, max } from 'd3-array';
|
|
5
|
+
import { clamp } from '@layerstack/utils';
|
|
6
|
+
import { cls } from '@layerstack/tailwind';
|
|
7
|
+
import { format as formatValue, type FormatType } from '@layerstack/utils';
|
|
8
|
+
|
|
9
|
+
import { chartContext } from './ChartContext.svelte';
|
|
10
|
+
import Frame from './Frame.svelte';
|
|
11
|
+
import Group from './Group.svelte';
|
|
12
|
+
import Text from './Text.svelte';
|
|
13
|
+
|
|
14
|
+
import { localPoint } from '../utils/event.js';
|
|
15
|
+
|
|
16
|
+
const { xScale, yScale, width, height, padding } = chartContext();
|
|
17
|
+
|
|
18
|
+
const dispatch = createEventDispatcher<{
|
|
19
|
+
change: { xDomain?: [any, any]; yDomain?: [any, any] };
|
|
20
|
+
brushStart: { xDomain?: [any, any]; yDomain?: [any, any] };
|
|
21
|
+
brushEnd: { xDomain?: [any, any]; yDomain?: [any, any] };
|
|
22
|
+
}>();
|
|
23
|
+
|
|
24
|
+
/** Axis to apply brushing */
|
|
25
|
+
export let axis: 'x' | 'y' | 'both' = 'x';
|
|
26
|
+
|
|
27
|
+
/** Size of draggable handles (width/height) */
|
|
28
|
+
export let handleSize = 5;
|
|
29
|
+
|
|
30
|
+
/** Only show range while actively brushing. Useful with `brushEnd` event */
|
|
31
|
+
export let resetOnEnd = false;
|
|
32
|
+
|
|
33
|
+
export let xDomain: [number | Date | null, number | Date | null] = $xScale.domain() as [
|
|
34
|
+
number,
|
|
35
|
+
number,
|
|
36
|
+
];
|
|
37
|
+
export let yDomain: [number | Date | null, number | Date | null] = $yScale.domain() as [
|
|
38
|
+
number,
|
|
39
|
+
number,
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
export let labels: ComponentProps<Text> | boolean = false;
|
|
43
|
+
|
|
44
|
+
// Capture original domains for reset()
|
|
45
|
+
const originalXDomain = $xScale.domain() as [number, number];
|
|
46
|
+
const originalYDomain = $yScale.domain() as [number, number];
|
|
47
|
+
|
|
48
|
+
$: [xDomainMin, xDomainMax] = extent<number>($xScale.domain()) as [number, number];
|
|
49
|
+
$: [yDomainMin, yDomainMax] = extent<number>($yScale.domain()) as [number, number];
|
|
50
|
+
|
|
51
|
+
/** Attributes passed to range <rect> element */
|
|
52
|
+
export let range: SVGAttributes<SVGRectElement> | undefined = undefined;
|
|
53
|
+
|
|
54
|
+
/** Attributes passed to handle <rect> elements */
|
|
55
|
+
export let handle: SVGAttributes<SVGRectElement> | undefined = undefined;
|
|
56
|
+
|
|
57
|
+
/** Apply format to labels, if shown */
|
|
58
|
+
export let format: FormatType | undefined = undefined;
|
|
59
|
+
|
|
60
|
+
export let classes: {
|
|
61
|
+
root?: string;
|
|
62
|
+
frame?: string;
|
|
63
|
+
range?: string;
|
|
64
|
+
handle?: string;
|
|
65
|
+
labels?: string;
|
|
66
|
+
} = {};
|
|
67
|
+
|
|
68
|
+
let frameEl: SVGRectElement;
|
|
69
|
+
|
|
70
|
+
function handler(
|
|
71
|
+
fn: (
|
|
72
|
+
start: {
|
|
73
|
+
xDomain: [number, number];
|
|
74
|
+
yDomain: [number, number];
|
|
75
|
+
value: { x: number; y: number };
|
|
76
|
+
},
|
|
77
|
+
value: { x: number; y: number }
|
|
78
|
+
) => void
|
|
79
|
+
) {
|
|
80
|
+
return (e: PointerEvent) => {
|
|
81
|
+
const start = {
|
|
82
|
+
xDomain: [xDomain[0] ?? xDomainMin, xDomain[1] ?? xDomainMax] as [number, number],
|
|
83
|
+
yDomain: [yDomain[0] ?? yDomainMin, yDomain[1] ?? yDomainMax] as [number, number],
|
|
84
|
+
value: {
|
|
85
|
+
x: $xScale.invert?.((localPoint(frameEl, e)?.x ?? 0) - $padding.left),
|
|
86
|
+
y: $yScale.invert?.((localPoint(frameEl, e)?.y ?? 0) - $padding.top),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
dispatch('brushStart', { xDomain, yDomain });
|
|
91
|
+
|
|
92
|
+
const onPointerMove = (e: PointerEvent) => {
|
|
93
|
+
fn(start, {
|
|
94
|
+
x: $xScale.invert?.((localPoint(frameEl, e)?.x ?? 0) - $padding.left),
|
|
95
|
+
y: $yScale.invert?.((localPoint(frameEl, e)?.y ?? 0) - $padding.top),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// if (xDomain[0] === xDomain[1] || yDomain[0] === yDomain[1]) {
|
|
99
|
+
// // Ignore?
|
|
100
|
+
// // TODO: What about when using `x` or `y` axis?
|
|
101
|
+
// } else {
|
|
102
|
+
dispatch('change', { xDomain, yDomain });
|
|
103
|
+
// }
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const onPointerUp = (e: PointerEvent) => {
|
|
107
|
+
if (e.target === frameEl) {
|
|
108
|
+
reset();
|
|
109
|
+
dispatch('change', { xDomain, yDomain });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
dispatch('brushEnd', { xDomain, yDomain });
|
|
113
|
+
|
|
114
|
+
if (resetOnEnd) {
|
|
115
|
+
reset();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
window.removeEventListener('pointermove', onPointerMove);
|
|
119
|
+
window.removeEventListener('pointerup', onPointerUp);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
window.addEventListener('pointermove', onPointerMove);
|
|
123
|
+
window.addEventListener('pointerup', onPointerUp);
|
|
67
124
|
};
|
|
68
|
-
}
|
|
69
|
-
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Add second value while maintaining `Date` or `number` type */
|
|
128
|
+
function add(value1: Date | number, value2: number) {
|
|
129
|
+
if (value1 instanceof Date) {
|
|
130
|
+
return new Date(value1.getTime() + value2);
|
|
131
|
+
} else {
|
|
132
|
+
return value1 + value2;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const createRange = handler((start, value) => {
|
|
70
137
|
isActive = true;
|
|
138
|
+
|
|
71
139
|
xDomain = [
|
|
72
|
-
|
|
73
|
-
|
|
140
|
+
// @ts-expect-error
|
|
141
|
+
clamp(min([start.value.x, value.x]), xDomainMin, xDomainMax),
|
|
142
|
+
// @ts-expect-error
|
|
143
|
+
clamp(max([start.value.x, value.x]), xDomainMin, xDomainMax),
|
|
74
144
|
];
|
|
145
|
+
// xDomain = [start.value.x, value.x];
|
|
146
|
+
|
|
75
147
|
yDomain = [
|
|
76
|
-
|
|
77
|
-
|
|
148
|
+
// @ts-expect-error
|
|
149
|
+
clamp(min([start.value.y, value.y]), yDomainMin, yDomainMax),
|
|
150
|
+
// @ts-expect-error
|
|
151
|
+
clamp(max([start.value.y, value.y]), yDomainMin, yDomainMax),
|
|
78
152
|
];
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const adjustRange = handler((start, value) => {
|
|
156
|
+
const dx = clamp(
|
|
157
|
+
value.x - start.value.x,
|
|
158
|
+
xDomainMin - start.xDomain[0],
|
|
159
|
+
xDomainMax - start.xDomain[1]
|
|
160
|
+
);
|
|
161
|
+
xDomain = [add(start.xDomain[0], dx), add(start.xDomain[1], dx)];
|
|
162
|
+
|
|
163
|
+
const dy = clamp(
|
|
164
|
+
value.y - start.value.y,
|
|
165
|
+
yDomainMin - start.yDomain[0],
|
|
166
|
+
yDomainMax - start.yDomain[1]
|
|
167
|
+
);
|
|
168
|
+
yDomain = [add(start.yDomain[0], dy), add(start.yDomain[1], dy)];
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const adjustBottom = handler((start, value) => {
|
|
87
172
|
yDomain = [
|
|
88
|
-
|
|
89
|
-
|
|
173
|
+
clamp(value.y > start.yDomain[1] ? start.yDomain[1] : value.y, yDomainMin, yDomainMax),
|
|
174
|
+
clamp(value.y > start.yDomain[1] ? value.y : start.yDomain[1], yDomainMin, yDomainMax),
|
|
90
175
|
];
|
|
91
|
-
});
|
|
92
|
-
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const adjustTop = handler((start, value) => {
|
|
93
179
|
yDomain = [
|
|
94
|
-
|
|
95
|
-
|
|
180
|
+
clamp(value.y < start.yDomain[1] ? value.y : start.yDomain[0], yDomainMin, yDomainMax),
|
|
181
|
+
clamp(value.y < start.yDomain[1] ? start.yDomain[0] : value.y, yDomainMin, yDomainMax),
|
|
96
182
|
];
|
|
97
|
-
});
|
|
98
|
-
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const adjustLeft = handler((start, value) => {
|
|
99
186
|
xDomain = [
|
|
100
|
-
|
|
101
|
-
|
|
187
|
+
clamp(value.x > start.xDomain[1] ? start.xDomain[1] : value.x, xDomainMin, xDomainMax),
|
|
188
|
+
clamp(value.x > start.xDomain[1] ? value.x : start.xDomain[1], xDomainMin, xDomainMax),
|
|
102
189
|
];
|
|
103
|
-
});
|
|
104
|
-
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const adjustRight = handler((start, value) => {
|
|
105
193
|
xDomain = [
|
|
106
|
-
|
|
107
|
-
|
|
194
|
+
clamp(value.x < start.xDomain[0] ? value.x : start.xDomain[0], xDomainMin, xDomainMax),
|
|
195
|
+
clamp(value.x < start.xDomain[0] ? start.xDomain[0] : value.x, xDomainMin, xDomainMax),
|
|
108
196
|
];
|
|
109
|
-
});
|
|
110
|
-
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
function reset() {
|
|
111
200
|
isActive = false;
|
|
201
|
+
|
|
112
202
|
xDomain = originalXDomain;
|
|
113
203
|
yDomain = originalYDomain;
|
|
114
|
-
}
|
|
115
|
-
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function selectAll() {
|
|
116
207
|
xDomain = [xDomainMin, xDomainMax];
|
|
117
208
|
yDomain = [yDomainMin, yDomainMax];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
$:
|
|
121
|
-
$:
|
|
122
|
-
$:
|
|
123
|
-
$:
|
|
124
|
-
|
|
125
|
-
$:
|
|
126
|
-
$:
|
|
127
|
-
|
|
128
|
-
$:
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
$: top = $yScale(yDomain[1]);
|
|
212
|
+
$: bottom = $yScale(yDomain[0]);
|
|
213
|
+
$: left = $xScale(xDomain[0]);
|
|
214
|
+
$: right = $xScale(xDomain[1]);
|
|
215
|
+
|
|
216
|
+
$: rangeTop = axis === 'both' || axis === 'y' ? top : 0;
|
|
217
|
+
$: rangeLeft = axis === 'both' || axis === 'x' ? left : 0;
|
|
218
|
+
$: rangeWidth = axis === 'both' || axis === 'x' ? right - left : $width;
|
|
219
|
+
$: rangeHeight = axis === 'both' || axis === 'y' ? bottom - top : $height;
|
|
220
|
+
|
|
221
|
+
// Set reactively to handle cases where xDomain/yDomain are set externally (ex. `bind:xDomain`)
|
|
222
|
+
$: isActive =
|
|
129
223
|
xDomain[0]?.valueOf() !== originalXDomain[0]?.valueOf() ||
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
224
|
+
xDomain[1]?.valueOf() !== originalXDomain[1]?.valueOf() ||
|
|
225
|
+
yDomain[0]?.valueOf() !== originalYDomain[0]?.valueOf() ||
|
|
226
|
+
yDomain[1]?.valueOf() !== originalYDomain[1]?.valueOf();
|
|
227
|
+
|
|
228
|
+
/** TODO: Fix types and remove workaround (Svelte 5)*/
|
|
229
|
+
function any(value: any): any {
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
133
232
|
</script>
|
|
134
233
|
|
|
135
234
|
<g class={cls('Brush select-none', classes.root, $$props.class)}>
|
|
@@ -242,6 +341,64 @@ $: isActive =
|
|
|
242
341
|
</Group>
|
|
243
342
|
{/if}
|
|
244
343
|
|
|
344
|
+
<slot name="labels">
|
|
345
|
+
{#if labels}
|
|
346
|
+
{@const labelClass = cls(
|
|
347
|
+
'text-xs',
|
|
348
|
+
classes.labels,
|
|
349
|
+
typeof labels === 'object' ? labels.class : null
|
|
350
|
+
)}
|
|
351
|
+
|
|
352
|
+
{#if axis === 'x' || axis === 'both'}
|
|
353
|
+
<Text
|
|
354
|
+
x={left}
|
|
355
|
+
y={rangeTop + rangeHeight / 2}
|
|
356
|
+
dx={-4}
|
|
357
|
+
textAnchor="end"
|
|
358
|
+
verticalAnchor="middle"
|
|
359
|
+
value={formatValue(any(xDomain[0]), format)}
|
|
360
|
+
{...typeof labels === 'object' ? labels : null}
|
|
361
|
+
class={labelClass}
|
|
362
|
+
/>
|
|
363
|
+
|
|
364
|
+
<Text
|
|
365
|
+
x={right}
|
|
366
|
+
y={rangeTop + rangeHeight / 2}
|
|
367
|
+
dx={4}
|
|
368
|
+
textAnchor="start"
|
|
369
|
+
verticalAnchor="middle"
|
|
370
|
+
value={formatValue(any(xDomain[1]), format)}
|
|
371
|
+
{...typeof labels === 'object' ? labels : null}
|
|
372
|
+
class={labelClass}
|
|
373
|
+
/>
|
|
374
|
+
{/if}
|
|
375
|
+
|
|
376
|
+
{#if axis === 'y' || axis === 'both'}
|
|
377
|
+
<Text
|
|
378
|
+
x={rangeLeft + rangeWidth / 2}
|
|
379
|
+
y={top}
|
|
380
|
+
dy={-4}
|
|
381
|
+
textAnchor="middle"
|
|
382
|
+
verticalAnchor="end"
|
|
383
|
+
value={formatValue(any(yDomain[1]), format)}
|
|
384
|
+
{...typeof labels === 'object' ? labels : null}
|
|
385
|
+
class={labelClass}
|
|
386
|
+
/>
|
|
387
|
+
|
|
388
|
+
<Text
|
|
389
|
+
x={rangeLeft + rangeWidth / 2}
|
|
390
|
+
y={bottom}
|
|
391
|
+
dy={4}
|
|
392
|
+
textAnchor="middle"
|
|
393
|
+
verticalAnchor="start"
|
|
394
|
+
value={formatValue(any(yDomain[0]), format)}
|
|
395
|
+
{...typeof labels === 'object' ? labels : null}
|
|
396
|
+
class={labelClass}
|
|
397
|
+
/>
|
|
398
|
+
{/if}
|
|
399
|
+
{/if}
|
|
400
|
+
</slot>
|
|
401
|
+
|
|
245
402
|
<!-- TODO: Add diagonal/corner handles -->
|
|
246
403
|
{/if}
|
|
247
404
|
</g>
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { type ComponentProps } from 'svelte';
|
|
2
3
|
import type { SVGAttributes } from 'svelte/elements';
|
|
4
|
+
import { type FormatType } from '@layerstack/utils';
|
|
5
|
+
import Text from './Text.svelte';
|
|
3
6
|
declare const __propDef: {
|
|
4
7
|
props: {
|
|
5
8
|
[x: string]: any;
|
|
@@ -8,13 +11,16 @@ declare const __propDef: {
|
|
|
8
11
|
resetOnEnd?: boolean | undefined;
|
|
9
12
|
xDomain?: [number | Date | null, number | Date | null] | undefined;
|
|
10
13
|
yDomain?: [number | Date | null, number | Date | null] | undefined;
|
|
14
|
+
labels?: (ComponentProps<Text> | boolean) | undefined;
|
|
11
15
|
range?: SVGAttributes<SVGRectElement> | undefined;
|
|
12
16
|
handle?: SVGAttributes<SVGRectElement> | undefined;
|
|
17
|
+
format?: FormatType | undefined;
|
|
13
18
|
classes?: {
|
|
14
19
|
root?: string;
|
|
15
20
|
frame?: string;
|
|
16
21
|
range?: string;
|
|
17
22
|
handle?: string;
|
|
23
|
+
labels?: string;
|
|
18
24
|
} | undefined;
|
|
19
25
|
};
|
|
20
26
|
events: {
|
|
@@ -43,6 +49,7 @@ declare const __propDef: {
|
|
|
43
49
|
rangeWidth: any;
|
|
44
50
|
rangeHeight: any;
|
|
45
51
|
};
|
|
52
|
+
labels: {};
|
|
46
53
|
};
|
|
47
54
|
};
|
|
48
55
|
export type BrushProps = typeof __propDef.props;
|
|
@@ -1,46 +1,59 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export let
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { type ComponentProps } from 'svelte';
|
|
3
|
+
import { timeDays, timeMonths, timeWeek, timeYear } from 'd3-time';
|
|
4
|
+
import { index } from 'd3-array';
|
|
5
|
+
import { format } from 'date-fns';
|
|
6
|
+
|
|
7
|
+
import { chartContext } from './ChartContext.svelte';
|
|
8
|
+
import Rect from './Rect.svelte';
|
|
9
|
+
import type { TooltipContextValue } from './tooltip/TooltipContext.svelte';
|
|
10
|
+
import MonthPath from './MonthPath.svelte';
|
|
11
|
+
import Text from './Text.svelte';
|
|
12
|
+
import { chartDataArray } from '../utils/common.js';
|
|
13
|
+
|
|
14
|
+
export let start: Date;
|
|
15
|
+
export let end: Date;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Size of cell. If `number`, sets width/height as same value (square). If array, sets as [width,height]. If undefined, is derived from Chart width/height
|
|
19
|
+
*/
|
|
20
|
+
export let cellSize: number | [number, number] | undefined = undefined;
|
|
21
|
+
|
|
22
|
+
/** Enable drawing path around each month. If object, pass as props to underlying <path> */
|
|
23
|
+
export let monthPath: boolean | Partial<ComponentProps<MonthPath>> = false;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Tooltip context to setup mouse events to show tooltip for related data
|
|
27
|
+
*/
|
|
28
|
+
export let tooltip: TooltipContextValue | undefined = undefined;
|
|
29
|
+
|
|
30
|
+
const { width, height, x, cGet, data, config } = chartContext();
|
|
31
|
+
|
|
32
|
+
$: yearDays = timeDays(start, end);
|
|
33
|
+
$: yearMonths = timeMonths(start, end);
|
|
34
|
+
$: yearWeeks = timeWeek.count(start, end);
|
|
35
|
+
|
|
36
|
+
$: chartCellWidth = $width / (yearWeeks + 1);
|
|
37
|
+
$: chartCellHeight = $height / 7;
|
|
38
|
+
$: chartCellSize = Math.min(chartCellWidth, chartCellHeight); // Use smallest to fit, and keep square aspect
|
|
39
|
+
|
|
40
|
+
$: [cellWidth, cellHeight] = Array.isArray(cellSize)
|
|
30
41
|
? cellSize
|
|
31
42
|
: typeof cellSize === 'number'
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
$:
|
|
43
|
+
? [cellSize, cellSize]
|
|
44
|
+
: [chartCellSize, chartCellSize];
|
|
45
|
+
|
|
46
|
+
$: dataByDate = data && $config.x ? index(chartDataArray($data), (d) => $x(d)) : new Map();
|
|
47
|
+
|
|
48
|
+
$: cells = yearDays.map((date) => {
|
|
36
49
|
const cellData = dataByDate.get(date) ?? { date };
|
|
37
50
|
return {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
x: timeWeek.count(timeYear(date), date) * cellWidth,
|
|
52
|
+
y: date.getDay() * cellHeight,
|
|
53
|
+
color: $config.c ? $cGet(cellData) : 'transparent',
|
|
54
|
+
data: cellData,
|
|
42
55
|
};
|
|
43
|
-
});
|
|
56
|
+
});
|
|
44
57
|
</script>
|
|
45
58
|
|
|
46
59
|
<slot {cells}>
|