@automattic/charts 1.3.1 → 1.4.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 CHANGED
@@ -5,6 +5,16 @@ 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
+ ## [1.4.0] - 2026-05-14
9
+ ### Changed
10
+ - Charts: expose a source-side `./style.css` alias so monorepo consumers can resolve the import without a prior build. [#48682]
11
+ - Charts: expose tickValues on AxisOptions and nice on ScaleOptions so callers can force exact axis ticks. [#48722]
12
+ - Update package dependencies. [#48695]
13
+ - Update package dependencies. [#48696]
14
+
15
+ ### Removed
16
+ - Charts: remove the `useTooltipPortalRelocator` hook and the `portalContainer` prop on `GlobalChartsProvider`. The relocator (added in #47118 / 0.56.4) caused tooltip glyphs and the tooltip box to drift away from the chart line by exactly the page scroll offset on scrolled pages. [#48617]
17
+
8
18
  ## [1.3.1] - 2026-05-11
9
19
  ### Changed
10
20
  - Update dependencies. [#43811]
@@ -820,6 +830,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
820
830
  - Fixed lints following ESLint rule changes for TS [#40584]
821
831
  - Fixing a bug in Chart storybook data. [#40640]
822
832
 
833
+ [1.4.0]: https://github.com/Automattic/charts/compare/v1.3.1...v1.4.0
823
834
  [1.3.1]: https://github.com/Automattic/charts/compare/v1.3.0...v1.3.1
824
835
  [1.3.0]: https://github.com/Automattic/charts/compare/v1.2.1...v1.3.0
825
836
  [1.2.1]: https://github.com/Automattic/charts/compare/v1.2.0...v1.2.1
package/dist/index.cjs CHANGED
@@ -495,103 +495,6 @@ var useSingleChartContext = useChartInstanceContext;
495
495
  var _d3color = require('@visx/vendor/d3-color');
496
496
 
497
497
 
498
- // src/hooks/use-tooltip-portal-relocator.ts
499
-
500
-
501
- // src/hooks/use-tooltip-portal-relocator.module.scss
502
- var use_tooltip_portal_relocator_module_default = {
503
- "relocatedPortal": "a8ccharts-jCw5dQ"
504
- };
505
-
506
- // src/hooks/use-tooltip-portal-relocator.ts
507
- function isVisxPortalNode(node2) {
508
- return node2 instanceof HTMLDivElement && node2.parentElement === document.body && !node2.id && !node2.className && node2.querySelector(".visx-tooltip") !== null;
509
- }
510
- var patchRefCount = 0;
511
- var origRemoveChild = null;
512
- var patchedRemoveChild = null;
513
- var relocatedNodes = /* @__PURE__ */ new WeakSet();
514
- function installRemoveChildPatch() {
515
- if (patchRefCount++ > 0) {
516
- return;
517
- }
518
- origRemoveChild = document.body.removeChild;
519
- patchedRemoveChild = function(child) {
520
- if (relocatedNodes.has(child) && child.parentNode !== this) {
521
- relocatedNodes.delete(child);
522
- _optionalChain([child, 'access', _2 => _2.parentNode, 'optionalAccess', _3 => _3.removeChild, 'call', _4 => _4(child)]);
523
- return child;
524
- }
525
- return origRemoveChild.call(this, child);
526
- };
527
- document.body.removeChild = patchedRemoveChild;
528
- }
529
- function uninstallRemoveChildPatch() {
530
- if (--patchRefCount > 0) {
531
- return;
532
- }
533
- if (document.body.removeChild === patchedRemoveChild) {
534
- document.body.removeChild = origRemoveChild;
535
- }
536
- origRemoveChild = null;
537
- patchedRemoveChild = null;
538
- }
539
- function useTooltipPortalRelocator(containerRef) {
540
- _react.useEffect.call(void 0, () => {
541
- const container = _optionalChain([containerRef, 'optionalAccess', _5 => _5.current]);
542
- if (!container) {
543
- return;
544
- }
545
- const instanceNodes = /* @__PURE__ */ new Set();
546
- const relocateNode = (node2) => {
547
- if (!isVisxPortalNode(node2)) {
548
- return;
549
- }
550
- node2.style.opacity = "0";
551
- node2.classList.add(use_tooltip_portal_relocator_module_default.relocatedPortal);
552
- const { activeElement } = node2.ownerDocument;
553
- const focusedElement = activeElement instanceof HTMLElement && node2.contains(activeElement) ? activeElement : null;
554
- container.insertBefore(node2, container.firstChild);
555
- relocatedNodes.add(node2);
556
- instanceNodes.add(node2);
557
- if (focusedElement) {
558
- focusedElement.focus();
559
- }
560
- requestAnimationFrame(() => {
561
- requestAnimationFrame(() => {
562
- node2.style.opacity = "";
563
- });
564
- });
565
- };
566
- installRemoveChildPatch();
567
- for (const child of Array.from(document.body.children)) {
568
- relocateNode(child);
569
- }
570
- const observer = new MutationObserver((mutations) => {
571
- for (const mutation of mutations) {
572
- for (const node2 of mutation.addedNodes) {
573
- relocateNode(node2);
574
- }
575
- }
576
- });
577
- observer.observe(document.body, { childList: true });
578
- return () => {
579
- observer.disconnect();
580
- for (const node2 of instanceNodes) {
581
- if (node2 instanceof HTMLElement) {
582
- node2.classList.remove(use_tooltip_portal_relocator_module_default.relocatedPortal);
583
- }
584
- if (node2.parentNode === container) {
585
- document.body.appendChild(node2);
586
- }
587
- relocatedNodes.delete(node2);
588
- }
589
- instanceNodes.clear();
590
- uninstallRemoveChildPatch();
591
- };
592
- }, [containerRef]);
593
- }
594
-
595
498
  // src/utils/create-composition.ts
596
499
  function attachSubComponents(Chart2, subComponents) {
597
500
  return Object.assign(Chart2, subComponents);
@@ -722,14 +625,14 @@ var getLongestTickWidth = (ticks, formatTick, labelStyle) => {
722
625
 
723
626
  // src/utils/get-styles.ts
724
627
  function getSeriesLineStyles(seriesData, index, providerTheme) {
725
- const themeSemanticLineStyle = _optionalChain([providerTheme, 'optionalAccess', _6 => _6.lineChart, 'optionalAccess', _7 => _7.lineStyles, 'optionalAccess', _8 => _8[_optionalChain([seriesData, 'access', _9 => _9.options, 'optionalAccess', _10 => _10.type])]]);
726
- const themeSeriesLineStyle = _optionalChain([providerTheme, 'optionalAccess', _11 => _11.seriesLineStyles, 'optionalAccess', _12 => _12[index % providerTheme.seriesLineStyles.length]]);
727
- return _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([seriesData, 'access', _13 => _13.options, 'optionalAccess', _14 => _14.seriesLineStyle]), () => ( themeSemanticLineStyle)), () => ( themeSeriesLineStyle)), () => ( {}));
628
+ const themeSemanticLineStyle = _optionalChain([providerTheme, 'optionalAccess', _2 => _2.lineChart, 'optionalAccess', _3 => _3.lineStyles, 'optionalAccess', _4 => _4[_optionalChain([seriesData, 'access', _5 => _5.options, 'optionalAccess', _6 => _6.type])]]);
629
+ const themeSeriesLineStyle = _optionalChain([providerTheme, 'optionalAccess', _7 => _7.seriesLineStyles, 'optionalAccess', _8 => _8[index % providerTheme.seriesLineStyles.length]]);
630
+ return _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([seriesData, 'access', _9 => _9.options, 'optionalAccess', _10 => _10.seriesLineStyle]), () => ( themeSemanticLineStyle)), () => ( themeSeriesLineStyle)), () => ( {}));
728
631
  }
729
632
  function getItemShapeStyles(series, index, theme, legendShape) {
730
- const seriesShapeStyles = _nullishCoalesce(_optionalChain([series, 'access', _15 => _15.options, 'optionalAccess', _16 => _16.legendShapeStyle]), () => ( {}));
633
+ const seriesShapeStyles = _nullishCoalesce(_optionalChain([series, 'access', _11 => _11.options, 'optionalAccess', _12 => _12.legendShapeStyle]), () => ( {}));
731
634
  const lineStyles = legendShape === "line" ? getSeriesLineStyles(series, index, theme) : {};
732
- const themeShapeStyles = _optionalChain([theme, 'access', _17 => _17.legend, 'optionalAccess', _18 => _18.shapeStyles, 'optionalAccess', _19 => _19[index]]);
635
+ const themeShapeStyles = _optionalChain([theme, 'access', _13 => _13.legend, 'optionalAccess', _14 => _14.shapeStyles, 'optionalAccess', _15 => _15[index]]);
733
636
  const itemShapeStyles = {
734
637
  ...seriesShapeStyles,
735
638
  ...lineStyles
@@ -1096,13 +999,11 @@ var _jsxruntime = require('react/jsx-runtime');
1096
999
  var GlobalChartsContext = /* @__PURE__ */ _react.createContext.call(void 0, null);
1097
1000
  var GlobalChartsProvider = ({
1098
1001
  children,
1099
- theme,
1100
- portalContainer
1002
+ theme
1101
1003
  }) => {
1102
1004
  const [charts, setCharts] = _react.useState.call(void 0, () => /* @__PURE__ */ new Map());
1103
1005
  const [hiddenSeries, setHiddenSeries] = _react.useState.call(void 0, () => /* @__PURE__ */ new Map());
1104
1006
  const wrapperRef = _react.useRef.call(void 0, null);
1105
- useTooltipPortalRelocator(_nullishCoalesce(portalContainer, () => ( wrapperRef)));
1106
1007
  const providerTheme = _react.useMemo.call(void 0, () => {
1107
1008
  return theme ? mergeThemes(defaultTheme, theme) : defaultTheme;
1108
1009
  }, [theme]);
@@ -1202,12 +1103,12 @@ var GlobalChartsProvider = ({
1202
1103
  const isPointPercentageData = data && typeof data === "object" && "value" in data && typeof data.value === "number" && !("data" in data);
1203
1104
  return {
1204
1105
  color: resolveColor({
1205
- group: _optionalChain([data, 'optionalAccess', _20 => _20.group]),
1106
+ group: _optionalChain([data, 'optionalAccess', _16 => _16.group]),
1206
1107
  index,
1207
- overrideColor: overrideColor || isSeriesData && _optionalChain([data, 'optionalAccess', _21 => _21.options, 'optionalAccess', _22 => _22.stroke]) || isPointPercentageData && _optionalChain([data, 'optionalAccess', _23 => _23.color])
1108
+ overrideColor: overrideColor || isSeriesData && _optionalChain([data, 'optionalAccess', _17 => _17.options, 'optionalAccess', _18 => _18.stroke]) || isPointPercentageData && _optionalChain([data, 'optionalAccess', _19 => _19.color])
1208
1109
  }),
1209
1110
  lineStyles: isSeriesData ? getSeriesLineStyles(data, index, providerTheme) : {},
1210
- glyph: _optionalChain([providerTheme, 'access', _24 => _24.glyphs, 'optionalAccess', _25 => _25[index]]),
1111
+ glyph: _optionalChain([providerTheme, 'access', _20 => _20.glyphs, 'optionalAccess', _21 => _21[index]]),
1211
1112
  shapeStyles: isSeriesData ? getItemShapeStyles(data, index, providerTheme, legendShape) : {}
1212
1113
  };
1213
1114
  }, [providerTheme, resolveColor]);
@@ -1298,7 +1199,7 @@ var useDeepMemo = (value) => {
1298
1199
  var useXYChartTheme = (data) => {
1299
1200
  const theme = useGlobalChartsTheme();
1300
1201
  return _react.useMemo.call(void 0, () => {
1301
- const seriesColors = (_nullishCoalesce(data, () => ( []))).map((series) => _optionalChain([series, 'access', _26 => _26.options, 'optionalAccess', _27 => _27.stroke])).filter((color) => Boolean(color));
1202
+ const seriesColors = (_nullishCoalesce(data, () => ( []))).map((series) => _optionalChain([series, 'access', _22 => _22.options, 'optionalAccess', _23 => _23.stroke])).filter((color) => Boolean(color));
1302
1203
  return _xychart.buildChartTheme.call(void 0, {
1303
1204
  ...theme,
1304
1205
  colors: [...seriesColors, ..._nullishCoalesce(theme.colors, () => ( []))]
@@ -1310,7 +1211,7 @@ var useXYChartTheme = (data) => {
1310
1211
 
1311
1212
  var useChartDataTransform = (data) => {
1312
1213
  return _react.useMemo.call(void 0, () => {
1313
- const firstPoint = _optionalChain([data, 'optionalAccess', _28 => _28[0], 'optionalAccess', _29 => _29.data, 'optionalAccess', _30 => _30[0]]);
1214
+ const firstPoint = _optionalChain([data, 'optionalAccess', _24 => _24[0], 'optionalAccess', _25 => _25.data, 'optionalAccess', _26 => _26[0]]);
1314
1215
  const hasDateProperties = firstPoint && ("date" in firstPoint || "dateString" in firstPoint);
1315
1216
  if (!hasDateProperties) {
1316
1217
  return data;
@@ -1348,9 +1249,9 @@ var DEFAULT_FONT_SIZE = 12;
1348
1249
  var DEFAULT_TICK_LENGTH = 8;
1349
1250
  var DEFAULT_Y_TICK_WIDTH = 40;
1350
1251
  var getXAxisLabelMetrics = (theme, orientation) => {
1351
- const xAxisStyles = orientation === "top" ? _optionalChain([theme, 'access', _31 => _31.axisStyles, 'optionalAccess', _32 => _32.x, 'optionalAccess', _33 => _33.top]) : _optionalChain([theme, 'access', _34 => _34.axisStyles, 'optionalAccess', _35 => _35.x, 'optionalAccess', _36 => _36.bottom]);
1352
- const fontSize = resolveFontSize(_optionalChain([xAxisStyles, 'optionalAccess', _37 => _37.axisLabel, 'optionalAccess', _38 => _38.fontSize])) || resolveFontSize(_optionalChain([theme, 'access', _39 => _39.svgLabelSmall, 'optionalAccess', _40 => _40.fontSize])) || DEFAULT_FONT_SIZE;
1353
- const tickLength = _nullishCoalesce(_optionalChain([xAxisStyles, 'optionalAccess', _41 => _41.tickLength]), () => ( DEFAULT_TICK_LENGTH));
1252
+ const xAxisStyles = orientation === "top" ? _optionalChain([theme, 'access', _27 => _27.axisStyles, 'optionalAccess', _28 => _28.x, 'optionalAccess', _29 => _29.top]) : _optionalChain([theme, 'access', _30 => _30.axisStyles, 'optionalAccess', _31 => _31.x, 'optionalAccess', _32 => _32.bottom]);
1253
+ const fontSize = resolveFontSize(_optionalChain([xAxisStyles, 'optionalAccess', _33 => _33.axisLabel, 'optionalAccess', _34 => _34.fontSize])) || resolveFontSize(_optionalChain([theme, 'access', _35 => _35.svgLabelSmall, 'optionalAccess', _36 => _36.fontSize])) || DEFAULT_FONT_SIZE;
1254
+ const tickLength = _nullishCoalesce(_optionalChain([xAxisStyles, 'optionalAccess', _37 => _37.tickLength]), () => ( DEFAULT_TICK_LENGTH));
1354
1255
  return {
1355
1256
  fontSize,
1356
1257
  tickLength
@@ -1360,7 +1261,10 @@ var useChartMargin = (height, options, data, theme, horizontal = false) => {
1360
1261
  const yTicks = _react.useMemo.call(void 0, () => {
1361
1262
  const allDataPoints = data.flatMap((series) => series.data);
1362
1263
  if (horizontal) {
1363
- return allDataPoints.map((d) => d.label || _optionalChain([options, 'access', _42 => _42.axis, 'optionalAccess', _43 => _43.y, 'optionalAccess', _44 => _44.tickFormat, 'call', _45 => _45(d.date.getTime(), 0, [])]));
1264
+ return allDataPoints.map((d) => d.label || _optionalChain([options, 'access', _38 => _38.axis, 'optionalAccess', _39 => _39.y, 'optionalAccess', _40 => _40.tickFormat, 'call', _41 => _41(d.date.getTime(), 0, [])]));
1265
+ }
1266
+ if (_optionalChain([options, 'access', _42 => _42.axis, 'optionalAccess', _43 => _43.y, 'optionalAccess', _44 => _44.tickValues, 'optionalAccess', _45 => _45.length])) {
1267
+ return options.axis.y.tickValues;
1364
1268
  }
1365
1269
  const minY = Math.min(...allDataPoints.map((d) => d.value));
1366
1270
  const maxY = Math.max(...allDataPoints.map((d) => d.value));