@makolabs/ripple 2.1.0 → 2.3.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/charts/Chart.svelte +307 -53
- package/dist/charts/chart-types.d.ts +12 -0
- package/dist/elements/accordion/Accordion.svelte +27 -10
- package/dist/elements/accordion/accordion-types.d.ts +6 -0
- package/dist/elements/dropdown/Select.svelte +191 -63
- package/dist/elements/dropdown/dropdown-types.d.ts +13 -1
- package/dist/elements/dropdown/select.d.ts +15 -0
- package/dist/elements/dropdown/select.js +14 -8
- package/dist/forms/DateRange.svelte +16 -3
- package/dist/forms/Input.svelte +6 -4
- package/dist/forms/MarketSelector.svelte +7 -27
- package/dist/forms/NumberInput.svelte +9 -6
- package/dist/forms/SegmentedControl.svelte +5 -18
- package/dist/forms/Tags.svelte +1 -1
- package/dist/forms/form-types.d.ts +2 -31
- package/dist/forms/market/market-selector-types.d.ts +1 -21
- package/dist/forms/segmented-control.d.ts +4 -34
- package/dist/forms/segmented-control.js +19 -59
- package/dist/index.d.ts +3 -11
- package/dist/index.js +0 -8
- package/dist/layout/activity-list/ActivityList.svelte +55 -1
- package/dist/variants.js +6 -6
- package/package.json +1 -1
- package/dist/elements/collapsible/Collapsible.svelte +0 -79
- package/dist/elements/collapsible/Collapsible.svelte.d.ts +0 -4
- package/dist/elements/collapsible/CollapsibleTestWrapper.svelte +0 -23
- package/dist/elements/collapsible/CollapsibleTestWrapper.svelte.d.ts +0 -8
- package/dist/elements/collapsible/collapsible-types.d.ts +0 -16
- package/dist/elements/collapsible/collapsible-types.js +0 -1
- package/dist/elements/combobox/Combobox.svelte +0 -274
- package/dist/elements/combobox/Combobox.svelte.d.ts +0 -25
- package/dist/elements/combobox/ComboboxTestWrapper.svelte +0 -38
- package/dist/elements/combobox/ComboboxTestWrapper.svelte.d.ts +0 -4
- package/dist/elements/combobox/combobox-types.d.ts +0 -39
- package/dist/elements/combobox/combobox-types.js +0 -1
- package/dist/elements/timeline/Timeline.svelte +0 -95
- package/dist/elements/timeline/Timeline.svelte.d.ts +0 -7
- package/dist/elements/timeline/timeline-types.d.ts +0 -11
- package/dist/elements/timeline/timeline-types.js +0 -1
- package/dist/forms/RadioInputs.svelte +0 -73
- package/dist/forms/RadioInputs.svelte.d.ts +0 -4
- package/dist/forms/RadioPill.svelte +0 -66
- package/dist/forms/RadioPill.svelte.d.ts +0 -4
package/dist/charts/Chart.svelte
CHANGED
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
type ChartProps,
|
|
20
20
|
type ChartColorString,
|
|
21
21
|
type ChartColors,
|
|
22
|
-
type
|
|
22
|
+
type ChartThreshold,
|
|
23
|
+
type ChartAnnotation,
|
|
24
|
+
type SeriesConfig,
|
|
25
|
+
type TooltipConfig
|
|
23
26
|
} from '../index.js';
|
|
24
27
|
import { defaultChartColors } from '../variants.js';
|
|
25
28
|
|
|
@@ -71,13 +74,12 @@
|
|
|
71
74
|
orient: 'horizontal',
|
|
72
75
|
...(config.legend || {})
|
|
73
76
|
});
|
|
74
|
-
const tooltip = $derived(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
);
|
|
77
|
+
const tooltip = $derived({
|
|
78
|
+
show: true,
|
|
79
|
+
trigger: 'axis' as const,
|
|
80
|
+
formatter: undefined as TooltipConfig['formatter'],
|
|
81
|
+
...(config.tooltip || {})
|
|
82
|
+
});
|
|
81
83
|
const toolbox = $derived(
|
|
82
84
|
config.toolbox || {
|
|
83
85
|
show: false,
|
|
@@ -113,35 +115,106 @@
|
|
|
113
115
|
return color ? chartColors[color as keyof ChartColors] || color : undefined;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
function hexToRgb(hex: string): [number, number, number] {
|
|
119
|
+
const h = hex.replace('#', '');
|
|
120
|
+
return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function rgbToHex(r: number, g: number, b: number): string {
|
|
124
|
+
return (
|
|
125
|
+
'#' +
|
|
126
|
+
[r, g, b]
|
|
127
|
+
.map((v) =>
|
|
128
|
+
Math.max(0, Math.min(255, Math.round(v)))
|
|
129
|
+
.toString(16)
|
|
130
|
+
.padStart(2, '0')
|
|
131
|
+
)
|
|
132
|
+
.join('')
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function lighten(hex: string, amount: number): string {
|
|
137
|
+
const [r, g, b] = hexToRgb(hex);
|
|
138
|
+
return rgbToHex(r + (255 - r) * amount, g + (255 - g) * amount, b + (255 - b) * amount);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function darken(hex: string, amount: number): string {
|
|
142
|
+
const [r, g, b] = hexToRgb(hex);
|
|
143
|
+
return rgbToHex(r * (1 - amount), g * (1 - amount), b * (1 - amount));
|
|
144
|
+
}
|
|
120
145
|
|
|
121
|
-
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
147
|
+
function barGradient(baseHex: string, stacked: boolean): any {
|
|
148
|
+
if (stacked) {
|
|
149
|
+
// Horizontal sheen — same light direction for all segments
|
|
150
|
+
return {
|
|
151
|
+
type: 'linear',
|
|
152
|
+
x: 0,
|
|
153
|
+
y: 0,
|
|
154
|
+
x2: 1,
|
|
155
|
+
y2: 0,
|
|
156
|
+
colorStops: [
|
|
157
|
+
{ offset: 0, color: baseHex },
|
|
158
|
+
{ offset: 0.5, color: lighten(baseHex, 0.1) },
|
|
159
|
+
{ offset: 1, color: baseHex }
|
|
160
|
+
]
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// Standalone bars — top-to-bottom depth
|
|
164
|
+
return {
|
|
122
165
|
type: 'linear',
|
|
123
166
|
x: 0,
|
|
124
167
|
y: 0,
|
|
125
168
|
x2: 0,
|
|
126
|
-
y2: 1
|
|
169
|
+
y2: 1,
|
|
170
|
+
colorStops: [
|
|
171
|
+
{ offset: 0, color: lighten(baseHex, 0.2) },
|
|
172
|
+
{ offset: 0.6, color: baseHex },
|
|
173
|
+
{ offset: 1, color: darken(baseHex, 0.15) }
|
|
174
|
+
]
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
179
|
+
function lineGradient(baseHex: string): any {
|
|
180
|
+
return {
|
|
181
|
+
type: 'linear',
|
|
182
|
+
x: 0,
|
|
183
|
+
y: 0,
|
|
184
|
+
x2: 1,
|
|
185
|
+
y2: 0,
|
|
186
|
+
colorStops: [
|
|
187
|
+
{ offset: 0, color: darken(baseHex, 0.05) },
|
|
188
|
+
{ offset: 0.5, color: baseHex },
|
|
189
|
+
{ offset: 1, color: lighten(baseHex, 0.1) }
|
|
190
|
+
]
|
|
127
191
|
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
195
|
+
function getAreaStyle(seriesConfig: SeriesConfig<any>) {
|
|
196
|
+
if (!seriesConfig.color) return undefined;
|
|
197
|
+
if (!seriesConfig.showArea) return undefined;
|
|
198
|
+
|
|
199
|
+
const color = getColor(seriesConfig.color) ?? '#6366f1';
|
|
200
|
+
const opacity = seriesConfig.areaOpacity || 0.25;
|
|
201
|
+
const opHigh = Math.floor(opacity * 255)
|
|
202
|
+
.toString(16)
|
|
203
|
+
.padStart(2, '0');
|
|
204
|
+
const opMid = Math.floor(opacity * 0.4 * 255)
|
|
131
205
|
.toString(16)
|
|
132
206
|
.padStart(2, '0');
|
|
133
207
|
return {
|
|
134
208
|
color: {
|
|
135
|
-
|
|
209
|
+
type: 'linear',
|
|
210
|
+
x: 0,
|
|
211
|
+
y: 0,
|
|
212
|
+
x2: 0,
|
|
213
|
+
y2: 1,
|
|
136
214
|
colorStops: [
|
|
137
|
-
{
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
offset: 1,
|
|
143
|
-
color: color + '00'
|
|
144
|
-
}
|
|
215
|
+
{ offset: 0, color: color + opHigh },
|
|
216
|
+
{ offset: 0.6, color: color + opMid },
|
|
217
|
+
{ offset: 1, color: color + '00' }
|
|
145
218
|
]
|
|
146
219
|
}
|
|
147
220
|
};
|
|
@@ -182,16 +255,128 @@
|
|
|
182
255
|
return String(value);
|
|
183
256
|
}
|
|
184
257
|
|
|
258
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
259
|
+
function buildMarkLineFromThresholds(axis: 'x' | 'y'): any {
|
|
260
|
+
const axisCfgs = axis === 'x' ? [xAxis] : yAxis;
|
|
261
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
262
|
+
const lines: any[] = [];
|
|
263
|
+
let lineIdx = 0;
|
|
264
|
+
|
|
265
|
+
for (const cfg of axisCfgs) {
|
|
266
|
+
if (!cfg.thresholds) continue;
|
|
267
|
+
for (const t of cfg.thresholds) {
|
|
268
|
+
// Alternate label positions to reduce overlap
|
|
269
|
+
const pos =
|
|
270
|
+
axis === 'x' ? 'insideEndTop' : lineIdx % 2 === 0 ? 'insideStartTop' : 'insideEndTop';
|
|
271
|
+
|
|
272
|
+
if (t === 'average') {
|
|
273
|
+
lines.push({
|
|
274
|
+
type: 'average',
|
|
275
|
+
name: 'Avg',
|
|
276
|
+
label: { formatter: 'Avg', position: pos, fontSize: 11 },
|
|
277
|
+
lineStyle: { type: 'dashed', color: '#6b7280', width: 1 }
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
const resolved = t as ChartThreshold;
|
|
281
|
+
const color = getColor(resolved.color) ?? '#6b7280';
|
|
282
|
+
const entry = axis === 'x' ? { xAxis: resolved.value } : { yAxis: resolved.value };
|
|
283
|
+
lines.push({
|
|
284
|
+
...entry,
|
|
285
|
+
label: resolved.label
|
|
286
|
+
? {
|
|
287
|
+
formatter: resolved.label,
|
|
288
|
+
position: pos,
|
|
289
|
+
fontSize: 11,
|
|
290
|
+
color,
|
|
291
|
+
...(axis === 'x' && { rotate: 0 })
|
|
292
|
+
}
|
|
293
|
+
: { show: false },
|
|
294
|
+
lineStyle: {
|
|
295
|
+
type: resolved.style ?? 'dashed',
|
|
296
|
+
color,
|
|
297
|
+
width: 2
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
lineIdx++;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (lines.length === 0) return undefined;
|
|
305
|
+
return { silent: true, symbol: 'none', data: lines };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
309
|
+
function buildMarkPointsFromData(seriesDataKey: string | number | symbol): any {
|
|
310
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
311
|
+
const points: any[] = [];
|
|
312
|
+
data.forEach((item) => {
|
|
313
|
+
const annotation = item.annotation as ChartAnnotation | undefined;
|
|
314
|
+
if (!annotation) return;
|
|
315
|
+
const xVal = String(item[xAxis.dataKey]);
|
|
316
|
+
const yVal = item[seriesDataKey as keyof typeof item];
|
|
317
|
+
if (yVal === undefined) return;
|
|
318
|
+
const color = getColor(annotation.color) ?? undefined;
|
|
319
|
+
// Use category name string for x — matches the xAxis.data categories
|
|
320
|
+
points.push({
|
|
321
|
+
coord: [xVal, yVal],
|
|
322
|
+
symbol: 'circle',
|
|
323
|
+
symbolSize: 12,
|
|
324
|
+
...(color && { itemStyle: { color } }),
|
|
325
|
+
label: annotation.label
|
|
326
|
+
? {
|
|
327
|
+
formatter: annotation.label,
|
|
328
|
+
position: 'top',
|
|
329
|
+
distance: 8,
|
|
330
|
+
color: color ?? '#374151',
|
|
331
|
+
fontSize: 11,
|
|
332
|
+
fontWeight: 500
|
|
333
|
+
}
|
|
334
|
+
: { show: false }
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
if (points.length === 0) return undefined;
|
|
338
|
+
return { data: points };
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function mergeMarkLine(
|
|
342
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
343
|
+
a: any | undefined,
|
|
344
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
345
|
+
b: any | undefined
|
|
346
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
347
|
+
): any | undefined {
|
|
348
|
+
if (!a && !b) return undefined;
|
|
349
|
+
if (!a) return b;
|
|
350
|
+
if (!b) return a;
|
|
351
|
+
return { ...a, data: [...(a.data ?? []), ...(b.data ?? [])] };
|
|
352
|
+
}
|
|
353
|
+
|
|
185
354
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
186
355
|
function configureSeries(): any[] {
|
|
187
356
|
return series.map((seriesConfig) => {
|
|
188
357
|
const seriesType = seriesConfig.type || 'line';
|
|
189
358
|
|
|
190
359
|
if (seriesType === 'pie') {
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
360
|
+
const sliceColors = getSeriesColors(data.length);
|
|
361
|
+
const pieData = data.map((item, i) => {
|
|
362
|
+
const baseHex = getColor(seriesConfig.color) ?? sliceColors[i % sliceColors.length];
|
|
363
|
+
return {
|
|
364
|
+
value: item[seriesConfig.dataKey],
|
|
365
|
+
name: item[xAxis?.dataKey] || item.label,
|
|
366
|
+
itemStyle: {
|
|
367
|
+
color: {
|
|
368
|
+
type: 'radial',
|
|
369
|
+
x: 0.4,
|
|
370
|
+
y: 0.35,
|
|
371
|
+
r: 0.8,
|
|
372
|
+
colorStops: [
|
|
373
|
+
{ offset: 0, color: lighten(baseHex, 0.15) },
|
|
374
|
+
{ offset: 1, color: darken(baseHex, 0.1) }
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
});
|
|
195
380
|
|
|
196
381
|
return {
|
|
197
382
|
name: seriesConfig.name || seriesConfig.dataKey,
|
|
@@ -201,19 +386,24 @@
|
|
|
201
386
|
itemStyle: {
|
|
202
387
|
borderRadius: 4,
|
|
203
388
|
borderWidth: 2,
|
|
204
|
-
borderColor: '#fff'
|
|
205
|
-
color: getColor(seriesConfig.color)
|
|
389
|
+
borderColor: '#fff'
|
|
206
390
|
},
|
|
207
391
|
label: {
|
|
208
|
-
show: seriesConfig.showLabel !== undefined ? seriesConfig.showLabel : true
|
|
392
|
+
show: seriesConfig.showLabel !== undefined ? seriesConfig.showLabel : true,
|
|
393
|
+
color: '#374151',
|
|
394
|
+
fontSize: 12
|
|
209
395
|
},
|
|
210
396
|
labelLine: {
|
|
211
|
-
show: seriesConfig.showLabel !== undefined ? seriesConfig.showLabel : true
|
|
397
|
+
show: seriesConfig.showLabel !== undefined ? seriesConfig.showLabel : true,
|
|
398
|
+
lineStyle: { color: '#d1d5db' }
|
|
212
399
|
},
|
|
213
400
|
data: pieData,
|
|
214
401
|
animation: true,
|
|
215
402
|
animationDuration: AnimationDuration,
|
|
216
|
-
emphasis: seriesConfig.emphasis || {
|
|
403
|
+
emphasis: seriesConfig.emphasis || {
|
|
404
|
+
focus: 'self',
|
|
405
|
+
itemStyle: { shadowBlur: 12, shadowColor: 'rgba(0,0,0,0.15)' }
|
|
406
|
+
}
|
|
217
407
|
};
|
|
218
408
|
}
|
|
219
409
|
|
|
@@ -229,6 +419,13 @@
|
|
|
229
419
|
(s) => s.type === 'bar' || s.type === 'horizontal-bar'
|
|
230
420
|
).length;
|
|
231
421
|
|
|
422
|
+
// Thresholds attach to the first non-pie series; annotations attach per-series
|
|
423
|
+
const isFirstNonPie = series.filter((s) => s.type !== 'pie').indexOf(seriesConfig) === 0;
|
|
424
|
+
const xMarkLine = isFirstNonPie ? buildMarkLineFromThresholds('x') : undefined;
|
|
425
|
+
const yMarkLine = isFirstNonPie ? buildMarkLineFromThresholds('y') : undefined;
|
|
426
|
+
const axisMarkLine = mergeMarkLine(xMarkLine, yMarkLine);
|
|
427
|
+
const pointAnnotations = buildMarkPointsFromData(seriesConfig.dataKey);
|
|
428
|
+
|
|
232
429
|
return {
|
|
233
430
|
name: seriesConfig.name || seriesConfig.dataKey,
|
|
234
431
|
type: actualType,
|
|
@@ -236,17 +433,30 @@
|
|
|
236
433
|
data: seriesData,
|
|
237
434
|
stack: seriesConfig.stack,
|
|
238
435
|
color: getColor(seriesConfig.color),
|
|
239
|
-
emphasis: seriesConfig.emphasis || {
|
|
436
|
+
emphasis: seriesConfig.emphasis || {
|
|
437
|
+
focus: 'series',
|
|
438
|
+
blurScope: 'global'
|
|
439
|
+
},
|
|
440
|
+
blur: { itemStyle: { opacity: 0.25 }, lineStyle: { opacity: 0.25 } },
|
|
240
441
|
animation: true,
|
|
241
442
|
animationDuration: AnimationDuration,
|
|
443
|
+
...(axisMarkLine && { markLine: axisMarkLine }),
|
|
444
|
+
...(pointAnnotations && { markPoint: pointAnnotations }),
|
|
242
445
|
|
|
243
446
|
...(actualType === 'line' && {
|
|
244
447
|
smooth: seriesConfig.smooth !== undefined ? seriesConfig.smooth : true,
|
|
245
448
|
showSymbol: seriesConfig.showSymbol !== undefined ? seriesConfig.showSymbol : true,
|
|
246
|
-
symbolSize:
|
|
247
|
-
|
|
248
|
-
width: seriesConfig.lineWidth || 2,
|
|
449
|
+
symbolSize: 8,
|
|
450
|
+
itemStyle: {
|
|
249
451
|
color: getColor(seriesConfig.color),
|
|
452
|
+
borderColor: '#fff',
|
|
453
|
+
borderWidth: 2,
|
|
454
|
+
shadowColor: (getColor(seriesConfig.color) ?? '#6366f1') + '40',
|
|
455
|
+
shadowBlur: 6
|
|
456
|
+
},
|
|
457
|
+
lineStyle: {
|
|
458
|
+
width: seriesConfig.lineWidth || 2.5,
|
|
459
|
+
color: lineGradient(getColor(seriesConfig.color) ?? '#6366f1'),
|
|
250
460
|
type: seriesConfig.lineStyle?.type || 'solid'
|
|
251
461
|
},
|
|
252
462
|
areaStyle: getAreaStyle(seriesConfig)
|
|
@@ -264,11 +474,18 @@
|
|
|
264
474
|
barCategoryGap: '20%',
|
|
265
475
|
barGap: '10%',
|
|
266
476
|
color: getColor(seriesConfig.color),
|
|
267
|
-
itemStyle: {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
477
|
+
itemStyle: (() => {
|
|
478
|
+
const baseHex = getColor(seriesConfig.color) ?? '#6366f1';
|
|
479
|
+
const isStacked = !!seriesConfig.stack;
|
|
480
|
+
const isLastInStack = isStacked
|
|
481
|
+
? series.filter((s) => s.stack === seriesConfig.stack).at(-1) === seriesConfig
|
|
482
|
+
: true;
|
|
483
|
+
return {
|
|
484
|
+
color: barGradient(baseHex, isStacked),
|
|
485
|
+
borderRadius: isLastInStack ? [4, 4, 0, 0] : [0, 0, 0, 0],
|
|
486
|
+
opacity: seriesConfig.opacity ?? 1
|
|
487
|
+
};
|
|
488
|
+
})()
|
|
272
489
|
}),
|
|
273
490
|
|
|
274
491
|
label: {
|
|
@@ -384,19 +601,41 @@
|
|
|
384
601
|
// Regular chart configuration
|
|
385
602
|
const categories = data.map((item) => item[xAxis.dataKey]);
|
|
386
603
|
|
|
604
|
+
const systemFont =
|
|
605
|
+
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif";
|
|
387
606
|
const options = {
|
|
388
607
|
color: colorPalette,
|
|
608
|
+
textStyle: { fontFamily: systemFont },
|
|
389
609
|
|
|
390
610
|
tooltip: {
|
|
391
611
|
show: tooltip.show,
|
|
392
612
|
trigger: tooltip.trigger,
|
|
393
|
-
formatter: tooltip.formatter || defaultFormatter
|
|
613
|
+
formatter: tooltip.formatter || defaultFormatter,
|
|
614
|
+
backgroundColor: 'rgba(255, 255, 255, 0.96)',
|
|
615
|
+
borderColor: 'transparent',
|
|
616
|
+
borderRadius: 8,
|
|
617
|
+
padding: [10, 14],
|
|
618
|
+
textStyle: { color: '#374151', fontSize: 12 },
|
|
619
|
+
extraCssText: 'box-shadow: 0 4px 12px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.06);',
|
|
620
|
+
axisPointer: {
|
|
621
|
+
type: 'line',
|
|
622
|
+
lineStyle: {
|
|
623
|
+
color: '#d1d5db',
|
|
624
|
+
width: 1,
|
|
625
|
+
type: 'solid'
|
|
626
|
+
},
|
|
627
|
+
crossStyle: { color: '#d1d5db' }
|
|
628
|
+
}
|
|
394
629
|
},
|
|
395
630
|
|
|
396
631
|
legend: {
|
|
397
632
|
show: legend.show,
|
|
398
633
|
type: 'scroll',
|
|
399
634
|
orient: legend.orient,
|
|
635
|
+
textStyle: { color: '#6b7280', fontSize: 12 },
|
|
636
|
+
itemWidth: 14,
|
|
637
|
+
itemHeight: 8,
|
|
638
|
+
itemGap: 16,
|
|
400
639
|
...(legend.position === 'top' && { top: 0, left: 'center' }),
|
|
401
640
|
...(legend.position === 'bottom' && { bottom: 0, left: 'center' }),
|
|
402
641
|
...(legend.position === 'left' && { left: 0, top: 'middle' }),
|
|
@@ -404,17 +643,22 @@
|
|
|
404
643
|
},
|
|
405
644
|
|
|
406
645
|
grid: {
|
|
407
|
-
top: legend.position === 'top' ? '
|
|
408
|
-
right: grid.right || '
|
|
646
|
+
top: legend.position === 'top' ? '18%' : grid.top || '12%',
|
|
647
|
+
right: grid.right || '4%',
|
|
409
648
|
bottom: legend.position === 'bottom' ? '15%' : grid.bottom || '10%',
|
|
410
|
-
left: grid.left || '
|
|
411
|
-
containLabel: grid.containLabel !== undefined ? grid.containLabel : true
|
|
649
|
+
left: grid.left || '4%',
|
|
650
|
+
containLabel: grid.containLabel !== undefined ? grid.containLabel : true,
|
|
651
|
+
backgroundColor: 'rgba(249, 250, 251, 0.5)',
|
|
652
|
+
show: true,
|
|
653
|
+
borderColor: 'transparent'
|
|
412
654
|
},
|
|
413
655
|
|
|
414
656
|
xAxis: {
|
|
415
657
|
type: 'category',
|
|
416
658
|
data: categories,
|
|
417
659
|
axisLabel: {
|
|
660
|
+
color: '#6b7280',
|
|
661
|
+
fontSize: 12,
|
|
418
662
|
...(xAxis.tick && {
|
|
419
663
|
fontSize: xAxis.tick.fontSize,
|
|
420
664
|
rotate: xAxis.tick.rotate,
|
|
@@ -422,6 +666,7 @@
|
|
|
422
666
|
}),
|
|
423
667
|
formatter: xAxis.format || '{value}'
|
|
424
668
|
},
|
|
669
|
+
axisTick: { show: false },
|
|
425
670
|
boundaryGap: series.every((s) => s.type === 'line')
|
|
426
671
|
? false
|
|
427
672
|
: series.some((s) => s.type === 'bar' || s.type === 'horizontal-bar')
|
|
@@ -430,11 +675,14 @@
|
|
|
430
675
|
name: xAxis.label,
|
|
431
676
|
nameLocation: 'middle',
|
|
432
677
|
nameGap: 30,
|
|
678
|
+
nameTextStyle: { color: '#6b7280', fontSize: 12 },
|
|
433
679
|
splitLine: {
|
|
434
|
-
show: grid.vertical || false
|
|
680
|
+
show: grid.vertical || false,
|
|
681
|
+
lineStyle: { color: '#f3f4f6' }
|
|
435
682
|
},
|
|
436
683
|
axisLine: xAxis.axisLine || {
|
|
437
|
-
show:
|
|
684
|
+
show: true,
|
|
685
|
+
lineStyle: { color: '#e5e7eb', width: 1 }
|
|
438
686
|
}
|
|
439
687
|
},
|
|
440
688
|
|
|
@@ -444,18 +692,24 @@
|
|
|
444
692
|
nameLocation: 'middle',
|
|
445
693
|
nameGap: 50,
|
|
446
694
|
nameRotate: 90,
|
|
695
|
+
nameTextStyle: { color: '#6b7280', fontSize: 12 },
|
|
447
696
|
position: axis.position || (index === 0 ? 'left' : 'right'),
|
|
448
697
|
min: axis.min,
|
|
449
698
|
max: axis.max,
|
|
450
699
|
axisLine: axis.axisLine || {
|
|
451
|
-
show:
|
|
700
|
+
show: true,
|
|
701
|
+
lineStyle: { color: '#e5e7eb', width: 1 }
|
|
452
702
|
},
|
|
703
|
+
axisTick: { show: false },
|
|
453
704
|
axisLabel: {
|
|
705
|
+
color: '#9ca3af',
|
|
706
|
+
fontSize: 11,
|
|
454
707
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
455
708
|
formatter: (value: any) => formatValue(value, axis.format, axis.unit)
|
|
456
709
|
},
|
|
457
710
|
splitLine: {
|
|
458
|
-
show: index === 0 ? grid.horizontal || true : false
|
|
711
|
+
show: index === 0 ? grid.horizontal || true : false,
|
|
712
|
+
lineStyle: { color: '#f3f4f6', type: 'dashed' }
|
|
459
713
|
}
|
|
460
714
|
})),
|
|
461
715
|
|
|
@@ -8,6 +8,16 @@ export type ChartColors = {
|
|
|
8
8
|
};
|
|
9
9
|
export type ChartType = 'line' | 'bar' | 'horizontal-bar' | 'pie' | 'stacked-bar';
|
|
10
10
|
export type ChartColorString = `#${string}` | keyof ChartColors;
|
|
11
|
+
export type ChartThreshold = {
|
|
12
|
+
value: number | string;
|
|
13
|
+
label?: string;
|
|
14
|
+
color?: ChartColorString;
|
|
15
|
+
style?: 'solid' | 'dashed' | 'dotted';
|
|
16
|
+
};
|
|
17
|
+
export type ChartAnnotation = {
|
|
18
|
+
label?: string;
|
|
19
|
+
color?: ChartColorString;
|
|
20
|
+
};
|
|
11
21
|
export type XAxisConfig<T> = {
|
|
12
22
|
dataKey: keyof T;
|
|
13
23
|
label?: string;
|
|
@@ -25,6 +35,7 @@ export type XAxisConfig<T> = {
|
|
|
25
35
|
type?: 'solid' | 'dashed' | 'dotted';
|
|
26
36
|
};
|
|
27
37
|
};
|
|
38
|
+
thresholds?: Array<ChartThreshold | 'average'>;
|
|
28
39
|
};
|
|
29
40
|
export type YAxisConfig<T> = {
|
|
30
41
|
dataKey: keyof T;
|
|
@@ -42,6 +53,7 @@ export type YAxisConfig<T> = {
|
|
|
42
53
|
type?: 'solid' | 'dashed' | 'dotted';
|
|
43
54
|
};
|
|
44
55
|
};
|
|
56
|
+
thresholds?: Array<ChartThreshold | 'average'>;
|
|
45
57
|
};
|
|
46
58
|
export interface SeriesConfig<T> {
|
|
47
59
|
dataKey: keyof T;
|
|
@@ -12,16 +12,20 @@
|
|
|
12
12
|
bordered,
|
|
13
13
|
color,
|
|
14
14
|
open = $bindable(false),
|
|
15
|
+
disabled = false,
|
|
15
16
|
onexpand,
|
|
16
17
|
oncollapse,
|
|
18
|
+
ontoggle,
|
|
17
19
|
class: className,
|
|
18
20
|
titleclass,
|
|
19
21
|
titleClass = titleclass ?? '',
|
|
20
22
|
bodyclass,
|
|
21
23
|
bodyClass = bodyclass ?? '',
|
|
24
|
+
contentClass,
|
|
22
25
|
headerclass,
|
|
23
26
|
headerClass = headerclass ?? '',
|
|
24
27
|
summary,
|
|
28
|
+
header,
|
|
25
29
|
children,
|
|
26
30
|
icon: Icon,
|
|
27
31
|
testId
|
|
@@ -47,13 +51,11 @@
|
|
|
47
51
|
);
|
|
48
52
|
|
|
49
53
|
function handleClick() {
|
|
50
|
-
if (!children) return;
|
|
54
|
+
if (!children || disabled) return;
|
|
51
55
|
open = !open;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
oncollapse();
|
|
56
|
-
}
|
|
56
|
+
ontoggle?.(open);
|
|
57
|
+
if (open) onexpand?.();
|
|
58
|
+
else oncollapse?.();
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
const baseClasses = $derived(cn(styles.base(), className));
|
|
@@ -62,13 +64,24 @@
|
|
|
62
64
|
<div class={baseClasses}>
|
|
63
65
|
{#if children}
|
|
64
66
|
<button
|
|
65
|
-
class={cn(
|
|
67
|
+
class={cn(
|
|
68
|
+
styles.header(),
|
|
69
|
+
'flex gap-3',
|
|
70
|
+
headerClass,
|
|
71
|
+
disabled && 'cursor-not-allowed opacity-50'
|
|
72
|
+
)}
|
|
66
73
|
aria-expanded={open}
|
|
67
74
|
aria-controls={id}
|
|
75
|
+
aria-disabled={disabled ? 'true' : undefined}
|
|
76
|
+
{disabled}
|
|
68
77
|
onclick={handleClick}
|
|
69
78
|
data-testid={buildTestId('accordion', 'trigger', testId)}
|
|
70
79
|
>
|
|
71
|
-
{
|
|
80
|
+
{#if header}
|
|
81
|
+
{@render header({ open })}
|
|
82
|
+
{:else}
|
|
83
|
+
{@render accordionHeaderContent()}
|
|
84
|
+
{/if}
|
|
72
85
|
<div class="flex items-center">
|
|
73
86
|
<svg
|
|
74
87
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -87,7 +100,7 @@
|
|
|
87
100
|
</button>
|
|
88
101
|
{#if open}
|
|
89
102
|
<div
|
|
90
|
-
class={cn(styles.body(), bodyClass)}
|
|
103
|
+
class={cn(styles.body(), bodyClass, contentClass)}
|
|
91
104
|
{id}
|
|
92
105
|
data-testid={buildTestId('accordion', 'content', testId)}
|
|
93
106
|
>
|
|
@@ -96,7 +109,11 @@
|
|
|
96
109
|
{/if}
|
|
97
110
|
{:else}
|
|
98
111
|
<div class={cn(styles.header(), 'flex gap-3', headerClass)}>
|
|
99
|
-
{
|
|
112
|
+
{#if header}
|
|
113
|
+
{@render header({ open })}
|
|
114
|
+
{:else}
|
|
115
|
+
{@render accordionHeaderContent()}
|
|
116
|
+
{/if}
|
|
100
117
|
</div>
|
|
101
118
|
{/if}
|
|
102
119
|
</div>
|
|
@@ -8,7 +8,11 @@ export type AccordionProps = {
|
|
|
8
8
|
description?: string;
|
|
9
9
|
children?: Snippet;
|
|
10
10
|
summary?: Snippet;
|
|
11
|
+
header?: Snippet<[{
|
|
12
|
+
open: boolean;
|
|
13
|
+
}]>;
|
|
11
14
|
open?: boolean;
|
|
15
|
+
disabled?: boolean;
|
|
12
16
|
color?: VariantColors;
|
|
13
17
|
class?: ClassValue;
|
|
14
18
|
/** @deprecated Use titleClass instead */
|
|
@@ -17,6 +21,7 @@ export type AccordionProps = {
|
|
|
17
21
|
/** @deprecated Use bodyClass instead */
|
|
18
22
|
bodyclass?: ClassValue;
|
|
19
23
|
bodyClass?: ClassValue;
|
|
24
|
+
contentClass?: ClassValue;
|
|
20
25
|
/** @deprecated Use headerClass instead */
|
|
21
26
|
headerclass?: ClassValue;
|
|
22
27
|
headerClass?: ClassValue;
|
|
@@ -25,5 +30,6 @@ export type AccordionProps = {
|
|
|
25
30
|
bordered?: boolean;
|
|
26
31
|
onexpand?: () => void;
|
|
27
32
|
oncollapse?: () => void;
|
|
33
|
+
ontoggle?: (open: boolean) => void;
|
|
28
34
|
testId?: string;
|
|
29
35
|
};
|