@cfasim-ui/charts 0.4.10 → 0.4.11
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/BarChart/BarChart.d.ts +10 -0
- package/dist/ChartMenu/ChartMenu.d.ts +2 -0
- package/dist/LineChart/LineChart.d.ts +16 -0
- package/dist/_shared/index.d.ts +2 -1
- package/dist/_shared/useChartFoundation.d.ts +19 -2
- package/dist/_shared/useChartFullscreen.d.ts +16 -0
- package/dist/_shared/useChartMenu.d.ts +10 -2
- package/dist/_shared/useChartPadding.d.ts +24 -4
- package/dist/_shared/useChartSize.d.ts +1 -0
- package/dist/index.css +1 -1
- package/dist/index.js +947 -793
- package/package.json +2 -2
|
@@ -9,6 +9,16 @@ export interface BarSeries {
|
|
|
9
9
|
opacity?: number;
|
|
10
10
|
/** Label shown in the inline legend. */
|
|
11
11
|
legend?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Whether this series appears in the inline legend. Defaults to true.
|
|
14
|
+
* Has no effect when `legend` is unset (no legend entry to begin with).
|
|
15
|
+
*/
|
|
16
|
+
showInLegend?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether this series contributes a value to the tooltip. Defaults to
|
|
19
|
+
* true. The bars are still drawn.
|
|
20
|
+
*/
|
|
21
|
+
showInTooltip?: boolean;
|
|
12
22
|
}
|
|
13
23
|
interface BarChartProps extends ChartCommonProps {
|
|
14
24
|
/** Single-series values. Equivalent to `y`. */
|
|
@@ -28,12 +28,28 @@ export interface Series {
|
|
|
28
28
|
lineOpacity?: number;
|
|
29
29
|
dotOpacity?: number;
|
|
30
30
|
line?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Draw a page-colored stroke behind the line so it stays visually
|
|
33
|
+
* separated from overlapping series and busy backgrounds. Has no
|
|
34
|
+
* effect when `line` is `false`.
|
|
35
|
+
*/
|
|
36
|
+
outline?: boolean;
|
|
31
37
|
dots?: boolean;
|
|
32
38
|
dotRadius?: number;
|
|
33
39
|
dotFill?: string;
|
|
34
40
|
dotStroke?: string;
|
|
35
41
|
/** Label shown in the inline legend */
|
|
36
42
|
legend?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether this series appears in the inline legend. Defaults to true.
|
|
45
|
+
* Has no effect when `legend` is unset (no legend entry to begin with).
|
|
46
|
+
*/
|
|
47
|
+
showInLegend?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Whether this series contributes a value to the tooltip and shows a
|
|
50
|
+
* hover dot. Defaults to true. The series line/dots are still drawn.
|
|
51
|
+
*/
|
|
52
|
+
showInTooltip?: boolean;
|
|
37
53
|
}
|
|
38
54
|
export interface Area {
|
|
39
55
|
upper: LineChartData;
|
package/dist/_shared/index.d.ts
CHANGED
|
@@ -2,9 +2,10 @@ export { snap, niceStep, intervalValues, formatTick, type ChartData, } from './a
|
|
|
2
2
|
export { computeTickValues, type TickValueOptions } from './computeTicks.js';
|
|
3
3
|
export { scaleFraction, clampExtentForScale, computeLogTickValues, LOG_FLOOR, type ScaleType, } from './scale.js';
|
|
4
4
|
export { useChartSize, type ChartSizeOptions } from './useChartSize.js';
|
|
5
|
-
export { useChartPadding,
|
|
5
|
+
export { useChartPadding, INLINE_LEGEND_ROW_HEIGHT, type ChartPaddingOptions, type ChartPadding, type ChartBounds, type PositionedLegendItem, } from './useChartPadding.js';
|
|
6
6
|
export { useChartTooltip, type ChartTooltipOptions, } from './useChartTooltip.js';
|
|
7
7
|
export { useChartMenu, type ChartMenuOptions } from './useChartMenu.js';
|
|
8
|
+
export { useChartFullscreen } from './useChartFullscreen.js';
|
|
8
9
|
export { seriesToCsv, categoricalToCsv, type CsvSeries } from './seriesCsv.js';
|
|
9
10
|
export { default as ChartAnnotations } from './ChartAnnotations';
|
|
10
11
|
export type { ChartAnnotation } from './annotations.js';
|
|
@@ -14,13 +14,24 @@ export interface ChartFoundationOptions {
|
|
|
14
14
|
filename: () => string | undefined;
|
|
15
15
|
downloadLink: () => boolean | string | undefined;
|
|
16
16
|
chartPadding: () => ChartPadding | undefined;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Labels for the inline legend in render order. Empty array = no
|
|
19
|
+
* legend strip. Drives wrapping into multiple rows and the resulting
|
|
20
|
+
* top-padding reservation.
|
|
21
|
+
*/
|
|
22
|
+
inlineLegendLabels: () => readonly string[];
|
|
18
23
|
hasTooltipSlot: () => boolean;
|
|
19
24
|
getCsv: () => string;
|
|
20
25
|
pointerToIndex: (clientX: number, clientY: number) => number | null;
|
|
21
26
|
onHover: (payload: {
|
|
22
27
|
index: number;
|
|
23
28
|
} | null) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Extra height (in px) the chart adds *below* the SVG plot area
|
|
31
|
+
* (e.g. LineChart's area-section labels). Used to keep the SVG total
|
|
32
|
+
* height matched to the container when fullscreen.
|
|
33
|
+
*/
|
|
34
|
+
extraBelowHeight?: () => number;
|
|
24
35
|
}
|
|
25
36
|
/**
|
|
26
37
|
* Wires up the shared chart plumbing — size measurement, padding, tooltip
|
|
@@ -35,11 +46,15 @@ export declare function useChartFoundation(opts: ChartFoundationOptions): {
|
|
|
35
46
|
height: import('vue').ComputedRef<number>;
|
|
36
47
|
padding: import('vue').ComputedRef<{
|
|
37
48
|
top: number;
|
|
38
|
-
right: number;
|
|
39
49
|
bottom: number;
|
|
40
50
|
left: number;
|
|
51
|
+
right: number;
|
|
41
52
|
}>;
|
|
42
53
|
legendY: import('vue').ComputedRef<number>;
|
|
54
|
+
inlineLegendLayout: import('vue').ComputedRef<{
|
|
55
|
+
positions: import('./useChartPadding.js').PositionedLegendItem[];
|
|
56
|
+
rowCount: number;
|
|
57
|
+
}>;
|
|
43
58
|
innerW: import('vue').ComputedRef<number>;
|
|
44
59
|
innerH: import('vue').ComputedRef<number>;
|
|
45
60
|
bounds: import('vue').ComputedRef<{
|
|
@@ -74,6 +89,8 @@ export declare function useChartFoundation(opts: ChartFoundationOptions): {
|
|
|
74
89
|
downloadLinkText: import('vue').ComputedRef<string | null>;
|
|
75
90
|
csvHref: import('vue').ComputedRef<string | null>;
|
|
76
91
|
menuFilename: () => string;
|
|
92
|
+
isFullscreen: import('vue').Ref<boolean, boolean>;
|
|
93
|
+
measuredHeight: import('vue').Ref<number, number>;
|
|
77
94
|
};
|
|
78
95
|
/**
|
|
79
96
|
* Build a tooltip value formatter that prefers `tooltipValueFormat`,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ChartMenuItem } from '../ChartMenu/ChartMenu';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks whether the chart is in "expanded" mode (fills the window via
|
|
4
|
+
* CSS). The browser Fullscreen API isn't used — the consumer wires a
|
|
5
|
+
* `.is-fullscreen` class to its wrapper and the CSS handles positioning,
|
|
6
|
+
* which avoids Fullscreen API restrictions (user-gesture requirement,
|
|
7
|
+
* permission policy, iframe sandboxing) and keeps the chart inside the
|
|
8
|
+
* document so the rest of the page remains keyboard-navigable.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useChartFullscreen(): {
|
|
11
|
+
isFullscreen: import('vue').Ref<boolean, boolean>;
|
|
12
|
+
toggle: () => void;
|
|
13
|
+
enter: () => void;
|
|
14
|
+
exit: () => void;
|
|
15
|
+
menuItem: import('vue').ComputedRef<ChartMenuItem>;
|
|
16
|
+
};
|
|
@@ -8,10 +8,17 @@ export interface ChartMenuOptions {
|
|
|
8
8
|
getCsv: () => string;
|
|
9
9
|
/** Whether a separate download link is rendered (and the CSV menu item should be hidden). */
|
|
10
10
|
downloadLink: () => boolean | string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* When true, prepends an Expand/Collapse menu item that toggles the
|
|
13
|
+
* chart into a full-window view. The consumer is responsible for
|
|
14
|
+
* binding the returned `isFullscreen` ref to a CSS class on its
|
|
15
|
+
* wrapper.
|
|
16
|
+
*/
|
|
17
|
+
fullscreen?: boolean;
|
|
11
18
|
}
|
|
12
19
|
/**
|
|
13
|
-
* Computes the standard chart menu items (SVG / PNG / CSV) plus
|
|
14
|
-
* CSV-download-link state shared by every chart.
|
|
20
|
+
* Computes the standard chart menu items (Expand / SVG / PNG / CSV) plus
|
|
21
|
+
* the CSV-download-link state shared by every chart.
|
|
15
22
|
*/
|
|
16
23
|
export declare function useChartMenu(opts: ChartMenuOptions): {
|
|
17
24
|
svgRef: Ref<SVGSVGElement | null>;
|
|
@@ -19,4 +26,5 @@ export declare function useChartMenu(opts: ChartMenuOptions): {
|
|
|
19
26
|
downloadLinkText: import('vue').ComputedRef<string | null>;
|
|
20
27
|
csvHref: import('vue').ComputedRef<string | null>;
|
|
21
28
|
resolvedFilename: () => string;
|
|
29
|
+
isFullscreen: Ref<boolean, boolean>;
|
|
22
30
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/** Vertical space reserved
|
|
2
|
-
export declare const
|
|
1
|
+
/** Vertical space reserved per row of the inline legend strip. */
|
|
2
|
+
export declare const INLINE_LEGEND_ROW_HEIGHT = 20;
|
|
3
3
|
/**
|
|
4
4
|
* Extra space added around the chart's standard layout. A number applies
|
|
5
5
|
* the same amount to all four sides; an object lets you pad sides
|
|
@@ -16,12 +16,24 @@ export interface ChartPaddingOptions {
|
|
|
16
16
|
title: () => string | undefined;
|
|
17
17
|
xLabel: () => string | undefined;
|
|
18
18
|
yLabel: () => string | undefined;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Labels for the inline legend items, in render order. Empty array
|
|
21
|
+
* (or omitted) means no legend strip. Drives both row-count for
|
|
22
|
+
* reserving top padding and per-item wrap positions.
|
|
23
|
+
*/
|
|
24
|
+
inlineLegendLabels: () => readonly string[];
|
|
20
25
|
width: () => number;
|
|
21
26
|
height: () => number;
|
|
22
27
|
/** Extra pixels added on top of the standard axis spacing. */
|
|
23
28
|
extraPadding?: () => ChartPadding | undefined;
|
|
24
29
|
}
|
|
30
|
+
/** Position of a single legend item within the legend strip. */
|
|
31
|
+
export interface PositionedLegendItem {
|
|
32
|
+
/** X offset relative to `padding.left`. */
|
|
33
|
+
x: number;
|
|
34
|
+
/** Row index, 0-based. */
|
|
35
|
+
row: number;
|
|
36
|
+
}
|
|
25
37
|
/**
|
|
26
38
|
* Computes the standard chart padding (top/right/bottom/left) and the
|
|
27
39
|
* derived inner plotting region (innerW, innerH). Shared by LineChart
|
|
@@ -29,15 +41,23 @@ export interface ChartPaddingOptions {
|
|
|
29
41
|
* consistent. `extraPadding` adds extra space outside the plot — useful
|
|
30
42
|
* for annotations that need to extend past the data area without
|
|
31
43
|
* clipping.
|
|
44
|
+
*
|
|
45
|
+
* The inline legend wraps to multiple rows when items don't fit in the
|
|
46
|
+
* available width; `padding.top` grows by `INLINE_LEGEND_ROW_HEIGHT` per
|
|
47
|
+
* row so the plot stays clear of the legend strip.
|
|
32
48
|
*/
|
|
33
49
|
export declare function useChartPadding(opts: ChartPaddingOptions): {
|
|
34
50
|
padding: import('vue').ComputedRef<{
|
|
35
51
|
top: number;
|
|
36
|
-
right: number;
|
|
37
52
|
bottom: number;
|
|
38
53
|
left: number;
|
|
54
|
+
right: number;
|
|
39
55
|
}>;
|
|
40
56
|
legendY: import('vue').ComputedRef<number>;
|
|
57
|
+
inlineLegendLayout: import('vue').ComputedRef<{
|
|
58
|
+
positions: PositionedLegendItem[];
|
|
59
|
+
rowCount: number;
|
|
60
|
+
}>;
|
|
41
61
|
innerW: import('vue').ComputedRef<number>;
|
|
42
62
|
innerH: import('vue').ComputedRef<number>;
|
|
43
63
|
bounds: import('vue').ComputedRef<{
|
package/dist/index.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.chart-menu-trigger-area[data-v-
|
|
1
|
+
.line-chart-wrapper:hover .chart-menu-button,.bar-chart-wrapper:hover .chart-menu-button,.choropleth-wrapper:hover .chart-menu-button,.line-chart-wrapper:focus-within .chart-menu-button,.bar-chart-wrapper:focus-within .chart-menu-button,.choropleth-wrapper:focus-within .chart-menu-button,.line-chart-wrapper.is-fullscreen .chart-menu-button,.bar-chart-wrapper.is-fullscreen .chart-menu-button,.choropleth-wrapper.is-fullscreen .chart-menu-button{opacity:1}.line-chart-wrapper.is-fullscreen,.bar-chart-wrapper.is-fullscreen,.choropleth-wrapper.is-fullscreen{z-index:var(--cfasim-z-fullscreen,1000);background:var(--color-bg-0,#fff);color:var(--color-text,inherit);box-sizing:border-box;flex-direction:column;justify-content:center;padding:2em;display:flex;position:fixed;inset:0}.choropleth-wrapper.is-fullscreen svg{flex:auto;width:100%;height:100%;min-height:0}.chart-sr-only{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.chart-menu-trigger-area[data-v-c74e2889]{z-index:1;position:absolute;top:0;right:0}.chart-menu-button[data-v-c74e2889]{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);width:28px;height:28px;color:var(--color-text-secondary);cursor:pointer;opacity:0;border-radius:.25em;justify-content:center;align-items:center;transition:opacity .15s;display:flex}.chart-menu-button[data-state=open][data-v-c74e2889]{opacity:1}.chart-menu-button[data-v-c74e2889]:hover{background:var(--color-bg-1,#0000000d);color:var(--color-text)}.chart-menu-content{z-index:100;background:var(--color-bg-0);border:1px solid var(--color-border);border-radius:.25em;min-width:140px;padding:.25em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.chart-menu-item{font-size:var(--font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;border-radius:.25em;outline:none;align-items:center;padding:.375em .5em;display:flex}.chart-menu-item[data-highlighted]{background:var(--color-primary);color:#fff}.line-chart-wrapper[data-v-c1d38be7]{width:100%;position:relative}.line-chart-tooltip-label[data-v-c1d38be7]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-c1d38be7]{align-items:center;gap:.375em;display:flex}.line-chart-download-link[data-v-c1d38be7]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.line-chart-tooltip-swatch[data-v-c1d38be7]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.bar-chart-wrapper[data-v-56a9e529]{width:100%;position:relative}.bar-chart-tooltip-label[data-v-56a9e529]{margin-bottom:.25em;font-weight:600}.bar-chart-tooltip-row[data-v-56a9e529]{align-items:center;gap:.375em;display:flex}.bar-chart-download-link[data-v-56a9e529]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.bar-chart-tooltip-swatch[data-v-56a9e529]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.choropleth-wrapper[data-v-110171fe]{--choropleth-legend-bg:var(--color-bg-0,#fff);width:100%;position:relative}.choropleth-wrapper svg[data-v-110171fe]{width:100%;height:auto;display:block}.choropleth-wrapper.pannable svg[data-v-110171fe]{cursor:grab}.choropleth-wrapper.pannable svg[data-v-110171fe]:active{cursor:grabbing}.state-path[data-v-110171fe]{cursor:pointer}.choropleth-reset[data-v-110171fe]{font:inherit;color:var(--color-text-secondary,#555);background:var(--color-bg-0,#fff);border:1px solid var(--color-border,#e5e7eb);cursor:pointer;border-radius:4px;padding:4px 10px;font-size:12px;position:absolute;bottom:8px;left:8px;box-shadow:0 1px 2px #0000000d}.choropleth-reset[data-v-110171fe]:hover{background:var(--color-bg-1,#f8f9fa);color:var(--color-text,#212529)}.choropleth-header[data-v-110171fe]{background:var(--choropleth-legend-bg);color:currentColor;border-radius:4px;flex-direction:column;align-items:center;gap:10px;width:fit-content;margin:0 auto;padding:8px 14px;display:flex}.choropleth-title[data-v-110171fe]{font-size:14px;font-weight:600;line-height:1.2}.choropleth-legend[data-v-110171fe]{align-items:center;gap:14px;font-size:13px;line-height:1.2;display:flex}.choropleth-legend-title[data-v-110171fe]{font-weight:600}.choropleth-legend-item[data-v-110171fe]{align-items:center;gap:6px;display:inline-flex}.choropleth-legend-swatch[data-v-110171fe]{border-radius:3px;width:12px;height:12px;display:inline-block}.choropleth-legend-continuous[data-v-110171fe]{flex-direction:column;width:160px;display:flex}.choropleth-legend-gradient[data-v-110171fe]{border-radius:2px;height:12px}.choropleth-legend-ticks[data-v-110171fe]{opacity:.7;height:14px;margin-top:4px;font-size:11px;position:relative}.choropleth-legend-ticks>span[data-v-110171fe]{position:absolute;transform:translate(-50%)}.chart-tooltip-anchor[data-v-44377f70]{pointer-events:none;width:1px;height:1px;position:absolute}.chart-tooltip-content{z-index:100;background:var(--color-bg-0,#fff);border:1px solid var(--color-border,#e5e7eb);font-size:var(--font-size-sm,.875rem);pointer-events:none;border-radius:.375em;padding:.5em .75em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.TableOuter[data-v-d6b3bce8]{display:inline-block;position:relative}.TableOuter.full-width[data-v-d6b3bce8]{display:block}.TableWrapper[data-v-d6b3bce8]{font-size:var(--font-size-sm);overflow-x:auto}.Table[data-v-d6b3bce8]{border-collapse:collapse;font-variant-numeric:tabular-nums;border:1px solid var(--color-border);table-layout:fixed;margin:0;display:table}.Table.full-width[data-v-d6b3bce8]{width:100%}.Table tr[data-v-d6b3bce8],.Table th[data-v-d6b3bce8],.Table td[data-v-d6b3bce8]{background:0 0;border:none}.Table th[data-v-d6b3bce8],.Table td[data-v-d6b3bce8]{white-space:nowrap;text-align:left;padding:.75em 1.25em}.Table th[data-v-d6b3bce8]{border-bottom:1px solid var(--color-border-header);font-weight:600;position:sticky;top:0}.Table tbody td[data-v-d6b3bce8]{border-bottom:1px solid var(--color-border)}.Table tbody tr:last-child td[data-v-d6b3bce8]{border-bottom:none}.TableOuter[data-v-d6b3bce8] .chart-menu-trigger-area{top:4px;right:4px}.TableOuter[data-v-d6b3bce8] .chart-menu-button{opacity:1}.TableOuter.has-menu .Table thead th[data-v-d6b3bce8]:last-child{padding-right:2.5em}
|
|
2
2
|
/*$vite$:1*/
|