@matthieumordrel/chart-studio 0.1.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/LICENSE +21 -0
- package/README.md +371 -0
- package/dist/core/chart-capabilities.d.ts +60 -0
- package/dist/core/chart-capabilities.d.ts.map +1 -0
- package/dist/core/chart-capabilities.js +55 -0
- package/dist/core/chart-capabilities.js.map +1 -0
- package/dist/core/colors.d.ts +25 -0
- package/dist/core/colors.d.ts.map +1 -0
- package/dist/core/colors.js +55 -0
- package/dist/core/colors.js.map +1 -0
- package/dist/core/config-utils.d.ts +43 -0
- package/dist/core/config-utils.d.ts.map +1 -0
- package/dist/core/config-utils.js +81 -0
- package/dist/core/config-utils.js.map +1 -0
- package/dist/core/date-utils.d.ts +29 -0
- package/dist/core/date-utils.d.ts.map +1 -0
- package/dist/core/date-utils.js +59 -0
- package/dist/core/date-utils.js.map +1 -0
- package/dist/core/define-chart-schema.d.ts +105 -0
- package/dist/core/define-chart-schema.d.ts.map +1 -0
- package/dist/core/define-chart-schema.js +45 -0
- package/dist/core/define-chart-schema.js.map +1 -0
- package/dist/core/formatting.d.ts +47 -0
- package/dist/core/formatting.d.ts.map +1 -0
- package/dist/core/formatting.js +397 -0
- package/dist/core/formatting.js.map +1 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/infer-columns.d.ts +6 -0
- package/dist/core/infer-columns.d.ts.map +1 -0
- package/dist/core/infer-columns.js +513 -0
- package/dist/core/infer-columns.js.map +1 -0
- package/dist/core/metric-utils.d.ts +43 -0
- package/dist/core/metric-utils.d.ts.map +1 -0
- package/dist/core/metric-utils.js +142 -0
- package/dist/core/metric-utils.js.map +1 -0
- package/dist/core/pipeline-data-points.d.ts +23 -0
- package/dist/core/pipeline-data-points.d.ts.map +1 -0
- package/dist/core/pipeline-data-points.js +236 -0
- package/dist/core/pipeline-data-points.js.map +1 -0
- package/dist/core/pipeline-helpers.d.ts +38 -0
- package/dist/core/pipeline-helpers.d.ts.map +1 -0
- package/dist/core/pipeline-helpers.js +98 -0
- package/dist/core/pipeline-helpers.js.map +1 -0
- package/dist/core/pipeline.d.ts +70 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +157 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/types.d.ts +1109 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +15 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/use-chart-options.d.ts +66 -0
- package/dist/core/use-chart-options.d.ts.map +1 -0
- package/dist/core/use-chart-options.js +5 -0
- package/dist/core/use-chart-options.js.map +1 -0
- package/dist/core/use-chart-resolvers.d.ts +14 -0
- package/dist/core/use-chart-resolvers.d.ts.map +1 -0
- package/dist/core/use-chart-resolvers.js +42 -0
- package/dist/core/use-chart-resolvers.js.map +1 -0
- package/dist/core/use-chart.d.ts +47 -0
- package/dist/core/use-chart.d.ts.map +1 -0
- package/dist/core/use-chart.js +266 -0
- package/dist/core/use-chart.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/chart-axis-ticks.d.ts +35 -0
- package/dist/ui/chart-axis-ticks.d.ts.map +1 -0
- package/dist/ui/chart-axis-ticks.js +80 -0
- package/dist/ui/chart-axis-ticks.js.map +1 -0
- package/dist/ui/chart-canvas.d.ts +22 -0
- package/dist/ui/chart-canvas.d.ts.map +1 -0
- package/dist/ui/chart-canvas.js +338 -0
- package/dist/ui/chart-canvas.js.map +1 -0
- package/dist/ui/chart-context.d.ts +89 -0
- package/dist/ui/chart-context.d.ts.map +1 -0
- package/dist/ui/chart-context.js +129 -0
- package/dist/ui/chart-context.js.map +1 -0
- package/dist/ui/chart-date-range-badge.d.ts +14 -0
- package/dist/ui/chart-date-range-badge.d.ts.map +1 -0
- package/dist/ui/chart-date-range-badge.js +31 -0
- package/dist/ui/chart-date-range-badge.js.map +1 -0
- package/dist/ui/chart-date-range-panel.d.ts +25 -0
- package/dist/ui/chart-date-range-panel.d.ts.map +1 -0
- package/dist/ui/chart-date-range-panel.js +126 -0
- package/dist/ui/chart-date-range-panel.js.map +1 -0
- package/dist/ui/chart-date-range.d.ts +14 -0
- package/dist/ui/chart-date-range.d.ts.map +1 -0
- package/dist/ui/chart-date-range.js +38 -0
- package/dist/ui/chart-date-range.js.map +1 -0
- package/dist/ui/chart-debug.d.ts +10 -0
- package/dist/ui/chart-debug.d.ts.map +1 -0
- package/dist/ui/chart-debug.js +127 -0
- package/dist/ui/chart-debug.js.map +1 -0
- package/dist/ui/chart-dropdown.d.ts +35 -0
- package/dist/ui/chart-dropdown.d.ts.map +1 -0
- package/dist/ui/chart-dropdown.js +77 -0
- package/dist/ui/chart-dropdown.js.map +1 -0
- package/dist/ui/chart-filters-panel.d.ts +19 -0
- package/dist/ui/chart-filters-panel.d.ts.map +1 -0
- package/dist/ui/chart-filters-panel.js +47 -0
- package/dist/ui/chart-filters-panel.js.map +1 -0
- package/dist/ui/chart-filters.d.ts +12 -0
- package/dist/ui/chart-filters.d.ts.map +1 -0
- package/dist/ui/chart-filters.js +27 -0
- package/dist/ui/chart-filters.js.map +1 -0
- package/dist/ui/chart-group-by-selector.d.ts +8 -0
- package/dist/ui/chart-group-by-selector.d.ts.map +1 -0
- package/dist/ui/chart-group-by-selector.js +20 -0
- package/dist/ui/chart-group-by-selector.js.map +1 -0
- package/dist/ui/chart-metric-panel.d.ts +18 -0
- package/dist/ui/chart-metric-panel.d.ts.map +1 -0
- package/dist/ui/chart-metric-panel.js +119 -0
- package/dist/ui/chart-metric-panel.js.map +1 -0
- package/dist/ui/chart-metric-selector.d.ts +10 -0
- package/dist/ui/chart-metric-selector.d.ts.map +1 -0
- package/dist/ui/chart-metric-selector.js +28 -0
- package/dist/ui/chart-metric-selector.js.map +1 -0
- package/dist/ui/chart-select.d.ts +25 -0
- package/dist/ui/chart-select.d.ts.map +1 -0
- package/dist/ui/chart-select.js +36 -0
- package/dist/ui/chart-select.js.map +1 -0
- package/dist/ui/chart-source-switcher.d.ts +16 -0
- package/dist/ui/chart-source-switcher.d.ts.map +1 -0
- package/dist/ui/chart-source-switcher.js +32 -0
- package/dist/ui/chart-source-switcher.js.map +1 -0
- package/dist/ui/chart-time-bucket-selector.d.ts +9 -0
- package/dist/ui/chart-time-bucket-selector.d.ts.map +1 -0
- package/dist/ui/chart-time-bucket-selector.js +26 -0
- package/dist/ui/chart-time-bucket-selector.js.map +1 -0
- package/dist/ui/chart-toolbar-overflow.d.ts +29 -0
- package/dist/ui/chart-toolbar-overflow.d.ts.map +1 -0
- package/dist/ui/chart-toolbar-overflow.js +110 -0
- package/dist/ui/chart-toolbar-overflow.js.map +1 -0
- package/dist/ui/chart-toolbar.d.ts +45 -0
- package/dist/ui/chart-toolbar.d.ts.map +1 -0
- package/dist/ui/chart-toolbar.js +45 -0
- package/dist/ui/chart-toolbar.js.map +1 -0
- package/dist/ui/chart-type-selector.d.ts +8 -0
- package/dist/ui/chart-type-selector.d.ts.map +1 -0
- package/dist/ui/chart-type-selector.js +23 -0
- package/dist/ui/chart-type-selector.js.map +1 -0
- package/dist/ui/chart-x-axis-selector.d.ts +8 -0
- package/dist/ui/chart-x-axis-selector.d.ts.map +1 -0
- package/dist/ui/chart-x-axis-selector.js +15 -0
- package/dist/ui/chart-x-axis-selector.js.map +1 -0
- package/dist/ui/index.d.ts +25 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +24 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/theme.css +62 -0
- package/dist/ui/toolbar-types.d.ts +43 -0
- package/dist/ui/toolbar-types.d.ts.map +1 -0
- package/dist/ui/toolbar-types.js +51 -0
- package/dist/ui/toolbar-types.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,YAAY,EACV,kBAAkB,EAClB,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,0BAA0B,EAC1B,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iCAAiC,EACjC,mCAAmC,EACnC,kCAAkC,EAClC,0BAA0B,EAC1B,6BAA6B,EAC7B,8BAA8B,EAC9B,UAAU,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,SAAS,EACT,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,WAAW,EACX,eAAe,EACf,MAAM,EACN,WAAW,EACX,aAAa,EACb,UAAU,EACV,wBAAwB,EACxB,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,uBAAuB,GACxB,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chart-studio — TanStack Table for charts.
|
|
3
|
+
*
|
|
4
|
+
* A headless, composable charting library built on top of Recharts.
|
|
5
|
+
* Pass raw data for the zero-config path, or add an explicit `schema` when you
|
|
6
|
+
* want full control over inference overrides, derived columns, and selectable
|
|
7
|
+
* chart controls.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { defineChartSchema, useChart } from '@matthieumordrel/chart-studio'
|
|
12
|
+
* import { Chart, ChartToolbar, ChartCanvas } from '@matthieumordrel/chart-studio/ui'
|
|
13
|
+
*
|
|
14
|
+
* function MyChart({ data }) {
|
|
15
|
+
* const chart = useChart({
|
|
16
|
+
* data,
|
|
17
|
+
* schema: defineChartSchema<typeof data[number]>()({
|
|
18
|
+
* columns: {
|
|
19
|
+
* dateAdded: { label: 'Date Added', type: 'date' },
|
|
20
|
+
* ownerName: { label: 'Consultant' },
|
|
21
|
+
* salary: { format: 'currency' }
|
|
22
|
+
* }
|
|
23
|
+
* })
|
|
24
|
+
* })
|
|
25
|
+
* return (
|
|
26
|
+
* <Chart chart={chart}>
|
|
27
|
+
* <ChartToolbar />
|
|
28
|
+
* <ChartCanvas />
|
|
29
|
+
* </Chart>
|
|
30
|
+
* )
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
// Headless charting API.
|
|
35
|
+
export { CHART_TYPE_CONFIG, defineChartSchema, inferColumnsFromData, useChart, getSeriesColor, buildColorMap, runPipeline, applyFilters, extractAvailableFilters, buildAvailableMetrics, getMetricLabel, } from './core/index.js';
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,yBAAyB;AACzB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,GACf,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared axis tick value type for cartesian X axes.
|
|
3
|
+
*/
|
|
4
|
+
export type AxisTickValue = string | number;
|
|
5
|
+
/**
|
|
6
|
+
* Options used to select the visible X-axis ticks for a categorical chart.
|
|
7
|
+
*/
|
|
8
|
+
type SelectVisibleXAxisTicksOptions = {
|
|
9
|
+
values: readonly AxisTickValue[];
|
|
10
|
+
labels: readonly string[];
|
|
11
|
+
plotWidth: number;
|
|
12
|
+
minimumTickGap?: number;
|
|
13
|
+
measureLabelWidth?: (label: string) => number;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Select visible X-axis tick values so labels stay readable, the first and last
|
|
17
|
+
* values always remain visible, and any unavoidable wider gaps are pushed away
|
|
18
|
+
* from the chart edges.
|
|
19
|
+
*/
|
|
20
|
+
export declare function selectVisibleXAxisTicks({ values, labels, plotWidth, minimumTickGap, measureLabelWidth, }: SelectVisibleXAxisTicksOptions): AxisTickValue[];
|
|
21
|
+
/**
|
|
22
|
+
* Estimate the minimum index distance required between rendered labels so they
|
|
23
|
+
* can fit inside the available plot width without overlapping.
|
|
24
|
+
*/
|
|
25
|
+
export declare function estimateMinimumTickStep(labels: readonly string[], plotWidth: number, minimumTickGap: number, measureLabelWidth: (label: string) => number): number;
|
|
26
|
+
/**
|
|
27
|
+
* Build the visible tick indices for a given point count and minimum step.
|
|
28
|
+
*
|
|
29
|
+
* The selector keeps the first and last tick, shows as many intermediate ticks
|
|
30
|
+
* as possible, and places any wider fallback gaps near the center so the edges
|
|
31
|
+
* stay visually balanced.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildVisibleTickIndices(pointCount: number, minimumStep: number): number[];
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=chart-axis-ticks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-axis-ticks.d.ts","sourceRoot":"","sources":["../../src/ui/chart-axis-ticks.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAA;AAE3C;;GAEG;AACH,KAAK,8BAA8B,GAAG;IACpC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAA;IAChC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CAC9C,CAAA;AAOD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,MAAM,EACN,SAAS,EACT,cAAyC,EACzC,iBAAqD,GACtD,EAAE,8BAA8B,GAAG,aAAa,EAAE,CAQlD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAC3C,MAAM,CAQR;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAkCzF"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default horizontal breathing room kept between two rendered tick labels.
|
|
3
|
+
*/
|
|
4
|
+
const DEFAULT_MINIMUM_TICK_GAP = 8;
|
|
5
|
+
/**
|
|
6
|
+
* Select visible X-axis tick values so labels stay readable, the first and last
|
|
7
|
+
* values always remain visible, and any unavoidable wider gaps are pushed away
|
|
8
|
+
* from the chart edges.
|
|
9
|
+
*/
|
|
10
|
+
export function selectVisibleXAxisTicks({ values, labels, plotWidth, minimumTickGap = DEFAULT_MINIMUM_TICK_GAP, measureLabelWidth = measureLabelWidthByCharacterCount, }) {
|
|
11
|
+
if (values.length <= 2) {
|
|
12
|
+
return [...values];
|
|
13
|
+
}
|
|
14
|
+
const minimumStep = estimateMinimumTickStep(labels, plotWidth, minimumTickGap, measureLabelWidth);
|
|
15
|
+
const visibleIndices = buildVisibleTickIndices(values.length, minimumStep);
|
|
16
|
+
return visibleIndices.map((index) => values[index]);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Estimate the minimum index distance required between rendered labels so they
|
|
20
|
+
* can fit inside the available plot width without overlapping.
|
|
21
|
+
*/
|
|
22
|
+
export function estimateMinimumTickStep(labels, plotWidth, minimumTickGap, measureLabelWidth) {
|
|
23
|
+
if (labels.length <= 1) {
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
const widestLabel = labels.reduce((maxWidth, label) => Math.max(maxWidth, measureLabelWidth(label)), 0);
|
|
27
|
+
const slotWidth = plotWidth / Math.max(labels.length - 1, 1);
|
|
28
|
+
return Math.max(1, Math.ceil((widestLabel + minimumTickGap) / Math.max(slotWidth, 1)));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build the visible tick indices for a given point count and minimum step.
|
|
32
|
+
*
|
|
33
|
+
* The selector keeps the first and last tick, shows as many intermediate ticks
|
|
34
|
+
* as possible, and places any wider fallback gaps near the center so the edges
|
|
35
|
+
* stay visually balanced.
|
|
36
|
+
*/
|
|
37
|
+
export function buildVisibleTickIndices(pointCount, minimumStep) {
|
|
38
|
+
if (pointCount <= 0) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
if (pointCount <= 2) {
|
|
42
|
+
return Array.from({ length: pointCount }, (_, index) => index);
|
|
43
|
+
}
|
|
44
|
+
const safeMinimumStep = Math.max(1, Math.floor(minimumStep));
|
|
45
|
+
if (safeMinimumStep === 1) {
|
|
46
|
+
return Array.from({ length: pointCount }, (_, index) => index);
|
|
47
|
+
}
|
|
48
|
+
const gapCount = Math.floor((pointCount - 1) / safeMinimumStep);
|
|
49
|
+
if (gapCount === 0) {
|
|
50
|
+
return [0, pointCount - 1];
|
|
51
|
+
}
|
|
52
|
+
const gaps = Array.from({ length: gapCount }, () => safeMinimumStep);
|
|
53
|
+
const remainder = (pointCount - 1) - safeMinimumStep * gapCount;
|
|
54
|
+
for (const gapIndex of getCenteredGapOrder(gapCount).slice(0, remainder)) {
|
|
55
|
+
const gap = gaps[gapIndex];
|
|
56
|
+
if (gap !== undefined) {
|
|
57
|
+
gaps[gapIndex] = gap + 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const visibleIndices = [0];
|
|
61
|
+
for (const gap of gaps) {
|
|
62
|
+
visibleIndices.push(visibleIndices[visibleIndices.length - 1] + gap);
|
|
63
|
+
}
|
|
64
|
+
return visibleIndices;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Order gap positions from the center outward so any larger fallback gaps land
|
|
68
|
+
* away from the chart edges.
|
|
69
|
+
*/
|
|
70
|
+
function getCenteredGapOrder(gapCount) {
|
|
71
|
+
const center = (gapCount - 1) / 2;
|
|
72
|
+
return Array.from({ length: gapCount }, (_, index) => index).sort((left, right) => Math.abs(left - center) - Math.abs(right - center) || left - right);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Lightweight default width estimate used by tests and non-DOM callers.
|
|
76
|
+
*/
|
|
77
|
+
function measureLabelWidthByCharacterCount(label) {
|
|
78
|
+
return label.length;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=chart-axis-ticks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-axis-ticks.js","sourceRoot":"","sources":["../../src/ui/chart-axis-ticks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chart canvas — renders the actual recharts chart based on the current state.
|
|
3
|
+
*
|
|
4
|
+
* Supports: bar, line, area (time-series), bar, pie, donut (categorical).
|
|
5
|
+
* Automatically switches between chart types based on the chart instance state.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Props for ChartCanvas.
|
|
9
|
+
*
|
|
10
|
+
* @property height - Chart height in pixels (default: 300)
|
|
11
|
+
* @property className - Additional CSS classes
|
|
12
|
+
* @property showDataLabels - Opt into cartesian/pie value labels using the shared formatting rules.
|
|
13
|
+
*/
|
|
14
|
+
type ChartCanvasProps = {
|
|
15
|
+
height?: number;
|
|
16
|
+
className?: string;
|
|
17
|
+
showDataLabels?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** Renders the appropriate recharts chart based on the chart instance state. */
|
|
20
|
+
export declare function ChartCanvas({ height, className, showDataLabels }: ChartCanvasProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=chart-canvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-canvas.d.ts","sourceRoot":"","sources":["../../src/ui/chart-canvas.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AA+KH;;;;;;GAMG;AACH,KAAK,gBAAgB,GAAG;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAuED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,EAAC,MAAY,EAAE,SAAS,EAAE,cAAsB,EAAC,EAAE,gBAAgB,2CA2F9F"}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Chart canvas — renders the actual recharts chart based on the current state.
|
|
4
|
+
*
|
|
5
|
+
* Supports: bar, line, area (time-series), bar, pie, donut (categorical).
|
|
6
|
+
* Automatically switches between chart types based on the chart instance state.
|
|
7
|
+
*/
|
|
8
|
+
import { useEffect, useRef, useState } from 'react';
|
|
9
|
+
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Legend, LabelList, Line, LineChart, Pie, PieChart, Tooltip, XAxis, YAxis, } from 'recharts';
|
|
10
|
+
import { createNumericRange, formatChartValue, formatTimeBucketLabel, shouldAllowDecimalTicks, } from '../core/formatting.js';
|
|
11
|
+
import { useChartContext } from './chart-context.js';
|
|
12
|
+
import { getSeriesColor } from '../core/colors.js';
|
|
13
|
+
import { selectVisibleXAxisTicks } from './chart-axis-ticks.js';
|
|
14
|
+
/**
|
|
15
|
+
* Estimates the pixel width the YAxis needs so no label is ever clipped.
|
|
16
|
+
* Considers both the visible range and the likely "nice" axis boundary Recharts
|
|
17
|
+
* may choose above it, then measures the widest formatted label and adds a
|
|
18
|
+
* small gutter for tick spacing.
|
|
19
|
+
*/
|
|
20
|
+
function estimateYAxisWidth(numericRange, valueColumn) {
|
|
21
|
+
const labels = getYAxisLabelCandidates(numericRange, valueColumn);
|
|
22
|
+
const widestLabel = labels.reduce((maxWidth, label) => Math.max(maxWidth, measureAxisLabelWidth(label)), 0);
|
|
23
|
+
return Math.max(MIN_Y_AXIS_WIDTH, Math.ceil(widestLabel + Y_AXIS_WIDTH_GUTTER));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Font used by the shared chart axis ticks (`text-xs` in the default theme).
|
|
27
|
+
*/
|
|
28
|
+
const AXIS_TICK_FONT = '12px system-ui, sans-serif';
|
|
29
|
+
/**
|
|
30
|
+
* Canvas measurement can be unavailable in some environments, so keep a
|
|
31
|
+
* slightly generous character-width fallback.
|
|
32
|
+
*/
|
|
33
|
+
const FALLBACK_AXIS_CHARACTER_WIDTH = 8;
|
|
34
|
+
/**
|
|
35
|
+
* Minimum width so short numeric axes still have breathing room.
|
|
36
|
+
*/
|
|
37
|
+
const MIN_Y_AXIS_WIDTH = 48;
|
|
38
|
+
/**
|
|
39
|
+
* Extra space for tick margin plus a small anti-clipping buffer.
|
|
40
|
+
*/
|
|
41
|
+
const Y_AXIS_WIDTH_GUTTER = 18;
|
|
42
|
+
/**
|
|
43
|
+
* Horizontal breathing room kept between two visible X-axis labels.
|
|
44
|
+
*/
|
|
45
|
+
const X_AXIS_MINIMUM_TICK_GAP = 8;
|
|
46
|
+
/**
|
|
47
|
+
* Build a small set of realistic axis labels and size for the widest one.
|
|
48
|
+
* This catches cases where the chart data tops out below the rounded axis
|
|
49
|
+
* tick, such as `950` minutes producing a `1000` minute top tick.
|
|
50
|
+
*/
|
|
51
|
+
function getYAxisLabelCandidates(numericRange, valueColumn) {
|
|
52
|
+
const candidates = getYAxisCandidateValues(numericRange);
|
|
53
|
+
return candidates.map((value) => formatChartValue(value, {
|
|
54
|
+
column: valueColumn,
|
|
55
|
+
surface: 'axis',
|
|
56
|
+
numericRange,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Include the visible extrema plus rounded axis boundaries so the width
|
|
61
|
+
* estimate matches what the axis is likely to render.
|
|
62
|
+
*/
|
|
63
|
+
function getYAxisCandidateValues(numericRange) {
|
|
64
|
+
if (!numericRange) {
|
|
65
|
+
return [0];
|
|
66
|
+
}
|
|
67
|
+
const maxAbs = Math.max(Math.abs(numericRange.min), Math.abs(numericRange.max));
|
|
68
|
+
const niceMaxAbs = getNiceAxisBoundary(maxAbs);
|
|
69
|
+
const values = new Set([0, numericRange.min, numericRange.max, maxAbs, niceMaxAbs]);
|
|
70
|
+
if (numericRange.min < 0) {
|
|
71
|
+
values.add(-niceMaxAbs);
|
|
72
|
+
}
|
|
73
|
+
return Array.from(values);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Approximate the rounded outer tick value chart libraries tend to choose for
|
|
77
|
+
* a human-friendly numeric axis.
|
|
78
|
+
*/
|
|
79
|
+
function getNiceAxisBoundary(value) {
|
|
80
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
const exponent = Math.floor(Math.log10(value));
|
|
84
|
+
const magnitude = 10 ** exponent;
|
|
85
|
+
const fraction = value / magnitude;
|
|
86
|
+
if (fraction <= 1)
|
|
87
|
+
return magnitude;
|
|
88
|
+
if (fraction <= 2)
|
|
89
|
+
return 2 * magnitude;
|
|
90
|
+
if (fraction <= 5)
|
|
91
|
+
return 5 * magnitude;
|
|
92
|
+
return 10 * magnitude;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Measure axis text width in the browser and fall back to a safe character
|
|
96
|
+
* estimate in non-DOM environments.
|
|
97
|
+
*/
|
|
98
|
+
function measureAxisLabelWidth(label) {
|
|
99
|
+
if (typeof document === 'undefined') {
|
|
100
|
+
return label.length * FALLBACK_AXIS_CHARACTER_WIDTH;
|
|
101
|
+
}
|
|
102
|
+
const canvas = document.createElement('canvas');
|
|
103
|
+
const context = canvas.getContext('2d');
|
|
104
|
+
if (!context) {
|
|
105
|
+
return label.length * FALLBACK_AXIS_CHARACTER_WIDTH;
|
|
106
|
+
}
|
|
107
|
+
context.font = AXIS_TICK_FONT;
|
|
108
|
+
return context.measureText(label).width;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Approximate the drawable X-axis width after margins, Y-axis labels, and axis
|
|
112
|
+
* padding have taken their share of the SVG width.
|
|
113
|
+
*/
|
|
114
|
+
function getCartesianPlotWidth(totalWidth, yAxisWidth) {
|
|
115
|
+
return Math.max(1, totalWidth
|
|
116
|
+
- yAxisWidth
|
|
117
|
+
- CARTESIAN_BASE_MARGIN.left
|
|
118
|
+
- CARTESIAN_BASE_MARGIN.right
|
|
119
|
+
- CARTESIAN_X_AXIS_PADDING.left
|
|
120
|
+
- CARTESIAN_X_AXIS_PADDING.right);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Resolve the raw categorical tick value used by Recharts for one transformed
|
|
124
|
+
* pipeline point.
|
|
125
|
+
*/
|
|
126
|
+
function getXAxisTickValue(point) {
|
|
127
|
+
return typeof point['xKey'] === 'string' || typeof point['xKey'] === 'number'
|
|
128
|
+
? point['xKey']
|
|
129
|
+
: String(point['xLabel']);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Important recharts styling — mirrors shadcn's ChartContainer CSS.
|
|
133
|
+
* Ensures proper text colors, grid lines, and outline handling.
|
|
134
|
+
*/
|
|
135
|
+
const RECHARTS_STYLES = [
|
|
136
|
+
'text-xs',
|
|
137
|
+
'[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground',
|
|
138
|
+
"[&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50",
|
|
139
|
+
'[&_.recharts-curve.recharts-tooltip-cursor]:stroke-border',
|
|
140
|
+
'[&_.recharts-layer]:outline-hidden',
|
|
141
|
+
'[&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted',
|
|
142
|
+
"[&_.recharts-reference-line_[stroke='#ccc']]:stroke-border",
|
|
143
|
+
'[&_.recharts-sector]:outline-hidden',
|
|
144
|
+
'[&_.recharts-surface]:outline-hidden',
|
|
145
|
+
].join(' ');
|
|
146
|
+
/**
|
|
147
|
+
* Reserve enough top padding for the tallest bar/point label plus its offset so
|
|
148
|
+
* data labels never clip against the SVG edge.
|
|
149
|
+
*/
|
|
150
|
+
const CARTESIAN_BASE_MARGIN = { top: 4, right: 8, left: 0, bottom: 0 };
|
|
151
|
+
/**
|
|
152
|
+
* Vertical headroom required for one top-positioned cartesian data label.
|
|
153
|
+
*/
|
|
154
|
+
const CARTESIAN_DATA_LABEL_TOP_CLEARANCE = 28;
|
|
155
|
+
/**
|
|
156
|
+
* Expand the cartesian chart margin only when top-positioned data labels are
|
|
157
|
+
* enabled.
|
|
158
|
+
*/
|
|
159
|
+
function getCartesianChartMargin(showDataLabels) {
|
|
160
|
+
return showDataLabels
|
|
161
|
+
? {
|
|
162
|
+
...CARTESIAN_BASE_MARGIN,
|
|
163
|
+
top: CARTESIAN_BASE_MARGIN.top + CARTESIAN_DATA_LABEL_TOP_CLEARANCE,
|
|
164
|
+
}
|
|
165
|
+
: CARTESIAN_BASE_MARGIN;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Keep the first and last rendered values from hugging the chart edges.
|
|
169
|
+
*/
|
|
170
|
+
const CARTESIAN_X_AXIS_PADDING = { left: 12, right: 12 };
|
|
171
|
+
/**
|
|
172
|
+
* Hook that measures a container's width using ResizeObserver.
|
|
173
|
+
* Avoids the ResponsiveContainer issues with flexbox/grid layouts.
|
|
174
|
+
*/
|
|
175
|
+
function useContainerWidth() {
|
|
176
|
+
const ref = useRef(null);
|
|
177
|
+
const [width, setWidth] = useState(0);
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
const el = ref.current;
|
|
180
|
+
if (!el)
|
|
181
|
+
return;
|
|
182
|
+
const observer = new ResizeObserver((entries) => {
|
|
183
|
+
const entry = entries[0];
|
|
184
|
+
if (entry)
|
|
185
|
+
setWidth(entry.contentRect.width);
|
|
186
|
+
});
|
|
187
|
+
observer.observe(el);
|
|
188
|
+
return () => observer.disconnect();
|
|
189
|
+
}, []);
|
|
190
|
+
return { ref, width };
|
|
191
|
+
}
|
|
192
|
+
/** Renders the appropriate recharts chart based on the chart instance state. */
|
|
193
|
+
export function ChartCanvas({ height = 300, className, showDataLabels = false }) {
|
|
194
|
+
const chart = useChartContext();
|
|
195
|
+
const { chartType, transformedData, series } = chart;
|
|
196
|
+
const { ref, width } = useContainerWidth();
|
|
197
|
+
const xColumn = chart.columns.find((column) => column.id === chart.xAxisId) ?? null;
|
|
198
|
+
const aggregateMetric = chart.metric.kind === 'aggregate' ? chart.metric : null;
|
|
199
|
+
const metricColumn = aggregateMetric
|
|
200
|
+
? chart.columns.find((column) => column.id === aggregateMetric.columnId && column.type === 'number')
|
|
201
|
+
: null;
|
|
202
|
+
const valueColumn = metricColumn ?? { type: 'number', format: undefined };
|
|
203
|
+
const numericValues = transformedData.flatMap((point) => series.flatMap((seriesItem) => {
|
|
204
|
+
const value = point[seriesItem.dataKey];
|
|
205
|
+
return typeof value === 'number' ? [value] : [];
|
|
206
|
+
}));
|
|
207
|
+
const valueRange = createNumericRange(numericValues);
|
|
208
|
+
const allowDecimalTicks = shouldAllowDecimalTicks(numericValues);
|
|
209
|
+
if (transformedData.length === 0) {
|
|
210
|
+
return (_jsx("div", { ref: ref, className: `flex items-center justify-center text-sm text-muted-foreground ${className ?? ''}`, style: { height }, children: "No data available" }));
|
|
211
|
+
}
|
|
212
|
+
return (_jsx("div", { ref: ref, className: `${RECHARTS_STYLES} ${className ?? ''}`, style: { height }, children: width > 0 &&
|
|
213
|
+
(chartType === 'pie' || chartType === 'donut' ? (_jsx(PieChartRenderer, { data: transformedData, series: series, innerRadius: chartType === 'donut', width: width, height: height, valueColumn: valueColumn, valueRange: valueRange, allowDecimalTicks: allowDecimalTicks, xColumn: xColumn, timeBucket: chart.isTimeSeries ? chart.timeBucket : undefined, showDataLabels: showDataLabels })) : chartType === 'line' ? (_jsx(LineChartRenderer, { data: transformedData, series: series, width: width, height: height, valueColumn: valueColumn, valueRange: valueRange, allowDecimalTicks: allowDecimalTicks, xColumn: xColumn, timeBucket: chart.isTimeSeries ? chart.timeBucket : undefined, showDataLabels: showDataLabels })) : chartType === 'area' ? (_jsx(AreaChartRenderer, { data: transformedData, series: series, width: width, height: height, valueColumn: valueColumn, valueRange: valueRange, allowDecimalTicks: allowDecimalTicks, xColumn: xColumn, timeBucket: chart.isTimeSeries ? chart.timeBucket : undefined, showDataLabels: showDataLabels })) : (_jsx(BarChartRenderer, { data: transformedData, series: series, width: width, height: height, valueColumn: valueColumn, valueRange: valueRange, allowDecimalTicks: allowDecimalTicks, xColumn: xColumn, timeBucket: chart.isTimeSeries ? chart.timeBucket : undefined, showDataLabels: showDataLabels }))) }));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Shared shell for all Cartesian chart types.
|
|
217
|
+
* Owns the grid, axes, tooltip, and legend — the only things that change
|
|
218
|
+
* per chart type are the root component and the series element.
|
|
219
|
+
*/
|
|
220
|
+
function CartesianChartShell({ data, series, width, height, valueColumn, valueRange, allowDecimalTicks, xColumn, timeBucket, showDataLabels, Chart, renderSeries, }) {
|
|
221
|
+
const yAxisWidth = estimateYAxisWidth(valueRange, valueColumn);
|
|
222
|
+
const xAxisTickValues = selectVisibleXAxisTicks({
|
|
223
|
+
values: data.map(getXAxisTickValue),
|
|
224
|
+
labels: data.map((point) => formatXAxisValue(getXAxisTickValue(point), xColumn, timeBucket, 'axis')),
|
|
225
|
+
plotWidth: getCartesianPlotWidth(width, yAxisWidth),
|
|
226
|
+
minimumTickGap: X_AXIS_MINIMUM_TICK_GAP,
|
|
227
|
+
measureLabelWidth: measureAxisLabelWidth,
|
|
228
|
+
});
|
|
229
|
+
return (_jsxs(Chart, { data: data, width: width, height: height, margin: getCartesianChartMargin(showDataLabels), children: [_jsx(CartesianGrid, { vertical: false, strokeDasharray: "3 3" }), _jsx(XAxis, { dataKey: "xKey", tickLine: false, axisLine: false, tickMargin: 8, interval: 0, padding: CARTESIAN_X_AXIS_PADDING, ticks: xAxisTickValues, tickFormatter: (value) => formatXAxisValue(value, xColumn, timeBucket, 'axis') }), _jsx(YAxis, { tickLine: false, axisLine: false, tickMargin: 4, allowDecimals: allowDecimalTicks, width: yAxisWidth, tickFormatter: (value) => typeof value === 'number'
|
|
230
|
+
? formatChartValue(value, {
|
|
231
|
+
column: valueColumn,
|
|
232
|
+
surface: 'axis',
|
|
233
|
+
numericRange: valueRange,
|
|
234
|
+
})
|
|
235
|
+
: String(value) }), _jsx(Tooltip, { formatter: (value) => typeof value === 'number'
|
|
236
|
+
? formatChartValue(value, {
|
|
237
|
+
column: valueColumn,
|
|
238
|
+
surface: 'tooltip',
|
|
239
|
+
numericRange: valueRange,
|
|
240
|
+
})
|
|
241
|
+
: value, labelFormatter: (label, payload) => formatTooltipLabel(label, payload, xColumn, timeBucket) }), series.length > 1 && _jsx(Legend, {}), series.map(renderSeries)] }));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Resolve the most descriptive tooltip label from the transformed data point.
|
|
245
|
+
*/
|
|
246
|
+
function formatTooltipLabel(label, payload, xColumn, timeBucket) {
|
|
247
|
+
if (!xColumn) {
|
|
248
|
+
return String(label);
|
|
249
|
+
}
|
|
250
|
+
const point = payload?.[0]?.payload;
|
|
251
|
+
const rawXValue = typeof point?.['xKey'] === 'string' || typeof point?.['xKey'] === 'number'
|
|
252
|
+
? point['xKey']
|
|
253
|
+
: label;
|
|
254
|
+
return formatXAxisValue(rawXValue, xColumn, timeBucket, 'tooltip');
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Format one X-axis value using the same shared column rules as the rest of the
|
|
258
|
+
* chart while preserving the special bucket labels for inferred date buckets.
|
|
259
|
+
*/
|
|
260
|
+
function formatXAxisValue(value, xColumn, timeBucket, surface) {
|
|
261
|
+
if (!xColumn) {
|
|
262
|
+
return String(value);
|
|
263
|
+
}
|
|
264
|
+
if (xColumn.type === 'date' && timeBucket && typeof value === 'string' && !xColumn.formatter) {
|
|
265
|
+
return formatTimeBucketLabel(value, timeBucket, surface);
|
|
266
|
+
}
|
|
267
|
+
return formatChartValue(value, {
|
|
268
|
+
column: xColumn,
|
|
269
|
+
surface,
|
|
270
|
+
timeBucket,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function BarChartRenderer(props) {
|
|
274
|
+
const { series, showDataLabels, valueColumn, valueRange } = props;
|
|
275
|
+
return (_jsx(CartesianChartShell, { ...props, Chart: BarChart, renderSeries: (s) => (_jsx(Bar, { dataKey: s.dataKey, name: s.label, fill: s.color, radius: [4, 4, 0, 0], stackId: series.length > 1 ? 'stack' : undefined, children: showDataLabels && (_jsx(LabelList, { position: "top", offset: 8, formatter: (value) => formatDataLabel(value, valueColumn, valueRange) })) }, s.dataKey)) }));
|
|
276
|
+
}
|
|
277
|
+
function LineChartRenderer(props) {
|
|
278
|
+
const { showDataLabels, valueColumn, valueRange } = props;
|
|
279
|
+
return (_jsx(CartesianChartShell, { ...props, Chart: LineChart, renderSeries: (s) => (_jsx(Line, { type: "monotone", dataKey: s.dataKey, name: s.label, stroke: s.color, strokeWidth: 2, dot: { r: 3 }, activeDot: { r: 5 }, children: showDataLabels && (_jsx(LabelList, { position: "top", offset: 8, formatter: (value) => formatDataLabel(value, valueColumn, valueRange) })) }, s.dataKey)) }));
|
|
280
|
+
}
|
|
281
|
+
function AreaChartRenderer(props) {
|
|
282
|
+
const { series, showDataLabels, valueColumn, valueRange } = props;
|
|
283
|
+
return (_jsx(CartesianChartShell, { ...props, Chart: AreaChart, renderSeries: (s) => (_jsx(Area, { type: "monotone", dataKey: s.dataKey, name: s.label, stroke: s.color, fill: s.color, fillOpacity: 0.3, stackId: series.length > 1 ? 'stack' : undefined, children: showDataLabels && (_jsx(LabelList, { position: "top", offset: 8, formatter: (value) => formatDataLabel(value, valueColumn, valueRange) })) }, s.dataKey)) }));
|
|
284
|
+
}
|
|
285
|
+
function PieChartRenderer({ data, series, innerRadius, width, height, valueColumn, valueRange, xColumn, timeBucket, showDataLabels, }) {
|
|
286
|
+
const valueKey = series[0]?.dataKey;
|
|
287
|
+
const pieData = data.map((point, index) => {
|
|
288
|
+
return {
|
|
289
|
+
name: typeof point['xKey'] === 'string' || typeof point['xKey'] === 'number'
|
|
290
|
+
? formatXAxisValue(point['xKey'], xColumn, timeBucket, 'tooltip')
|
|
291
|
+
: String(point['xLabel']),
|
|
292
|
+
value: valueKey && typeof point[valueKey] === 'number' ? point[valueKey] : 0,
|
|
293
|
+
fill: getSeriesColor(index),
|
|
294
|
+
};
|
|
295
|
+
});
|
|
296
|
+
return (_jsxs(PieChart, { width: width, height: height, children: [_jsx(Tooltip, { formatter: (value) => typeof value === 'number'
|
|
297
|
+
? formatChartValue(value, {
|
|
298
|
+
column: valueColumn,
|
|
299
|
+
surface: 'tooltip',
|
|
300
|
+
numericRange: valueRange,
|
|
301
|
+
})
|
|
302
|
+
: value }), _jsx(Legend, {}), _jsx(Pie, { data: pieData, dataKey: "value", nameKey: "name", cx: "50%", cy: "50%", innerRadius: innerRadius ? '40%' : 0, outerRadius: "80%", label: showDataLabels
|
|
303
|
+
? ({ name, value }) => shouldHideDataLabel(value)
|
|
304
|
+
? ''
|
|
305
|
+
: `${name}: ${typeof value === 'number'
|
|
306
|
+
? formatChartValue(value, {
|
|
307
|
+
column: valueColumn,
|
|
308
|
+
surface: 'data-label',
|
|
309
|
+
numericRange: valueRange,
|
|
310
|
+
})
|
|
311
|
+
: value}`
|
|
312
|
+
: false, labelLine: false })] }));
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Format one cartesian data label with the same surface-aware rules used
|
|
316
|
+
* elsewhere in the chart UI.
|
|
317
|
+
*/
|
|
318
|
+
function formatDataLabel(value, valueColumn, valueRange) {
|
|
319
|
+
if (shouldHideDataLabel(value)) {
|
|
320
|
+
return '';
|
|
321
|
+
}
|
|
322
|
+
if (typeof value !== 'number') {
|
|
323
|
+
return String(value);
|
|
324
|
+
}
|
|
325
|
+
return formatChartValue(value, {
|
|
326
|
+
column: valueColumn,
|
|
327
|
+
surface: 'data-label',
|
|
328
|
+
numericRange: valueRange,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Suppress zero-value labels in the built-in UI so charts stay quieter by
|
|
333
|
+
* default while tooltips and raw values remain unchanged.
|
|
334
|
+
*/
|
|
335
|
+
function shouldHideDataLabel(value) {
|
|
336
|
+
return typeof value === 'number' && value === 0;
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=chart-canvas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-canvas.js","sourceRoot":"","sources":["../../src/ui/chart-canvas.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React context for sharing the chart instance across composable UI components.
|
|
3
|
+
*/
|
|
4
|
+
import { type ReactElement, type ReactNode } from 'react';
|
|
5
|
+
import type { ChartColumn, ChartInstance, ChartInstanceFromSchema, ChartSchema, Metric, ResolvedChartSchemaFromDefinition } from '../core/types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Type-erased chart instance stored in React context.
|
|
8
|
+
* This keeps the default UI primitives honest and safe for both single-source
|
|
9
|
+
* and multi-source charts.
|
|
10
|
+
*/
|
|
11
|
+
type ChartContextChart = Omit<ChartInstance<unknown, string>, 'columns' | 'filters'> & {
|
|
12
|
+
columns: readonly ChartColumn<any, string>[];
|
|
13
|
+
filters: Map<string, Set<string>>;
|
|
14
|
+
};
|
|
15
|
+
type AnyChartInstance = {
|
|
16
|
+
activeSourceId: string;
|
|
17
|
+
setActiveSource: (...args: any[]) => unknown;
|
|
18
|
+
hasMultipleSources: boolean;
|
|
19
|
+
sources: Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}>;
|
|
23
|
+
chartType: ChartContextChart['chartType'];
|
|
24
|
+
setChartType: (...args: any[]) => unknown;
|
|
25
|
+
availableChartTypes: ChartContextChart['availableChartTypes'];
|
|
26
|
+
xAxisId: string | null;
|
|
27
|
+
setXAxis: (...args: any[]) => unknown;
|
|
28
|
+
availableXAxes: ChartContextChart['availableXAxes'];
|
|
29
|
+
groupById: string | null;
|
|
30
|
+
setGroupBy: (...args: any[]) => unknown;
|
|
31
|
+
availableGroupBys: ChartContextChart['availableGroupBys'];
|
|
32
|
+
metric: Metric<any>;
|
|
33
|
+
setMetric: (...args: any[]) => unknown;
|
|
34
|
+
availableMetrics: ChartContextChart['availableMetrics'];
|
|
35
|
+
timeBucket: ChartContextChart['timeBucket'];
|
|
36
|
+
setTimeBucket: (...args: any[]) => unknown;
|
|
37
|
+
availableTimeBuckets: ChartContextChart['availableTimeBuckets'];
|
|
38
|
+
isTimeSeries: boolean;
|
|
39
|
+
filters: Map<any, Set<string>>;
|
|
40
|
+
toggleFilter: (...args: any[]) => unknown;
|
|
41
|
+
clearFilter: (...args: any[]) => unknown;
|
|
42
|
+
clearAllFilters: () => void;
|
|
43
|
+
availableFilters: ChartContextChart['availableFilters'];
|
|
44
|
+
sorting: ChartContextChart['sorting'];
|
|
45
|
+
setSorting: (...args: any[]) => unknown;
|
|
46
|
+
dateRange: ChartContextChart['dateRange'];
|
|
47
|
+
referenceDateId: string | null;
|
|
48
|
+
setReferenceDateId: (...args: any[]) => unknown;
|
|
49
|
+
availableDateColumns: ChartContextChart['availableDateColumns'];
|
|
50
|
+
dateRangeFilter: ChartContextChart['dateRangeFilter'];
|
|
51
|
+
setDateRangeFilter: (...args: any[]) => unknown;
|
|
52
|
+
transformedData: ChartContextChart['transformedData'];
|
|
53
|
+
series: ChartContextChart['series'];
|
|
54
|
+
columns: readonly ChartColumn<any, string>[];
|
|
55
|
+
rawData: readonly unknown[];
|
|
56
|
+
recordCount: number;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Hook to access the chart instance from context.
|
|
60
|
+
* Must be used within a `<Chart>` provider.
|
|
61
|
+
*
|
|
62
|
+
* This hook stays intentionally broad so the default UI primitives remain safe
|
|
63
|
+
* for both single-source and multi-source charts.
|
|
64
|
+
*/
|
|
65
|
+
export declare function useChartContext(): ChartContextChart;
|
|
66
|
+
/**
|
|
67
|
+
* Typed single-source chart context escape hatch for inferred charts.
|
|
68
|
+
* React cannot infer provider generics through arbitrary subtrees, so callers
|
|
69
|
+
* provide the row type (and optional schema type) explicitly.
|
|
70
|
+
*/
|
|
71
|
+
export declare function useTypedChartContext<T, const TSchema extends ChartSchema<T, any> | undefined = undefined>(): ChartInstanceFromSchema<T, ResolvedChartSchemaFromDefinition<TSchema>>;
|
|
72
|
+
/**
|
|
73
|
+
* Root provider component. Wraps children with the chart instance context.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```tsx
|
|
77
|
+
* <Chart chart={chart}>
|
|
78
|
+
* <ChartToolbar />
|
|
79
|
+
* <ChartCanvas />
|
|
80
|
+
* </Chart>
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function Chart({ chart, children, className, }: {
|
|
84
|
+
chart: AnyChartInstance;
|
|
85
|
+
children: ReactNode;
|
|
86
|
+
className?: string;
|
|
87
|
+
}): ReactElement;
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=chart-context.d.ts.map
|