@reshape-biotech/design-system 2.7.37 → 2.7.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/graphs/scatterplot/Scatterplot.stories.svelte +119 -50
- package/dist/components/graphs/scatterplot/Scatterplot.svelte +99 -80
- package/dist/components/graphs/scatterplot/Scatterplot.svelte.d.ts +1 -1
- package/dist/components/status-badge/StatusBadge.stories.svelte +74 -0
- package/dist/components/status-badge/StatusBadge.svelte +11 -1
- package/dist/components/status-badge/StatusBadge.svelte.d.ts +1 -1
- package/package.json +1 -1
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
const data: DataPoint[] = [
|
|
13
|
-
{ value: [10
|
|
14
|
-
{ value: [8
|
|
15
|
-
{ value: [13
|
|
16
|
-
{ value: [9
|
|
17
|
-
{ value: [12
|
|
18
|
-
{ value: [14
|
|
13
|
+
{ value: [10, 8], metadata: { id: '1' } },
|
|
14
|
+
{ value: [8, 7], metadata: { id: '2' } },
|
|
15
|
+
{ value: [13, 8], metadata: { id: '3' } },
|
|
16
|
+
{ value: [9, 9], metadata: { id: '4' } },
|
|
17
|
+
{ value: [12, 8], metadata: { id: '5' } },
|
|
18
|
+
{ value: [14, 8], metadata: { id: '6' } },
|
|
19
19
|
];
|
|
20
20
|
|
|
21
21
|
const errorBarsData: DataPoint[] = data.map((d) => ({
|
|
@@ -28,78 +28,147 @@
|
|
|
28
28
|
[12, 14],
|
|
29
29
|
];
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
function handleMouseOver(params: echarts.ECElementEvent) {}
|
|
34
|
-
|
|
35
|
-
function handleMouseOut() {}
|
|
31
|
+
let tooltipState = $state({ visible: false, x: 0, y: 0, point: null as DataPoint | null });
|
|
36
32
|
</script>
|
|
37
33
|
|
|
38
34
|
<Story name="Base" asChild>
|
|
39
35
|
<div class="h-[400px] w-full">
|
|
40
|
-
<Scatterplot
|
|
41
|
-
{data}
|
|
42
|
-
xAxisName="Manual count"
|
|
43
|
-
yAxisName="Analysis count"
|
|
44
|
-
onitemclick={handleItemClick}
|
|
45
|
-
onmouseover={handleMouseOver}
|
|
46
|
-
onmouseout={handleMouseOut}
|
|
47
|
-
/>
|
|
36
|
+
<Scatterplot {data} xAxisName="X axis" yAxisName="Y axis" />
|
|
48
37
|
</div>
|
|
49
38
|
</Story>
|
|
50
39
|
|
|
51
|
-
<Story name="With
|
|
40
|
+
<Story name="With reference line" asChild>
|
|
52
41
|
<div class="h-[400px] w-full">
|
|
53
|
-
<Scatterplot
|
|
54
|
-
{data}
|
|
55
|
-
{lineData}
|
|
56
|
-
xAxisName="Manual count"
|
|
57
|
-
yAxisName="Analysis count"
|
|
58
|
-
onitemclick={handleItemClick}
|
|
59
|
-
onmouseover={handleMouseOver}
|
|
60
|
-
onmouseout={handleMouseOut}
|
|
61
|
-
/>
|
|
42
|
+
<Scatterplot {data} {lineData} xAxisName="X axis" yAxisName="Y axis" />
|
|
62
43
|
</div>
|
|
63
44
|
</Story>
|
|
64
|
-
|
|
45
|
+
|
|
46
|
+
<Story name="With error bars" asChild>
|
|
47
|
+
<div class="h-[400px] w-full">
|
|
48
|
+
<Scatterplot data={errorBarsData} {lineData} xAxisName="X axis" yAxisName="Y axis" />
|
|
49
|
+
</div>
|
|
50
|
+
</Story>
|
|
51
|
+
|
|
52
|
+
<Story name="With confidence band" asChild>
|
|
65
53
|
<div class="h-[400px] w-full">
|
|
66
54
|
<Scatterplot
|
|
67
55
|
data={errorBarsData}
|
|
68
56
|
{lineData}
|
|
69
|
-
xAxisName="
|
|
70
|
-
yAxisName="
|
|
71
|
-
|
|
72
|
-
onmouseover={handleMouseOver}
|
|
73
|
-
onmouseout={handleMouseOut}
|
|
57
|
+
xAxisName="X axis"
|
|
58
|
+
yAxisName="Y axis"
|
|
59
|
+
showConfidenceBand
|
|
74
60
|
/>
|
|
75
61
|
</div>
|
|
76
62
|
</Story>
|
|
77
|
-
|
|
63
|
+
|
|
64
|
+
<Story name="With legend" asChild>
|
|
78
65
|
<div class="h-[400px] w-full">
|
|
79
66
|
<Scatterplot
|
|
80
|
-
data
|
|
67
|
+
{data}
|
|
81
68
|
{lineData}
|
|
82
|
-
xAxisName="
|
|
83
|
-
yAxisName="
|
|
69
|
+
xAxisName="X axis"
|
|
70
|
+
yAxisName="Y axis"
|
|
84
71
|
showConfidenceBand
|
|
85
|
-
|
|
86
|
-
onmouseover={handleMouseOver}
|
|
87
|
-
onmouseout={handleMouseOut}
|
|
72
|
+
showLegend
|
|
88
73
|
/>
|
|
89
74
|
</div>
|
|
90
75
|
</Story>
|
|
91
|
-
|
|
76
|
+
|
|
77
|
+
<Story name="With groups" asChild>
|
|
78
|
+
{@const data: DataPoint[] = [
|
|
79
|
+
{ value: [8, 7], metadata: { id: 'A' } },
|
|
80
|
+
{ value: [8, 10], metadata: { id: 'A' } },
|
|
81
|
+
{ value: [15, 14], metadata: { id: 'B' } },
|
|
82
|
+
{ value: [23, 21], metadata: { id: 'C' } },
|
|
83
|
+
{ value: [23, 25], metadata: { id: 'C' } },
|
|
84
|
+
{ value: [23, 22], metadata: { id: 'C' } },
|
|
85
|
+
{ value: [35, 32], metadata: { id: 'D' } },
|
|
86
|
+
{ value: [35, 39], metadata: { id: 'D' }, disagreement: true },
|
|
87
|
+
{ value: [42, 41], metadata: { id: 'E' } },
|
|
88
|
+
{ value: [42, 44], metadata: { id: 'E' } },
|
|
89
|
+
{ value: [56, 58], metadata: { id: 'F' } },
|
|
90
|
+
]}
|
|
91
|
+
{@const groups = [[0, 1], [2], [3, 4, 5], [6, 7], [8, 9], [10]]}
|
|
92
|
+
{@const lineData: [[number, number], [number, number]] = [[0, 0], [65, 65]]}
|
|
92
93
|
<div class="h-[400px] w-full">
|
|
93
94
|
<Scatterplot
|
|
94
95
|
{data}
|
|
96
|
+
{groups}
|
|
95
97
|
{lineData}
|
|
96
|
-
xAxisName="
|
|
97
|
-
yAxisName="
|
|
98
|
+
xAxisName="X axis"
|
|
99
|
+
yAxisName="Y axis"
|
|
98
100
|
showConfidenceBand
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
onmouseover={(params) => {
|
|
102
|
+
tooltipState.visible = true;
|
|
103
|
+
tooltipState.x = (params.event?.event as MouseEvent)?.offsetX ?? 0;
|
|
104
|
+
tooltipState.y = (params.event?.event as MouseEvent)?.offsetY ?? 0;
|
|
105
|
+
tooltipState.point = params.data;
|
|
106
|
+
}}
|
|
107
|
+
onmouseout={() => {
|
|
108
|
+
tooltipState.visible = false;
|
|
109
|
+
tooltipState.point = null;
|
|
110
|
+
}}
|
|
111
|
+
>
|
|
112
|
+
{#if tooltipState.visible && tooltipState.point}
|
|
113
|
+
<div
|
|
114
|
+
class="pointer-events-none absolute z-50 rounded border bg-white p-2 text-xs shadow-lg"
|
|
115
|
+
style="left: {tooltipState.x + 10}px; top: {tooltipState.y + 10}px;"
|
|
116
|
+
>
|
|
117
|
+
<div class="font-medium">ID: {tooltipState.point.metadata.id}</div>
|
|
118
|
+
<div>X: {tooltipState.point.value[0]}</div>
|
|
119
|
+
<div>Y: {tooltipState.point.value[1]}</div>
|
|
120
|
+
</div>
|
|
121
|
+
{/if}
|
|
122
|
+
</Scatterplot>
|
|
123
|
+
</div>
|
|
124
|
+
</Story>
|
|
125
|
+
|
|
126
|
+
<Story name="Overlapping groups" asChild>
|
|
127
|
+
{@const data: DataPoint[] = [
|
|
128
|
+
{ value: [12, 9], metadata: { id: 'A' } },
|
|
129
|
+
{ value: [12, 15], metadata: { id: 'A' } },
|
|
130
|
+
{ value: [12, 12], metadata: { id: 'B' } },
|
|
131
|
+
{ value: [12, 18], metadata: { id: 'B' } },
|
|
132
|
+
{ value: [12, 14], metadata: { id: 'B' } },
|
|
133
|
+
{ value: [31, 27], metadata: { id: 'C' } },
|
|
134
|
+
{ value: [31, 34], metadata: { id: 'C' } },
|
|
135
|
+
{ value: [31, 30], metadata: { id: 'D' } },
|
|
136
|
+
]}
|
|
137
|
+
{@const groups = [
|
|
138
|
+
[0, 1],
|
|
139
|
+
[2, 3, 4],
|
|
140
|
+
[5, 6],
|
|
141
|
+
[7],
|
|
142
|
+
]}
|
|
143
|
+
{@const lineData: [[number, number], [number, number]] = [[0, 0], [40, 40]]}
|
|
144
|
+
<div class="h-[400px] w-full">
|
|
145
|
+
<Scatterplot
|
|
146
|
+
{data}
|
|
147
|
+
{groups}
|
|
148
|
+
{lineData}
|
|
149
|
+
xAxisName="X axis"
|
|
150
|
+
yAxisName="Y axis"
|
|
151
|
+
onmouseover={(params) => {
|
|
152
|
+
tooltipState.visible = true;
|
|
153
|
+
tooltipState.x = (params.event?.event as MouseEvent)?.offsetX ?? 0;
|
|
154
|
+
tooltipState.y = (params.event?.event as MouseEvent)?.offsetY ?? 0;
|
|
155
|
+
tooltipState.point = params.data;
|
|
156
|
+
}}
|
|
157
|
+
onmouseout={() => {
|
|
158
|
+
tooltipState.visible = false;
|
|
159
|
+
tooltipState.point = null;
|
|
160
|
+
}}
|
|
161
|
+
>
|
|
162
|
+
{#if tooltipState.visible && tooltipState.point}
|
|
163
|
+
<div
|
|
164
|
+
class="pointer-events-none absolute z-50 rounded border bg-white p-2 text-xs shadow-lg"
|
|
165
|
+
style="left: {tooltipState.x + 10}px; top: {tooltipState.y + 10}px;"
|
|
166
|
+
>
|
|
167
|
+
<div class="font-medium">ID: {tooltipState.point.metadata.id}</div>
|
|
168
|
+
<div>X: {tooltipState.point.value[0]}</div>
|
|
169
|
+
<div>Y: {tooltipState.point.value[1]}</div>
|
|
170
|
+
</div>
|
|
171
|
+
{/if}
|
|
172
|
+
</Scatterplot>
|
|
104
173
|
</div>
|
|
105
174
|
</Story>
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
export type DataPoint = {
|
|
17
17
|
value: [number, number];
|
|
18
18
|
metadata: any;
|
|
19
|
-
error_value?: number;
|
|
20
19
|
disagreement?: boolean | null;
|
|
21
20
|
highlighted?: boolean | null;
|
|
22
21
|
};
|
|
@@ -31,9 +30,15 @@
|
|
|
31
30
|
type: 'point' | 'line' | 'area';
|
|
32
31
|
};
|
|
33
32
|
|
|
33
|
+
type LineSegment = {
|
|
34
|
+
points: [number, number][];
|
|
35
|
+
disagreement?: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
34
38
|
type ScatterPlotProps = {
|
|
35
39
|
data: DataPoint[];
|
|
36
40
|
lineData?: [[number, number], [number, number]];
|
|
41
|
+
groups?: number[][];
|
|
37
42
|
showConfidenceBand?: boolean;
|
|
38
43
|
showLegend?: boolean;
|
|
39
44
|
onitemclick?: (params: ScatterPlotEchartsEvent) => void;
|
|
@@ -58,10 +63,55 @@
|
|
|
58
63
|
{ label: 'Perfect agreement', color: backgroundColor['lilac-inverse'], type: 'line' },
|
|
59
64
|
],
|
|
60
65
|
highlightIndex = null,
|
|
66
|
+
groups = [],
|
|
61
67
|
children,
|
|
62
68
|
...props
|
|
63
69
|
}: ScatterPlotProps = $props();
|
|
64
70
|
|
|
71
|
+
let hoveredGroupIndices = $state<number[] | null>(null);
|
|
72
|
+
|
|
73
|
+
const findGroupForIndex = (idx: number): number[] | null => {
|
|
74
|
+
if (groups.length === 0) return null;
|
|
75
|
+
return groups.find((g) => g.includes(idx)) ?? null;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const highlightedIndices = $derived.by((): number[] | null => {
|
|
79
|
+
if (hoveredGroupIndices !== null) return hoveredGroupIndices;
|
|
80
|
+
if (highlightIndex !== null) {
|
|
81
|
+
const group = findGroupForIndex(highlightIndex);
|
|
82
|
+
return group ?? [highlightIndex];
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const groupLines = $derived.by((): LineSegment[] => {
|
|
88
|
+
if (groups.length === 0) return [];
|
|
89
|
+
|
|
90
|
+
return groups
|
|
91
|
+
.filter((g) => g.length > 1)
|
|
92
|
+
.map((groupIndices) => {
|
|
93
|
+
const points = groupIndices.map((i) => data[i]?.value).filter(Boolean) as [
|
|
94
|
+
number,
|
|
95
|
+
number,
|
|
96
|
+
][];
|
|
97
|
+
const hasDisagreement = groupIndices.some((i) => data[i]?.disagreement);
|
|
98
|
+
return { points, disagreement: hasDisagreement };
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const groupedDisagreement = $derived.by((): boolean[] => {
|
|
103
|
+
const result = data.map((d) => d.disagreement ?? false);
|
|
104
|
+
for (const groupIndices of groups) {
|
|
105
|
+
const hasDisagreement = groupIndices.some((i) => data[i]?.disagreement);
|
|
106
|
+
if (hasDisagreement) {
|
|
107
|
+
for (const i of groupIndices) {
|
|
108
|
+
result[i] = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
});
|
|
114
|
+
|
|
65
115
|
const displayedLegendItems: LegendItem[] = $derived([
|
|
66
116
|
...legendItems,
|
|
67
117
|
...(showConfidenceBand
|
|
@@ -82,75 +132,44 @@
|
|
|
82
132
|
}
|
|
83
133
|
|
|
84
134
|
function handleMouseOver(params: ScatterPlotEchartsEvent) {
|
|
135
|
+
const hoveredIdx = params.dataIndex;
|
|
136
|
+
if (hoveredIdx !== undefined && hoveredIdx >= 0) {
|
|
137
|
+
const group = findGroupForIndex(hoveredIdx);
|
|
138
|
+
hoveredGroupIndices = group ?? [hoveredIdx];
|
|
139
|
+
}
|
|
85
140
|
onmouseover?.(params);
|
|
86
141
|
}
|
|
87
142
|
|
|
88
143
|
function handleMouseOut() {
|
|
144
|
+
hoveredGroupIndices = null;
|
|
89
145
|
onmouseout?.();
|
|
90
146
|
}
|
|
91
147
|
|
|
92
|
-
|
|
93
|
-
function renderErrorBarItem(
|
|
94
|
-
params: CustomSeriesRenderItemParams,
|
|
95
|
-
api: CustomSeriesRenderItemAPI
|
|
96
|
-
) {
|
|
148
|
+
function renderLineItem(params: CustomSeriesRenderItemParams, api: CustomSeriesRenderItemAPI) {
|
|
97
149
|
const xValue = api.value(0) as number;
|
|
98
|
-
const
|
|
99
|
-
const
|
|
150
|
+
const yMin = api.value(1) as number;
|
|
151
|
+
const yMax = api.value(2) as number;
|
|
100
152
|
const disagreement = api.value(3) as number;
|
|
101
153
|
|
|
102
|
-
const
|
|
103
|
-
const
|
|
154
|
+
const topPoint = api.coord([xValue, yMax]);
|
|
155
|
+
const bottomPoint = api.coord([xValue, yMin]);
|
|
104
156
|
|
|
105
|
-
if (!
|
|
157
|
+
if (!topPoint || !bottomPoint) {
|
|
106
158
|
return undefined;
|
|
107
159
|
}
|
|
108
160
|
|
|
109
|
-
// calculate a dynamic width for the caps based on the x-axis scale
|
|
110
|
-
const sizeValue = api.size?.([1, 0]);
|
|
111
|
-
const baseWidth = Array.isArray(sizeValue) ? sizeValue[0] : 10;
|
|
112
|
-
const halfWidth = Math.min((baseWidth ?? 10) * 1.5, 3);
|
|
113
|
-
const style = {
|
|
114
|
-
stroke: disagreement ? textColor['icon-tertiary'] : backgroundColor['blue-inverse'],
|
|
115
|
-
};
|
|
116
|
-
|
|
117
161
|
return {
|
|
118
|
-
type: '
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
style,
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
type: 'line' as const,
|
|
133
|
-
transition: 'shape' as const,
|
|
134
|
-
shape: {
|
|
135
|
-
x1: highPoint[0],
|
|
136
|
-
y1: highPoint[1],
|
|
137
|
-
x2: lowPoint[0],
|
|
138
|
-
y2: lowPoint[1],
|
|
139
|
-
},
|
|
140
|
-
style,
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
type: 'line' as const,
|
|
144
|
-
transition: 'shape' as const,
|
|
145
|
-
shape: {
|
|
146
|
-
x1: lowPoint[0] - halfWidth,
|
|
147
|
-
y1: lowPoint[1],
|
|
148
|
-
x2: lowPoint[0] + halfWidth,
|
|
149
|
-
y2: lowPoint[1],
|
|
150
|
-
},
|
|
151
|
-
style,
|
|
152
|
-
},
|
|
153
|
-
],
|
|
162
|
+
type: 'line' as const,
|
|
163
|
+
shape: {
|
|
164
|
+
x1: topPoint[0],
|
|
165
|
+
y1: topPoint[1],
|
|
166
|
+
x2: bottomPoint[0],
|
|
167
|
+
y2: bottomPoint[1],
|
|
168
|
+
},
|
|
169
|
+
style: {
|
|
170
|
+
stroke: disagreement ? textColor['icon-tertiary'] : backgroundColor['blue-inverse'],
|
|
171
|
+
lineWidth: 1.5,
|
|
172
|
+
},
|
|
154
173
|
};
|
|
155
174
|
}
|
|
156
175
|
|
|
@@ -158,9 +177,6 @@
|
|
|
158
177
|
|
|
159
178
|
function getChartOptions(): EChartsOption {
|
|
160
179
|
const series: SeriesOption[] = [];
|
|
161
|
-
const errorBarData = data
|
|
162
|
-
.filter((d) => d.error_value != 0)
|
|
163
|
-
.map((d) => [...d.value, d.error_value, d.disagreement ? 1 : 0]);
|
|
164
180
|
|
|
165
181
|
if (props.lineData && props.lineData.length > 0) {
|
|
166
182
|
const extendedLineData = [
|
|
@@ -226,36 +242,32 @@
|
|
|
226
242
|
type: 'scatter',
|
|
227
243
|
itemStyle: {
|
|
228
244
|
color: (params: any) =>
|
|
229
|
-
params
|
|
245
|
+
groupedDisagreement[params.dataIndex]
|
|
246
|
+
? textColor['icon-tertiary']
|
|
247
|
+
: backgroundColor['blue-inverse'],
|
|
230
248
|
opacity: 1,
|
|
231
249
|
},
|
|
232
250
|
emphasis: {
|
|
233
|
-
|
|
234
|
-
color: (params: any) => {
|
|
235
|
-
const point = params?.data as DataPoint;
|
|
236
|
-
return point?.disagreement
|
|
237
|
-
? textColor['icon-tertiary']
|
|
238
|
-
: backgroundColor['blue-inverse'];
|
|
239
|
-
},
|
|
240
|
-
opacity: 1,
|
|
241
|
-
},
|
|
251
|
+
disabled: true,
|
|
242
252
|
},
|
|
243
253
|
animation: false,
|
|
244
254
|
});
|
|
245
255
|
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
?
|
|
249
|
-
|
|
256
|
+
const highlightPoints =
|
|
257
|
+
highlightedIndices !== null
|
|
258
|
+
? highlightedIndices
|
|
259
|
+
.filter((i) => i >= 0 && i < data.length)
|
|
260
|
+
.map((i) => ({ point: data[i], index: i }))
|
|
261
|
+
: [];
|
|
250
262
|
series.push({
|
|
251
263
|
id: 'highlight-overlay',
|
|
252
264
|
type: 'scatter',
|
|
253
|
-
data:
|
|
265
|
+
data: highlightPoints.map((h) => h.point),
|
|
254
266
|
symbolSize: 16,
|
|
255
267
|
itemStyle: {
|
|
256
268
|
color: (params: any) => {
|
|
257
|
-
const
|
|
258
|
-
return
|
|
269
|
+
const originalIndex = highlightPoints[params.dataIndex]?.index;
|
|
270
|
+
return groupedDisagreement[originalIndex]
|
|
259
271
|
? backgroundColor['neutral-hover']
|
|
260
272
|
: backgroundColor['blue-hover'];
|
|
261
273
|
},
|
|
@@ -264,16 +276,23 @@
|
|
|
264
276
|
silent: true,
|
|
265
277
|
});
|
|
266
278
|
|
|
267
|
-
if (
|
|
279
|
+
if (groupLines.length > 0) {
|
|
280
|
+
const linesData = groupLines.map((line) => {
|
|
281
|
+
const yValues = line.points.map((p: [number, number]) => p[1]);
|
|
282
|
+
const xValue = line.points[0][0];
|
|
283
|
+
return [xValue, Math.min(...yValues), Math.max(...yValues), line.disagreement ? 1 : 0];
|
|
284
|
+
});
|
|
285
|
+
|
|
268
286
|
series.push({
|
|
269
287
|
type: 'custom',
|
|
270
|
-
name: '
|
|
288
|
+
name: 'lines',
|
|
271
289
|
silent: true,
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
290
|
+
renderItem: renderLineItem,
|
|
291
|
+
data: linesData,
|
|
292
|
+
z: -1,
|
|
275
293
|
});
|
|
276
294
|
}
|
|
295
|
+
|
|
277
296
|
return {
|
|
278
297
|
xAxis: {
|
|
279
298
|
type: 'value',
|
|
@@ -4,7 +4,6 @@ import type { Snippet } from 'svelte';
|
|
|
4
4
|
export type DataPoint = {
|
|
5
5
|
value: [number, number];
|
|
6
6
|
metadata: any;
|
|
7
|
-
error_value?: number;
|
|
8
7
|
disagreement?: boolean | null;
|
|
9
8
|
highlighted?: boolean | null;
|
|
10
9
|
};
|
|
@@ -19,6 +18,7 @@ type LegendItem = {
|
|
|
19
18
|
type ScatterPlotProps = {
|
|
20
19
|
data: DataPoint[];
|
|
21
20
|
lineData?: [[number, number], [number, number]];
|
|
21
|
+
groups?: number[][];
|
|
22
22
|
showConfidenceBand?: boolean;
|
|
23
23
|
showLegend?: boolean;
|
|
24
24
|
onitemclick?: (params: ScatterPlotEchartsEvent) => void;
|
|
@@ -486,6 +486,80 @@
|
|
|
486
486
|
</div>
|
|
487
487
|
</Story>
|
|
488
488
|
|
|
489
|
+
<Story name="Init" asChild>
|
|
490
|
+
<p class="font-mono text-xs">Medium:</p>
|
|
491
|
+
<div class="flex flex-row gap-1">
|
|
492
|
+
<Tooltip>
|
|
493
|
+
{#snippet trigger()}
|
|
494
|
+
<StatusBadge type="init">
|
|
495
|
+
{#snippet icon()}
|
|
496
|
+
<Icon>
|
|
497
|
+
{#snippet children(props)}
|
|
498
|
+
<SpinnerGap {...props} />
|
|
499
|
+
{/snippet}
|
|
500
|
+
</Icon>
|
|
501
|
+
{/snippet}
|
|
502
|
+
{#snippet content()}
|
|
503
|
+
<div>Initializing</div>
|
|
504
|
+
{/snippet}
|
|
505
|
+
</StatusBadge>
|
|
506
|
+
{/snippet}
|
|
507
|
+
{#snippet content()}
|
|
508
|
+
<div class="flex flex-col text-left">
|
|
509
|
+
<p class="font-bold">Device initializing</p>
|
|
510
|
+
<p class="text-xs">Will be ready soon</p>
|
|
511
|
+
</div>
|
|
512
|
+
{/snippet}</Tooltip
|
|
513
|
+
>
|
|
514
|
+
|
|
515
|
+
<StatusBadge type="init">
|
|
516
|
+
{#snippet icon()}
|
|
517
|
+
<Icon>
|
|
518
|
+
{#snippet children(props)}
|
|
519
|
+
<SpinnerGap {...props} />
|
|
520
|
+
{/snippet}
|
|
521
|
+
</Icon>
|
|
522
|
+
{/snippet}
|
|
523
|
+
</StatusBadge>
|
|
524
|
+
</div>
|
|
525
|
+
<br />
|
|
526
|
+
<p class="font-mono text-xs">Small:</p>
|
|
527
|
+
<div class="flex flex-row gap-1">
|
|
528
|
+
<Tooltip>
|
|
529
|
+
{#snippet trigger()}
|
|
530
|
+
<StatusBadge type="init" size="sm">
|
|
531
|
+
{#snippet icon()}
|
|
532
|
+
<Icon>
|
|
533
|
+
{#snippet children(props)}
|
|
534
|
+
<SpinnerGap {...props} />
|
|
535
|
+
{/snippet}
|
|
536
|
+
</Icon>
|
|
537
|
+
{/snippet}
|
|
538
|
+
{#snippet content()}
|
|
539
|
+
<div>Initializing</div>
|
|
540
|
+
{/snippet}
|
|
541
|
+
</StatusBadge>
|
|
542
|
+
{/snippet}
|
|
543
|
+
{#snippet content()}
|
|
544
|
+
<div class="flex flex-col text-left">
|
|
545
|
+
<p class="font-bold">Device initializing</p>
|
|
546
|
+
<p class="text-xs">Will be ready soon</p>
|
|
547
|
+
</div>
|
|
548
|
+
{/snippet}</Tooltip
|
|
549
|
+
>
|
|
550
|
+
|
|
551
|
+
<StatusBadge type="init" size="sm">
|
|
552
|
+
{#snippet icon()}
|
|
553
|
+
<Icon>
|
|
554
|
+
{#snippet children(props)}
|
|
555
|
+
<SpinnerGap {...props} />
|
|
556
|
+
{/snippet}
|
|
557
|
+
</Icon>
|
|
558
|
+
{/snippet}
|
|
559
|
+
</StatusBadge>
|
|
560
|
+
</div>
|
|
561
|
+
</Story>
|
|
562
|
+
|
|
489
563
|
<Story name="Icon only" asChild>
|
|
490
564
|
<StatusBadge type="neutral" iconOnly>
|
|
491
565
|
{#snippet icon()}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
// we can add dynamic classes because they are safelisted in tailwind-safelist.txt
|
|
7
|
-
type?: 'neutral' | 'success' | 'progress' | 'warning' | 'error';
|
|
7
|
+
type?: 'neutral' | 'success' | 'progress' | 'warning' | 'error' | 'init';
|
|
8
8
|
size?: 'md' | 'sm';
|
|
9
9
|
content?: Snippet;
|
|
10
10
|
progress?: Snippet;
|
|
@@ -145,6 +145,16 @@
|
|
|
145
145
|
--tw-text-opacity: 1;
|
|
146
146
|
color: rgb(235 70 71 / var(--tw-text-opacity, 1))
|
|
147
147
|
}
|
|
148
|
+
.badge-init {
|
|
149
|
+
background-color: #ff7a001A
|
|
150
|
+
}
|
|
151
|
+
.badge-init:hover {
|
|
152
|
+
background-color: #ff7a0040
|
|
153
|
+
}
|
|
154
|
+
.badge-init .icon {
|
|
155
|
+
--tw-text-opacity: 1;
|
|
156
|
+
color: rgb(255 122 0 / var(--tw-text-opacity, 1))
|
|
157
|
+
}
|
|
148
158
|
|
|
149
159
|
:global(.badge > div) {
|
|
150
160
|
display: flex;
|