@auth0/quantum-charts 1.3.18 → 1.3.20

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/common/chart.d.ts CHANGED
@@ -47,3 +47,4 @@ export type IDonutChartDataPoint<DataType = unknown> = {
47
47
  value?: number;
48
48
  } & DataType;
49
49
  export declare const tickFormatter: (value: any, scaleType: any) => any;
50
+ export declare const truncateLabel: (value: string | number, maxLength: number) => string;
package/common/chart.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.tickFormatter = void 0;
3
+ exports.truncateLabel = exports.tickFormatter = void 0;
4
4
  var date_fns_1 = require("date-fns");
5
5
  var tickFormatter = function (value, scaleType) {
6
6
  switch (scaleType) {
@@ -34,3 +34,11 @@ var tickFormatter = function (value, scaleType) {
34
34
  }
35
35
  };
36
36
  exports.tickFormatter = tickFormatter;
37
+ var truncateLabel = function (value, maxLength) {
38
+ var stringValue = String(value !== null && value !== void 0 ? value : '');
39
+ if (stringValue.length > maxLength) {
40
+ return "".concat(stringValue.substring(0, maxLength).trim(), "...");
41
+ }
42
+ return stringValue;
43
+ };
44
+ exports.truncateLabel = truncateLabel;
@@ -30,3 +30,10 @@ export var tickFormatter = function (value, scaleType) {
30
30
  break;
31
31
  }
32
32
  };
33
+ export var truncateLabel = function (value, maxLength) {
34
+ var stringValue = String(value !== null && value !== void 0 ? value : '');
35
+ if (stringValue.length > maxLength) {
36
+ return "".concat(stringValue.substring(0, maxLength).trim(), "...");
37
+ }
38
+ return stringValue;
39
+ };
@@ -33,9 +33,10 @@ import { getColorScale, getStatusColorForGroup } from '../theme';
33
33
  import CustomActiveDot from './custom-active-dot';
34
34
  import CustomTooltip from '../common/custom-tooltip';
35
35
  import { ChartCard } from '../chart-card';
36
- import { tickFormatter } from '../common/chart';
36
+ import { tickFormatter, truncateLabel } from '../common/chart';
37
37
  import { CustomLegend } from '../common/custom-legend';
38
38
  import { DataTableChart } from '../chart-summary/data-table-chart';
39
+ import { MAX_DATE_LARGE_SCREEN_LIMIT, MAX_DATE_LENGTH, MAX_SCREEN_SIZE_LIMIT, MAX_TICK_WIDTH_PX, MIN_SAFE_CHART_WIDTH, } from '../utils/constants';
39
40
  var getThresholdColor = function (data, baseColor) {
40
41
  return data.hover === 'thresholdControl' || !data.hover ? baseColor : alpha(baseColor, 0.35);
41
42
  };
@@ -60,7 +61,7 @@ export function LineChart(props) {
60
61
  React.useEffect(function () {
61
62
  setThreshold(thresholds === null || thresholds === void 0 ? void 0 : thresholds[0]);
62
63
  setLineVisibility(__assign(__assign({}, ((thresholds === null || thresholds === void 0 ? void 0 : thresholds[0]) && { thresholdControl: false })), lineVisibility));
63
- }, [thresholds, lineVisibility]);
64
+ }, [thresholds]); // ⚠️ removed lineVisibility to avoid infinite loop
64
65
  var handleLegendMouseEnter = function (e) {
65
66
  if (!lineVisibility[e.dataKey]) {
66
67
  setLineVisibility(__assign(__assign({}, lineVisibility), { hover: e.dataKey }));
@@ -160,6 +161,17 @@ export function LineChart(props) {
160
161
  var _r = __read(React.useState(height), 2), responsiveContainerHeight = _r[0], setResponsiveContainerHeight = _r[1];
161
162
  var _s = __read(React.useState(isVertical ? '0%' : '100%'), 2), responsiveContainerWidth = _s[0], setResponsiveContainerWidth = _s[1];
162
163
  var _t = __read(React.useState(!isVertical), 2), visibility = _t[0], setVisibility = _t[1];
164
+ var _u = __read(React.useState(typeof window !== 'undefined' ? window.innerWidth : 0), 2), windowWidth = _u[0], setWindowWidth = _u[1];
165
+ React.useEffect(function () {
166
+ if (typeof window !== 'undefined') {
167
+ var handleResize_1 = function () { return setWindowWidth(window.innerWidth); };
168
+ window.addEventListener('resize', handleResize_1);
169
+ return function () { return window.removeEventListener('resize', handleResize_1); };
170
+ }
171
+ return undefined;
172
+ }, []);
173
+ // Define a breakpoint where you want the font size to change
174
+ var isSmallScreen = windowWidth < MAX_SCREEN_SIZE_LIMIT;
163
175
  var getContainerHeight = function () {
164
176
  if (!isVertical) {
165
177
  return height;
@@ -178,6 +190,21 @@ export function LineChart(props) {
178
190
  }, 10);
179
191
  }
180
192
  }, [legendContainerHeight, data.length]);
193
+ var MAX_TICKS_THAT_FIT = Math.floor(MIN_SAFE_CHART_WIDTH / MAX_TICK_WIDTH_PX);
194
+ var calculatedInterval = Math.floor(Object.values(entries).length / MAX_TICKS_THAT_FIT);
195
+ var finalInterval = Math.max(1, calculatedInterval);
196
+ var CustomXAxisTick = function (props) {
197
+ var x = props.x, y = props.y, payload = props.payload, isSmallScreen = props.isSmallScreen, bottomAxis = props.bottomAxis, theme = props.theme;
198
+ if (!theme || !theme.tokens) {
199
+ return null;
200
+ }
201
+ var value = tickFormatter(payload.value, bottomAxis.scaleType);
202
+ var FONT_SIZE_SMALL = theme.unsafe_globalTokens.type_global_primary_25.fontSize;
203
+ var FONT_SIZE_DEFAULT = theme.unsafe_globalTokens.type_global_primary_50.fontSize;
204
+ var fontSize = isSmallScreen ? FONT_SIZE_SMALL : FONT_SIZE_DEFAULT;
205
+ return (React.createElement("g", { transform: "translate(".concat(x, ",").concat(y, ")") },
206
+ React.createElement("text", { x: 0, y: 0, dy: 10, textAnchor: "middle", fill: theme.tokens.color_fg_default, style: { fontSize: fontSize } }, truncateLabel(value, isSmallScreen ? MAX_DATE_LENGTH : MAX_DATE_LARGE_SCREEN_LIMIT))));
207
+ };
181
208
  return (React.createElement(React.Fragment, null,
182
209
  React.createElement(ChartCard, { title: title, chartStatus: chartStatus, value: value, dataTable: data, label: label, helperText: helperText, headerAction: (groups === null || groups === void 0 ? void 0 : groups.length) > 1 ? headerActionWithThresholdDropdown : headerAction, finalMenuItem: finalMenuItem, additionalMenuItems: additionalMenuItems, allowDownload: allowDownload, showChartTable: showChartTable, triggerButtonSize: headerButtonsSize, titleIcon: titleIcon, isVertical: isVertical },
183
210
  React.createElement(ResponsiveContainer, { width: responsiveContainerWidth, height: responsiveContainerHeight, style: {
@@ -190,7 +217,7 @@ export function LineChart(props) {
190
217
  bottom: 5,
191
218
  } },
192
219
  React.createElement(CartesianGrid, { vertical: false, stroke: theme.tokens.color_border_default }),
193
- React.createElement(XAxis, { tickFormatter: function (value) { return tickFormatter(value, bottomAxis.scaleType); }, dataKey: bottomAxisDataKey, height: 30, interval: "equidistantPreserveStart", minTickGap: theme.spacingPX(14), tickMargin: theme.spacingPX(2), padding: isVertical ? { right: 40 } : undefined, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold }, allowDecimals: bottomAxis.allowDecimals }),
220
+ React.createElement(XAxis, { dataKey: bottomAxisDataKey, height: 30, interval: finalInterval, minTickGap: theme.spacingPX(14), tickMargin: theme.spacingPX(2), padding: isVertical ? { right: 40 } : undefined, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold }, allowDecimals: bottomAxis.allowDecimals, tick: function (tickProps) { return (React.createElement(CustomXAxisTick, __assign({}, tickProps, { isSmallScreen: isSmallScreen, bottomAxis: bottomAxis, theme: theme }))); } }),
194
221
  React.createElement(YAxis, { tickFormatter: function (value) { return tickFormatter(value, leftAxis.scaleType); }, domain: ['auto', 'auto'], width: 78, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold }, allowDecimals: leftAxis.allowDecimals }),
195
222
  React.createElement(Tooltip, { wrapperStyle: { outline: 'none' }, content: React.createElement(CustomTooltip, { active: undefined, payload: undefined, scaleType: bottomAxis.scaleType }) }),
196
223
  legend && isVertical ? (React.createElement(Legend, { align: "right", verticalAlign: "top", layout: "vertical", iconSize: 14, wrapperStyle: {
@@ -0,0 +1,5 @@
1
+ export var MAX_TICK_WIDTH_PX = 90;
2
+ export var MIN_SAFE_CHART_WIDTH = 800;
3
+ export var MAX_DATE_LENGTH = 10;
4
+ export var MAX_SCREEN_SIZE_LIMIT = 1000;
5
+ export var MAX_DATE_LARGE_SCREEN_LIMIT = 16;
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { IIconButtonProps } from '@auth0/quantum-product';
2
+ import { IIconButtonProps, ITheme } from '@auth0/quantum-product';
3
3
  import { IBaseChartProps } from '../common/chart';
4
4
  export interface ILineChartProps<DataType = unknown> extends IBaseChartProps<DataType> {
5
5
  syncId?: number | string;
@@ -18,4 +18,18 @@ export interface ILineChartProps<DataType = unknown> extends IBaseChartProps<Dat
18
18
  titleIcon?: React.ReactNode;
19
19
  isVertical?: boolean;
20
20
  }
21
+ export interface CustomXAxisTickProps {
22
+ x: number;
23
+ y: number;
24
+ payload: {
25
+ value: any;
26
+ [key: string]: any;
27
+ };
28
+ isSmallScreen: boolean;
29
+ bottomAxis: {
30
+ scaleType: string;
31
+ [key: string]: any;
32
+ };
33
+ theme: ITheme;
34
+ }
21
35
  export declare function LineChart<DataType = unknown>(props: ILineChartProps<DataType>): React.JSX.Element;
@@ -75,6 +75,7 @@ var chart_card_1 = require("../chart-card");
75
75
  var chart_1 = require("../common/chart");
76
76
  var custom_legend_1 = require("../common/custom-legend");
77
77
  var data_table_chart_1 = require("../chart-summary/data-table-chart");
78
+ var constants_1 = require("../utils/constants");
78
79
  var getThresholdColor = function (data, baseColor) {
79
80
  return data.hover === 'thresholdControl' || !data.hover ? baseColor : (0, quantum_product_1.alpha)(baseColor, 0.35);
80
81
  };
@@ -99,7 +100,7 @@ function LineChart(props) {
99
100
  React.useEffect(function () {
100
101
  setThreshold(thresholds === null || thresholds === void 0 ? void 0 : thresholds[0]);
101
102
  setLineVisibility(__assign(__assign({}, ((thresholds === null || thresholds === void 0 ? void 0 : thresholds[0]) && { thresholdControl: false })), lineVisibility));
102
- }, [thresholds, lineVisibility]);
103
+ }, [thresholds]); // ⚠️ removed lineVisibility to avoid infinite loop
103
104
  var handleLegendMouseEnter = function (e) {
104
105
  if (!lineVisibility[e.dataKey]) {
105
106
  setLineVisibility(__assign(__assign({}, lineVisibility), { hover: e.dataKey }));
@@ -199,6 +200,17 @@ function LineChart(props) {
199
200
  var _r = __read(React.useState(height), 2), responsiveContainerHeight = _r[0], setResponsiveContainerHeight = _r[1];
200
201
  var _s = __read(React.useState(isVertical ? '0%' : '100%'), 2), responsiveContainerWidth = _s[0], setResponsiveContainerWidth = _s[1];
201
202
  var _t = __read(React.useState(!isVertical), 2), visibility = _t[0], setVisibility = _t[1];
203
+ var _u = __read(React.useState(typeof window !== 'undefined' ? window.innerWidth : 0), 2), windowWidth = _u[0], setWindowWidth = _u[1];
204
+ React.useEffect(function () {
205
+ if (typeof window !== 'undefined') {
206
+ var handleResize_1 = function () { return setWindowWidth(window.innerWidth); };
207
+ window.addEventListener('resize', handleResize_1);
208
+ return function () { return window.removeEventListener('resize', handleResize_1); };
209
+ }
210
+ return undefined;
211
+ }, []);
212
+ // Define a breakpoint where you want the font size to change
213
+ var isSmallScreen = windowWidth < constants_1.MAX_SCREEN_SIZE_LIMIT;
202
214
  var getContainerHeight = function () {
203
215
  if (!isVertical) {
204
216
  return height;
@@ -217,6 +229,21 @@ function LineChart(props) {
217
229
  }, 10);
218
230
  }
219
231
  }, [legendContainerHeight, data.length]);
232
+ var MAX_TICKS_THAT_FIT = Math.floor(constants_1.MIN_SAFE_CHART_WIDTH / constants_1.MAX_TICK_WIDTH_PX);
233
+ var calculatedInterval = Math.floor(Object.values(entries).length / MAX_TICKS_THAT_FIT);
234
+ var finalInterval = Math.max(1, calculatedInterval);
235
+ var CustomXAxisTick = function (props) {
236
+ var x = props.x, y = props.y, payload = props.payload, isSmallScreen = props.isSmallScreen, bottomAxis = props.bottomAxis, theme = props.theme;
237
+ if (!theme || !theme.tokens) {
238
+ return null;
239
+ }
240
+ var value = (0, chart_1.tickFormatter)(payload.value, bottomAxis.scaleType);
241
+ var FONT_SIZE_SMALL = theme.unsafe_globalTokens.type_global_primary_25.fontSize;
242
+ var FONT_SIZE_DEFAULT = theme.unsafe_globalTokens.type_global_primary_50.fontSize;
243
+ var fontSize = isSmallScreen ? FONT_SIZE_SMALL : FONT_SIZE_DEFAULT;
244
+ return (React.createElement("g", { transform: "translate(".concat(x, ",").concat(y, ")") },
245
+ React.createElement("text", { x: 0, y: 0, dy: 10, textAnchor: "middle", fill: theme.tokens.color_fg_default, style: { fontSize: fontSize } }, (0, chart_1.truncateLabel)(value, isSmallScreen ? constants_1.MAX_DATE_LENGTH : constants_1.MAX_DATE_LARGE_SCREEN_LIMIT))));
246
+ };
220
247
  return (React.createElement(React.Fragment, null,
221
248
  React.createElement(chart_card_1.ChartCard, { title: title, chartStatus: chartStatus, value: value, dataTable: data, label: label, helperText: helperText, headerAction: (groups === null || groups === void 0 ? void 0 : groups.length) > 1 ? headerActionWithThresholdDropdown : headerAction, finalMenuItem: finalMenuItem, additionalMenuItems: additionalMenuItems, allowDownload: allowDownload, showChartTable: showChartTable, triggerButtonSize: headerButtonsSize, titleIcon: titleIcon, isVertical: isVertical },
222
249
  React.createElement(recharts_1.ResponsiveContainer, { width: responsiveContainerWidth, height: responsiveContainerHeight, style: {
@@ -229,7 +256,7 @@ function LineChart(props) {
229
256
  bottom: 5,
230
257
  } },
231
258
  React.createElement(recharts_1.CartesianGrid, { vertical: false, stroke: theme.tokens.color_border_default }),
232
- React.createElement(recharts_1.XAxis, { tickFormatter: function (value) { return (0, chart_1.tickFormatter)(value, bottomAxis.scaleType); }, dataKey: bottomAxisDataKey, height: 30, interval: "equidistantPreserveStart", minTickGap: theme.spacingPX(14), tickMargin: theme.spacingPX(2), padding: isVertical ? { right: 40 } : undefined, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold }, allowDecimals: bottomAxis.allowDecimals }),
259
+ React.createElement(recharts_1.XAxis, { dataKey: bottomAxisDataKey, height: 30, interval: finalInterval, minTickGap: theme.spacingPX(14), tickMargin: theme.spacingPX(2), padding: isVertical ? { right: 40 } : undefined, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold }, allowDecimals: bottomAxis.allowDecimals, tick: function (tickProps) { return (React.createElement(CustomXAxisTick, __assign({}, tickProps, { isSmallScreen: isSmallScreen, bottomAxis: bottomAxis, theme: theme }))); } }),
233
260
  React.createElement(recharts_1.YAxis, { tickFormatter: function (value) { return (0, chart_1.tickFormatter)(value, leftAxis.scaleType); }, domain: ['auto', 'auto'], width: 78, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold }, allowDecimals: leftAxis.allowDecimals }),
234
261
  React.createElement(recharts_1.Tooltip, { wrapperStyle: { outline: 'none' }, content: React.createElement(custom_tooltip_1.default, { active: undefined, payload: undefined, scaleType: bottomAxis.scaleType }) }),
235
262
  legend && isVertical ? (React.createElement(recharts_1.Legend, { align: "right", verticalAlign: "top", layout: "vertical", iconSize: 14, wrapperStyle: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@auth0/quantum-charts",
3
- "version": "1.3.18",
3
+ "version": "1.3.20",
4
4
  "sideEffects": false,
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -0,0 +1,5 @@
1
+ export declare const MAX_TICK_WIDTH_PX = 90;
2
+ export declare const MIN_SAFE_CHART_WIDTH = 800;
3
+ export declare const MAX_DATE_LENGTH = 10;
4
+ export declare const MAX_SCREEN_SIZE_LIMIT = 1000;
5
+ export declare const MAX_DATE_LARGE_SCREEN_LIMIT = 16;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_DATE_LARGE_SCREEN_LIMIT = exports.MAX_SCREEN_SIZE_LIMIT = exports.MAX_DATE_LENGTH = exports.MIN_SAFE_CHART_WIDTH = exports.MAX_TICK_WIDTH_PX = void 0;
4
+ exports.MAX_TICK_WIDTH_PX = 90;
5
+ exports.MIN_SAFE_CHART_WIDTH = 800;
6
+ exports.MAX_DATE_LENGTH = 10;
7
+ exports.MAX_SCREEN_SIZE_LIMIT = 1000;
8
+ exports.MAX_DATE_LARGE_SCREEN_LIMIT = 16;