@reshape-biotech/design-system 0.0.54 → 1.1.2

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.
Files changed (181) hide show
  1. package/dist/components/activity/Activity.stories.svelte +21 -8
  2. package/dist/components/activity/Activity.svelte +44 -6
  3. package/dist/components/activity/Activity.svelte.d.ts +1 -1
  4. package/dist/components/avatar/Avatar.stories.svelte +7 -17
  5. package/dist/components/avatar/Avatar.svelte +2 -2
  6. package/dist/components/avatar/Avatar.svelte.d.ts +2 -2
  7. package/dist/components/banner/Banner.stories.svelte +5 -5
  8. package/dist/components/banner/Banner.svelte +1 -1
  9. package/dist/components/button/Button.stories.svelte +54 -21
  10. package/dist/components/button/Button.svelte +58 -11
  11. package/dist/components/button/Button.svelte.d.ts +4 -3
  12. package/dist/components/card/Card.stories.svelte +130 -0
  13. package/dist/components/card/Card.stories.svelte.d.ts +19 -0
  14. package/dist/components/card/Card.svelte +25 -0
  15. package/dist/components/card/Card.svelte.d.ts +10 -0
  16. package/dist/components/card/index.d.ts +1 -0
  17. package/dist/components/card/index.js +1 -0
  18. package/dist/components/checkbox/Checkbox.stories.svelte +7 -15
  19. package/dist/components/checkbox/Checkbox.svelte +7 -7
  20. package/dist/components/checkbox/Checkbox.svelte.d.ts +3 -5
  21. package/dist/components/collapsible/Collapsible.stories.svelte +5 -4
  22. package/dist/components/combobox/Combobox.stories.svelte +7 -5
  23. package/dist/components/datepicker/DatePicker.stories.svelte +13 -18
  24. package/dist/components/datepicker/DatePicker.svelte +1 -0
  25. package/dist/components/divider/Divider.stories.svelte +1 -3
  26. package/dist/components/divider/Divider.svelte +8 -2
  27. package/dist/components/divider/Divider.svelte.d.ts +2 -0
  28. package/dist/components/drawer/Drawer.stories.svelte +3 -3
  29. package/dist/components/dropdown/Dropdown.stories.svelte +8 -8
  30. package/dist/components/empty-content/EmptyContent.stories.svelte +2 -2
  31. package/dist/components/graphs/bar-chart/BarChart.stories.svelte +81 -0
  32. package/dist/components/graphs/bar-chart/BarChart.stories.svelte.d.ts +19 -0
  33. package/dist/components/graphs/bar-chart/BarChart.svelte +136 -0
  34. package/dist/components/graphs/bar-chart/BarChart.svelte.d.ts +15 -0
  35. package/dist/components/graphs/bar-chart/StackedBarChart.stories.svelte +42 -0
  36. package/dist/components/graphs/bar-chart/StackedBarChart.stories.svelte.d.ts +19 -0
  37. package/dist/components/graphs/bar-chart/StackedBarChart.svelte +177 -0
  38. package/dist/components/graphs/bar-chart/StackedBarChart.svelte.d.ts +16 -0
  39. package/dist/components/graphs/chart/Chart.stories.svelte +30 -25
  40. package/dist/components/graphs/chart/Chart.svelte +104 -32
  41. package/dist/components/graphs/chart/Chart.svelte.d.ts +15 -5
  42. package/dist/components/graphs/index.d.ts +3 -0
  43. package/dist/components/graphs/index.js +3 -0
  44. package/dist/components/graphs/line/LineChart.stories.svelte +97 -17
  45. package/dist/components/graphs/line/LineChart.svelte +90 -51
  46. package/dist/components/graphs/line/LineChart.svelte.d.ts +6 -13
  47. package/dist/components/graphs/matrix/Matrix.stories.svelte +142 -0
  48. package/dist/components/graphs/matrix/Matrix.stories.svelte.d.ts +19 -0
  49. package/dist/components/graphs/matrix/Matrix.svelte +149 -0
  50. package/dist/components/graphs/matrix/Matrix.svelte.d.ts +24 -0
  51. package/dist/components/graphs/matrix/index.d.ts +3 -0
  52. package/dist/components/graphs/matrix/index.js +3 -0
  53. package/dist/components/graphs/multiline/MultiLineChart.stories.svelte +115 -28
  54. package/dist/components/graphs/multiline/MultiLineChart.svelte +187 -50
  55. package/dist/components/graphs/multiline/MultiLineChart.svelte.d.ts +9 -12
  56. package/dist/components/graphs/scatterplot/Scatterplot.stories.svelte +68 -41
  57. package/dist/components/graphs/scatterplot/Scatterplot.svelte +312 -45
  58. package/dist/components/graphs/scatterplot/Scatterplot.svelte.d.ts +23 -13
  59. package/dist/components/graphs/utils/tooltipFormatter.d.ts +10 -0
  60. package/dist/components/graphs/utils/tooltipFormatter.js +52 -0
  61. package/dist/components/icon-button/IconButton.stories.svelte +6 -6
  62. package/dist/components/icon-button/IconButton.svelte +50 -9
  63. package/dist/components/icon-button/IconButton.svelte.d.ts +3 -5
  64. package/dist/components/icons/AnalysisIcon.stories.svelte +15 -21
  65. package/dist/components/icons/AnalysisIcon.svelte +63 -44
  66. package/dist/components/icons/AnalysisIcon.svelte.d.ts +1 -0
  67. package/dist/components/icons/Icon.stories.svelte +4 -4
  68. package/dist/components/icons/Icon.svelte +1 -1
  69. package/dist/components/icons/PrincipalIcon.svelte +96 -0
  70. package/dist/components/icons/PrincipalIcon.svelte.d.ts +10 -0
  71. package/dist/components/icons/custom/Halo.svelte +14 -8
  72. package/dist/components/icons/custom/Halo.svelte.d.ts +7 -25
  73. package/dist/components/icons/custom/Well.svelte +14 -6
  74. package/dist/components/icons/custom/Well.svelte.d.ts +7 -25
  75. package/dist/components/icons/index.d.ts +3 -2
  76. package/dist/components/icons/index.js +34 -0
  77. package/dist/components/input/Input.stories.svelte +16 -22
  78. package/dist/components/input/Input.svelte +140 -134
  79. package/dist/components/input/Input.svelte.d.ts +12 -13
  80. package/dist/components/label/Label.stories.svelte +28 -0
  81. package/dist/components/label/Label.stories.svelte.d.ts +19 -0
  82. package/dist/components/label/Label.svelte +17 -0
  83. package/dist/components/label/Label.svelte.d.ts +9 -0
  84. package/dist/components/list/List.stories.svelte +3 -3
  85. package/dist/components/logo/Logo.stories.svelte +1 -1
  86. package/dist/components/manual-cfu-counter/ManualCFUCounter.stories.svelte +125 -0
  87. package/dist/components/manual-cfu-counter/ManualCFUCounter.stories.svelte.d.ts +3 -0
  88. package/dist/components/manual-cfu-counter/ManualCFUCounter.svelte +577 -0
  89. package/dist/components/manual-cfu-counter/ManualCFUCounter.svelte.d.ts +16 -0
  90. package/dist/components/manual-cfu-counter/index.d.ts +1 -0
  91. package/dist/components/manual-cfu-counter/index.js +1 -0
  92. package/dist/components/manual-cfu-counter/test/ManualCFUCounterTestWrapper.svelte +22 -0
  93. package/dist/components/manual-cfu-counter/test/ManualCFUCounterTestWrapper.svelte.d.ts +19 -0
  94. package/dist/components/markdown/Markdown.stories.svelte +1 -1
  95. package/dist/components/markdown/Markdown.svelte +1 -1
  96. package/dist/components/modal/Modal.stories.svelte +2 -2
  97. package/dist/components/modal/Modal.svelte +27 -22
  98. package/dist/components/modal/Modal.svelte.d.ts +4 -1
  99. package/dist/components/notification-popup/NotificationPopup.stories.svelte +1 -1
  100. package/dist/components/pill/Pill.stories.svelte +13 -0
  101. package/dist/components/pill/Pill.stories.svelte.d.ts +19 -0
  102. package/dist/components/progress-circle/ProgressCircle.stories.svelte +15 -0
  103. package/dist/components/progress-circle/ProgressCircle.stories.svelte.d.ts +19 -0
  104. package/dist/components/required-status-indicator/RequiredStatusIndicator.stories.svelte +28 -0
  105. package/dist/components/required-status-indicator/RequiredStatusIndicator.stories.svelte.d.ts +19 -0
  106. package/dist/components/required-status-indicator/RequiredStatusIndicator.svelte +22 -0
  107. package/dist/components/required-status-indicator/RequiredStatusIndicator.svelte.d.ts +8 -0
  108. package/dist/components/required-status-indicator/index.d.ts +1 -0
  109. package/dist/components/required-status-indicator/index.js +1 -0
  110. package/dist/components/segmented-control-buttons/SegmentedControlButtons.stories.svelte +3 -3
  111. package/dist/components/select/Select.stories.svelte +12 -12
  112. package/dist/components/select/Select.svelte +0 -2
  113. package/dist/components/select-new/Select.stories.svelte +219 -0
  114. package/dist/components/select-new/Select.stories.svelte.d.ts +19 -0
  115. package/dist/components/select-new/components/Group.svelte +24 -0
  116. package/dist/components/select-new/components/Group.svelte.d.ts +11 -0
  117. package/dist/components/select-new/components/MultiSelectTrigger.svelte +66 -0
  118. package/dist/components/select-new/components/MultiSelectTrigger.svelte.d.ts +17 -0
  119. package/dist/components/select-new/components/SelectContent.svelte +33 -0
  120. package/dist/components/select-new/components/SelectContent.svelte.d.ts +10 -0
  121. package/dist/components/select-new/components/SelectGroupHeading.svelte +19 -0
  122. package/dist/components/select-new/components/SelectGroupHeading.svelte.d.ts +9 -0
  123. package/dist/components/select-new/components/SelectItem.svelte +41 -0
  124. package/dist/components/select-new/components/SelectItem.svelte.d.ts +9 -0
  125. package/dist/components/select-new/components/SelectTrigger.svelte +48 -0
  126. package/dist/components/select-new/components/SelectTrigger.svelte.d.ts +12 -0
  127. package/dist/components/select-new/index.d.ts +10 -0
  128. package/dist/components/select-new/index.js +12 -0
  129. package/dist/components/select-new/types.d.ts +25 -0
  130. package/dist/components/select-new/types.js +1 -0
  131. package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte +92 -0
  132. package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte.d.ts +3 -0
  133. package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte +65 -0
  134. package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte.d.ts +3 -0
  135. package/dist/components/sjsf-wrappers/index.d.ts +2 -0
  136. package/dist/components/sjsf-wrappers/index.js +2 -0
  137. package/dist/components/sjsf-wrappers/sjsfCustomTheme.d.ts +2 -0
  138. package/dist/components/sjsf-wrappers/sjsfCustomTheme.js +8 -0
  139. package/dist/components/skeleton-loader/SkeletonLoader.stories.svelte +4 -4
  140. package/dist/components/slider/Slider.stories.svelte +4 -4
  141. package/dist/components/spinner/Spinner.stories.svelte +13 -0
  142. package/dist/components/spinner/Spinner.stories.svelte.d.ts +19 -0
  143. package/dist/components/stat-card/StatCard.stories.svelte +27 -19
  144. package/dist/components/stat-card/StatCard.svelte +100 -6
  145. package/dist/components/stat-card/StatCard.svelte.d.ts +3 -0
  146. package/dist/components/status-badge/StatusBadge.stories.svelte +6 -6
  147. package/dist/components/status-badge/StatusBadge.svelte +5 -3
  148. package/dist/components/stepper/Stepper.stories.svelte +243 -0
  149. package/dist/components/stepper/Stepper.stories.svelte.d.ts +19 -0
  150. package/dist/components/stepper/components/stepper-root.svelte +20 -0
  151. package/dist/components/stepper/components/stepper-root.svelte.d.ts +9 -0
  152. package/dist/components/stepper/components/stepper-step.svelte +100 -0
  153. package/dist/components/stepper/components/stepper-step.svelte.d.ts +11 -0
  154. package/dist/components/stepper/index.d.ts +15 -0
  155. package/dist/components/stepper/index.js +2 -0
  156. package/dist/components/table/Table.stories.svelte +1 -1
  157. package/dist/components/table/components/Td.svelte +3 -2
  158. package/dist/components/table/components/Td.svelte.d.ts +1 -0
  159. package/dist/components/table/components/Tr.svelte +3 -2
  160. package/dist/components/table/components/Tr.svelte.d.ts +1 -0
  161. package/dist/components/tabs/Tabs.stories.svelte +1 -1
  162. package/dist/components/tag/Tag.stories.svelte +9 -9
  163. package/dist/components/tag/Tag.svelte +0 -18
  164. package/dist/components/textarea/Textarea.stories.svelte +97 -0
  165. package/dist/components/textarea/Textarea.stories.svelte.d.ts +19 -0
  166. package/dist/components/textarea/Textarea.svelte +94 -0
  167. package/dist/components/textarea/Textarea.svelte.d.ts +17 -0
  168. package/dist/components/textarea/index.d.ts +1 -0
  169. package/dist/components/textarea/index.js +1 -0
  170. package/dist/components/toggle/Toggle.stories.svelte +1 -1
  171. package/dist/components/toggle/Toggle.svelte +3 -2
  172. package/dist/components/toggle/Toggle.svelte.d.ts +1 -0
  173. package/dist/components/toggle-icon-button/ToggleIconButton.stories.svelte +6 -6
  174. package/dist/components/tooltip/Tooltip.stories.svelte +6 -6
  175. package/dist/components/tooltip/Tooltip.svelte +1 -1
  176. package/dist/index.d.ts +7 -0
  177. package/dist/index.js +7 -0
  178. package/dist/tailwind.preset.d.ts +5 -0
  179. package/dist/tokens.d.ts +10 -0
  180. package/dist/tokens.js +6 -4
  181. package/package.json +1 -2
@@ -1,67 +1,334 @@
1
1
  <script lang="ts">
2
- import { colors, textColor } from '../../../tokens';
3
- import Chart from '../chart/Chart.svelte';
4
- import type { EChartsOption } from 'echarts';
5
-
6
- type Props = {
7
- data: number[][];
8
- lineData?: number[];
9
- xAxis: string;
10
- yAxis: string;
11
- loading?: boolean;
12
- xAxisOptions?: EChartsOption['xAxis'];
13
- yAxisOptions?: EChartsOption['yAxis'];
14
- onitemclick?: (params: echarts.ECElementEvent) => void;
15
- onmouseover?: (params: echarts.ECElementEvent) => void;
16
- onmouseout?: () => void;
2
+ import { backgroundColor } from '../../../tokens';
3
+ import Icon from '../../icons/Icon.svelte';
4
+ import Chart, { type GenericChartProps } from '../chart/Chart.svelte';
5
+ import type {
6
+ EChartsOption,
7
+ SeriesOption,
8
+ CustomSeriesRenderItemAPI,
9
+ CustomSeriesRenderItemParams
10
+ } from 'echarts';
11
+ import Tooltip from '../../tooltip/Tooltip.svelte';
12
+ import type { Snippet } from 'svelte';
13
+
14
+ export type DataPoint = { value: [number, number]; metadata: any; error_value?: number };
15
+
16
+ export type ScatterPlotEchartsEvent = echarts.ECElementEvent & {
17
+ data: DataPoint;
18
+ };
19
+
20
+ type LegendItem = {
21
+ label: string;
22
+ color: string;
23
+ type: 'point' | 'line' | 'area';
17
24
  };
18
25
 
26
+ type ScatterPlotProps = {
27
+ data: DataPoint[];
28
+ lineData?: [[number, number], [number, number]];
29
+ showConfidenceBand?: boolean;
30
+ showLegend?: boolean;
31
+ legendItems?: LegendItem[];
32
+ children?: Snippet;
33
+ } & Omit<GenericChartProps, 'timeIndex'>;
34
+
19
35
  const {
20
36
  data,
21
- xAxis,
22
- yAxis,
37
+ xAxisName,
38
+ yAxisName,
23
39
  loading = false,
40
+ showConfidenceBand = false,
24
41
  onitemclick,
25
42
  onmouseover,
26
43
  onmouseout,
44
+ showLegend = false,
45
+ legendItems = [
46
+ { label: 'Count', color: backgroundColor['blue-inverse'], type: 'point' },
47
+ { label: 'Perfect agreement', color: backgroundColor['lilac-inverse'], type: 'line' }
48
+ ],
49
+ children,
27
50
  ...props
28
- }: Props = $props();
51
+ }: ScatterPlotProps = $props();
52
+
53
+ const displayedLegendItems: LegendItem[] = $derived([
54
+ ...legendItems,
55
+ ...(showConfidenceBand
56
+ ? [
57
+ {
58
+ label: 'Error margin',
59
+ color: backgroundColor.lilac,
60
+ type: 'area' as const
61
+ }
62
+ ]
63
+ : [])
64
+ ]);
29
65
 
30
- function handleClick(params: echarts.ECElementEvent) {
66
+ let chartComponent: any;
67
+
68
+ function handleClick(params: ScatterPlotEchartsEvent) {
31
69
  onitemclick?.(params);
32
70
  }
33
71
 
34
- let options: EChartsOption = {
35
- xAxis: {
36
- type: 'value',
37
- name: xAxis,
38
- ...props.xAxisOptions
39
- },
40
- yAxis: {
41
- type: 'value',
42
- name: yAxis,
43
- ...props.yAxisOptions
44
- },
45
- series: [
46
- {
47
- symbolSize: 8,
48
- data,
49
- type: 'scatter',
50
- itemStyle: {
51
- color: colors.blue[5].default
72
+ function handleMouseOver(params: ScatterPlotEchartsEvent) {
73
+ onmouseover?.(params);
74
+ }
75
+
76
+ function handleMouseOut() {
77
+ onmouseout?.();
78
+ }
79
+
80
+ // from https://echarts.apache.org/examples/en/editor.html?c=custom-error-bar
81
+ function renderErrorBarItem(
82
+ params: CustomSeriesRenderItemParams,
83
+ api: CustomSeriesRenderItemAPI
84
+ ) {
85
+ const xValue = api.value(0) as number;
86
+ const yValue = api.value(1) as number;
87
+ const error = api.value(2) as number;
88
+
89
+ const highPoint = api.coord([xValue, yValue + error]);
90
+ const lowPoint = api.coord([xValue, yValue - error]);
91
+
92
+ if (!highPoint || !lowPoint) {
93
+ return undefined;
94
+ }
95
+
96
+ // calculate a dynamic width for the caps based on the x-axis scale
97
+ const sizeValue = api.size?.([1, 0]);
98
+ const baseWidth = Array.isArray(sizeValue) ? sizeValue[0] : 10;
99
+ const halfWidth = Math.min((baseWidth ?? 10) * 1.5, 3);
100
+ const style = {
101
+ stroke: api.visual('color') as string,
102
+ fill: undefined
103
+ };
104
+
105
+ return {
106
+ type: 'group' as const,
107
+ children: [
108
+ {
109
+ type: 'line' as const,
110
+ transition: 'shape' as const,
111
+ shape: {
112
+ x1: highPoint[0] - halfWidth,
113
+ y1: highPoint[1],
114
+ x2: highPoint[0] + halfWidth,
115
+ y2: highPoint[1]
116
+ },
117
+ style
118
+ },
119
+ {
120
+ type: 'line' as const,
121
+ transition: 'shape' as const,
122
+ shape: {
123
+ x1: highPoint[0],
124
+ y1: highPoint[1],
125
+ x2: lowPoint[0],
126
+ y2: lowPoint[1]
127
+ },
128
+ style
129
+ },
130
+ {
131
+ type: 'line' as const,
132
+ transition: 'shape' as const,
133
+ shape: {
134
+ x1: lowPoint[0] - halfWidth,
135
+ y1: lowPoint[1],
136
+ x2: lowPoint[0] + halfWidth,
137
+ y2: lowPoint[1]
138
+ },
139
+ style
52
140
  }
53
- },
54
- {
141
+ ]
142
+ };
143
+ }
144
+
145
+ const options = $derived(getChartOptions());
146
+
147
+ function getChartOptions(): EChartsOption {
148
+ const series: SeriesOption[] = [];
149
+ const errorBarData = data
150
+ .filter((d) => d.error_value != 0)
151
+ .map((d) => [...d.value, d.error_value]);
152
+
153
+ if (props.lineData && props.lineData.length > 0) {
154
+ const extendedLineData = [
155
+ props.lineData[0],
156
+ [
157
+ props.lineData[props.lineData.length - 1][0] + 10,
158
+ props.lineData[props.lineData.length - 1][1] + 10
159
+ ]
160
+ ];
161
+ series.push({
55
162
  type: 'line',
56
- data: props.lineData,
163
+ data: extendedLineData,
57
164
  lineStyle: {
58
165
  type: 'dashed',
59
- color: colors.blue[6]
166
+ color: backgroundColor['lilac-inverse']
167
+ },
168
+ symbol: 'none',
169
+ emphasis: {
170
+ disabled: true
60
171
  },
61
- showSymbol: false
172
+ silent: true,
173
+ zlevel: 0
174
+ });
175
+
176
+ if (showConfidenceBand && props.lineData && props.lineData.length > 0) {
177
+ const lowerBandData = extendedLineData.map((point) => {
178
+ const yValue = point[1];
179
+ // 0-30 = ±3, 30+ = ±10%
180
+ return [point[0], yValue <= 30 ? yValue - 3 : yValue * 0.9];
181
+ });
182
+
183
+ const upperBandData = extendedLineData.map((point) => {
184
+ const yValue = point[1];
185
+ // 0-30 = ±3, 30+ = ±10%
186
+ return [point[0], yValue <= 30 ? yValue + 3 : yValue * 1.1];
187
+ });
188
+
189
+ series.push({
190
+ name: 'Confidence Band',
191
+ type: 'line',
192
+ data: [...upperBandData, ...lowerBandData.reverse()],
193
+ symbol: 'none',
194
+ areaStyle: {
195
+ color: backgroundColor.lilac,
196
+ opacity: 0.5
197
+ },
198
+ lineStyle: {
199
+ opacity: 0
200
+ },
201
+ tooltip: {
202
+ show: false
203
+ },
204
+ emphasis: {
205
+ disabled: true
206
+ },
207
+ silent: true,
208
+ zlevel: 0
209
+ });
62
210
  }
63
- ]
64
- };
211
+ }
212
+
213
+ series.push({
214
+ symbolSize: 8,
215
+ data,
216
+ type: 'scatter',
217
+ itemStyle: {
218
+ color: backgroundColor['blue-inverse'],
219
+ opacity: 0.8
220
+ },
221
+ emphasis: {
222
+ itemStyle: {
223
+ color: backgroundColor['blue-inverse'],
224
+ opacity: 1
225
+ }
226
+ },
227
+ animation: false,
228
+ zlevel: 1
229
+ });
230
+
231
+ if (errorBarData.length > 0) {
232
+ series.push({
233
+ type: 'custom',
234
+ name: 'error',
235
+ silent: true,
236
+ itemStyle: {
237
+ borderWidth: 1.5,
238
+ color: backgroundColor['blue-inverse']
239
+ },
240
+ renderItem: renderErrorBarItem,
241
+ data: errorBarData,
242
+ zlevel: 0
243
+ });
244
+ }
245
+
246
+ return {
247
+ xAxis: {
248
+ type: 'value',
249
+ name: xAxisName,
250
+ max: props.lineData
251
+ ? Math.ceil(props.lineData[props.lineData.length - 1][0] / 10) * 10
252
+ : undefined,
253
+ ...props.xAxisOptions
254
+ },
255
+ yAxis: {
256
+ type: 'value',
257
+ name: yAxisName,
258
+ min: 0,
259
+ max: props.lineData
260
+ ? Math.ceil(props.lineData[props.lineData.length - 1][1] / 10) * 10
261
+ : undefined,
262
+ ...props.yAxisOptions
263
+ },
264
+ animation: false,
265
+ tooltip: { show: false },
266
+ series
267
+ };
268
+ }
269
+
270
+ $effect(() => {
271
+ if (chartComponent && data) {
272
+ chartComponent.updateOptions(options);
273
+ }
274
+ });
65
275
  </script>
66
276
 
67
- <Chart {options} onitemclick={handleClick} {onmouseover} {onmouseout} {loading} />
277
+ {#snippet confBandTooltip()}
278
+ <div class="flex flex-col text-left">
279
+ <div class="w-max">
280
+ ±3 <span class="text-sm text-secondary-inverse">colonies if count</span> ≤30
281
+ </div>
282
+ <div>
283
+ ±10% <span class="text-sm text-secondary-inverse">if count</span> >30
284
+ </div>
285
+ </div>
286
+ {/snippet}
287
+
288
+ <div class="relative h-full" role="presentation">
289
+ <Chart
290
+ bind:this={chartComponent}
291
+ {options}
292
+ onitemclick={(e) => handleClick(e as ScatterPlotEchartsEvent)}
293
+ onmouseover={(e) => handleMouseOver(e as ScatterPlotEchartsEvent)}
294
+ onmouseout={handleMouseOut}
295
+ {loading}
296
+ {xAxisName}
297
+ {yAxisName}
298
+ >
299
+ {@render children?.()}
300
+ </Chart>
301
+ {#if showLegend}
302
+ <div
303
+ class="absolute left-14 top-6 flex h-auto rounded-lg border bg-surface transition-all duration-200"
304
+ >
305
+ <div class="ml-1 flex flex-col justify-center p-2">
306
+ {#each displayedLegendItems as item}
307
+ <div class="flex items-center gap-2">
308
+ {#if item.type === 'point'}
309
+ <div class="h-2 w-2 rounded-full" style="background-color: {item.color}"></div>
310
+ {:else if item.type === 'line'}
311
+ <div
312
+ class="h-[1px] w-2 border border-dashed"
313
+ style="border-color: {item.color}"
314
+ ></div>
315
+ {:else if item.type === 'area'}
316
+ <div class="h-2 w-2" style="background-color: {item.color}"></div>
317
+ {/if}
318
+ <span class="text-sm text-secondary">{item.label}</span>
319
+ {#if item.label === 'Error margin'}
320
+ <Tooltip placement="right">
321
+ {#snippet trigger()}
322
+ <Icon iconName="Info" color="icon-tertiary" />
323
+ {/snippet}
324
+ {#snippet content()}
325
+ {@render confBandTooltip()}
326
+ {/snippet}
327
+ </Tooltip>
328
+ {/if}
329
+ </div>
330
+ {/each}
331
+ </div>
332
+ </div>
333
+ {/if}
334
+ </div>
@@ -1,16 +1,26 @@
1
- import type { EChartsOption } from 'echarts';
2
- type Props = {
3
- data: number[][];
4
- lineData?: number[];
5
- xAxis: string;
6
- yAxis: string;
7
- loading?: boolean;
8
- xAxisOptions?: EChartsOption['xAxis'];
9
- yAxisOptions?: EChartsOption['yAxis'];
10
- onitemclick?: (params: echarts.ECElementEvent) => void;
11
- onmouseover?: (params: echarts.ECElementEvent) => void;
12
- onmouseout?: () => void;
1
+ import { type GenericChartProps } from '../chart/Chart.svelte';
2
+ import type { Snippet } from 'svelte';
3
+ export type DataPoint = {
4
+ value: [number, number];
5
+ metadata: any;
6
+ error_value?: number;
13
7
  };
14
- declare const Scatterplot: import("svelte").Component<Props, {}, "">;
8
+ export type ScatterPlotEchartsEvent = echarts.ECElementEvent & {
9
+ data: DataPoint;
10
+ };
11
+ type LegendItem = {
12
+ label: string;
13
+ color: string;
14
+ type: 'point' | 'line' | 'area';
15
+ };
16
+ type ScatterPlotProps = {
17
+ data: DataPoint[];
18
+ lineData?: [[number, number], [number, number]];
19
+ showConfidenceBand?: boolean;
20
+ showLegend?: boolean;
21
+ legendItems?: LegendItem[];
22
+ children?: Snippet;
23
+ } & Omit<GenericChartProps, 'timeIndex'>;
24
+ declare const Scatterplot: import("svelte").Component<ScatterPlotProps, {}, "">;
15
25
  type Scatterplot = ReturnType<typeof Scatterplot>;
16
26
  export default Scatterplot;
@@ -0,0 +1,10 @@
1
+ import type { CallbackDataParams } from 'echarts/types/dist/shared';
2
+ interface TooltipFormatterConfig {
3
+ yAxisName?: string;
4
+ yAxisUnit?: string;
5
+ focusedSeriesAccessor?: () => string | undefined;
6
+ getSeriesColor?: (seriesName: string, seriesIndex: number) => string;
7
+ maxSeriesToShow?: number;
8
+ }
9
+ export declare const createTooltipFormatter: (config: TooltipFormatterConfig) => (params: CallbackDataParams | CallbackDataParams[]) => string;
10
+ export {};
@@ -0,0 +1,52 @@
1
+ import { textColor } from '../../../tokens';
2
+ const toFixedLocaleString = (value, fractionDigits = 0, locale = undefined) => value?.toLocaleString(locale, {
3
+ minimumFractionDigits: fractionDigits,
4
+ maximumFractionDigits: fractionDigits
5
+ }) ?? '';
6
+ export const createTooltipFormatter = (config) => {
7
+ const { maxSeriesToShow = 10 } = config;
8
+ return (params) => {
9
+ if (typeof params !== 'object' || params === null) {
10
+ return '';
11
+ }
12
+ let paramArray = Array.isArray(params) ? params : [params];
13
+ if (paramArray.length === 0)
14
+ return '';
15
+ const currentFocusedSeries = config.focusedSeriesAccessor?.();
16
+ if (currentFocusedSeries !== undefined) {
17
+ paramArray = paramArray.filter((p) => currentFocusedSeries.includes(p.seriesName ?? ''));
18
+ if (paramArray.length === 0)
19
+ return '';
20
+ }
21
+ const firstParam = paramArray[0];
22
+ const categoryName = firstParam.name ?? ''; // X-axis value (category)
23
+ const unit = config.yAxisUnit ?? '';
24
+ let tooltipContent = `<div style="font-weight:bold; margin-bottom: 5px;">${categoryName}</div>`;
25
+ const originalSeriesCount = paramArray.length;
26
+ let seriesToShow = paramArray;
27
+ if (originalSeriesCount > maxSeriesToShow) {
28
+ seriesToShow = paramArray.slice(0, maxSeriesToShow);
29
+ }
30
+ seriesToShow.forEach((p, index) => {
31
+ if (p.value == null || p.value === undefined)
32
+ return; // Skip null/undefined values
33
+ const seriesName = p.seriesName ?? config.yAxisName ?? ''; // Use series name or configured yAxisName
34
+ const value = p.value; // Assume number after null check
35
+ let color = p.color;
36
+ // Resolve color for multiline if needed and getter provided
37
+ if (!color && config.getSeriesColor && p.seriesName) {
38
+ color = config.getSeriesColor(p.seriesName, p.seriesIndex ?? index);
39
+ }
40
+ // Fallback color if still unresolved (should ideally not happen if configured correctly)
41
+ color = color || textColor['icon-blue'];
42
+ const marker = `<span style="display:inline-block;margin-right:5px;border-radius:2px;width:8px;height:8px;background-color:${color}; vertical-align: baseline;"></span>`;
43
+ const valueString = `<span style="font-weight:500;">${toFixedLocaleString(value, 2)} ${unit}</span>`;
44
+ tooltipContent += `<div>${marker}${seriesName}: ${valueString}</div>`;
45
+ });
46
+ if (originalSeriesCount > maxSeriesToShow) {
47
+ const remainingCount = originalSeriesCount - maxSeriesToShow;
48
+ tooltipContent += `<div style="margin-top: 5px; font-style: italic;">... and ${remainingCount} more series</div>`;
49
+ }
50
+ return tooltipContent;
51
+ };
52
+ };
@@ -10,7 +10,7 @@
10
10
  });
11
11
  </script>
12
12
 
13
- <Story name="Base">
13
+ <Story name="Base" asChild>
14
14
  <div class="flex flex-col gap-2">
15
15
  <IconButton variant="primary">
16
16
  <Icon iconName="Plus" />
@@ -27,7 +27,7 @@
27
27
  </div>
28
28
  </Story>
29
29
 
30
- <Story name="Sizes">
30
+ <Story name="Sizes" asChild>
31
31
  <div class="flex flex-col gap-2">
32
32
  <IconButton variant="secondary" size="xs">
33
33
  <Icon iconName="Plus" />
@@ -40,7 +40,7 @@
40
40
  </IconButton>
41
41
  </div>
42
42
  </Story>
43
- <Story name="Not rounded base">
43
+ <Story name="Not rounded base" asChild>
44
44
  <div class="flex flex-col gap-2">
45
45
  <IconButton variant="primary" rounded={false}>
46
46
  <Icon iconName="Plus" />
@@ -57,7 +57,7 @@
57
57
  </div>
58
58
  </Story>
59
59
 
60
- <Story name="Not rounded sizes">
60
+ <Story name="Not rounded sizes" asChild>
61
61
  <div class="flex flex-col gap-2">
62
62
  <IconButton variant="secondary" size="xs" rounded={false}>
63
63
  <Icon iconName="Plus" />
@@ -70,12 +70,12 @@
70
70
  </IconButton>
71
71
  </div>
72
72
  </Story>
73
- <Story name="Disabled">
73
+ <Story name="Disabled" asChild>
74
74
  <IconButton disabled>
75
75
  <Icon iconName="Plus" />
76
76
  </IconButton>
77
77
  </Story>
78
- <Story name="Loading">
78
+ <Story name="Loading" asChild>
79
79
  <IconButton loading>
80
80
  <Icon iconName="Plus" />
81
81
  </IconButton>
@@ -1,20 +1,28 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
3
  import { Spinner } from '../spinner/';
4
+ import type { HTMLButtonAttributes } from 'svelte/elements';
4
5
 
5
- type Variant = 'primary' | 'secondary' | 'transparent' | 'danger';
6
- interface Props {
6
+ type Variant =
7
+ | 'primary'
8
+ | 'secondary'
9
+ | 'transparent'
10
+ | 'danger'
11
+ | 'secondary-inverse'
12
+ | 'transparent-inverse';
13
+
14
+ // Combine custom props with standard HTML button attributes,
15
+ // omitting ones we handle explicitly (like 'class', 'onclick')
16
+ interface Props extends HTMLButtonAttributes {
7
17
  variant?: Variant;
8
18
  type?: 'button' | 'submit' | 'reset' | null | undefined;
9
19
  loading?: boolean;
10
- disabled?: boolean;
11
20
  size?: 'xs' | 'sm' | 'md' | 'lg';
12
21
  children?: Snippet;
13
- onclick?: (e: MouseEvent) => void;
14
- tabindex?: number | undefined;
15
22
  rounded?: boolean;
16
23
  }
17
24
 
25
+ // Destructure only the component's specific props
18
26
  let {
19
27
  variant = 'transparent',
20
28
  type = 'button',
@@ -24,7 +32,9 @@
24
32
  children,
25
33
  onclick,
26
34
  tabindex,
27
- rounded = true
35
+ rounded = true,
36
+ class: className,
37
+ ...rest
28
38
  }: Props = $props();
29
39
 
30
40
  let sizeClass = $derived(`size-${size}`);
@@ -38,8 +48,9 @@
38
48
  }}
39
49
  {type}
40
50
  {disabled}
41
- class="{sizeClass} {variantClass} disabled"
51
+ class="{sizeClass} {variantClass} disabled {className}"
42
52
  class:rounded
53
+ {...rest}
43
54
  >
44
55
  {#if loading}
45
56
  <Spinner />
@@ -48,7 +59,15 @@
48
59
  {/if}
49
60
  </button>
50
61
  {:else}
51
- <button {onclick} {type} {disabled} {tabindex} class="{sizeClass} {variantClass}" class:rounded>
62
+ <button
63
+ {onclick}
64
+ {type}
65
+ {disabled}
66
+ {tabindex}
67
+ class="{sizeClass} {variantClass} {className}"
68
+ class:rounded
69
+ {...rest}
70
+ >
52
71
  {@render children?.()}
53
72
  </button>
54
73
  {/if}
@@ -66,7 +85,7 @@
66
85
  border-radius: 9999px
67
86
  }
68
87
  .disabled {
69
- cursor: default
88
+ cursor: not-allowed
70
89
  }
71
90
  .disabled:disabled {
72
91
  background-color: #12192a0d;
@@ -148,5 +167,27 @@
148
167
  .color-danger:hover {
149
168
  --tw-bg-opacity: 1;
150
169
  background-color: rgb(191 57 58 / var(--tw-bg-opacity, 1))
170
+ }
171
+ .color-secondary-inverse {
172
+ background-color: #FFFFFF0D;
173
+ --tw-text-opacity: 1;
174
+ color: rgb(255 255 255 / var(--tw-text-opacity, 1))
175
+ }
176
+ .color-secondary-inverse:hover {
177
+ background-color: #FFFFFF26
178
+ }
179
+
180
+ .color-transparent-inverse {
181
+ background-color: transparent;
182
+ --tw-text-opacity: 1;
183
+ color: rgb(255 255 255 / var(--tw-text-opacity, 1))
184
+ }
185
+
186
+ .color-transparent-inverse:hover {
187
+ background-color: #FFFFFF26
188
+ }
189
+
190
+ .color-transparent-inverse:hover:disabled {
191
+ background-color: transparent
151
192
  }
152
193
  </style>
@@ -1,14 +1,12 @@
1
1
  import type { Snippet } from 'svelte';
2
- type Variant = 'primary' | 'secondary' | 'transparent' | 'danger';
3
- interface Props {
2
+ import type { HTMLButtonAttributes } from 'svelte/elements';
3
+ type Variant = 'primary' | 'secondary' | 'transparent' | 'danger' | 'secondary-inverse' | 'transparent-inverse';
4
+ interface Props extends HTMLButtonAttributes {
4
5
  variant?: Variant;
5
6
  type?: 'button' | 'submit' | 'reset' | null | undefined;
6
7
  loading?: boolean;
7
- disabled?: boolean;
8
8
  size?: 'xs' | 'sm' | 'md' | 'lg';
9
9
  children?: Snippet;
10
- onclick?: (e: MouseEvent) => void;
11
- tabindex?: number | undefined;
12
10
  rounded?: boolean;
13
11
  }
14
12
  declare const IconButton: import("svelte").Component<Props, {}, "">;