@cfasim-ui/docs 0.4.4 → 0.4.6
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/charts/BarChart/BarChart.md +126 -14
- package/charts/BarChart/BarChart.vue +113 -131
- package/charts/ChoroplethMap/ChoroplethMap.md +153 -1
- package/charts/ChoroplethMap/ChoroplethMap.vue +369 -106
- package/charts/LineChart/LineChart.md +209 -14
- package/charts/LineChart/LineChart.vue +118 -146
- package/charts/_shared/ChartAnnotations.vue +346 -0
- package/charts/_shared/annotations.ts +101 -0
- package/charts/_shared/chartProps.ts +75 -0
- package/charts/_shared/index.ts +15 -0
- package/charts/_shared/useChartFoundation.ts +124 -0
- package/charts/_shared/useChartPadding.ts +74 -10
- package/charts/index.ts +5 -0
- package/components/ParamEditor/ParamEditor.md +78 -0
- package/components/ParamEditor/ParamEditor.vue +39 -0
- package/components/ParamEditor/ParamEditorImpl.vue +355 -0
- package/components/SidebarLayout/SidebarLayout.vue +10 -9
- package/components/index.ts +5 -0
- package/index.json +18 -1
- package/package.json +1 -1
- package/wasm/index.ts +1 -1
- package/wasm/wasmWorkerApi.ts +38 -6
|
@@ -391,6 +391,199 @@ Highlight a range of a series line by filling the area between the line and the
|
|
|
391
391
|
</template>
|
|
392
392
|
</ComponentDemo>
|
|
393
393
|
|
|
394
|
+
### Annotations
|
|
395
|
+
|
|
396
|
+
Pin callouts to data points with `annotations`. Each annotation anchors at
|
|
397
|
+
`(x, y)` in data coordinates (the same x-space as the chart axis, so it
|
|
398
|
+
respects `xMin` and explicit `x` values), with a pixel
|
|
399
|
+
`offset: { x, y }` for the label position. Text supports `\n` for line
|
|
400
|
+
breaks. A curved
|
|
401
|
+
pointer line connects the anchor to the label, and the label gets a halo
|
|
402
|
+
stroke matching the background so it stays legible over series lines.
|
|
403
|
+
|
|
404
|
+
<ComponentDemo>
|
|
405
|
+
<LineChart
|
|
406
|
+
:data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
|
|
407
|
+
:annotations="[
|
|
408
|
+
{ x: 5, y: 30, offset: { x: 24, y: -28 }, text: 'Peak\nDay 5' },
|
|
409
|
+
{ x: 0, y: 0, offset: { x: 28, y: -22 }, text: 'Onset' },
|
|
410
|
+
]"
|
|
411
|
+
:chart-padding="{ top: 40, right: 24 }"
|
|
412
|
+
:height="240"
|
|
413
|
+
x-label="Days"
|
|
414
|
+
y-label="Cases"
|
|
415
|
+
/>
|
|
416
|
+
|
|
417
|
+
<template #code>
|
|
418
|
+
|
|
419
|
+
```vue
|
|
420
|
+
<LineChart
|
|
421
|
+
:data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
|
|
422
|
+
:annotations="[
|
|
423
|
+
{ x: 5, y: 30, offset: { x: 24, y: -28 }, text: 'Peak\nDay 5' },
|
|
424
|
+
{ x: 0, y: 0, offset: { x: 28, y: -22 }, text: 'Onset' },
|
|
425
|
+
]"
|
|
426
|
+
:chart-padding="{ top: 40, right: 24 }"
|
|
427
|
+
:height="240"
|
|
428
|
+
x-label="Days"
|
|
429
|
+
y-label="Cases"
|
|
430
|
+
/>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
</template>
|
|
434
|
+
</ComponentDemo>
|
|
435
|
+
|
|
436
|
+
Use `chart-padding` to reserve room outside the plot so annotations (or
|
|
437
|
+
any other overlay) don't clip the data area. It accepts a number (same on
|
|
438
|
+
all sides) or an object with `top`, `right`, `bottom`, `left`.
|
|
439
|
+
|
|
440
|
+
Annotation text supports a small set of inline markers:
|
|
441
|
+
|
|
442
|
+
- `**bold**` — bold
|
|
443
|
+
- `_italic_` — italic
|
|
444
|
+
- `\n` — line break
|
|
445
|
+
|
|
446
|
+
Markers compose (`**_bold italic_**`).
|
|
447
|
+
|
|
448
|
+
<ComponentDemo>
|
|
449
|
+
<LineChart
|
|
450
|
+
:data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
|
|
451
|
+
:annotations="[
|
|
452
|
+
{ x: 5, y: 30, offset: { x: 24, y: -28 }, text: '**Peak**\n_Day 5_' },
|
|
453
|
+
]"
|
|
454
|
+
:chart-padding="{ top: 40, right: 24 }"
|
|
455
|
+
:height="240"
|
|
456
|
+
x-label="Days"
|
|
457
|
+
y-label="Cases"
|
|
458
|
+
/>
|
|
459
|
+
|
|
460
|
+
<template #code>
|
|
461
|
+
|
|
462
|
+
```vue
|
|
463
|
+
<LineChart
|
|
464
|
+
:data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
|
|
465
|
+
:annotations="[
|
|
466
|
+
{ x: 5, y: 30, offset: { x: 24, y: -28 }, text: '**Peak**\n_Day 5_' },
|
|
467
|
+
]"
|
|
468
|
+
:chart-padding="{ top: 40, right: 24 }"
|
|
469
|
+
:height="240"
|
|
470
|
+
x-label="Days"
|
|
471
|
+
y-label="Cases"
|
|
472
|
+
/>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
</template>
|
|
476
|
+
</ComponentDemo>
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
interface ChartAnnotation {
|
|
480
|
+
x: number; // anchor in data coords (x-axis)
|
|
481
|
+
y: number; // anchor in data coords (y-axis)
|
|
482
|
+
text: string; // label text; \n produces line breaks
|
|
483
|
+
offset: { x: number; y: number }; // pixel offset from anchor to label
|
|
484
|
+
color?: string; // text / pointer color (default: currentColor)
|
|
485
|
+
fontSize?: number; // default: 13 (matches axis labels)
|
|
486
|
+
fontWeight?: string | number; // default: "normal"
|
|
487
|
+
haloColor?: string; // background-matched halo (default: var(--color-bg-0, #fff))
|
|
488
|
+
haloWidth?: number; // default: 3
|
|
489
|
+
textAnchor?: "start" | "middle" | "end"; // default: derived from offset[0] sign
|
|
490
|
+
lineColor?: string; // connector-line color override (default: color)
|
|
491
|
+
lineWidth?: number; // default: 1
|
|
492
|
+
lineDash?: string | number | readonly number[]; // SVG stroke-dasharray
|
|
493
|
+
// default: "curved"
|
|
494
|
+
// "ruleX" / "ruleY" span the full plot on the named axis;
|
|
495
|
+
// "ruleUp" / "ruleDown" / "ruleFromLeft" / "ruleFromRight" run from an edge to the anchor.
|
|
496
|
+
pointer?:
|
|
497
|
+
| "curved"
|
|
498
|
+
| "straight"
|
|
499
|
+
| "none"
|
|
500
|
+
| "ruleX"
|
|
501
|
+
| "ruleY"
|
|
502
|
+
| "ruleUp"
|
|
503
|
+
| "ruleDown"
|
|
504
|
+
| "ruleFromLeft"
|
|
505
|
+
| "ruleFromRight";
|
|
506
|
+
arrow?: boolean; // triangle marker at the anchor end (default: true)
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Rules
|
|
511
|
+
|
|
512
|
+
Set `pointer` to one of the rule values to replace the curved /
|
|
513
|
+
straight connector with a straight line through the anchor:
|
|
514
|
+
|
|
515
|
+
- `"ruleX"` — vertical line spanning the plot height at the annotation's `x`.
|
|
516
|
+
- `"ruleY"` — horizontal line spanning the plot width at the annotation's `y`.
|
|
517
|
+
- `"ruleUp"` — vertical from the bottom edge up to the anchor.
|
|
518
|
+
- `"ruleDown"` — vertical from the top edge down to the anchor.
|
|
519
|
+
- `"ruleFromLeft"` — horizontal from the left edge in to the anchor.
|
|
520
|
+
- `"ruleFromRight"` — horizontal from the right edge in to the anchor.
|
|
521
|
+
|
|
522
|
+
`lineColor`, `lineWidth`, and `lineDash` style the line. The label is
|
|
523
|
+
positioned from the anchor as usual via `offset`.
|
|
524
|
+
|
|
525
|
+
<ComponentDemo>
|
|
526
|
+
<LineChart
|
|
527
|
+
:data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
|
|
528
|
+
:annotations="[
|
|
529
|
+
{
|
|
530
|
+
x: 5,
|
|
531
|
+
y: 30,
|
|
532
|
+
offset: { x: 8, y: 14 },
|
|
533
|
+
text: 'Peak',
|
|
534
|
+
pointer: 'ruleX',
|
|
535
|
+
lineDash: '4 3',
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
x: 5,
|
|
539
|
+
y: 30,
|
|
540
|
+
offset: { x: -8, y: -6 },
|
|
541
|
+
text: 'Max',
|
|
542
|
+
textAnchor: 'end',
|
|
543
|
+
pointer: 'ruleFromLeft',
|
|
544
|
+
lineDash: '4 3',
|
|
545
|
+
},
|
|
546
|
+
]"
|
|
547
|
+
:chart-padding="{ top: 24, right: 24 }"
|
|
548
|
+
:height="240"
|
|
549
|
+
x-label="Days"
|
|
550
|
+
y-label="Cases"
|
|
551
|
+
/>
|
|
552
|
+
|
|
553
|
+
<template #code>
|
|
554
|
+
|
|
555
|
+
```vue
|
|
556
|
+
<LineChart
|
|
557
|
+
:data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
|
|
558
|
+
:annotations="[
|
|
559
|
+
{
|
|
560
|
+
x: 5,
|
|
561
|
+
y: 30,
|
|
562
|
+
offset: { x: 8, y: 14 },
|
|
563
|
+
text: 'Peak',
|
|
564
|
+
pointer: 'ruleX',
|
|
565
|
+
lineDash: '4 3',
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
x: 5,
|
|
569
|
+
y: 30,
|
|
570
|
+
offset: { x: -8, y: -6 },
|
|
571
|
+
text: 'Max',
|
|
572
|
+
textAnchor: 'end',
|
|
573
|
+
pointer: 'ruleFromLeft',
|
|
574
|
+
lineDash: '4 3',
|
|
575
|
+
},
|
|
576
|
+
]"
|
|
577
|
+
:chart-padding="{ top: 24, right: 24 }"
|
|
578
|
+
:height="240"
|
|
579
|
+
x-label="Days"
|
|
580
|
+
y-label="Cases"
|
|
581
|
+
/>
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
</template>
|
|
585
|
+
</ComponentDemo>
|
|
586
|
+
|
|
394
587
|
### Custom CSV download
|
|
395
588
|
|
|
396
589
|
By default, the Download CSV menu item exports the chart series as CSV. Use
|
|
@@ -444,36 +637,38 @@ until the user clicks Download:
|
|
|
444
637
|
|
|
445
638
|
| Prop | Type | Required | Default |
|
|
446
639
|
|------|------|----------|---------|
|
|
640
|
+
| `width` | `number` | No | — |
|
|
641
|
+
| `height` | `number` | No | — |
|
|
642
|
+
| `title` | `string` | No | — |
|
|
643
|
+
| `xLabel` | `string` | No | — |
|
|
644
|
+
| `yLabel` | `string` | No | — |
|
|
645
|
+
| `debounce` | `number` | No | — |
|
|
646
|
+
| `menu` | `boolean \| string` | No | `true` |
|
|
647
|
+
| `tooltipData` | `ArrayLike<unknown>` | No | — |
|
|
648
|
+
| `tooltipTrigger` | `"hover" \| "click"` | No | — |
|
|
649
|
+
| `tooltipClamp` | `"none" \| "chart" \| "window"` | No | `"chart"` |
|
|
650
|
+
| `tooltipValueFormat` | `(value: number) => string` | No | — |
|
|
651
|
+
| `csv` | `string \| (() => string)` | No | — |
|
|
652
|
+
| `filename` | `string` | No | — |
|
|
653
|
+
| `downloadLink` | `boolean \| string` | No | — |
|
|
654
|
+
| `annotations` | `readonly ChartAnnotation[]` | No | — |
|
|
655
|
+
| `chartPadding` | `ChartPadding` | No | — |
|
|
447
656
|
| `y` | `LineChartData` | No | — |
|
|
448
657
|
| `data` | `LineChartData` | No | — |
|
|
449
658
|
| `x` | `LineChartData` | No | — |
|
|
450
659
|
| `series` | `Series[]` | No | — |
|
|
451
660
|
| `areas` | `Area[]` | No | — |
|
|
452
661
|
| `areaSections` | `AreaSection[]` | No | — |
|
|
453
|
-
| `width` | `number` | No | — |
|
|
454
|
-
| `height` | `number` | No | — |
|
|
455
662
|
| `lineOpacity` | `number` | No | `1` |
|
|
456
|
-
| `title` | `string` | No | — |
|
|
457
|
-
| `xLabel` | `string` | No | — |
|
|
458
|
-
| `yLabel` | `string` | No | — |
|
|
459
663
|
| `yMin` | `number` | No | — |
|
|
460
664
|
| `xMin` | `number` | No | — |
|
|
461
665
|
| `xTicks` | `number \| number[]` | No | — |
|
|
462
666
|
| `yTicks` | `number \| number[]` | No | — |
|
|
463
667
|
| `xTickFormat` | `(value: number, index: number) => string` | No | — |
|
|
464
668
|
| `yTickFormat` | `(value: number) => string` | No | — |
|
|
465
|
-
| `tooltipValueFormat` | `(value: number) => string` | No | — |
|
|
466
669
|
| `xLabels` | `string[]` | No | — |
|
|
467
|
-
| `debounce` | `number` | No | — |
|
|
468
|
-
| `menu` | `boolean \| string` | No | `true` |
|
|
469
670
|
| `xGrid` | `boolean` | No | — |
|
|
470
671
|
| `yGrid` | `boolean` | No | — |
|
|
471
|
-
| `tooltipData` | `ArrayLike<unknown>` | No | — |
|
|
472
|
-
| `tooltipTrigger` | `"hover" \| "click"` | No | — |
|
|
473
|
-
| `tooltipClamp` | `"none" \| "chart" \| "window"` | No | `"chart"` |
|
|
474
|
-
| `csv` | `string \| (() => string)` | No | — |
|
|
475
|
-
| `filename` | `string` | No | — |
|
|
476
|
-
| `downloadLink` | `boolean \| string` | No | — |
|
|
477
672
|
|
|
478
673
|
|
|
479
674
|
### Data
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed
|
|
2
|
+
import { computed } from "vue";
|
|
3
3
|
import ChartMenu from "../ChartMenu/ChartMenu.vue";
|
|
4
4
|
import {
|
|
5
5
|
snap,
|
|
6
6
|
formatTick,
|
|
7
7
|
computeTickValues,
|
|
8
8
|
seriesToCsv,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
useChartPadding,
|
|
13
|
-
INLINE_LEGEND_HEIGHT,
|
|
9
|
+
useChartFoundation,
|
|
10
|
+
makeTooltipValueFormatter,
|
|
11
|
+
ChartAnnotations,
|
|
14
12
|
type ChartData,
|
|
13
|
+
type ChartCommonProps,
|
|
14
|
+
type ChartHoverPayload,
|
|
15
|
+
type ChartTooltipBaseProps,
|
|
15
16
|
} from "../_shared/index.js";
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -83,118 +84,69 @@ export interface AreaSection {
|
|
|
83
84
|
legend?: "inline" | "below" | false;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
*/
|
|
141
|
-
xLabels?: string[];
|
|
142
|
-
debounce?: number;
|
|
143
|
-
menu?: boolean | string;
|
|
144
|
-
xGrid?: boolean;
|
|
145
|
-
yGrid?: boolean;
|
|
146
|
-
/**
|
|
147
|
-
* Custom per-index data passed to the tooltip slot. Accepts a plain
|
|
148
|
-
* array or any `ArrayLike` (e.g. a typed array column from a
|
|
149
|
-
* `ModelOutput`).
|
|
150
|
-
*/
|
|
151
|
-
tooltipData?: ArrayLike<unknown>;
|
|
152
|
-
/** Tooltip activation mode. Default: 'hover' */
|
|
153
|
-
tooltipTrigger?: "hover" | "click";
|
|
154
|
-
/**
|
|
155
|
-
* Boundary for tooltip flip/clamp. `"none"` always places to the right of
|
|
156
|
-
* the pointer with no clamping. `"chart"` (default) uses the chart
|
|
157
|
-
* container's bounding box. `"window"` uses the viewport.
|
|
158
|
-
*/
|
|
159
|
-
tooltipClamp?: "none" | "chart" | "window";
|
|
160
|
-
/**
|
|
161
|
-
* Custom CSV content for the Download CSV menu item. Can be a raw CSV
|
|
162
|
-
* string or a function returning one. When omitted, CSV is generated
|
|
163
|
-
* from the chart series.
|
|
164
|
-
*/
|
|
165
|
-
csv?: string | (() => string);
|
|
166
|
-
/** Filename (without extension) for downloaded SVG, PNG and CSV files. */
|
|
167
|
-
filename?: string;
|
|
168
|
-
/**
|
|
169
|
-
* Show a plain text link below the chart to download the CSV data.
|
|
170
|
-
* Pass `true` for the default label ("Download data (CSV)") or a string
|
|
171
|
-
* to customize the link text.
|
|
172
|
-
*/
|
|
173
|
-
downloadLink?: boolean | string;
|
|
174
|
-
}>(),
|
|
175
|
-
{ lineOpacity: 1, menu: true, tooltipClamp: "chart" },
|
|
176
|
-
);
|
|
87
|
+
interface LineChartProps extends ChartCommonProps {
|
|
88
|
+
/** Y-values. Equivalent to `data`. If both are set, `y` wins. */
|
|
89
|
+
y?: LineChartData;
|
|
90
|
+
/** Y-values (alternative name for `y`). */
|
|
91
|
+
data?: LineChartData;
|
|
92
|
+
/**
|
|
93
|
+
* Optional x-values paired with `y`/`data`. When provided, points
|
|
94
|
+
* are plotted at the given x positions instead of at their indices.
|
|
95
|
+
* Ignored when `series` is used — set `x` on each `Series` instead.
|
|
96
|
+
*/
|
|
97
|
+
x?: LineChartData;
|
|
98
|
+
series?: Series[];
|
|
99
|
+
areas?: Area[];
|
|
100
|
+
areaSections?: AreaSection[];
|
|
101
|
+
lineOpacity?: number;
|
|
102
|
+
yMin?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Offset applied to index-based x values (e.g. `xMin: 10` starts the
|
|
105
|
+
* x axis at 10 instead of 0). Ignored when any series or area has
|
|
106
|
+
* explicit `x` values.
|
|
107
|
+
*/
|
|
108
|
+
xMin?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Tick placement on the x-axis. Number = interval in data units
|
|
111
|
+
* (respecting `xMin`, e.g. `7` ticks every 7 days). Array = explicit tick
|
|
112
|
+
* values in data space; values outside the data range are dropped.
|
|
113
|
+
* When omitted, ticks are chosen automatically.
|
|
114
|
+
*/
|
|
115
|
+
xTicks?: number | number[];
|
|
116
|
+
/**
|
|
117
|
+
* Tick placement on the y-axis. Number = interval in data units. Array =
|
|
118
|
+
* explicit tick values; values outside the data range are dropped. When
|
|
119
|
+
* omitted, ticks are chosen automatically.
|
|
120
|
+
*/
|
|
121
|
+
yTicks?: number | number[];
|
|
122
|
+
/** Formatter for x-axis tick labels. Receives the raw numeric value. */
|
|
123
|
+
xTickFormat?: (value: number, index: number) => string;
|
|
124
|
+
/** Formatter for y-axis tick labels. Receives the raw numeric value. */
|
|
125
|
+
yTickFormat?: (value: number) => string;
|
|
126
|
+
/**
|
|
127
|
+
* @deprecated Use `xTickFormat` (e.g. `(_, i) => labels[i]`) together
|
|
128
|
+
* with `xTicks` for explicit control. Still honored for tooltip x-labels
|
|
129
|
+
* and as a default x-tick formatter when `xTickFormat` is not provided.
|
|
130
|
+
*/
|
|
131
|
+
xLabels?: string[];
|
|
132
|
+
xGrid?: boolean;
|
|
133
|
+
yGrid?: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const props = withDefaults(defineProps<LineChartProps>(), {
|
|
137
|
+
lineOpacity: 1,
|
|
138
|
+
menu: true,
|
|
139
|
+
tooltipClamp: "chart",
|
|
140
|
+
});
|
|
177
141
|
|
|
178
142
|
const emit = defineEmits<{
|
|
179
|
-
(e: "hover", payload:
|
|
143
|
+
(e: "hover", payload: ChartHoverPayload): void;
|
|
180
144
|
}>();
|
|
181
145
|
|
|
182
146
|
defineSlots<{
|
|
183
|
-
tooltip?(props: {
|
|
184
|
-
index: number;
|
|
185
|
-
xLabel?: string;
|
|
186
|
-
values: { value: number; color: string; seriesIndex: number }[];
|
|
187
|
-
data: unknown;
|
|
188
|
-
}): unknown;
|
|
147
|
+
tooltip?(props: ChartTooltipBaseProps & { xLabel?: string }): unknown;
|
|
189
148
|
}>();
|
|
190
149
|
|
|
191
|
-
const { containerRef, measuredWidth } = useChartSize({
|
|
192
|
-
debounce: () => props.debounce,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const width = computed(() => props.width ?? (measuredWidth.value || 400));
|
|
196
|
-
const height = computed(() => props.height ?? 200);
|
|
197
|
-
|
|
198
150
|
const hasInlineLegend = computed(
|
|
199
151
|
() =>
|
|
200
152
|
allSeries.value.some((s) => s.legend) ||
|
|
@@ -204,15 +156,6 @@ const hasInlineLegend = computed(
|
|
|
204
156
|
false,
|
|
205
157
|
);
|
|
206
158
|
|
|
207
|
-
const { padding, innerW, innerH } = useChartPadding({
|
|
208
|
-
title: () => props.title,
|
|
209
|
-
xLabel: () => props.xLabel,
|
|
210
|
-
yLabel: () => props.yLabel,
|
|
211
|
-
hasInlineLegend: () => hasInlineLegend.value,
|
|
212
|
-
width: () => width.value,
|
|
213
|
-
height: () => height.value,
|
|
214
|
-
});
|
|
215
|
-
|
|
216
159
|
/**
|
|
217
160
|
* Internal series shape where `data` (y-values) is always resolved.
|
|
218
161
|
* `Series.y` takes precedence over `Series.data` when both are set.
|
|
@@ -225,11 +168,10 @@ function resolveSeries(s: Series): ResolvedSeries {
|
|
|
225
168
|
return { ...s, data: s.y ?? s.data ?? EMPTY_DATA };
|
|
226
169
|
}
|
|
227
170
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
171
|
+
const formatTooltipValue = makeTooltipValueFormatter(
|
|
172
|
+
() => props.tooltipValueFormat,
|
|
173
|
+
() => props.yTickFormat,
|
|
174
|
+
);
|
|
233
175
|
|
|
234
176
|
const allSeries = computed<ResolvedSeries[]>(() => {
|
|
235
177
|
if (props.series && props.series.length > 0)
|
|
@@ -758,6 +700,18 @@ const hoverSlotProps = computed(() => {
|
|
|
758
700
|
};
|
|
759
701
|
});
|
|
760
702
|
|
|
703
|
+
function projectAnnotation(
|
|
704
|
+
x: number,
|
|
705
|
+
y: number,
|
|
706
|
+
): { x: number; y: number } | null {
|
|
707
|
+
if (!isFinite(x) || !isFinite(y)) return null;
|
|
708
|
+
const internalX = x - xDisplayOffset.value;
|
|
709
|
+
const { min, range } = extent.value;
|
|
710
|
+
const py =
|
|
711
|
+
padding.value.top + innerH.value - (y - min) * (innerH.value / range);
|
|
712
|
+
return { x: xPixel(internalX), y: py };
|
|
713
|
+
}
|
|
714
|
+
|
|
761
715
|
function indexFromPointer(clientX: number): number | null {
|
|
762
716
|
const rect = containerRef.value?.getBoundingClientRect();
|
|
763
717
|
if (!rect) return null;
|
|
@@ -771,30 +725,41 @@ function indexFromPointer(clientX: number): number | null {
|
|
|
771
725
|
}
|
|
772
726
|
|
|
773
727
|
const {
|
|
728
|
+
containerRef,
|
|
729
|
+
svgRef,
|
|
730
|
+
width,
|
|
731
|
+
height,
|
|
732
|
+
padding,
|
|
733
|
+
legendY,
|
|
734
|
+
innerW,
|
|
735
|
+
innerH,
|
|
736
|
+
bounds,
|
|
774
737
|
hoverIndex,
|
|
775
738
|
tooltipRef,
|
|
776
739
|
tooltipPos,
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
enabled: () => hasTooltipSlot.value,
|
|
780
|
-
trigger: () => props.tooltipTrigger,
|
|
781
|
-
clamp: () => props.tooltipClamp,
|
|
782
|
-
pointerToIndex: indexFromPointer,
|
|
783
|
-
containerRef,
|
|
784
|
-
onHover: (payload) => emit("hover", payload),
|
|
785
|
-
});
|
|
786
|
-
|
|
787
|
-
const {
|
|
788
|
-
svgRef,
|
|
789
|
-
items: menuItems,
|
|
740
|
+
tooltipHandlers,
|
|
741
|
+
menuItems,
|
|
790
742
|
downloadLinkText,
|
|
791
743
|
csvHref,
|
|
792
|
-
|
|
793
|
-
} =
|
|
744
|
+
menuFilename,
|
|
745
|
+
} = useChartFoundation({
|
|
746
|
+
width: () => props.width,
|
|
747
|
+
height: () => props.height,
|
|
748
|
+
title: () => props.title,
|
|
749
|
+
xLabel: () => props.xLabel,
|
|
750
|
+
yLabel: () => props.yLabel,
|
|
751
|
+
debounce: () => props.debounce,
|
|
752
|
+
menu: () => props.menu,
|
|
753
|
+
tooltipTrigger: () => props.tooltipTrigger,
|
|
754
|
+
tooltipClamp: () => props.tooltipClamp,
|
|
794
755
|
filename: () => props.filename,
|
|
795
|
-
legacyMenuLabel: () => props.menu,
|
|
796
|
-
getCsv: toCsv,
|
|
797
756
|
downloadLink: () => props.downloadLink,
|
|
757
|
+
chartPadding: () => props.chartPadding,
|
|
758
|
+
hasInlineLegend: () => hasInlineLegend.value,
|
|
759
|
+
hasTooltipSlot: () => hasTooltipSlot.value,
|
|
760
|
+
getCsv: toCsv,
|
|
761
|
+
pointerToIndex: indexFromPointer,
|
|
762
|
+
onHover: (payload) => emit("hover", payload),
|
|
798
763
|
});
|
|
799
764
|
</script>
|
|
800
765
|
|
|
@@ -821,9 +786,9 @@ const {
|
|
|
821
786
|
<line
|
|
822
787
|
v-if="item.type === 'series'"
|
|
823
788
|
:x1="padding.left + i * 120"
|
|
824
|
-
:y1="
|
|
789
|
+
:y1="legendY"
|
|
825
790
|
:x2="padding.left + i * 120 + 12"
|
|
826
|
-
:y2="
|
|
791
|
+
:y2="legendY"
|
|
827
792
|
:stroke="item.color"
|
|
828
793
|
stroke-width="2"
|
|
829
794
|
:stroke-dasharray="item.dashed ? '4 2' : undefined"
|
|
@@ -832,7 +797,7 @@ const {
|
|
|
832
797
|
<circle
|
|
833
798
|
v-else
|
|
834
799
|
:cx="padding.left + i * 120 + 4"
|
|
835
|
-
:cy="
|
|
800
|
+
:cy="legendY"
|
|
836
801
|
r="4"
|
|
837
802
|
:fill="item.color"
|
|
838
803
|
:fill-opacity="item.fillOpacity"
|
|
@@ -841,7 +806,7 @@ const {
|
|
|
841
806
|
/>
|
|
842
807
|
<text
|
|
843
808
|
:x="padding.left + i * 120 + 18"
|
|
844
|
-
:y="
|
|
809
|
+
:y="legendY + 4"
|
|
845
810
|
font-size="11"
|
|
846
811
|
fill="currentColor"
|
|
847
812
|
>
|
|
@@ -1074,6 +1039,13 @@ const {
|
|
|
1074
1039
|
style="cursor: crosshair; touch-action: none"
|
|
1075
1040
|
v-on="tooltipHandlers"
|
|
1076
1041
|
/>
|
|
1042
|
+
<!-- annotations (top layer) -->
|
|
1043
|
+
<ChartAnnotations
|
|
1044
|
+
v-if="annotations && annotations.length > 0"
|
|
1045
|
+
:annotations="annotations"
|
|
1046
|
+
:project="projectAnnotation"
|
|
1047
|
+
:bounds="bounds"
|
|
1048
|
+
/>
|
|
1077
1049
|
<!-- area section labels -->
|
|
1078
1050
|
<g v-for="(item, i) in sectionLabels.labels" :key="'seclab' + i">
|
|
1079
1051
|
<circle
|