@automattic/charts 0.31.0 → 0.32.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/CHANGELOG.md +26 -12
- package/dist/cjs/components/conversion-funnel-chart/conversion-funnel-chart.js +4 -3
- package/dist/cjs/components/leaderboard-chart/index.js +1 -0
- package/dist/cjs/components/leaderboard-chart/leaderboard-chart.js +1 -0
- package/dist/cjs/components/legend/hooks/use-chart-legend-items.js +2 -1
- package/dist/cjs/components/pie-chart/pie-chart.js +4 -4
- package/dist/cjs/style.css +1 -1
- package/dist/cjs/utils/format-percentage.js +24 -0
- package/dist/mjs/components/conversion-funnel-chart/conversion-funnel-chart.js +4 -3
- package/dist/mjs/components/leaderboard-chart/index.js +1 -0
- package/dist/mjs/components/leaderboard-chart/leaderboard-chart.js +1 -0
- package/dist/mjs/components/legend/hooks/use-chart-legend-items.js +2 -1
- package/dist/mjs/components/pie-chart/pie-chart.js +4 -4
- package/dist/mjs/style.css +1 -1
- package/dist/mjs/utils/format-percentage.js +22 -0
- package/dist/types/components/pie-chart/pie-chart.d.ts +4 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,35 +5,48 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.32.0] - 2025-09-02
|
|
9
|
+
### Added
|
|
10
|
+
- Charts: adds controls for label visibility [#45040]
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Charts: format percentage values to be prettier [#45032]
|
|
14
|
+
- Charts: Use a global context provider for theme configuration in all stories [#45028]
|
|
15
|
+
- Charts: use getStringWidth for label size calculations [#45030]
|
|
16
|
+
- Fix the conversion-funnel-chart component exportation [#45033]
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- All charts were affected due to z-index. [#45043]
|
|
20
|
+
|
|
8
21
|
## [0.31.0] - 2025-09-01
|
|
9
22
|
### Added
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- Refactor Pie Chart to improve readability. [#44989]
|
|
23
|
+
- Add an agents.md file to project root. [#44954]
|
|
24
|
+
- Ensure stable colors for series groups. [#44730]
|
|
25
|
+
- Pie Chart: Refactor to improve readability. [#44989]
|
|
14
26
|
|
|
15
27
|
### Changed
|
|
16
|
-
-
|
|
28
|
+
- Enhance ConversionFunnelChart with render props and TooltipInPortal. [#45019]
|
|
29
|
+
- Refactor shared components, hooks and utils. [#44971]
|
|
17
30
|
|
|
18
31
|
### Fixed
|
|
19
|
-
-
|
|
20
|
-
-
|
|
32
|
+
- Fix label background and text color. [#44990]
|
|
33
|
+
- Refactor leaderboard chart to remove progress bar. [#44982]
|
|
21
34
|
|
|
22
35
|
## [0.30.0] - 2025-08-27
|
|
23
36
|
### Added
|
|
24
37
|
- Export ConversionFunnelChart for usage outside. [#44952]
|
|
25
38
|
|
|
26
39
|
### Changed
|
|
27
|
-
- Consolidate sample data across
|
|
40
|
+
- Storybook: Consolidate sample data across stories for consistency and maintainability. [#44903]
|
|
28
41
|
|
|
29
42
|
## [0.29.0] - 2025-08-25
|
|
30
43
|
### Changed
|
|
31
|
-
-
|
|
44
|
+
- Consolidate and clean up pie chart composition API. [#44856]
|
|
32
45
|
|
|
33
46
|
## [0.28.0] - 2025-08-21
|
|
34
47
|
### Added
|
|
35
|
-
-
|
|
36
|
-
-
|
|
48
|
+
- Add composition legend to pie family charts. [#44796]
|
|
49
|
+
- Add theme to global context and use instead of that from theme provider. [#44809]
|
|
37
50
|
|
|
38
51
|
## [0.27.0] - 2025-08-18
|
|
39
52
|
### Added
|
|
@@ -46,7 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
46
59
|
- Line Chart: Add comparison style to theme. [#44676]
|
|
47
60
|
|
|
48
61
|
### Changed
|
|
49
|
-
-
|
|
62
|
+
- Update legend positioning and alignment. [#44747]
|
|
50
63
|
- Update package dependencies. [#44701]
|
|
51
64
|
|
|
52
65
|
## [0.25.0] - 2025-08-11
|
|
@@ -405,6 +418,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
405
418
|
- Fixed lints following ESLint rule changes for TS [#40584]
|
|
406
419
|
- Fixing a bug in Chart storybook data. [#40640]
|
|
407
420
|
|
|
421
|
+
[0.32.0]: https://github.com/Automattic/charts/compare/v0.31.0...v0.32.0
|
|
408
422
|
[0.31.0]: https://github.com/Automattic/charts/compare/v0.30.0...v0.31.0
|
|
409
423
|
[0.30.0]: https://github.com/Automattic/charts/compare/v0.29.0...v0.30.0
|
|
410
424
|
[0.29.0]: https://github.com/Automattic/charts/compare/v0.28.0...v0.29.0
|
|
@@ -12,6 +12,7 @@ require('fast-deep-equal');
|
|
|
12
12
|
require('@visx/xychart');
|
|
13
13
|
require('date-fns');
|
|
14
14
|
require('@automattic/number-formatters');
|
|
15
|
+
var formatPercentage = require('../../utils/format-percentage.js');
|
|
15
16
|
require('@visx/text');
|
|
16
17
|
require('deepmerge');
|
|
17
18
|
var colorUtils = require('../../utils/color-utils.js');
|
|
@@ -187,9 +188,9 @@ const ConversionFunnelChart = ({ mainRate, changeIndicator, steps, loading = fal
|
|
|
187
188
|
...style,
|
|
188
189
|
};
|
|
189
190
|
// Default main metric rendering function
|
|
190
|
-
const renderDefaultMainMetric = () => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.
|
|
191
|
+
const renderDefaultMainMetric = () => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: conversionFunnelChart_module.default['main-rate'], children: formatPercentage.formatPercentage(mainRate) }), changeIndicator && (jsxRuntime.jsx("span", { className: conversionFunnelChart_module.default['change-indicator'], children: changeIndicator }))] }));
|
|
191
192
|
// Default tooltip rendering function
|
|
192
|
-
const renderDefaultTooltip = (step) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: conversionFunnelChart_module.default['tooltip-title'], children: step.label }), jsxRuntime.jsxs("div", { className: conversionFunnelChart_module.default['tooltip-content'], children: [step.rate
|
|
193
|
+
const renderDefaultTooltip = (step) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: conversionFunnelChart_module.default['tooltip-title'], children: step.label }), jsxRuntime.jsxs("div", { className: conversionFunnelChart_module.default['tooltip-content'], children: [formatPercentage.formatPercentage(step.rate), step.count && ` • ${step.count.toLocaleString()} items`] })] }));
|
|
193
194
|
// Handle empty or undefined data
|
|
194
195
|
if (!steps || steps.length === 0) {
|
|
195
196
|
return (jsxRuntime.jsx("div", { className: clsx(conversionFunnelChart_module.default.conversionFunnelChart, loading && conversionFunnelChart_module.default.loading, className), style: chartStyle, children: jsxRuntime.jsx("div", { className: conversionFunnelChart_module.default['empty-state'], children: loading ? 'Loading...' : 'No data available' }) }));
|
|
@@ -216,7 +217,7 @@ const ConversionFunnelChart = ({ mainRate, changeIndicator, steps, loading = fal
|
|
|
216
217
|
step,
|
|
217
218
|
index,
|
|
218
219
|
className: conversionFunnelChart_module.default['step-rate'],
|
|
219
|
-
})) : (jsxRuntime.
|
|
220
|
+
})) : (jsxRuntime.jsx("span", { className: conversionFunnelChart_module.default['step-rate'], children: formatPercentage.formatPercentage(step.rate) }))] }), jsxRuntime.jsx("div", { className: clsx(conversionFunnelChart_module.default['bar-container'], isClicked && conversionFunnelChart_module.default.selected, isBlurred && conversionFunnelChart_module.default.disabled), onClick: stepHandlers.get(step.id)?.onClick, onKeyDown: stepHandlers.get(step.id)?.onKeyDown, role: "button", tabIndex: isBlurred ? -1 : 0, "aria-label": step.label, children: jsxRuntime.jsx("div", { className: clsx(conversionFunnelChart_module.default['funnel-bar'], isClicked && conversionFunnelChart_module.default.selected), style: {
|
|
220
221
|
height: `${barHeight}%`,
|
|
221
222
|
backgroundColor: primaryColor,
|
|
222
223
|
} }) })] }, step.id));
|
|
@@ -14,6 +14,7 @@ require('@visx/tooltip');
|
|
|
14
14
|
require('@visx/xychart');
|
|
15
15
|
require('date-fns');
|
|
16
16
|
var formatMetricValue = require('../../utils/format-metric-value.js');
|
|
17
|
+
require('@automattic/number-formatters');
|
|
17
18
|
require('@visx/text');
|
|
18
19
|
require('deepmerge');
|
|
19
20
|
require('@visx/scale');
|
|
@@ -8,6 +8,7 @@ require('@visx/tooltip');
|
|
|
8
8
|
require('@visx/xychart');
|
|
9
9
|
require('date-fns');
|
|
10
10
|
require('@automattic/number-formatters');
|
|
11
|
+
var formatPercentage = require('../../../utils/format-percentage.js');
|
|
11
12
|
require('@visx/text');
|
|
12
13
|
var getStyles = require('../../../utils/get-styles.js');
|
|
13
14
|
require('deepmerge');
|
|
@@ -25,7 +26,7 @@ function formatPointValue(point, showValues) {
|
|
|
25
26
|
return '';
|
|
26
27
|
}
|
|
27
28
|
if ('percentage' in point) {
|
|
28
|
-
return
|
|
29
|
+
return formatPercentage.formatPercentage(point.percentage);
|
|
29
30
|
}
|
|
30
31
|
else if ('value' in point) {
|
|
31
32
|
return point.value.toString();
|
|
@@ -18,7 +18,7 @@ var useGlobalChartsTheme = require('../../providers/chart-context/hooks/use-glob
|
|
|
18
18
|
var createComposition = require('../../utils/create-composition.js');
|
|
19
19
|
require('date-fns');
|
|
20
20
|
require('@automattic/number-formatters');
|
|
21
|
-
require('@visx/text');
|
|
21
|
+
var text = require('@visx/text');
|
|
22
22
|
require('deepmerge');
|
|
23
23
|
require('@visx/scale');
|
|
24
24
|
var useElementHeight = require('../../hooks/use-element-height.js');
|
|
@@ -60,7 +60,7 @@ const validateData = (data) => {
|
|
|
60
60
|
* @param {PieChartProps} props - Component props
|
|
61
61
|
* @return {JSX.Element} The rendered chart component
|
|
62
62
|
*/
|
|
63
|
-
const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false, className, showLegend = false, legendOrientation = 'horizontal', legendPosition = 'bottom', legendAlignment = 'center', legendShape = 'circle', size, thickness = 1, padding = 20, gapScale = 0, cornerScale = 0, children = null, }) => {
|
|
63
|
+
const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false, className, showLegend = false, legendOrientation = 'horizontal', legendPosition = 'bottom', legendAlignment = 'center', legendShape = 'circle', size, thickness = 1, padding = 20, gapScale = 0, cornerScale = 0, showLabels = true, children = null, }) => {
|
|
64
64
|
const providerTheme = useGlobalChartsTheme.useGlobalChartsTheme();
|
|
65
65
|
const chartId = useChartId.useChartId(providedChartId);
|
|
66
66
|
const [legendRef, legendHeight] = useElementHeight.useElementHeight();
|
|
@@ -138,11 +138,11 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
138
138
|
}
|
|
139
139
|
// Estimate text width more accurately for background sizing
|
|
140
140
|
const fontSize = 12;
|
|
141
|
-
const estimatedTextWidth = arc.data.label
|
|
141
|
+
const estimatedTextWidth = text.getStringWidth(arc.data.label, { fontSize });
|
|
142
142
|
const labelPadding = 6;
|
|
143
143
|
const backgroundWidth = estimatedTextWidth + labelPadding * 2;
|
|
144
144
|
const backgroundHeight = fontSize + labelPadding * 2;
|
|
145
|
-
return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("path", { ...pathProps }), hasSpaceForLabel && (jsxRuntime.jsxs("g", { children: [providerTheme.labelBackgroundColor && (jsxRuntime.jsx("rect", { x: centroidX - backgroundWidth / 2, y: centroidY - backgroundHeight / 2, width: backgroundWidth, height: backgroundHeight, fill: providerTheme.labelBackgroundColor, rx: 4, ry: 4, pointerEvents: "none" })), jsxRuntime.jsx("text", { x: centroidX, y: centroidY, dy: ".33em", fill: providerTheme.labelTextColor || '#333', fontSize: fontSize, textAnchor: "middle", pointerEvents: "none", children: arc.data.label })] }))] }, `arc-${index}`));
|
|
145
|
+
return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("path", { ...pathProps }), showLabels && hasSpaceForLabel && (jsxRuntime.jsxs("g", { children: [providerTheme.labelBackgroundColor && (jsxRuntime.jsx("rect", { x: centroidX - backgroundWidth / 2, y: centroidY - backgroundHeight / 2, width: backgroundWidth, height: backgroundHeight, fill: providerTheme.labelBackgroundColor, rx: 4, ry: 4, pointerEvents: "none" })), jsxRuntime.jsx("text", { x: centroidX, y: centroidY, dy: ".33em", fill: providerTheme.labelTextColor || '#333', fontSize: fontSize, textAnchor: "middle", pointerEvents: "none", children: arc.data.label })] }))] }, `arc-${index}`));
|
|
146
146
|
});
|
|
147
147
|
} }), svgChildren] }) }), showLegend && (jsxRuntime.jsx(legend.Legend, { orientation: legendOrientation, position: legendPosition, alignment: legendAlignment, className: pieChart_module.default['pie-chart-legend'], shape: legendShape, ref: legendRef, chartId: chartId })), withTooltips && tooltipOpen && tooltipData && (jsxRuntime.jsx(baseTooltip.BaseTooltip, { data: tooltipData, top: tooltipTop || 0, left: tooltipLeft || 0, style: {
|
|
148
148
|
transform: 'translate(-50%, -100%)',
|
package/dist/cjs/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.line-chart-module_line-chart__ITM3d{display:flex;flex-direction:column}.line-chart-module_line-chart__ITM3d svg{overflow:visible}.line-chart-module_line-chart__annotation-label-popover__TqNZk,.line-chart-module_line-chart__tooltip__aqcme{background:#fff;padding:.5rem}.line-chart-module_line-chart__tooltip-date__4Dzab{font-weight:700;padding-bottom:10px}.line-chart-module_line-chart__tooltip-row__6A37G{align-items:center;display:flex;justify-content:space-between;padding:4px 0}.line-chart-module_line-chart__tooltip-label__IvnFF{font-weight:500;padding-right:1rem}.line-chart-module_line-chart__annotations-overlay__4nR2p{left:0;overflow:visible;pointer-events:none;position:absolute;top:0}.line-chart-module_line-chart__annotation-label__OmgiT{pointer-events:auto}.line-chart-module_line-chart__annotation-label-trigger-button__mcIb3{align-items:center;background:none;border:none;cursor:pointer;display:flex;justify-content:center;padding:0;pointer-events:auto}.line-chart-module_line-chart__annotation-label-popover__TqNZk{background:#fff;border:none;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);font-size:14px;margin:.5rem;min-width:125px;position:fixed;visibility:hidden}.line-chart-module_line-chart__annotation-label-popover--visible__dE0cV{visibility:visible}.line-chart-module_line-chart__annotation-label-popover--safari__i3NHT{margin:auto;position:static}.line-chart-module_line-chart__annotation-label-popover-header__Owypo{align-items:start;display:flex;flex-direction:row;justify-content:space-between}.line-chart-module_line-chart__annotation-label-popover-content__vtgQt{padding:.5rem}.line-chart-module_line-chart__annotation-label-popover-close-button__i8KUc{align-items:center;background:none;border:none;cursor:pointer;display:flex;height:44px;justify-content:center;padding:0;width:44px}.visx-tooltip-glyph svg{height:10px;width:10px}.pie-chart-module_pie-chart__R12Vh{display:flex;flex-direction:column;overflow:hidden}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9{display:flex;flex-direction:column;text-align:center}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_label__nPqOg{font-size:16px;font-weight:600;margin-bottom:0}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_note__LpBZQ{font-size:14px;margin-top:0}.leaderboard-chart-module_leaderboardChart__zxakP{transition:opacity .3s ease-in-out}.leaderboard-chart-module_leaderboardChart__zxakP.leaderboard-chart-module_loading__-AGv-{opacity:.5}.leaderboard-chart-module_barWithLabelContainer__9RE0U{align-items:center;display:grid;grid-template-columns:1fr;row-gap:6px}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5{grid-template:"overlap" 1fr/1fr}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5>*{grid-area:overlap}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5 .leaderboard-chart-module_label__7ZUu0{padding-left:8px}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_bar__CnJvg{background-color:var(--bar-color,#3858e9);border-radius:var(--bar-border,9999px);height:100%;min-height:6px;transition:width .3s ease-in-out;z-index:-1}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_primaryBar__iybII{--bar-color:var(--primary-color,#3858e9)}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_secondaryBar__A7tLz{--bar-color:var(--secondary-color,#66bdff)}.leaderboard-chart-module_valueContainer__ZlLh4{display:flex;gap:4px;justify-content:flex-end}.leaderboard-chart-module_overlayLabel__pRqSh{align-items:center}.leaderboard-chart-module_emptyState__0dkfy{color:#666;font-size:14px;font-style:italic;padding:32px 16px;text-align:center}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb{font-family:var(--funnel-font-family,"SF Pro Text")}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb.conversion-funnel-chart-module_loading__Kw-iZ{opacity:.6;pointer-events:none}.conversion-funnel-chart-module_main-metric__8mIwV{align-items:baseline;display:flex;gap:8px;margin-bottom:24px}.conversion-funnel-chart-module_main-rate__D93Ub{color:#1e1e1e;font-size:18px}.conversion-funnel-chart-module_change-indicator__QWypV,.conversion-funnel-chart-module_main-rate__D93Ub{font-family:var(--funnel-font-family,"SF Pro Text");font-style:normal;font-weight:500;line-height:20px;margin:0;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_change-indicator__QWypV{color:var(--change-indicator-color,#008a20);font-size:13px}.conversion-funnel-chart-module_funnel-container__RR7xa{align-items:flex-end;display:flex;gap:16px;height:200px;width:100%}.conversion-funnel-chart-module_funnel-step__VIVzt{display:flex;flex:1 1 0;flex-direction:column;height:100%;min-width:0;transition:all .3s ease}.conversion-funnel-chart-module_funnel-step__VIVzt.conversion-funnel-chart-module_blurred__Ax4cu{opacity:.3}.conversion-funnel-chart-module_step-header__bUrZ0{margin-bottom:24px}.conversion-funnel-chart-module_step-label__SCy8F{color:#757575;display:block;font-family:var(--step-font-family,"SF Pro");font-size:12px;font-style:normal;font-weight:400;line-height:16px;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_step-rate__A0irB{color:#1e1e1e;display:block;font-family:var(--step-font-family,"SF Pro");font-size:13px;font-style:normal;font-weight:500;line-height:20px;margin:0}.conversion-funnel-chart-module_bar-container__5Dl5-{align-items:flex-end;background-color:var(--light-background-color,rgba(79,70,229,.08));border-radius:4px;cursor:pointer;display:flex;flex:1;position:relative;transition:all .2s ease}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_selected__W40FY{background-color:var(--light-background-color,rgba(79,70,229,.15))}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_disabled__Reovk{cursor:pointer}.conversion-funnel-chart-module_funnel-bar__tG5m3{background-color:var(--primary-color,#4f46e5);border-radius:4px 4px 0 0;min-height:4px;transition:all .3s ease;width:100%}.conversion-funnel-chart-module_funnel-bar__tG5m3.conversion-funnel-chart-module_selected__W40FY{box-shadow:0 4px 16px rgba(0,0,0,.2);filter:brightness(1.1)}.conversion-funnel-chart-module_tooltip-wrapper__NohPt{align-items:flex-start;background:var(--black-white-white,#fff);border-bottom:1px solid var(--Gray-Gray-5,#dcdcde);border-radius:4px!important;box-shadow:0 1px 3px 0 rgba(0,0,0,.15),0 3px 9px 0 rgba(0,0,0,.12)!important;display:inline-flex;flex-direction:column;gap:4px;justify-content:center;padding:12px!important}.conversion-funnel-chart-module_tooltip-title__hjZr3{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:16px}.conversion-funnel-chart-module_tooltip-content__ocwAP{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:13px;font-style:normal;font-weight:500;line-height:20px}.conversion-funnel-chart-module_empty-state__9c0ps{color:#6b7280;font-size:16px;padding:48px 24px;text-align:center}
|
|
1
|
+
.base-legend-module_legend--horizontal__AELBv{display:flex;flex-direction:row;flex-wrap:wrap;gap:16px}.base-legend-module_legend--vertical__fX8uQ{display:flex;flex-direction:column;gap:8px}.base-legend-module_legend--vertical__fX8uQ.base-legend-module_legend--alignment-start__DEe0w{align-items:flex-start}.base-legend-module_legend--vertical__fX8uQ.base-legend-module_legend--alignment-center__WBKF9{align-items:center}.base-legend-module_legend--vertical__fX8uQ.base-legend-module_legend--alignment-end__JfwMn{align-items:flex-end}.base-legend-module_legend--position-top__8Y73K{position:relative}.base-legend-module_legend--position-top__8Y73K.base-legend-module_legend--alignment-start__DEe0w{justify-content:flex-start}.base-legend-module_legend--position-top__8Y73K.base-legend-module_legend--alignment-center__WBKF9{justify-content:center}.base-legend-module_legend--position-top__8Y73K.base-legend-module_legend--alignment-end__JfwMn{justify-content:flex-end}.base-legend-module_legend--position-bottom__TVM-I{position:relative}.base-legend-module_legend--position-bottom__TVM-I.base-legend-module_legend--alignment-start__DEe0w{justify-content:flex-start}.base-legend-module_legend--position-bottom__TVM-I.base-legend-module_legend--alignment-center__WBKF9{justify-content:center}.base-legend-module_legend--position-bottom__TVM-I.base-legend-module_legend--alignment-end__JfwMn{justify-content:flex-end}.base-legend-module_legend-item__Vflwq{align-items:center;display:flex;font-size:.875rem}.base-legend-module_legend-item-label__2H65K{align-items:center;display:flex;gap:.5rem}.base-legend-module_legend-item-value__DTZlT{font-weight:500}.base-tooltip-module_tooltip__OfX6n{background-color:rgba(0,0,0,.85);border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);color:#fff;font-size:14px;padding:.5rem;pointer-events:none;position:absolute;transform:translate(-50%,-100%)}.bar-chart-module_bar-chart__lmYNi{display:flex;flex-direction:column}.bar-chart-module_bar-chart__lmYNi svg{overflow:visible}.bar-chart-module_bar-chart-legend__vgKKq{margin-top:1rem}.line-chart-module_line-chart__ITM3d{display:flex;flex-direction:column}.line-chart-module_line-chart__ITM3d svg{overflow:visible}.line-chart-module_line-chart__annotation-label-popover__TqNZk,.line-chart-module_line-chart__tooltip__aqcme{background:#fff;padding:.5rem}.line-chart-module_line-chart__tooltip-date__4Dzab{font-weight:700;padding-bottom:10px}.line-chart-module_line-chart__tooltip-row__6A37G{align-items:center;display:flex;justify-content:space-between;padding:4px 0}.line-chart-module_line-chart__tooltip-label__IvnFF{font-weight:500;padding-right:1rem}.line-chart-module_line-chart__annotations-overlay__4nR2p{left:0;overflow:visible;pointer-events:none;position:absolute;top:0}.line-chart-module_line-chart__annotation-label__OmgiT{pointer-events:auto}.line-chart-module_line-chart__annotation-label-trigger-button__mcIb3{align-items:center;background:none;border:none;cursor:pointer;display:flex;justify-content:center;padding:0;pointer-events:auto}.line-chart-module_line-chart__annotation-label-popover__TqNZk{background:#fff;border:none;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);font-size:14px;margin:.5rem;min-width:125px;position:fixed;visibility:hidden}.line-chart-module_line-chart__annotation-label-popover--visible__dE0cV{visibility:visible}.line-chart-module_line-chart__annotation-label-popover--safari__i3NHT{margin:auto;position:static}.line-chart-module_line-chart__annotation-label-popover-header__Owypo{align-items:start;display:flex;flex-direction:row;justify-content:space-between}.line-chart-module_line-chart__annotation-label-popover-content__vtgQt{padding:.5rem}.line-chart-module_line-chart__annotation-label-popover-close-button__i8KUc{align-items:center;background:none;border:none;cursor:pointer;display:flex;height:44px;justify-content:center;padding:0;width:44px}.visx-tooltip-glyph svg{height:10px;width:10px}.pie-chart-module_pie-chart__R12Vh{display:flex;flex-direction:column;overflow:hidden}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9{display:flex;flex-direction:column;text-align:center}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_label__nPqOg{font-size:16px;font-weight:600;margin-bottom:0}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_note__LpBZQ{font-size:14px;margin-top:0}.leaderboard-chart-module_leaderboardChart__zxakP{transition:opacity .3s ease-in-out}.leaderboard-chart-module_leaderboardChart__zxakP.leaderboard-chart-module_loading__-AGv-{opacity:.5}.leaderboard-chart-module_barWithLabelContainer__9RE0U{align-items:center;display:grid;grid-template-columns:1fr;isolation:isolate;row-gap:6px}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5{grid-template:"overlap" 1fr/1fr}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5>*{grid-area:overlap}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5 .leaderboard-chart-module_label__7ZUu0{padding-left:8px}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_bar__CnJvg{background-color:var(--bar-color,#3858e9);border-radius:var(--bar-border,9999px);height:100%;min-height:6px;transition:width .3s ease-in-out;z-index:-1}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_primaryBar__iybII{--bar-color:var(--primary-color,#3858e9)}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_secondaryBar__A7tLz{--bar-color:var(--secondary-color,#66bdff)}.leaderboard-chart-module_valueContainer__ZlLh4{display:flex;gap:4px;justify-content:flex-end}.leaderboard-chart-module_overlayLabel__pRqSh{align-items:center}.leaderboard-chart-module_emptyState__0dkfy{color:#666;font-size:14px;font-style:italic;padding:32px 16px;text-align:center}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb{font-family:var(--funnel-font-family,"SF Pro Text")}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb.conversion-funnel-chart-module_loading__Kw-iZ{opacity:.6;pointer-events:none}.conversion-funnel-chart-module_main-metric__8mIwV{align-items:baseline;display:flex;gap:8px;margin-bottom:24px}.conversion-funnel-chart-module_main-rate__D93Ub{color:#1e1e1e;font-size:18px}.conversion-funnel-chart-module_change-indicator__QWypV,.conversion-funnel-chart-module_main-rate__D93Ub{font-family:var(--funnel-font-family,"SF Pro Text");font-style:normal;font-weight:500;line-height:20px;margin:0;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_change-indicator__QWypV{color:var(--change-indicator-color,#008a20);font-size:13px}.conversion-funnel-chart-module_funnel-container__RR7xa{align-items:flex-end;display:flex;gap:16px;height:200px;width:100%}.conversion-funnel-chart-module_funnel-step__VIVzt{display:flex;flex:1 1 0;flex-direction:column;height:100%;min-width:0;transition:all .3s ease}.conversion-funnel-chart-module_funnel-step__VIVzt.conversion-funnel-chart-module_blurred__Ax4cu{opacity:.3}.conversion-funnel-chart-module_step-header__bUrZ0{margin-bottom:24px}.conversion-funnel-chart-module_step-label__SCy8F{color:#757575;display:block;font-family:var(--step-font-family,"SF Pro");font-size:12px;font-style:normal;font-weight:400;line-height:16px;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_step-rate__A0irB{color:#1e1e1e;display:block;font-family:var(--step-font-family,"SF Pro");font-size:13px;font-style:normal;font-weight:500;line-height:20px;margin:0}.conversion-funnel-chart-module_bar-container__5Dl5-{align-items:flex-end;background-color:var(--light-background-color,rgba(79,70,229,.08));border-radius:4px;cursor:pointer;display:flex;flex:1;position:relative;transition:all .2s ease}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_selected__W40FY{background-color:var(--light-background-color,rgba(79,70,229,.15))}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_disabled__Reovk{cursor:pointer}.conversion-funnel-chart-module_funnel-bar__tG5m3{background-color:var(--primary-color,#4f46e5);border-radius:4px 4px 0 0;min-height:4px;transition:all .3s ease;width:100%}.conversion-funnel-chart-module_funnel-bar__tG5m3.conversion-funnel-chart-module_selected__W40FY{box-shadow:0 4px 16px rgba(0,0,0,.2);filter:brightness(1.1)}.conversion-funnel-chart-module_tooltip-wrapper__NohPt{align-items:flex-start;background:var(--black-white-white,#fff);border-bottom:1px solid var(--Gray-Gray-5,#dcdcde);border-radius:4px!important;box-shadow:0 1px 3px 0 rgba(0,0,0,.15),0 3px 9px 0 rgba(0,0,0,.12)!important;display:inline-flex;flex-direction:column;gap:4px;justify-content:center;padding:12px!important}.conversion-funnel-chart-module_tooltip-title__hjZr3{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:16px}.conversion-funnel-chart-module_tooltip-content__ocwAP{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:13px;font-style:normal;font-weight:500;line-height:20px}.conversion-funnel-chart-module_empty-state__9c0ps{color:#6b7280;font-size:16px;padding:48px 24px;text-align:center}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var numberFormatters = require('@automattic/number-formatters');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Format a percentage value with smart decimal handling.
|
|
7
|
+
* Uses @automattic/number-formatters for consistent formatting.
|
|
8
|
+
* Removes unnecessary trailing zeros and caps at 2 decimal places.
|
|
9
|
+
*
|
|
10
|
+
* @param value - The percentage value (0-100 range)
|
|
11
|
+
* @return Formatted percentage string (e.g., "30%", "30.1%", "30.25%")
|
|
12
|
+
*/
|
|
13
|
+
const formatPercentage = (value) => {
|
|
14
|
+
// Use formatNumber with percentage style, but convert from 0-100 range to 0-1 range
|
|
15
|
+
return numberFormatters.formatNumber(value / 100, {
|
|
16
|
+
numberFormatOptions: {
|
|
17
|
+
style: 'percent',
|
|
18
|
+
minimumFractionDigits: 0,
|
|
19
|
+
maximumFractionDigits: 2,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
exports.formatPercentage = formatPercentage;
|
|
@@ -8,6 +8,7 @@ import 'fast-deep-equal';
|
|
|
8
8
|
import '@visx/xychart';
|
|
9
9
|
import 'date-fns';
|
|
10
10
|
import '@automattic/number-formatters';
|
|
11
|
+
import { formatPercentage } from '../../utils/format-percentage.js';
|
|
11
12
|
import '@visx/text';
|
|
12
13
|
import 'deepmerge';
|
|
13
14
|
import { hexToRgba } from '../../utils/color-utils.js';
|
|
@@ -183,9 +184,9 @@ const ConversionFunnelChart = ({ mainRate, changeIndicator, steps, loading = fal
|
|
|
183
184
|
...style,
|
|
184
185
|
};
|
|
185
186
|
// Default main metric rendering function
|
|
186
|
-
const renderDefaultMainMetric = () => (jsxs(Fragment, { children: [
|
|
187
|
+
const renderDefaultMainMetric = () => (jsxs(Fragment, { children: [jsx("span", { className: styles['main-rate'], children: formatPercentage(mainRate) }), changeIndicator && (jsx("span", { className: styles['change-indicator'], children: changeIndicator }))] }));
|
|
187
188
|
// Default tooltip rendering function
|
|
188
|
-
const renderDefaultTooltip = (step) => (jsxs(Fragment, { children: [jsx("div", { className: styles['tooltip-title'], children: step.label }), jsxs("div", { className: styles['tooltip-content'], children: [step.rate
|
|
189
|
+
const renderDefaultTooltip = (step) => (jsxs(Fragment, { children: [jsx("div", { className: styles['tooltip-title'], children: step.label }), jsxs("div", { className: styles['tooltip-content'], children: [formatPercentage(step.rate), step.count && ` • ${step.count.toLocaleString()} items`] })] }));
|
|
189
190
|
// Handle empty or undefined data
|
|
190
191
|
if (!steps || steps.length === 0) {
|
|
191
192
|
return (jsx("div", { className: clsx(styles.conversionFunnelChart, loading && styles.loading, className), style: chartStyle, children: jsx("div", { className: styles['empty-state'], children: loading ? 'Loading...' : 'No data available' }) }));
|
|
@@ -212,7 +213,7 @@ const ConversionFunnelChart = ({ mainRate, changeIndicator, steps, loading = fal
|
|
|
212
213
|
step,
|
|
213
214
|
index,
|
|
214
215
|
className: styles['step-rate'],
|
|
215
|
-
})) : (
|
|
216
|
+
})) : (jsx("span", { className: styles['step-rate'], children: formatPercentage(step.rate) }))] }), jsx("div", { className: clsx(styles['bar-container'], isClicked && styles.selected, isBlurred && styles.disabled), onClick: stepHandlers.get(step.id)?.onClick, onKeyDown: stepHandlers.get(step.id)?.onKeyDown, role: "button", tabIndex: isBlurred ? -1 : 0, "aria-label": step.label, children: jsx("div", { className: clsx(styles['funnel-bar'], isClicked && styles.selected), style: {
|
|
216
217
|
height: `${barHeight}%`,
|
|
217
218
|
backgroundColor: primaryColor,
|
|
218
219
|
} }) })] }, step.id));
|
|
@@ -10,6 +10,7 @@ import '@visx/tooltip';
|
|
|
10
10
|
import '@visx/xychart';
|
|
11
11
|
import 'date-fns';
|
|
12
12
|
import { formatMetricValue } from '../../utils/format-metric-value.js';
|
|
13
|
+
import '@automattic/number-formatters';
|
|
13
14
|
import '@visx/text';
|
|
14
15
|
import 'deepmerge';
|
|
15
16
|
import '@visx/scale';
|
|
@@ -6,6 +6,7 @@ import '@visx/tooltip';
|
|
|
6
6
|
import '@visx/xychart';
|
|
7
7
|
import 'date-fns';
|
|
8
8
|
import '@automattic/number-formatters';
|
|
9
|
+
import { formatPercentage } from '../../../utils/format-percentage.js';
|
|
9
10
|
import '@visx/text';
|
|
10
11
|
import { getItemShapeStyles, getSeriesStroke } from '../../../utils/get-styles.js';
|
|
11
12
|
import 'deepmerge';
|
|
@@ -23,7 +24,7 @@ function formatPointValue(point, showValues) {
|
|
|
23
24
|
return '';
|
|
24
25
|
}
|
|
25
26
|
if ('percentage' in point) {
|
|
26
|
-
return
|
|
27
|
+
return formatPercentage(point.percentage);
|
|
27
28
|
}
|
|
28
29
|
else if ('value' in point) {
|
|
29
30
|
return point.value.toString();
|
|
@@ -14,7 +14,7 @@ import { useGlobalChartsTheme } from '../../providers/chart-context/hooks/use-gl
|
|
|
14
14
|
import { attachSubComponents } from '../../utils/create-composition.js';
|
|
15
15
|
import 'date-fns';
|
|
16
16
|
import '@automattic/number-formatters';
|
|
17
|
-
import '@visx/text';
|
|
17
|
+
import { getStringWidth } from '@visx/text';
|
|
18
18
|
import 'deepmerge';
|
|
19
19
|
import '@visx/scale';
|
|
20
20
|
import { useElementHeight } from '../../hooks/use-element-height.js';
|
|
@@ -56,7 +56,7 @@ const validateData = (data) => {
|
|
|
56
56
|
* @param {PieChartProps} props - Component props
|
|
57
57
|
* @return {JSX.Element} The rendered chart component
|
|
58
58
|
*/
|
|
59
|
-
const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false, className, showLegend = false, legendOrientation = 'horizontal', legendPosition = 'bottom', legendAlignment = 'center', legendShape = 'circle', size, thickness = 1, padding = 20, gapScale = 0, cornerScale = 0, children = null, }) => {
|
|
59
|
+
const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false, className, showLegend = false, legendOrientation = 'horizontal', legendPosition = 'bottom', legendAlignment = 'center', legendShape = 'circle', size, thickness = 1, padding = 20, gapScale = 0, cornerScale = 0, showLabels = true, children = null, }) => {
|
|
60
60
|
const providerTheme = useGlobalChartsTheme();
|
|
61
61
|
const chartId = useChartId(providedChartId);
|
|
62
62
|
const [legendRef, legendHeight] = useElementHeight();
|
|
@@ -134,11 +134,11 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
134
134
|
}
|
|
135
135
|
// Estimate text width more accurately for background sizing
|
|
136
136
|
const fontSize = 12;
|
|
137
|
-
const estimatedTextWidth = arc.data.label
|
|
137
|
+
const estimatedTextWidth = getStringWidth(arc.data.label, { fontSize });
|
|
138
138
|
const labelPadding = 6;
|
|
139
139
|
const backgroundWidth = estimatedTextWidth + labelPadding * 2;
|
|
140
140
|
const backgroundHeight = fontSize + labelPadding * 2;
|
|
141
|
-
return (jsxs("g", { children: [jsx("path", { ...pathProps }), hasSpaceForLabel && (jsxs("g", { children: [providerTheme.labelBackgroundColor && (jsx("rect", { x: centroidX - backgroundWidth / 2, y: centroidY - backgroundHeight / 2, width: backgroundWidth, height: backgroundHeight, fill: providerTheme.labelBackgroundColor, rx: 4, ry: 4, pointerEvents: "none" })), jsx("text", { x: centroidX, y: centroidY, dy: ".33em", fill: providerTheme.labelTextColor || '#333', fontSize: fontSize, textAnchor: "middle", pointerEvents: "none", children: arc.data.label })] }))] }, `arc-${index}`));
|
|
141
|
+
return (jsxs("g", { children: [jsx("path", { ...pathProps }), showLabels && hasSpaceForLabel && (jsxs("g", { children: [providerTheme.labelBackgroundColor && (jsx("rect", { x: centroidX - backgroundWidth / 2, y: centroidY - backgroundHeight / 2, width: backgroundWidth, height: backgroundHeight, fill: providerTheme.labelBackgroundColor, rx: 4, ry: 4, pointerEvents: "none" })), jsx("text", { x: centroidX, y: centroidY, dy: ".33em", fill: providerTheme.labelTextColor || '#333', fontSize: fontSize, textAnchor: "middle", pointerEvents: "none", children: arc.data.label })] }))] }, `arc-${index}`));
|
|
142
142
|
});
|
|
143
143
|
} }), svgChildren] }) }), showLegend && (jsx(Legend, { orientation: legendOrientation, position: legendPosition, alignment: legendAlignment, className: styles['pie-chart-legend'], shape: legendShape, ref: legendRef, chartId: chartId })), withTooltips && tooltipOpen && tooltipData && (jsx(BaseTooltip, { data: tooltipData, top: tooltipTop || 0, left: tooltipLeft || 0, style: {
|
|
144
144
|
transform: 'translate(-50%, -100%)',
|
package/dist/mjs/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.line-chart-module_line-chart__ITM3d{display:flex;flex-direction:column}.line-chart-module_line-chart__ITM3d svg{overflow:visible}.line-chart-module_line-chart__annotation-label-popover__TqNZk,.line-chart-module_line-chart__tooltip__aqcme{background:#fff;padding:.5rem}.line-chart-module_line-chart__tooltip-date__4Dzab{font-weight:700;padding-bottom:10px}.line-chart-module_line-chart__tooltip-row__6A37G{align-items:center;display:flex;justify-content:space-between;padding:4px 0}.line-chart-module_line-chart__tooltip-label__IvnFF{font-weight:500;padding-right:1rem}.line-chart-module_line-chart__annotations-overlay__4nR2p{left:0;overflow:visible;pointer-events:none;position:absolute;top:0}.line-chart-module_line-chart__annotation-label__OmgiT{pointer-events:auto}.line-chart-module_line-chart__annotation-label-trigger-button__mcIb3{align-items:center;background:none;border:none;cursor:pointer;display:flex;justify-content:center;padding:0;pointer-events:auto}.line-chart-module_line-chart__annotation-label-popover__TqNZk{background:#fff;border:none;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);font-size:14px;margin:.5rem;min-width:125px;position:fixed;visibility:hidden}.line-chart-module_line-chart__annotation-label-popover--visible__dE0cV{visibility:visible}.line-chart-module_line-chart__annotation-label-popover--safari__i3NHT{margin:auto;position:static}.line-chart-module_line-chart__annotation-label-popover-header__Owypo{align-items:start;display:flex;flex-direction:row;justify-content:space-between}.line-chart-module_line-chart__annotation-label-popover-content__vtgQt{padding:.5rem}.line-chart-module_line-chart__annotation-label-popover-close-button__i8KUc{align-items:center;background:none;border:none;cursor:pointer;display:flex;height:44px;justify-content:center;padding:0;width:44px}.visx-tooltip-glyph svg{height:10px;width:10px}.pie-chart-module_pie-chart__R12Vh{display:flex;flex-direction:column;overflow:hidden}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9{display:flex;flex-direction:column;text-align:center}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_label__nPqOg{font-size:16px;font-weight:600;margin-bottom:0}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_note__LpBZQ{font-size:14px;margin-top:0}.leaderboard-chart-module_leaderboardChart__zxakP{transition:opacity .3s ease-in-out}.leaderboard-chart-module_leaderboardChart__zxakP.leaderboard-chart-module_loading__-AGv-{opacity:.5}.leaderboard-chart-module_barWithLabelContainer__9RE0U{align-items:center;display:grid;grid-template-columns:1fr;row-gap:6px}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5{grid-template:"overlap" 1fr/1fr}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5>*{grid-area:overlap}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5 .leaderboard-chart-module_label__7ZUu0{padding-left:8px}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_bar__CnJvg{background-color:var(--bar-color,#3858e9);border-radius:var(--bar-border,9999px);height:100%;min-height:6px;transition:width .3s ease-in-out;z-index:-1}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_primaryBar__iybII{--bar-color:var(--primary-color,#3858e9)}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_secondaryBar__A7tLz{--bar-color:var(--secondary-color,#66bdff)}.leaderboard-chart-module_valueContainer__ZlLh4{display:flex;gap:4px;justify-content:flex-end}.leaderboard-chart-module_overlayLabel__pRqSh{align-items:center}.leaderboard-chart-module_emptyState__0dkfy{color:#666;font-size:14px;font-style:italic;padding:32px 16px;text-align:center}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb{font-family:var(--funnel-font-family,"SF Pro Text")}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb.conversion-funnel-chart-module_loading__Kw-iZ{opacity:.6;pointer-events:none}.conversion-funnel-chart-module_main-metric__8mIwV{align-items:baseline;display:flex;gap:8px;margin-bottom:24px}.conversion-funnel-chart-module_main-rate__D93Ub{color:#1e1e1e;font-size:18px}.conversion-funnel-chart-module_change-indicator__QWypV,.conversion-funnel-chart-module_main-rate__D93Ub{font-family:var(--funnel-font-family,"SF Pro Text");font-style:normal;font-weight:500;line-height:20px;margin:0;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_change-indicator__QWypV{color:var(--change-indicator-color,#008a20);font-size:13px}.conversion-funnel-chart-module_funnel-container__RR7xa{align-items:flex-end;display:flex;gap:16px;height:200px;width:100%}.conversion-funnel-chart-module_funnel-step__VIVzt{display:flex;flex:1 1 0;flex-direction:column;height:100%;min-width:0;transition:all .3s ease}.conversion-funnel-chart-module_funnel-step__VIVzt.conversion-funnel-chart-module_blurred__Ax4cu{opacity:.3}.conversion-funnel-chart-module_step-header__bUrZ0{margin-bottom:24px}.conversion-funnel-chart-module_step-label__SCy8F{color:#757575;display:block;font-family:var(--step-font-family,"SF Pro");font-size:12px;font-style:normal;font-weight:400;line-height:16px;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_step-rate__A0irB{color:#1e1e1e;display:block;font-family:var(--step-font-family,"SF Pro");font-size:13px;font-style:normal;font-weight:500;line-height:20px;margin:0}.conversion-funnel-chart-module_bar-container__5Dl5-{align-items:flex-end;background-color:var(--light-background-color,rgba(79,70,229,.08));border-radius:4px;cursor:pointer;display:flex;flex:1;position:relative;transition:all .2s ease}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_selected__W40FY{background-color:var(--light-background-color,rgba(79,70,229,.15))}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_disabled__Reovk{cursor:pointer}.conversion-funnel-chart-module_funnel-bar__tG5m3{background-color:var(--primary-color,#4f46e5);border-radius:4px 4px 0 0;min-height:4px;transition:all .3s ease;width:100%}.conversion-funnel-chart-module_funnel-bar__tG5m3.conversion-funnel-chart-module_selected__W40FY{box-shadow:0 4px 16px rgba(0,0,0,.2);filter:brightness(1.1)}.conversion-funnel-chart-module_tooltip-wrapper__NohPt{align-items:flex-start;background:var(--black-white-white,#fff);border-bottom:1px solid var(--Gray-Gray-5,#dcdcde);border-radius:4px!important;box-shadow:0 1px 3px 0 rgba(0,0,0,.15),0 3px 9px 0 rgba(0,0,0,.12)!important;display:inline-flex;flex-direction:column;gap:4px;justify-content:center;padding:12px!important}.conversion-funnel-chart-module_tooltip-title__hjZr3{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:16px}.conversion-funnel-chart-module_tooltip-content__ocwAP{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:13px;font-style:normal;font-weight:500;line-height:20px}.conversion-funnel-chart-module_empty-state__9c0ps{color:#6b7280;font-size:16px;padding:48px 24px;text-align:center}
|
|
1
|
+
.base-legend-module_legend--horizontal__AELBv{display:flex;flex-direction:row;flex-wrap:wrap;gap:16px}.base-legend-module_legend--vertical__fX8uQ{display:flex;flex-direction:column;gap:8px}.base-legend-module_legend--vertical__fX8uQ.base-legend-module_legend--alignment-start__DEe0w{align-items:flex-start}.base-legend-module_legend--vertical__fX8uQ.base-legend-module_legend--alignment-center__WBKF9{align-items:center}.base-legend-module_legend--vertical__fX8uQ.base-legend-module_legend--alignment-end__JfwMn{align-items:flex-end}.base-legend-module_legend--position-top__8Y73K{position:relative}.base-legend-module_legend--position-top__8Y73K.base-legend-module_legend--alignment-start__DEe0w{justify-content:flex-start}.base-legend-module_legend--position-top__8Y73K.base-legend-module_legend--alignment-center__WBKF9{justify-content:center}.base-legend-module_legend--position-top__8Y73K.base-legend-module_legend--alignment-end__JfwMn{justify-content:flex-end}.base-legend-module_legend--position-bottom__TVM-I{position:relative}.base-legend-module_legend--position-bottom__TVM-I.base-legend-module_legend--alignment-start__DEe0w{justify-content:flex-start}.base-legend-module_legend--position-bottom__TVM-I.base-legend-module_legend--alignment-center__WBKF9{justify-content:center}.base-legend-module_legend--position-bottom__TVM-I.base-legend-module_legend--alignment-end__JfwMn{justify-content:flex-end}.base-legend-module_legend-item__Vflwq{align-items:center;display:flex;font-size:.875rem}.base-legend-module_legend-item-label__2H65K{align-items:center;display:flex;gap:.5rem}.base-legend-module_legend-item-value__DTZlT{font-weight:500}.base-tooltip-module_tooltip__OfX6n{background-color:rgba(0,0,0,.85);border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);color:#fff;font-size:14px;padding:.5rem;pointer-events:none;position:absolute;transform:translate(-50%,-100%)}.bar-chart-module_bar-chart__lmYNi{display:flex;flex-direction:column}.bar-chart-module_bar-chart__lmYNi svg{overflow:visible}.bar-chart-module_bar-chart-legend__vgKKq{margin-top:1rem}.line-chart-module_line-chart__ITM3d{display:flex;flex-direction:column}.line-chart-module_line-chart__ITM3d svg{overflow:visible}.line-chart-module_line-chart__annotation-label-popover__TqNZk,.line-chart-module_line-chart__tooltip__aqcme{background:#fff;padding:.5rem}.line-chart-module_line-chart__tooltip-date__4Dzab{font-weight:700;padding-bottom:10px}.line-chart-module_line-chart__tooltip-row__6A37G{align-items:center;display:flex;justify-content:space-between;padding:4px 0}.line-chart-module_line-chart__tooltip-label__IvnFF{font-weight:500;padding-right:1rem}.line-chart-module_line-chart__annotations-overlay__4nR2p{left:0;overflow:visible;pointer-events:none;position:absolute;top:0}.line-chart-module_line-chart__annotation-label__OmgiT{pointer-events:auto}.line-chart-module_line-chart__annotation-label-trigger-button__mcIb3{align-items:center;background:none;border:none;cursor:pointer;display:flex;justify-content:center;padding:0;pointer-events:auto}.line-chart-module_line-chart__annotation-label-popover__TqNZk{background:#fff;border:none;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);font-size:14px;margin:.5rem;min-width:125px;position:fixed;visibility:hidden}.line-chart-module_line-chart__annotation-label-popover--visible__dE0cV{visibility:visible}.line-chart-module_line-chart__annotation-label-popover--safari__i3NHT{margin:auto;position:static}.line-chart-module_line-chart__annotation-label-popover-header__Owypo{align-items:start;display:flex;flex-direction:row;justify-content:space-between}.line-chart-module_line-chart__annotation-label-popover-content__vtgQt{padding:.5rem}.line-chart-module_line-chart__annotation-label-popover-close-button__i8KUc{align-items:center;background:none;border:none;cursor:pointer;display:flex;height:44px;justify-content:center;padding:0;width:44px}.visx-tooltip-glyph svg{height:10px;width:10px}.pie-chart-module_pie-chart__R12Vh{display:flex;flex-direction:column;overflow:hidden}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9{display:flex;flex-direction:column;text-align:center}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_label__nPqOg{font-size:16px;font-weight:600;margin-bottom:0}.pie-semi-circle-chart-module_pie-semi-circle-chart__r5jk9 .pie-semi-circle-chart-module_note__LpBZQ{font-size:14px;margin-top:0}.leaderboard-chart-module_leaderboardChart__zxakP{transition:opacity .3s ease-in-out}.leaderboard-chart-module_leaderboardChart__zxakP.leaderboard-chart-module_loading__-AGv-{opacity:.5}.leaderboard-chart-module_barWithLabelContainer__9RE0U{align-items:center;display:grid;grid-template-columns:1fr;isolation:isolate;row-gap:6px}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5{grid-template:"overlap" 1fr/1fr}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5>*{grid-area:overlap}.leaderboard-chart-module_barWithLabelContainer__9RE0U.leaderboard-chart-module_is-overlay__Fqdi5 .leaderboard-chart-module_label__7ZUu0{padding-left:8px}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_bar__CnJvg{background-color:var(--bar-color,#3858e9);border-radius:var(--bar-border,9999px);height:100%;min-height:6px;transition:width .3s ease-in-out;z-index:-1}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_primaryBar__iybII{--bar-color:var(--primary-color,#3858e9)}.leaderboard-chart-module_barWithLabelContainer__9RE0U .leaderboard-chart-module_secondaryBar__A7tLz{--bar-color:var(--secondary-color,#66bdff)}.leaderboard-chart-module_valueContainer__ZlLh4{display:flex;gap:4px;justify-content:flex-end}.leaderboard-chart-module_overlayLabel__pRqSh{align-items:center}.leaderboard-chart-module_emptyState__0dkfy{color:#666;font-size:14px;font-style:italic;padding:32px 16px;text-align:center}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb{font-family:var(--funnel-font-family,"SF Pro Text")}.conversion-funnel-chart-module_conversionFunnelChart__-9Qsb.conversion-funnel-chart-module_loading__Kw-iZ{opacity:.6;pointer-events:none}.conversion-funnel-chart-module_main-metric__8mIwV{align-items:baseline;display:flex;gap:8px;margin-bottom:24px}.conversion-funnel-chart-module_main-rate__D93Ub{color:#1e1e1e;font-size:18px}.conversion-funnel-chart-module_change-indicator__QWypV,.conversion-funnel-chart-module_main-rate__D93Ub{font-family:var(--funnel-font-family,"SF Pro Text");font-style:normal;font-weight:500;line-height:20px;margin:0;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_change-indicator__QWypV{color:var(--change-indicator-color,#008a20);font-size:13px}.conversion-funnel-chart-module_funnel-container__RR7xa{align-items:flex-end;display:flex;gap:16px;height:200px;width:100%}.conversion-funnel-chart-module_funnel-step__VIVzt{display:flex;flex:1 1 0;flex-direction:column;height:100%;min-width:0;transition:all .3s ease}.conversion-funnel-chart-module_funnel-step__VIVzt.conversion-funnel-chart-module_blurred__Ax4cu{opacity:.3}.conversion-funnel-chart-module_step-header__bUrZ0{margin-bottom:24px}.conversion-funnel-chart-module_step-label__SCy8F{color:#757575;display:block;font-family:var(--step-font-family,"SF Pro");font-size:12px;font-style:normal;font-weight:400;line-height:16px;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis}.conversion-funnel-chart-module_step-rate__A0irB{color:#1e1e1e;display:block;font-family:var(--step-font-family,"SF Pro");font-size:13px;font-style:normal;font-weight:500;line-height:20px;margin:0}.conversion-funnel-chart-module_bar-container__5Dl5-{align-items:flex-end;background-color:var(--light-background-color,rgba(79,70,229,.08));border-radius:4px;cursor:pointer;display:flex;flex:1;position:relative;transition:all .2s ease}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_selected__W40FY{background-color:var(--light-background-color,rgba(79,70,229,.15))}.conversion-funnel-chart-module_bar-container__5Dl5-.conversion-funnel-chart-module_disabled__Reovk{cursor:pointer}.conversion-funnel-chart-module_funnel-bar__tG5m3{background-color:var(--primary-color,#4f46e5);border-radius:4px 4px 0 0;min-height:4px;transition:all .3s ease;width:100%}.conversion-funnel-chart-module_funnel-bar__tG5m3.conversion-funnel-chart-module_selected__W40FY{box-shadow:0 4px 16px rgba(0,0,0,.2);filter:brightness(1.1)}.conversion-funnel-chart-module_tooltip-wrapper__NohPt{align-items:flex-start;background:var(--black-white-white,#fff);border-bottom:1px solid var(--Gray-Gray-5,#dcdcde);border-radius:4px!important;box-shadow:0 1px 3px 0 rgba(0,0,0,.15),0 3px 9px 0 rgba(0,0,0,.12)!important;display:inline-flex;flex-direction:column;gap:4px;justify-content:center;padding:12px!important}.conversion-funnel-chart-module_tooltip-title__hjZr3{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:16px}.conversion-funnel-chart-module_tooltip-content__ocwAP{color:#1e1e1e;font-family:SF Pro,sans-serif;font-size:13px;font-style:normal;font-weight:500;line-height:20px}.conversion-funnel-chart-module_empty-state__9c0ps{color:#6b7280;font-size:16px;padding:48px 24px;text-align:center}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { formatNumber } from '@automattic/number-formatters';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Format a percentage value with smart decimal handling.
|
|
5
|
+
* Uses @automattic/number-formatters for consistent formatting.
|
|
6
|
+
* Removes unnecessary trailing zeros and caps at 2 decimal places.
|
|
7
|
+
*
|
|
8
|
+
* @param value - The percentage value (0-100 range)
|
|
9
|
+
* @return Formatted percentage string (e.g., "30%", "30.1%", "30.25%")
|
|
10
|
+
*/
|
|
11
|
+
const formatPercentage = (value) => {
|
|
12
|
+
// Use formatNumber with percentage style, but convert from 0-100 range to 0-1 range
|
|
13
|
+
return formatNumber(value / 100, {
|
|
14
|
+
numberFormatOptions: {
|
|
15
|
+
style: 'percent',
|
|
16
|
+
minimumFractionDigits: 0,
|
|
17
|
+
maximumFractionDigits: 2,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { formatPercentage };
|
|
@@ -28,6 +28,10 @@ interface PieChartProps extends BaseChartProps<DataPointPercentage[]> {
|
|
|
28
28
|
* A value between 0 and 1, where 0 means no corner radius.
|
|
29
29
|
*/
|
|
30
30
|
cornerScale?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Whether to show labels on pie segments. Defaults to true.
|
|
33
|
+
*/
|
|
34
|
+
showLabels?: boolean;
|
|
31
35
|
/**
|
|
32
36
|
* Use the children prop to render additional elements on the chart.
|
|
33
37
|
*/
|
package/package.json
CHANGED