layerchart 2.0.0-next.38 → 2.0.0-next.39
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/AnnotationLine.svelte +15 -2
- package/dist/components/AnnotationPoint.svelte +13 -2
- package/dist/components/AnnotationRange.svelte +16 -2
- package/dist/components/Arc.svelte +3 -3
- package/dist/components/Area.svelte +10 -2
- package/dist/components/Axis.svelte +43 -26
- package/dist/components/Bar.svelte +6 -5
- package/dist/components/Bar.svelte.d.ts +2 -2
- package/dist/components/Bars.svelte +3 -3
- package/dist/components/Blur.svelte +2 -3
- package/dist/components/BrushContext.svelte +44 -44
- package/dist/components/Calendar.svelte +21 -4
- package/dist/components/Chart.svelte +1 -2
- package/dist/components/ChartClipPath.svelte +1 -1
- package/dist/components/Circle.svelte +44 -3
- package/dist/components/CircleClipPath.svelte +8 -1
- package/dist/components/ClipPath.svelte +1 -2
- package/dist/components/ColorRamp.svelte +1 -1
- package/dist/components/ComputedStyles.svelte +9 -2
- package/dist/components/Connector.svelte +1 -1
- package/dist/components/Ellipse.svelte +44 -3
- package/dist/components/Frame.svelte +1 -1
- package/dist/components/GeoCircle.svelte +1 -1
- package/dist/components/GeoEdgeFade.svelte +1 -1
- package/dist/components/GeoPath.svelte +18 -3
- package/dist/components/GeoPoint.svelte +3 -3
- package/dist/components/GeoSpline.svelte +1 -1
- package/dist/components/GeoTile.svelte +1 -1
- package/dist/components/Graticule.svelte +5 -5
- package/dist/components/Grid.svelte +57 -60
- package/dist/components/Group.svelte +11 -6
- package/dist/components/Highlight.svelte +46 -22
- package/dist/components/Highlight.svelte.d.ts +4 -0
- package/dist/components/Hull.svelte +11 -4
- package/dist/components/Labels.svelte +21 -11
- package/dist/components/Legend.svelte +133 -67
- package/dist/components/Legend.svelte.d.ts +7 -3
- package/dist/components/Line.svelte +40 -3
- package/dist/components/LinearGradient.svelte +35 -4
- package/dist/components/Link.svelte +1 -1
- package/dist/components/Marker.svelte +37 -26
- package/dist/components/MonthPath.svelte +14 -3
- package/dist/components/MotionPath.svelte +1 -1
- package/dist/components/Pattern.svelte +5 -5
- package/dist/components/Pie.svelte +1 -2
- package/dist/components/Points.svelte +1 -1
- package/dist/components/Polygon.svelte +27 -3
- package/dist/components/RadialGradient.svelte +3 -3
- package/dist/components/Rect.svelte +55 -5
- package/dist/components/Rect.svelte.d.ts +2 -2
- package/dist/components/RectClipPath.svelte +4 -3
- package/dist/components/RectClipPath.svelte.d.ts +2 -2
- package/dist/components/Rule.svelte +30 -23
- package/dist/components/Spline.svelte +29 -10
- package/dist/components/Text.svelte +59 -13
- package/dist/components/TileImage.svelte +19 -4
- package/dist/components/TransformContext.svelte +9 -3
- package/dist/components/TransformControls.svelte +72 -17
- package/dist/components/Voronoi.svelte +12 -13
- package/dist/components/charts/ArcChart.svelte +40 -69
- package/dist/components/charts/AreaChart.svelte +19 -42
- package/dist/components/charts/BarChart.svelte +7 -18
- package/dist/components/charts/DefaultTooltip.svelte +2 -2
- package/dist/components/charts/DefaultTooltip.svelte.d.ts +1 -1
- package/dist/components/charts/LineChart.svelte +61 -66
- package/dist/components/charts/LineChart.svelte.d.ts +11 -5
- package/dist/components/charts/PieChart.svelte +41 -69
- package/dist/components/charts/ScatterChart.svelte +8 -19
- package/dist/components/charts/utils.svelte.d.ts +1 -19
- package/dist/components/charts/utils.svelte.js +7 -39
- package/dist/components/layout/Canvas.svelte +29 -20
- package/dist/components/layout/Html.svelte +15 -9
- package/dist/components/layout/Svg.svelte +19 -11
- package/dist/components/layout/WebGL.svelte +26 -6
- package/dist/components/layout/WebGL.svelte.d.ts +5 -2
- package/dist/components/tooltip/Tooltip.svelte +60 -29
- package/dist/components/tooltip/TooltipContext.svelte +73 -36
- package/dist/components/tooltip/TooltipContext.svelte.d.ts +7 -0
- package/dist/components/tooltip/TooltipHeader.svelte +27 -14
- package/dist/components/tooltip/TooltipItem.svelte +41 -33
- package/dist/components/tooltip/TooltipList.svelte +12 -10
- package/dist/components/tooltip/TooltipSeparator.svelte +18 -10
- package/dist/states/series.svelte.d.ts +30 -0
- package/dist/states/series.svelte.js +54 -0
- package/dist/styles/daisyui-5.css +6 -0
- package/dist/styles/shadcn-svelte.css +11 -0
- package/dist/styles/skeleton-3.css +15 -0
- package/dist/utils/attributes.d.ts +3 -13
- package/dist/utils/attributes.js +4 -18
- package/dist/utils/common.d.ts +9 -0
- package/dist/utils/common.js +18 -1
- package/dist/utils/common.test.js +26 -1
- package/dist/utils/math.d.ts +17 -0
- package/dist/utils/math.js +17 -0
- package/dist/utils/types.d.ts +15 -2
- package/package.json +5 -1
|
@@ -44,12 +44,11 @@
|
|
|
44
44
|
LineChartExtraSnippetProps<TData>
|
|
45
45
|
> & {
|
|
46
46
|
/**
|
|
47
|
-
* The
|
|
47
|
+
* The orientation of the line chart.
|
|
48
|
+
*
|
|
49
|
+
* @default 'horizontal'
|
|
48
50
|
*/
|
|
49
|
-
|
|
50
|
-
e: MouseEvent,
|
|
51
|
-
details: { data: HighlightPointData; series: SeriesData<TData, typeof Spline> }
|
|
52
|
-
) => void;
|
|
51
|
+
orientation?: 'vertical' | 'horizontal';
|
|
53
52
|
|
|
54
53
|
props?: LineChartPropsObjProp;
|
|
55
54
|
|
|
@@ -64,6 +63,14 @@
|
|
|
64
63
|
seriesIndex: number;
|
|
65
64
|
}
|
|
66
65
|
>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The event to be dispatched when the point is clicked.
|
|
69
|
+
*/
|
|
70
|
+
onPointClick?: (
|
|
71
|
+
e: MouseEvent,
|
|
72
|
+
details: { data: HighlightPointData; series: SeriesData<TData, typeof Spline> }
|
|
73
|
+
) => void;
|
|
67
74
|
};
|
|
68
75
|
</script>
|
|
69
76
|
|
|
@@ -83,12 +90,7 @@
|
|
|
83
90
|
import Rule from '../Rule.svelte';
|
|
84
91
|
import Spline from '../Spline.svelte';
|
|
85
92
|
|
|
86
|
-
import {
|
|
87
|
-
accessor,
|
|
88
|
-
chartDataArray,
|
|
89
|
-
defaultChartPadding,
|
|
90
|
-
findRelatedData,
|
|
91
|
-
} from '../../utils/common.js';
|
|
93
|
+
import { chartDataArray, defaultChartPadding, findRelatedData } from '../../utils/common.js';
|
|
92
94
|
import { asAny } from '../../utils/types.js';
|
|
93
95
|
import type {
|
|
94
96
|
SeriesData,
|
|
@@ -96,18 +98,22 @@
|
|
|
96
98
|
SimplifiedChartPropsObject,
|
|
97
99
|
SimplifiedChartSnippet,
|
|
98
100
|
} from './types.js';
|
|
99
|
-
import {
|
|
101
|
+
import { SeriesState } from '../../states/series.svelte.js';
|
|
102
|
+
import { createLegendProps } from './utils.svelte.js';
|
|
100
103
|
import { setTooltipMetaContext } from '../tooltip/tooltipMetaContext.js';
|
|
101
|
-
import { layerClass } from '../../utils/attributes.js';
|
|
102
104
|
import DefaultTooltip from './DefaultTooltip.svelte';
|
|
103
105
|
import ChartAnnotations from './ChartAnnotations.svelte';
|
|
106
|
+
import { isScaleTime } from '../../utils/scales.svelte.js';
|
|
104
107
|
|
|
105
108
|
let {
|
|
106
109
|
data = [],
|
|
107
110
|
x: xProp,
|
|
108
|
-
|
|
111
|
+
xScale,
|
|
109
112
|
xDomain,
|
|
113
|
+
y: yProp,
|
|
114
|
+
yScale,
|
|
110
115
|
radial = false,
|
|
116
|
+
orientation = 'horizontal',
|
|
111
117
|
series: seriesProp,
|
|
112
118
|
seriesLayout = 'overlap',
|
|
113
119
|
axis = true,
|
|
@@ -137,14 +143,23 @@
|
|
|
137
143
|
...restProps
|
|
138
144
|
}: LineChartProps<TData> = $props();
|
|
139
145
|
|
|
146
|
+
const isVertical = $derived(orientation === 'vertical');
|
|
147
|
+
|
|
140
148
|
const series = $derived(
|
|
141
149
|
seriesProp === undefined
|
|
142
150
|
? [
|
|
143
151
|
{
|
|
144
152
|
key: 'default',
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
153
|
+
|
|
154
|
+
label: isVertical
|
|
155
|
+
? typeof xProp === 'string'
|
|
156
|
+
? xProp
|
|
157
|
+
: 'value'
|
|
158
|
+
: typeof yProp === 'string'
|
|
159
|
+
? yProp
|
|
160
|
+
: 'value',
|
|
161
|
+
value: isVertical ? xProp : yProp,
|
|
162
|
+
color: 'var(--color-primary, currentColor)',
|
|
148
163
|
},
|
|
149
164
|
]
|
|
150
165
|
: seriesProp
|
|
@@ -160,21 +175,15 @@
|
|
|
160
175
|
function getSplineProps(s: SeriesData<TData, typeof Spline>, i: number) {
|
|
161
176
|
const splineProps: ComponentProps<typeof Spline> = {
|
|
162
177
|
data: s.data,
|
|
163
|
-
|
|
178
|
+
x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
179
|
+
y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
164
180
|
stroke: s.color,
|
|
181
|
+
opacity:
|
|
182
|
+
// Checking `visibleSeries.length <= 1` fixes re-animated tweened areas on hover
|
|
183
|
+
seriesState.visibleSeries.length <= 1 || seriesState.isHighlighted(s.key, true) ? 1 : 0.1,
|
|
165
184
|
...props.spline,
|
|
166
185
|
...s.props,
|
|
167
|
-
class: cls(
|
|
168
|
-
layerClass('line-chart-line'),
|
|
169
|
-
'transition-opacity',
|
|
170
|
-
// Checking `visibleSeries.length > 1` fixes re-animated tweened areas on hover
|
|
171
|
-
seriesState.visibleSeries.length > 1 &&
|
|
172
|
-
seriesState.highlightKey.current &&
|
|
173
|
-
seriesState.highlightKey.current !== s.key &&
|
|
174
|
-
'opacity-10',
|
|
175
|
-
props.spline?.class,
|
|
176
|
-
s.props?.class
|
|
177
|
-
),
|
|
186
|
+
class: cls(props.spline?.class, s.props?.class),
|
|
178
187
|
};
|
|
179
188
|
|
|
180
189
|
return splineProps;
|
|
@@ -183,18 +192,14 @@
|
|
|
183
192
|
function getPointsProps(s: SeriesData<TData, typeof Spline>, i: number) {
|
|
184
193
|
const pointsProps: ComponentProps<typeof Points> = {
|
|
185
194
|
data: s.data,
|
|
186
|
-
|
|
195
|
+
x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
196
|
+
y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
187
197
|
fill: s.color,
|
|
198
|
+
stroke: 'var(--color-surface-100, light-dark(white, black))',
|
|
199
|
+
opacity: seriesState.isHighlighted(s.key, true) ? 1 : 0.1,
|
|
188
200
|
...props.points,
|
|
189
201
|
...(typeof points === 'object' ? points : null),
|
|
190
|
-
class: cls(
|
|
191
|
-
'stroke-surface-200 transition-opacity',
|
|
192
|
-
seriesState.highlightKey.current &&
|
|
193
|
-
seriesState.highlightKey.current !== s.key &&
|
|
194
|
-
'opacity-10',
|
|
195
|
-
props.points?.class,
|
|
196
|
-
typeof points === 'object' && points.class
|
|
197
|
-
),
|
|
202
|
+
class: cls(props.points?.class, typeof points === 'object' && points.class),
|
|
198
203
|
};
|
|
199
204
|
|
|
200
205
|
return pointsProps;
|
|
@@ -203,26 +208,17 @@
|
|
|
203
208
|
function getLabelsProps(s: SeriesData<TData, typeof Spline>, i: number) {
|
|
204
209
|
const labelsProps: ComponentProps<typeof Labels<TData>> = {
|
|
205
210
|
data: s.data,
|
|
206
|
-
|
|
211
|
+
x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
212
|
+
y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
213
|
+
opacity: seriesState.isHighlighted(s.key, true) ? 1 : 0.1,
|
|
207
214
|
...props.labels,
|
|
208
215
|
...(typeof labels === 'object' ? labels : null),
|
|
209
|
-
class: cls(
|
|
210
|
-
'stroke-surface-200 transition-opacity',
|
|
211
|
-
seriesState.highlightKey.current &&
|
|
212
|
-
seriesState.highlightKey.current !== s.key &&
|
|
213
|
-
'opacity-10',
|
|
214
|
-
props.labels?.class,
|
|
215
|
-
typeof labels === 'object' && labels.class
|
|
216
|
-
),
|
|
216
|
+
class: cls(props.labels?.class, typeof labels === 'object' && labels.class),
|
|
217
217
|
};
|
|
218
218
|
|
|
219
219
|
return labelsProps;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
const highlightPointsProps = $derived(
|
|
223
|
-
typeof props.highlight?.points === 'object' ? props.highlight.points : null
|
|
224
|
-
);
|
|
225
|
-
|
|
226
222
|
function getHighlightProps(
|
|
227
223
|
s: SeriesData<TData, typeof Spline>,
|
|
228
224
|
i: number
|
|
@@ -230,18 +226,22 @@
|
|
|
230
226
|
if (!context || !context.tooltip.data) return {};
|
|
231
227
|
const seriesTooltipData =
|
|
232
228
|
s.data && context.tooltip.data
|
|
233
|
-
? findRelatedData(s.data, context.tooltip.data, context.x)
|
|
229
|
+
? (findRelatedData(s.data, context.tooltip.data, context.x) ?? {})
|
|
234
230
|
: null;
|
|
231
|
+
const highlightPointsProps =
|
|
232
|
+
typeof props.highlight?.points === 'object' ? props.highlight.points : null;
|
|
235
233
|
|
|
236
234
|
return {
|
|
237
235
|
data: seriesTooltipData,
|
|
238
|
-
|
|
236
|
+
x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
237
|
+
y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined,
|
|
239
238
|
lines: i === 0,
|
|
240
239
|
onPointClick: onPointClick
|
|
241
240
|
? (e, detail) => onPointClick(e, { ...detail, series: s })
|
|
242
241
|
: undefined,
|
|
243
242
|
onPointEnter: () => (seriesState.highlightKey.current = s.key),
|
|
244
243
|
onPointLeave: () => (seriesState.highlightKey.current = null),
|
|
244
|
+
opacity: seriesState.isHighlighted(s.key, true) ? 1 : 0.1,
|
|
245
245
|
...props.highlight,
|
|
246
246
|
points:
|
|
247
247
|
props.highlight?.points == false
|
|
@@ -249,13 +249,6 @@
|
|
|
249
249
|
: {
|
|
250
250
|
...highlightPointsProps,
|
|
251
251
|
fill: s.color,
|
|
252
|
-
class: cls(
|
|
253
|
-
'transition-opacity',
|
|
254
|
-
seriesState.highlightKey.current &&
|
|
255
|
-
seriesState.highlightKey.current !== s.key &&
|
|
256
|
-
'opacity-10',
|
|
257
|
-
highlightPointsProps?.class
|
|
258
|
-
),
|
|
259
252
|
},
|
|
260
253
|
};
|
|
261
254
|
}
|
|
@@ -264,8 +257,8 @@
|
|
|
264
257
|
return createLegendProps({
|
|
265
258
|
seriesState,
|
|
266
259
|
props: {
|
|
267
|
-
...props.legend,
|
|
268
260
|
...(typeof legend === 'object' ? legend : null),
|
|
261
|
+
...props.legend,
|
|
269
262
|
},
|
|
270
263
|
});
|
|
271
264
|
}
|
|
@@ -324,18 +317,20 @@
|
|
|
324
317
|
<Chart
|
|
325
318
|
bind:context
|
|
326
319
|
data={chartData}
|
|
327
|
-
x={xProp}
|
|
320
|
+
x={xProp ?? (isVertical ? series.map((s) => s.value ?? s.key) : undefined)}
|
|
328
321
|
{xDomain}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
322
|
+
xBaseline={!isVertical || (xScale && isScaleTime(xScale)) ? undefined : 0}
|
|
323
|
+
xNice={orientation === 'vertical'}
|
|
324
|
+
y={yProp ?? (isVertical ? undefined : series.map((s) => s.value ?? s.key))}
|
|
325
|
+
yBaseline={isVertical || (yScale && isScaleTime(yScale)) ? undefined : 0}
|
|
326
|
+
yNice={orientation === 'horizontal'}
|
|
332
327
|
{radial}
|
|
333
328
|
padding={radial ? undefined : defaultChartPadding(axis, legend)}
|
|
334
329
|
{...restProps}
|
|
335
330
|
tooltip={tooltip === false
|
|
336
331
|
? false
|
|
337
332
|
: {
|
|
338
|
-
mode: 'quadtree-x',
|
|
333
|
+
mode: isVertical ? 'quadtree-y' : 'quadtree-x',
|
|
339
334
|
onclick: onTooltipClick,
|
|
340
335
|
debug,
|
|
341
336
|
...props.tooltip?.context,
|
|
@@ -10,12 +10,11 @@ export type LineChartExtraSnippetProps<TData> = {
|
|
|
10
10
|
export type LineChartPropsObjProp = Pick<SimplifiedChartPropsObject, 'brush' | 'canvas' | 'grid' | 'highlight' | 'labels' | 'legend' | 'points' | 'rule' | 'spline' | 'svg' | 'tooltip' | 'xAxis' | 'yAxis'>;
|
|
11
11
|
export type LineChartProps<TData> = SimplifiedChartProps<TData, typeof Spline, LineChartExtraSnippetProps<TData>> & {
|
|
12
12
|
/**
|
|
13
|
-
* The
|
|
13
|
+
* The orientation of the line chart.
|
|
14
|
+
*
|
|
15
|
+
* @default 'horizontal'
|
|
14
16
|
*/
|
|
15
|
-
|
|
16
|
-
data: HighlightPointData;
|
|
17
|
-
series: SeriesData<TData, typeof Spline>;
|
|
18
|
-
}) => void;
|
|
17
|
+
orientation?: 'vertical' | 'horizontal';
|
|
19
18
|
props?: LineChartPropsObjProp;
|
|
20
19
|
spline?: SimplifiedChartSnippet<TData, typeof Spline, LineChartExtraSnippetProps<TData> & {
|
|
21
20
|
props: ComponentProps<typeof Spline>;
|
|
@@ -24,6 +23,13 @@ export type LineChartProps<TData> = SimplifiedChartProps<TData, typeof Spline, L
|
|
|
24
23
|
*/
|
|
25
24
|
seriesIndex: number;
|
|
26
25
|
}>;
|
|
26
|
+
/**
|
|
27
|
+
* The event to be dispatched when the point is clicked.
|
|
28
|
+
*/
|
|
29
|
+
onPointClick?: (e: MouseEvent, details: {
|
|
30
|
+
data: HighlightPointData;
|
|
31
|
+
series: SeriesData<TData, typeof Spline>;
|
|
32
|
+
}) => void;
|
|
27
33
|
};
|
|
28
34
|
import { type ComponentProps } from 'svelte';
|
|
29
35
|
import Axis from '../Axis.svelte';
|
|
@@ -172,11 +172,11 @@
|
|
|
172
172
|
</script>
|
|
173
173
|
|
|
174
174
|
<script lang="ts" generics="TData">
|
|
175
|
-
import { onMount, type ComponentProps
|
|
175
|
+
import { onMount, type ComponentProps } from 'svelte';
|
|
176
176
|
import { format } from '@layerstack/utils';
|
|
177
|
-
import { cls } from '@layerstack/tailwind';
|
|
178
|
-
import { SelectionState } from '@layerstack/svelte-state';
|
|
179
177
|
import type { PieArcDatum } from 'd3-shape';
|
|
178
|
+
import { schemeObservable10 } from 'd3-scale-chromatic';
|
|
179
|
+
import { getObjectOrNull } from '../../utils/common.js';
|
|
180
180
|
|
|
181
181
|
import Arc from '../Arc.svelte';
|
|
182
182
|
import Chart from '../Chart.svelte';
|
|
@@ -194,7 +194,8 @@
|
|
|
194
194
|
SimplifiedChartPropsObject,
|
|
195
195
|
SimplifiedChartSnippet,
|
|
196
196
|
} from './types.js';
|
|
197
|
-
import {
|
|
197
|
+
import { SeriesState } from '../../states/series.svelte.js';
|
|
198
|
+
import { createLegendProps } from './utils.svelte.js';
|
|
198
199
|
import { setTooltipMetaContext } from '../tooltip/tooltipMetaContext.js';
|
|
199
200
|
|
|
200
201
|
let {
|
|
@@ -237,67 +238,37 @@
|
|
|
237
238
|
const series = $derived(
|
|
238
239
|
seriesProp === undefined ? [{ key: 'default', value: value }] : seriesProp
|
|
239
240
|
);
|
|
241
|
+
const seriesState = new SeriesState(() => series);
|
|
240
242
|
|
|
241
243
|
const keyAccessor = $derived(accessor(key));
|
|
242
244
|
const labelAccessor = $derived(accessor(label));
|
|
243
245
|
const valueAccessor = $derived(accessor(value));
|
|
244
246
|
const cAccessor = $derived(accessor(c));
|
|
245
247
|
|
|
246
|
-
const allSeriesData = $derived(
|
|
247
|
-
series
|
|
248
|
-
.flatMap((s) => s.data?.map((d) => ({ seriesKey: s.key, ...d })))
|
|
249
|
-
.filter((d) => d) as Array<TData>
|
|
250
|
-
);
|
|
251
|
-
|
|
252
248
|
const chartData = $derived(
|
|
253
|
-
allSeriesData.length ? allSeriesData : chartDataArray(data)
|
|
249
|
+
seriesState.allSeriesData.length ? seriesState.allSeriesData : chartDataArray(data)
|
|
254
250
|
) as Array<TData>;
|
|
255
251
|
|
|
256
|
-
const seriesColors = $derived(series.map((s) => s.color).filter((d) => d != null));
|
|
257
|
-
|
|
258
|
-
const highlightKey = new HighlightKey<TData, typeof Arc>();
|
|
259
|
-
const selectedKeys = new SelectionState();
|
|
260
|
-
const selectedSeries = new SelectionState();
|
|
261
|
-
|
|
262
252
|
const visibleData = $derived(
|
|
263
253
|
chartData.filter((d) => {
|
|
264
254
|
const dataKey = keyAccessor(d);
|
|
265
|
-
return selectedKeys.isEmpty() || selectedKeys.isSelected(dataKey);
|
|
255
|
+
return seriesState.selectedKeys.isEmpty() || seriesState.selectedKeys.isSelected(dataKey);
|
|
266
256
|
})
|
|
267
257
|
);
|
|
268
258
|
|
|
269
|
-
// TODO: note, I added this because it wasn't consistent with all the other charts
|
|
270
|
-
// unsure if it is correct but will validate with Sean
|
|
271
|
-
const visibleSeries = $derived(
|
|
272
|
-
series.filter((s) => selectedSeries.isEmpty() || selectedSeries.isSelected(s.key))
|
|
273
|
-
);
|
|
274
|
-
|
|
275
259
|
function getLegendProps(): ComponentProps<typeof Legend> {
|
|
276
|
-
return {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
// selectedSeries.toggle(item.value);
|
|
287
|
-
},
|
|
288
|
-
onpointerenter: (e, item) => (highlightKey.current = item.value),
|
|
289
|
-
onpointerleave: (e) => (highlightKey.current = null),
|
|
290
|
-
...props.legend,
|
|
291
|
-
...(typeof legend === 'object' ? legend : null),
|
|
292
|
-
classes: {
|
|
293
|
-
item: (item) =>
|
|
294
|
-
visibleData.length && !visibleData.some((d) => keyAccessor(d) === item.value)
|
|
295
|
-
? 'opacity-50'
|
|
296
|
-
: '',
|
|
297
|
-
...props.legend?.classes,
|
|
298
|
-
...(typeof legend === 'object' ? legend.classes : null),
|
|
260
|
+
return createLegendProps({
|
|
261
|
+
seriesState,
|
|
262
|
+
props: {
|
|
263
|
+
tickFormat: (tick) => {
|
|
264
|
+
// Use data label instead of series label
|
|
265
|
+
const item = chartData.find((d) => keyAccessor(d) === tick);
|
|
266
|
+
return item ? (labelAccessor(item) ?? tick) : tick;
|
|
267
|
+
},
|
|
268
|
+
...props.legend,
|
|
269
|
+
...getObjectOrNull(legend),
|
|
299
270
|
},
|
|
300
|
-
};
|
|
271
|
+
});
|
|
301
272
|
}
|
|
302
273
|
|
|
303
274
|
function getGroupProps(): ComponentProps<typeof Group> {
|
|
@@ -338,7 +309,8 @@
|
|
|
338
309
|
return {
|
|
339
310
|
startAngle: arc.startAngle,
|
|
340
311
|
endAngle: arc.endAngle,
|
|
341
|
-
outerRadius:
|
|
312
|
+
outerRadius:
|
|
313
|
+
seriesState.visibleSeries.length > 1 ? seriesIndex * (outerRadius ?? 0) : outerRadius,
|
|
342
314
|
innerRadius,
|
|
343
315
|
cornerRadius,
|
|
344
316
|
padAngle,
|
|
@@ -350,10 +322,7 @@
|
|
|
350
322
|
// Workaround for `tooltip={{ mode: 'manual' }}
|
|
351
323
|
onTooltipClick(e, { data: arc.data });
|
|
352
324
|
},
|
|
353
|
-
|
|
354
|
-
'transition-opacity',
|
|
355
|
-
highlightKey.current && highlightKey.current !== keyAccessor(arc.data) && 'opacity-50'
|
|
356
|
-
),
|
|
325
|
+
opacity: seriesState.isHighlighted(keyAccessor(arc.data), true) ? 1 : 0.5,
|
|
357
326
|
...props.arc,
|
|
358
327
|
...s.props,
|
|
359
328
|
...arcDataProps,
|
|
@@ -382,7 +351,7 @@
|
|
|
382
351
|
return key;
|
|
383
352
|
},
|
|
384
353
|
get visibleSeries() {
|
|
385
|
-
return visibleSeries;
|
|
354
|
+
return seriesState.visibleSeries;
|
|
386
355
|
},
|
|
387
356
|
});
|
|
388
357
|
</script>
|
|
@@ -394,19 +363,21 @@
|
|
|
394
363
|
x={value}
|
|
395
364
|
c={key}
|
|
396
365
|
cDomain={chartData.map(keyAccessor)}
|
|
397
|
-
cRange={
|
|
398
|
-
?
|
|
366
|
+
cRange={seriesState.allSeriesColors.length
|
|
367
|
+
? seriesState.allSeriesColors
|
|
399
368
|
: c !== key
|
|
400
369
|
? chartData.map((d) => cAccessor(d))
|
|
401
370
|
: [
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
371
|
+
`var(--color-primary, ${schemeObservable10[0]})`,
|
|
372
|
+
`var(--color-secondary, ${schemeObservable10[1]})`,
|
|
373
|
+
`var(--color-info, ${schemeObservable10[2]})`,
|
|
374
|
+
`var(--color-success, ${schemeObservable10[3]})`,
|
|
375
|
+
`var(--color-warning, ${schemeObservable10[4]})`,
|
|
376
|
+
`var(--color-danger, ${schemeObservable10[5]})`,
|
|
408
377
|
]}
|
|
409
|
-
padding={{
|
|
378
|
+
padding={{
|
|
379
|
+
bottom: legend === true || getObjectOrNull(legend)?.placement?.includes('bottom') ? 32 : 0,
|
|
380
|
+
}}
|
|
410
381
|
{...restProps}
|
|
411
382
|
tooltip={tooltip === false
|
|
412
383
|
? false
|
|
@@ -420,10 +391,10 @@
|
|
|
420
391
|
color: cAccessor,
|
|
421
392
|
context,
|
|
422
393
|
series,
|
|
423
|
-
visibleSeries,
|
|
394
|
+
visibleSeries: seriesState.visibleSeries,
|
|
424
395
|
visibleData,
|
|
425
|
-
highlightKey: highlightKey.current,
|
|
426
|
-
setHighlightKey: highlightKey.set,
|
|
396
|
+
highlightKey: seriesState.highlightKey.current,
|
|
397
|
+
setHighlightKey: seriesState.highlightKey.set,
|
|
427
398
|
getLegendProps,
|
|
428
399
|
getGroupProps,
|
|
429
400
|
}}
|
|
@@ -444,7 +415,8 @@
|
|
|
444
415
|
{@render marks(snippetProps)}
|
|
445
416
|
{:else}
|
|
446
417
|
<Group {...getGroupProps()}>
|
|
447
|
-
|
|
418
|
+
<!-- Use `series` instead of `visibleSeries` since data is filtered (legend) instead of series -->
|
|
419
|
+
{#each series as s, seriesIdx (s.key)}
|
|
448
420
|
{#if typeof pie === 'function'}
|
|
449
421
|
{@render pie({
|
|
450
422
|
...snippetProps,
|
|
@@ -496,8 +468,8 @@
|
|
|
496
468
|
value={valueAccessor(data)}
|
|
497
469
|
color={context.cScale?.(context.c(data))}
|
|
498
470
|
{format}
|
|
499
|
-
onpointerenter={() => (highlightKey.current = keyAccessor(data))}
|
|
500
|
-
onpointerleave={() => (highlightKey.current = null)}
|
|
471
|
+
onpointerenter={() => (seriesState.highlightKey.current = keyAccessor(data))}
|
|
472
|
+
onpointerleave={() => (seriesState.highlightKey.current = null)}
|
|
501
473
|
{...props.tooltip?.item}
|
|
502
474
|
/>
|
|
503
475
|
</Tooltip.List>
|
|
@@ -61,9 +61,10 @@
|
|
|
61
61
|
import Rule from '../Rule.svelte';
|
|
62
62
|
import * as Tooltip from '../tooltip/index.js';
|
|
63
63
|
|
|
64
|
-
import {
|
|
64
|
+
import { chartDataArray, defaultChartPadding } from '../../utils/common.js';
|
|
65
65
|
import { asAny } from '../../utils/types.js';
|
|
66
|
-
import {
|
|
66
|
+
import { SeriesState } from '../../states/series.svelte.js';
|
|
67
|
+
import { createLegendProps } from './utils.svelte.js';
|
|
67
68
|
|
|
68
69
|
let {
|
|
69
70
|
data = [],
|
|
@@ -117,16 +118,10 @@
|
|
|
117
118
|
return {
|
|
118
119
|
data: s.data,
|
|
119
120
|
fill: s.color,
|
|
121
|
+
opacity: seriesState.isHighlighted(s.key, true) ? 1 : 0.1,
|
|
120
122
|
...props.points,
|
|
121
123
|
...s.props,
|
|
122
|
-
class: cls(
|
|
123
|
-
'transition-opacity',
|
|
124
|
-
seriesState.highlightKey.current &&
|
|
125
|
-
seriesState.highlightKey.current !== s.key &&
|
|
126
|
-
'opacity-10',
|
|
127
|
-
props.points?.class,
|
|
128
|
-
s.props?.class
|
|
129
|
-
),
|
|
124
|
+
class: cls(props.points?.class, s.props?.class),
|
|
130
125
|
};
|
|
131
126
|
}
|
|
132
127
|
|
|
@@ -136,16 +131,10 @@
|
|
|
136
131
|
): ComponentProps<typeof Labels<TData>> {
|
|
137
132
|
return {
|
|
138
133
|
data: s.data,
|
|
134
|
+
opacity: seriesState.isHighlighted(s.key, true) ? 1 : 0.1,
|
|
139
135
|
...props.labels,
|
|
140
136
|
...(typeof labels === 'object' ? labels : null),
|
|
141
|
-
class: cls(
|
|
142
|
-
'stroke-surface-200 transition-opacity',
|
|
143
|
-
seriesState.highlightKey.current &&
|
|
144
|
-
seriesState.highlightKey.current !== s.key &&
|
|
145
|
-
'opacity-10',
|
|
146
|
-
props.labels?.class,
|
|
147
|
-
typeof labels === 'object' && labels.class
|
|
148
|
-
),
|
|
137
|
+
class: cls(props.labels?.class, typeof labels === 'object' && labels.class),
|
|
149
138
|
};
|
|
150
139
|
}
|
|
151
140
|
|
|
@@ -230,7 +219,7 @@
|
|
|
230
219
|
{yDomain}
|
|
231
220
|
yNice
|
|
232
221
|
c={yProp}
|
|
233
|
-
cRange={['var(--color-primary)']}
|
|
222
|
+
cRange={['var(--color-primary, currentColor)']}
|
|
234
223
|
padding={defaultChartPadding(axis, legend)}
|
|
235
224
|
{...restProps}
|
|
236
225
|
tooltip={tooltip === false
|
|
@@ -1,24 +1,6 @@
|
|
|
1
1
|
import type { Component, ComponentProps } from 'svelte';
|
|
2
|
-
import { SelectionState } from '@layerstack/svelte-state';
|
|
3
|
-
import type { SeriesData } from './types.js';
|
|
4
2
|
import type Legend from '../Legend.svelte';
|
|
5
|
-
|
|
6
|
-
current: string | null;
|
|
7
|
-
set: (seriesKey: typeof this.current) => void;
|
|
8
|
-
}
|
|
9
|
-
export declare class SeriesState<TData, TComponent extends Component> {
|
|
10
|
-
#private;
|
|
11
|
-
selectedSeries: SelectionState<unknown, false>;
|
|
12
|
-
selectedKeys: SelectionState<unknown, false>;
|
|
13
|
-
highlightKey: HighlightKey<TData, TComponent>;
|
|
14
|
-
constructor(getSeries: () => SeriesData<TData, TComponent>[]);
|
|
15
|
-
get series(): SeriesData<TData, TComponent>[];
|
|
16
|
-
get isDefaultSeries(): boolean;
|
|
17
|
-
get allSeriesData(): Array<TData & {
|
|
18
|
-
seriesKey: string;
|
|
19
|
-
}>;
|
|
20
|
-
get visibleSeries(): SeriesData<TData, TComponent>[];
|
|
21
|
-
}
|
|
3
|
+
import type { SeriesState } from '../../states/series.svelte.js';
|
|
22
4
|
type CreateLegendPropsOptions<TData, TComponent extends Component> = {
|
|
23
5
|
seriesState: SeriesState<TData, TComponent>;
|
|
24
6
|
props: Partial<ComponentProps<typeof Legend>>;
|
|
@@ -1,38 +1,6 @@
|
|
|
1
|
-
import { SelectionState } from '@layerstack/svelte-state';
|
|
2
1
|
import { scaleOrdinal } from 'd3-scale';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
set = (seriesKey) => {
|
|
6
|
-
this.current = seriesKey;
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
export class SeriesState {
|
|
10
|
-
#series = $state.raw([]);
|
|
11
|
-
selectedSeries = new SelectionState();
|
|
12
|
-
selectedKeys = new SelectionState();
|
|
13
|
-
highlightKey = new HighlightKey();
|
|
14
|
-
constructor(getSeries) {
|
|
15
|
-
this.#series = getSeries();
|
|
16
|
-
$effect.pre(() => {
|
|
17
|
-
// keep series state in sync with the prop
|
|
18
|
-
this.#series = getSeries();
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
get series() {
|
|
22
|
-
return this.#series;
|
|
23
|
-
}
|
|
24
|
-
get isDefaultSeries() {
|
|
25
|
-
return this.#series.length === 1 && this.#series[0].key === 'default';
|
|
26
|
-
}
|
|
27
|
-
get allSeriesData() {
|
|
28
|
-
return this.#series
|
|
29
|
-
.flatMap((s) => s.data?.map((d) => ({ seriesKey: s.key, ...d })))
|
|
30
|
-
.filter((d) => d);
|
|
31
|
-
}
|
|
32
|
-
get visibleSeries() {
|
|
33
|
-
return this.#series.filter((s) => this.selectedSeries.isEmpty() || this.selectedSeries.isSelected(s.key));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
2
|
+
import { cls } from '@layerstack/tailwind';
|
|
3
|
+
import { resolveMaybeFn } from '../../utils/common.js';
|
|
36
4
|
/**
|
|
37
5
|
* A prop builder for the legend component shared between the simplified charts.
|
|
38
6
|
*/
|
|
@@ -44,15 +12,15 @@ export function createLegendProps(opts) {
|
|
|
44
12
|
tickFormat: (key) => opts.seriesState.series.find((s) => s.key === key)?.label ?? key,
|
|
45
13
|
placement: 'bottom',
|
|
46
14
|
variant: 'swatches',
|
|
47
|
-
|
|
15
|
+
selected: opts.seriesState.selectedKeys.current,
|
|
16
|
+
onclick: (_, item) => opts.seriesState.selectedKeys.toggle(item.value),
|
|
48
17
|
onpointerenter: (_, item) => (opts.seriesState.highlightKey.current = item.value),
|
|
49
18
|
onpointerleave: () => (opts.seriesState.highlightKey.current = null),
|
|
50
19
|
...opts.props,
|
|
51
20
|
classes: {
|
|
52
|
-
item: (item) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
: '',
|
|
21
|
+
item: (item) => {
|
|
22
|
+
return cls(resolveMaybeFn(opts.props?.classes?.item, item));
|
|
23
|
+
},
|
|
56
24
|
...opts.props?.classes,
|
|
57
25
|
},
|
|
58
26
|
};
|