@monolith-forensics/monolith-ui 1.9.3-dev.0 → 1.9.3-dev.1

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.
Files changed (48) hide show
  1. package/dist/Charts/BarChart/BarChart.js +28 -14
  2. package/dist/Charts/BarChart/BarChart.styled.d.ts +7 -2
  3. package/dist/Charts/BarChart/BarChart.styled.js +5 -1
  4. package/dist/Charts/BarChart/BarChart.types.d.ts +13 -5
  5. package/dist/Charts/ChartUtils/chartSizing.d.ts +20 -0
  6. package/dist/Charts/ChartUtils/chartSizing.js +83 -0
  7. package/dist/Charts/ChartUtils/index.d.ts +1 -0
  8. package/dist/Charts/ChartUtils/index.js +1 -0
  9. package/dist/Charts/HeatMap/HeatMap.js +28 -7
  10. package/dist/Charts/HeatMap/HeatMap.styled.d.ts +6 -2
  11. package/dist/Charts/HeatMap/HeatMap.styled.js +3 -0
  12. package/dist/Charts/HeatMap/HeatMap.types.d.ts +7 -1
  13. package/dist/Charts/LineChart/LineChart.js +34 -15
  14. package/dist/Charts/LineChart/LineChart.styled.d.ts +7 -2
  15. package/dist/Charts/LineChart/LineChart.styled.js +5 -1
  16. package/dist/Charts/LineChart/LineChart.types.d.ts +13 -5
  17. package/dist/Charts/PieChart/PieChart.js +48 -33
  18. package/dist/Charts/PieChart/PieChart.styled.d.ts +7 -2
  19. package/dist/Charts/PieChart/PieChart.styled.js +6 -1
  20. package/dist/Charts/PieChart/PieChart.types.d.ts +7 -3
  21. package/dist/FieldLabel/FieldLabel.js +3 -18
  22. package/dist/RichTextEditor/Extensions/getSlashCommand.d.ts +23 -3
  23. package/dist/RichTextEditor/Extensions/getSlashCommand.js +14 -6
  24. package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +5 -2
  25. package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +3 -1
  26. package/dist/RichTextEditor/RichTextEditor.d.ts +6 -3
  27. package/dist/RichTextEditor/RichTextEditor.js +6 -6
  28. package/dist/SegmentedControl/SegmentedControl.js +1 -1
  29. package/dist/SegmentedControl/SegmentedControl.styles.d.ts +1 -0
  30. package/dist/SegmentedControl/SegmentedControl.styles.js +30 -14
  31. package/dist/SegmentedControl/SegmentedControl.utils.d.ts +1 -0
  32. package/dist/SegmentedControl/SegmentedControl.utils.js +5 -2
  33. package/dist/Table/Table.js +4 -3
  34. package/dist/Table/TableComponents.d.ts +3 -0
  35. package/dist/Table/TableComponents.js +47 -0
  36. package/dist/Table/TableHeader.js +1 -1
  37. package/dist/Table/TableMenu/TableMenu.js +4 -3
  38. package/dist/Table/TableProvider.js +39 -0
  39. package/dist/Table/TableRow.js +1 -1
  40. package/dist/Table/types.d.ts +6 -0
  41. package/dist/Utilities/getImageTextContent.d.ts +78 -0
  42. package/dist/Utilities/getImageTextContent.js +222 -0
  43. package/dist/core/controlSizes.js +9 -9
  44. package/package.json +1 -1
  45. package/dist/RichTextEditor/Components/TableCornerMenu.d.ts +0 -16
  46. package/dist/RichTextEditor/Components/TableCornerMenu.js +0 -202
  47. package/dist/RichTextEditor/Components/TableTools.d.ts +0 -44
  48. package/dist/RichTextEditor/Components/TableTools.js +0 -790
@@ -23,15 +23,16 @@ import { scaleBand, scaleLinear } from "d3-scale";
23
23
  import { forwardRef, useEffect, useId, useImperativeHandle, useMemo, useRef, useState, } from "react";
24
24
  import { useTheme } from "styled-components";
25
25
  import { ChartExportControl } from "../ChartPrimitives";
26
- import { DEFAULT_CHART_EXPORT_FORMATS, copyChartImage, downloadChartImage, } from "../ChartUtils";
26
+ import { DEFAULT_CHART_EXPORT_FORMATS, copyChartImage, downloadChartImage, useChartResponsiveSize, } from "../ChartUtils";
27
27
  import { clamp, easeOutCubic, formatDefaultValue, getBandPadding, getBarKey, getCategoryKey, getGradientColor, getGradientColorFromStops, getGradientStops, getRoundedBarPath, getSeriesKey, getSeriesLabelText, getValueDomain, mergeChartMargin, normalizeTickValue, useThemeColors, } from "./BarChart.lib";
28
28
  import { StyledAxisLine, StyledAxisText, StyledBar, StyledChartActions, StyledChartFrame, StyledChartScroller, StyledContainer, StyledEmptyState, StyledGridLine, StyledLegend, StyledLegendItem, StyledLegendLabel, StyledLegendValue, StyledSvg, StyledSwatch, StyledTooltip, StyledTooltipHeader, StyledTooltipLabel, StyledTooltipList, StyledTooltipMeta, StyledTooltipRow, StyledTooltipSwatch, StyledTooltipValue, StyledValueLabel, } from "./BarChart.styled";
29
29
  const BarChartInner = (_a, ref) => {
30
30
  var _b, _c, _d;
31
- var { data, series, width = 640, height = 320, orientation = "vertical", seriesLayout = "grouped", margin, barGap = 10, groupBarGap, maxBarThickness, barRadius = 3, colors, colorGradient, barOpacity = 1, barBorderColor, barBorderWidth = 1, barBorderOpacity = 1, minValue, maxValue, valueTickCount = 5, showGridLines = true, showAxisLines = true, showCategoryAxisLabels = true, showValueAxisLabels = true, showLegend = false, showLegendSwatches = true, showLegendLabels = true, showLegendValues = true, showLabels = false, emptyLabel = "No data", ariaLabel = "Bar chart", animateOnRender = false, animationDuration = 520, animationStagger = 35, showExportButton = false, exportFileName = "bar-chart", exportFormats = DEFAULT_CHART_EXPORT_FORMATS, exportScale = 2, exportBackgroundColor, showTooltips = false, valueFormatter, categoryLabelFormatter, tickFormatter, labelFormatter, tooltipFormatter, onBarClick, onLegendItemClick, onSeriesLegendItemClick, className } = _a, props = __rest(_a, ["data", "series", "width", "height", "orientation", "seriesLayout", "margin", "barGap", "groupBarGap", "maxBarThickness", "barRadius", "colors", "colorGradient", "barOpacity", "barBorderColor", "barBorderWidth", "barBorderOpacity", "minValue", "maxValue", "valueTickCount", "showGridLines", "showAxisLines", "showCategoryAxisLabels", "showValueAxisLabels", "showLegend", "showLegendSwatches", "showLegendLabels", "showLegendValues", "showLabels", "emptyLabel", "ariaLabel", "animateOnRender", "animationDuration", "animationStagger", "showExportButton", "exportFileName", "exportFormats", "exportScale", "exportBackgroundColor", "showTooltips", "valueFormatter", "categoryLabelFormatter", "tickFormatter", "labelFormatter", "tooltipFormatter", "onBarClick", "onLegendItemClick", "onSeriesLegendItemClick", "className"]);
31
+ var { data, series, width, height, responsive = false, aspectRatio, minWidth = 180, minHeight = 180, orientation = "vertical", seriesLayout = "grouped", margin, barGap = 10, groupBarGap, maxBarThickness, barRadius = 3, colors, colorGradient, barOpacity = 1, barBorderColor, barBorderWidth = 1, barBorderOpacity = 1, minValue, maxValue, valueTickCount = 5, showGridLines = true, showAxisLines = true, showCategoryAxisLabels = true, showValueAxisLabels = true, showLegend = false, showLegendSwatches = true, showLegendLabels = true, showLegendValues = true, showLabels = false, emptyLabel = "No data", ariaLabel = "Bar chart", animateOnRender = false, animationDuration = 520, animationStagger = 35, showExportButton = false, exportFileName = "bar-chart", exportFormats = DEFAULT_CHART_EXPORT_FORMATS, exportScale = 2, exportBackgroundColor, showTooltips = false, valueFormatter, categoryLabelFormatter, tickFormatter, labelFormatter, tooltipFormatter, onBarClick, onLegendItemClick, onSeriesLegendItemClick, className } = _a, props = __rest(_a, ["data", "series", "width", "height", "responsive", "aspectRatio", "minWidth", "minHeight", "orientation", "seriesLayout", "margin", "barGap", "groupBarGap", "maxBarThickness", "barRadius", "colors", "colorGradient", "barOpacity", "barBorderColor", "barBorderWidth", "barBorderOpacity", "minValue", "maxValue", "valueTickCount", "showGridLines", "showAxisLines", "showCategoryAxisLabels", "showValueAxisLabels", "showLegend", "showLegendSwatches", "showLegendLabels", "showLegendValues", "showLabels", "emptyLabel", "ariaLabel", "animateOnRender", "animationDuration", "animationStagger", "showExportButton", "exportFileName", "exportFormats", "exportScale", "exportBackgroundColor", "showTooltips", "valueFormatter", "categoryLabelFormatter", "tickFormatter", "labelFormatter", "tooltipFormatter", "onBarClick", "onLegendItemClick", "onSeriesLegendItemClick", "className"]);
32
32
  const descriptionId = useId();
33
33
  const theme = useTheme();
34
34
  const containerRef = useRef(null);
35
+ const chartSizeRef = useRef(null);
35
36
  const chartFrameRef = useRef(null);
36
37
  const svgRef = useRef(null);
37
38
  const tooltipRef = useRef(null);
@@ -69,8 +70,18 @@ const BarChartInner = (_a, ref) => {
69
70
  },
70
71
  ];
71
72
  }, [data, series]);
72
- const safeWidth = Math.max(width, 180);
73
- const safeHeight = Math.max(height, 180);
73
+ const chartSize = useChartResponsiveSize(chartSizeRef, {
74
+ width,
75
+ height,
76
+ responsive,
77
+ aspectRatio,
78
+ defaultWidth: 640,
79
+ defaultHeight: 320,
80
+ minWidth: Math.max(minWidth, 1),
81
+ minHeight: Math.max(minHeight, 1),
82
+ });
83
+ const safeWidth = chartSize.width;
84
+ const safeHeight = chartSize.height;
74
85
  const safeBarRadius = Math.max(barRadius, 0);
75
86
  const safeBarGap = Math.max(barGap, 0);
76
87
  const safeGroupBarGap = Math.max(groupBarGap !== null && groupBarGap !== void 0 ? groupBarGap : barGap, 0);
@@ -286,8 +297,7 @@ const BarChartInner = (_a, ref) => {
286
297
  }, [categories, isMultiSeries, seriesLayout]);
287
298
  const safeAnimationDuration = Math.max(animationDuration, 0);
288
299
  const safeAnimationStagger = Math.max(animationStagger, 0);
289
- const totalAnimationDuration = safeAnimationDuration +
290
- Math.max(bars.length - 1, 0) * safeAnimationStagger;
300
+ const totalAnimationDuration = safeAnimationDuration + Math.max(bars.length - 1, 0) * safeAnimationStagger;
291
301
  useEffect(() => {
292
302
  var _a;
293
303
  if (!animateOnRender || bars.length === 0) {
@@ -329,7 +339,10 @@ const BarChartInner = (_a, ref) => {
329
339
  const elapsed = animationElapsed - index * safeAnimationStagger;
330
340
  return easeOutCubic(clamp(elapsed / safeAnimationDuration, 0, 1));
331
341
  };
332
- const formatValue = (datum, sourceSeries) => { var _a; return (_a = valueFormatter === null || valueFormatter === void 0 ? void 0 : valueFormatter(datum.value, datum, sourceSeries)) !== null && _a !== void 0 ? _a : formatDefaultValue(datum.value); };
342
+ const formatValue = (datum, sourceSeries) => {
343
+ var _a;
344
+ return (_a = valueFormatter === null || valueFormatter === void 0 ? void 0 : valueFormatter(datum.value, datum, sourceSeries)) !== null && _a !== void 0 ? _a : formatDefaultValue(datum.value);
345
+ };
333
346
  const formatCategoryLabel = (category) => {
334
347
  var _a, _b;
335
348
  return (_b = categoryLabelFormatter === null || categoryLabelFormatter === void 0 ? void 0 : categoryLabelFormatter(category.representativeDatum, category.index, (_a = category.bars[0]) === null || _a === void 0 ? void 0 : _a.sourceSeries)) !== null && _b !== void 0 ? _b : category.label;
@@ -354,10 +367,10 @@ const BarChartInner = (_a, ref) => {
354
367
  });
355
368
  };
356
369
  const activeTooltipBar = showTooltips && activeTooltip
357
- ? (_c = bars.find((bar) => bar.key === activeTooltip.barKey)) !== null && _c !== void 0 ? _c : null
370
+ ? ((_c = bars.find((bar) => bar.key === activeTooltip.barKey)) !== null && _c !== void 0 ? _c : null)
358
371
  : null;
359
372
  const activeTooltipCategory = isMultiSeries && activeTooltipBar
360
- ? (_d = categories.find((category) => category.key === activeTooltipBar.categoryKey)) !== null && _d !== void 0 ? _d : null
373
+ ? ((_d = categories.find((category) => category.key === activeTooltipBar.categoryKey)) !== null && _d !== void 0 ? _d : null)
361
374
  : null;
362
375
  const tooltipStyle = useMemo(() => {
363
376
  if (!activeTooltip ||
@@ -410,7 +423,7 @@ const BarChartInner = (_a, ref) => {
410
423
  height: tooltipRef.current.offsetHeight,
411
424
  });
412
425
  }, [activeTooltipBar, activeTooltipCategory, isMultiSeries]);
413
- return (_jsxs(StyledContainer, Object.assign({ ref: containerRef, className: className }, props, { children: [bars.length === 0 ? (_jsx(StyledEmptyState, { "$width": safeWidth, "$height": safeHeight, children: emptyLabel })) : (_jsx(StyledChartScroller, { children: _jsxs(StyledChartFrame, { ref: chartFrameRef, children: [showExportButton && exportFormats.length > 0 && (_jsx(StyledChartActions, { "data-chart-export-ignore": "true", children: _jsx(ChartExportControl, { rootRef: containerRef, svgRef: svgRef, fileName: exportFileName, formats: exportFormats, scale: exportScale, backgroundColor: resolvedExportBackgroundColor }) })), _jsxs(StyledSvg, { ref: svgRef, width: safeWidth, height: safeHeight, viewBox: `0 0 ${safeWidth} ${safeHeight}`, role: "img", "aria-label": ariaLabel, "aria-describedby": descriptionId, children: [_jsx("desc", { id: descriptionId, children: description }), showGridLines &&
426
+ return (_jsxs(StyledContainer, Object.assign({ ref: containerRef, className: className, "$fillAvailableWidth": chartSize.fillAvailableWidth }, props, { children: [_jsx(StyledChartScroller, { ref: chartSizeRef, "$width": chartSize.widthStyle, "$height": chartSize.heightStyle, children: bars.length === 0 ? (_jsx(StyledEmptyState, { "$width": safeWidth, "$height": safeHeight, children: emptyLabel })) : (_jsxs(StyledChartFrame, { ref: chartFrameRef, children: [showExportButton && exportFormats.length > 0 && (_jsx(StyledChartActions, { "data-chart-export-ignore": "true", children: _jsx(ChartExportControl, { rootRef: containerRef, svgRef: svgRef, fileName: exportFileName, formats: exportFormats, scale: exportScale, backgroundColor: resolvedExportBackgroundColor }) })), _jsxs(StyledSvg, { ref: svgRef, width: safeWidth, height: safeHeight, viewBox: `0 0 ${safeWidth} ${safeHeight}`, role: "img", "aria-label": ariaLabel, "aria-describedby": descriptionId, children: [_jsx("desc", { id: descriptionId, children: description }), showGridLines &&
414
427
  tickValues.map((tick) => {
415
428
  const tickPosition = valueScale(tick);
416
429
  return orientation === "vertical" ? (_jsx(StyledGridLine, { x1: resolvedMargin.left, x2: resolvedMargin.left + plotWidth, y1: resolvedMargin.top + tickPosition, y2: resolvedMargin.top + tickPosition }, `grid-${tick}`)) : (_jsx(StyledGridLine, { x1: resolvedMargin.left + tickPosition, x2: resolvedMargin.left + tickPosition, y1: resolvedMargin.top, y2: resolvedMargin.top + plotHeight }, `grid-${tick}`));
@@ -434,7 +447,8 @@ const BarChartInner = (_a, ref) => {
434
447
  const endPosition = valueScale(bar.valueEnd);
435
448
  const animatedStartPosition = zeroPosition +
436
449
  (startPosition - zeroPosition) * animationProgress;
437
- const animatedEndPosition = zeroPosition + (endPosition - zeroPosition) * animationProgress;
450
+ const animatedEndPosition = zeroPosition +
451
+ (endPosition - zeroPosition) * animationProgress;
438
452
  const x = orientation === "vertical"
439
453
  ? resolvedMargin.left +
440
454
  categoryBandStart +
@@ -528,7 +542,7 @@ const BarChartInner = (_a, ref) => {
528
542
  categoryScale.bandwidth() / 2, y: resolvedMargin.top + plotHeight + 20, textAnchor: "middle", children: formatCategoryLabel(category) }, `category-${category.key}`)) : (_jsx(StyledAxisText, { x: resolvedMargin.left - 10, y: resolvedMargin.top +
529
543
  ((_b = categoryScale(category.key)) !== null && _b !== void 0 ? _b : 0) +
530
544
  categoryScale.bandwidth() / 2, textAnchor: "end", dominantBaseline: "middle", children: formatCategoryLabel(category) }, `category-${category.key}`));
531
- })] })] }) })), activeTooltip && activeTooltipBar && tooltipStyle && (_jsx(StyledTooltip, { ref: tooltipRef, style: tooltipStyle, children: tooltipFormatter ? (tooltipFormatter(activeTooltipBar, activeTooltipBar.index, activeTooltipBar.sourceSeries)) : isMultiSeries && activeTooltipCategory ? (_jsxs(_Fragment, { children: [_jsx(StyledTooltipHeader, { children: _jsx(StyledTooltipLabel, { children: activeTooltipCategory.label }) }), _jsxs(StyledTooltipMeta, { children: [formatDefaultValue(activeTooltipCategory.bars.reduce((sum, bar) => sum + bar.value, 0)), " ", "total"] }), _jsx(StyledTooltipList, { children: activeTooltipCategory.bars.map((bar) => (_jsxs(StyledTooltipRow, { children: [_jsx(StyledTooltipSwatch, { "$color": bar.color }), _jsx(StyledTooltipLabel, { children: bar.seriesLabel }), _jsx(StyledTooltipValue, { children: formatValue(bar, bar.sourceSeries) })] }, `tooltip-${bar.key}`))) })] })) : (_jsxs(_Fragment, { children: [_jsxs(StyledTooltipHeader, { children: [_jsx(StyledTooltipSwatch, { "$color": activeTooltipBar.color }), _jsx(StyledTooltipLabel, { children: activeTooltipBar.label })] }), _jsx(StyledTooltipMeta, { children: formatValue(activeTooltipBar, activeTooltipBar.sourceSeries) })] })) })), shouldShowLegend && (_jsx(StyledLegend, { children: isMultiSeries
545
+ })] })] })) }), activeTooltip && activeTooltipBar && tooltipStyle && (_jsx(StyledTooltip, { ref: tooltipRef, style: tooltipStyle, children: tooltipFormatter ? (tooltipFormatter(activeTooltipBar, activeTooltipBar.index, activeTooltipBar.sourceSeries)) : isMultiSeries && activeTooltipCategory ? (_jsxs(_Fragment, { children: [_jsx(StyledTooltipHeader, { children: _jsx(StyledTooltipLabel, { children: activeTooltipCategory.label }) }), _jsxs(StyledTooltipMeta, { children: [formatDefaultValue(activeTooltipCategory.bars.reduce((sum, bar) => sum + bar.value, 0)), " ", "total"] }), _jsx(StyledTooltipList, { children: activeTooltipCategory.bars.map((bar) => (_jsxs(StyledTooltipRow, { children: [_jsx(StyledTooltipSwatch, { "$color": bar.color }), _jsx(StyledTooltipLabel, { children: bar.seriesLabel }), _jsx(StyledTooltipValue, { children: formatValue(bar, bar.sourceSeries) })] }, `tooltip-${bar.key}`))) })] })) : (_jsxs(_Fragment, { children: [_jsxs(StyledTooltipHeader, { children: [_jsx(StyledTooltipSwatch, { "$color": activeTooltipBar.color }), _jsx(StyledTooltipLabel, { children: activeTooltipBar.label })] }), _jsx(StyledTooltipMeta, { children: formatValue(activeTooltipBar, activeTooltipBar.sourceSeries) })] })) })), shouldShowLegend && (_jsx(StyledLegend, { children: isMultiSeries
532
546
  ? resolvedSeries.map((seriesEntry) => (_jsxs(StyledLegendItem, { "$active": activeSeriesKey === seriesEntry.key, "$showSwatch": showLegendSwatches, "$showLabel": showLegendLabels, "$showValue": showLegendValues, tabIndex: 0, onMouseEnter: () => setActiveSeriesKey(seriesEntry.key), onMouseLeave: () => setActiveSeriesKey(null), onFocus: () => setActiveSeriesKey(seriesEntry.key), onBlur: () => setActiveSeriesKey(null), onClick: (event) => seriesEntry.sourceSeries &&
533
547
  (onSeriesLegendItemClick === null || onSeriesLegendItemClick === void 0 ? void 0 : onSeriesLegendItemClick(event, seriesEntry.sourceSeries)), onKeyDown: (event) => {
534
548
  if (event.key !== "Enter" && event.key !== " ")
@@ -537,13 +551,13 @@ const BarChartInner = (_a, ref) => {
537
551
  if (seriesEntry.sourceSeries) {
538
552
  onSeriesLegendItemClick === null || onSeriesLegendItemClick === void 0 ? void 0 : onSeriesLegendItemClick(event, seriesEntry.sourceSeries);
539
553
  }
540
- }, children: [showLegendSwatches && _jsx(StyledSwatch, { "$color": seriesEntry.color }), showLegendLabels && (_jsx(StyledLegendLabel, { children: seriesEntry.label })), showLegendValues && (_jsx(StyledLegendValue, { children: formatSeriesValue(seriesEntry) }))] }, `legend-${seriesEntry.key}`)))
554
+ }, children: [showLegendSwatches && (_jsx(StyledSwatch, { "$color": seriesEntry.color })), showLegendLabels && (_jsx(StyledLegendLabel, { children: seriesEntry.label })), showLegendValues && (_jsx(StyledLegendValue, { children: formatSeriesValue(seriesEntry) }))] }, `legend-${seriesEntry.key}`)))
541
555
  : bars.map((bar) => (_jsxs(StyledLegendItem, { "$active": activeBarKey === bar.key, "$showSwatch": showLegendSwatches, "$showLabel": showLegendLabels, "$showValue": showLegendValues, tabIndex: 0, onMouseEnter: () => setActiveBarKey(bar.key), onMouseLeave: () => setActiveBarKey(null), onFocus: () => setActiveBarKey(bar.key), onBlur: () => setActiveBarKey(null), onClick: (event) => onLegendItemClick === null || onLegendItemClick === void 0 ? void 0 : onLegendItemClick(event, bar), onKeyDown: (event) => {
542
556
  if (event.key !== "Enter" && event.key !== " ")
543
557
  return;
544
558
  event.preventDefault();
545
559
  onLegendItemClick === null || onLegendItemClick === void 0 ? void 0 : onLegendItemClick(event, bar);
546
- }, children: [showLegendSwatches && _jsx(StyledSwatch, { "$color": bar.color }), showLegendLabels && _jsx(StyledLegendLabel, { children: bar.label }), showLegendValues && (_jsx(StyledLegendValue, { children: formatValue(bar, bar.sourceSeries) }))] }, bar.key))) }))] })));
560
+ }, children: [showLegendSwatches && _jsx(StyledSwatch, { "$color": bar.color }), showLegendLabels && (_jsx(StyledLegendLabel, { children: bar.label })), showLegendValues && (_jsx(StyledLegendValue, { children: formatValue(bar, bar.sourceSeries) }))] }, bar.key))) }))] })));
547
561
  };
548
562
  export const BarChart = forwardRef(BarChartInner);
549
563
  export default BarChart;
@@ -1,6 +1,11 @@
1
1
  import { StyledChartActions } from "../ChartPrimitives";
2
- export declare const StyledContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
3
- export declare const StyledChartScroller: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
2
+ export declare const StyledContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
3
+ $fillAvailableWidth: boolean;
4
+ }>> & string;
5
+ export declare const StyledChartScroller: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
6
+ $width?: string;
7
+ $height?: string;
8
+ }>> & string;
4
9
  export declare const StyledChartFrame: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
5
10
  export { StyledChartActions };
6
11
  export declare const StyledSvg: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").SVGProps<SVGSVGElement>, never>> & string;
@@ -11,7 +11,7 @@ export const StyledContainer = styled.div `
11
11
  align-items: flex-start;
12
12
  flex-wrap: wrap;
13
13
  gap: 20px;
14
- width: fit-content;
14
+ width: ${({ $fillAvailableWidth }) => $fillAvailableWidth ? "100%" : "fit-content"};
15
15
  max-width: 100%;
16
16
  color: ${({ theme }) => theme.palette.text.primary};
17
17
  box-sizing: border-box;
@@ -19,10 +19,13 @@ export const StyledContainer = styled.div `
19
19
  `;
20
20
  export const StyledChartScroller = styled.div `
21
21
  display: flex;
22
+ width: ${({ $width }) => $width !== null && $width !== void 0 ? $width : "auto"};
23
+ height: ${({ $height }) => $height !== null && $height !== void 0 ? $height : "auto"};
22
24
  max-width: 100%;
23
25
  overflow-x: auto;
24
26
  overflow-y: visible;
25
27
  padding-bottom: 2px;
28
+ box-sizing: border-box;
26
29
  `;
27
30
  export const StyledChartFrame = styled.div `
28
31
  position: relative;
@@ -93,6 +96,7 @@ export const StyledEmptyState = styled.div `
93
96
  justify-content: center;
94
97
  width: ${({ $width }) => $width}px;
95
98
  height: ${({ $height }) => $height}px;
99
+ box-sizing: border-box;
96
100
  border: 1px dashed ${({ theme }) => theme.palette.divider};
97
101
  border-radius: 8px;
98
102
  background: linear-gradient(
@@ -1,5 +1,5 @@
1
1
  import React, { HTMLAttributes } from "react";
2
- import type { ChartExportOptions } from "../ChartUtils";
2
+ import type { ChartDimension, ChartExportOptions } from "../ChartUtils";
3
3
  export type BarChartDatum<TData = unknown> = {
4
4
  /** Stable identifier for the bar. Falls back to label and index when omitted. */
5
5
  id?: string | number;
@@ -86,10 +86,18 @@ export type BarChartProps<TData = unknown> = HTMLAttributes<HTMLDivElement> & Ch
86
86
  data?: BarChartDatum<TData>[];
87
87
  /** Multi-series bar data. Takes precedence over data when provided. */
88
88
  series?: BarChartSeries<TData>[];
89
- /** SVG width in pixels. Defaults to 640. */
90
- width?: number;
91
- /** SVG height in pixels. Defaults to 320. */
92
- height?: number;
89
+ /** SVG width in pixels or any CSS length measured from the chart frame. Defaults to 640. */
90
+ width?: ChartDimension;
91
+ /** SVG height in pixels or any CSS length measured from the chart frame. Defaults to 320. */
92
+ height?: ChartDimension;
93
+ /** Measures the chart frame and fits the SVG width to its available space. Defaults to false. */
94
+ responsive?: boolean;
95
+ /** Calculates height from resolved width when height is omitted. */
96
+ aspectRatio?: number;
97
+ /** Minimum rendered SVG width in pixels. Defaults to 180. */
98
+ minWidth?: number;
99
+ /** Minimum rendered SVG height in pixels. Defaults to 180. */
100
+ minHeight?: number;
93
101
  /** Bar layout direction. Defaults to "vertical". */
94
102
  orientation?: BarChartOrientation;
95
103
  /** Multi-series layout mode. Defaults to "grouped". */
@@ -0,0 +1,20 @@
1
+ import { RefObject } from "react";
2
+ export type ChartDimension = number | string;
3
+ export type ChartResponsiveSizeOptions = {
4
+ width?: ChartDimension;
5
+ height?: ChartDimension;
6
+ responsive?: boolean;
7
+ aspectRatio?: number;
8
+ defaultWidth: number;
9
+ defaultHeight: number;
10
+ minWidth: number;
11
+ minHeight: number;
12
+ };
13
+ export type ResolvedChartSize = {
14
+ width: number;
15
+ height: number;
16
+ widthStyle?: string;
17
+ heightStyle?: string;
18
+ fillAvailableWidth: boolean;
19
+ };
20
+ export declare const useChartResponsiveSize: (ref: RefObject<HTMLElement | null>, { width, height, responsive, aspectRatio, defaultWidth, defaultHeight, minWidth, minHeight, }: ChartResponsiveSizeOptions) => ResolvedChartSize;
@@ -0,0 +1,83 @@
1
+ import { useEffect, useMemo, useState } from "react";
2
+ const toDimensionStyle = (dimension) => {
3
+ if (dimension == null || typeof dimension === "number")
4
+ return undefined;
5
+ return dimension;
6
+ };
7
+ const toNumericDimension = (dimension, fallback) => typeof dimension === "number" && Number.isFinite(dimension)
8
+ ? dimension
9
+ : fallback;
10
+ const getElementSize = (element) => {
11
+ const rect = element.getBoundingClientRect();
12
+ return {
13
+ width: Math.max(Math.round(rect.width || element.clientWidth || 0), 0),
14
+ height: Math.max(Math.round(rect.height || element.clientHeight || 0), 0),
15
+ };
16
+ };
17
+ export const useChartResponsiveSize = (ref, { width, height, responsive = false, aspectRatio, defaultWidth, defaultHeight, minWidth, minHeight, }) => {
18
+ const resolvedWidthInput = width !== null && width !== void 0 ? width : (responsive ? "100%" : defaultWidth);
19
+ const resolvedHeightInput = height !== null && height !== void 0 ? height : defaultHeight;
20
+ const shouldMeasureWidth = responsive || typeof resolvedWidthInput === "string";
21
+ const shouldMeasureHeight = typeof resolvedHeightInput === "string";
22
+ const shouldMeasure = shouldMeasureWidth || shouldMeasureHeight;
23
+ const [measuredSize, setMeasuredSize] = useState({ width: 0, height: 0 });
24
+ useEffect(() => {
25
+ if (!shouldMeasure)
26
+ return;
27
+ const element = ref.current;
28
+ if (!element)
29
+ return;
30
+ const updateSize = () => {
31
+ const nextSize = getElementSize(element);
32
+ setMeasuredSize((currentSize) => currentSize.width === nextSize.width &&
33
+ currentSize.height === nextSize.height
34
+ ? currentSize
35
+ : nextSize);
36
+ };
37
+ updateSize();
38
+ if (typeof ResizeObserver === "undefined") {
39
+ window.addEventListener("resize", updateSize);
40
+ return () => window.removeEventListener("resize", updateSize);
41
+ }
42
+ const observer = new ResizeObserver(updateSize);
43
+ observer.observe(element);
44
+ return () => observer.disconnect();
45
+ }, [ref, shouldMeasure]);
46
+ return useMemo(() => {
47
+ const fallbackWidth = toNumericDimension(resolvedWidthInput, defaultWidth);
48
+ const fallbackHeight = toNumericDimension(resolvedHeightInput, defaultHeight);
49
+ const measuredWidth = shouldMeasureWidth && measuredSize.width > 0
50
+ ? measuredSize.width
51
+ : fallbackWidth;
52
+ const safeWidth = Math.max(measuredWidth, minWidth);
53
+ const resolvedAspectRatio = aspectRatio != null && Number.isFinite(aspectRatio) && aspectRatio > 0
54
+ ? aspectRatio
55
+ : null;
56
+ const measuredHeight = height == null && resolvedAspectRatio != null
57
+ ? safeWidth / resolvedAspectRatio
58
+ : shouldMeasureHeight && measuredSize.height > 0
59
+ ? measuredSize.height
60
+ : fallbackHeight;
61
+ return {
62
+ width: Math.max(Math.round(safeWidth), minWidth),
63
+ height: Math.max(Math.round(measuredHeight), minHeight),
64
+ widthStyle: toDimensionStyle(resolvedWidthInput),
65
+ heightStyle: toDimensionStyle(resolvedHeightInput),
66
+ fillAvailableWidth: responsive || typeof resolvedWidthInput === "string",
67
+ };
68
+ }, [
69
+ aspectRatio,
70
+ defaultHeight,
71
+ defaultWidth,
72
+ height,
73
+ measuredSize.height,
74
+ measuredSize.width,
75
+ minHeight,
76
+ minWidth,
77
+ resolvedHeightInput,
78
+ resolvedWidthInput,
79
+ responsive,
80
+ shouldMeasureHeight,
81
+ shouldMeasureWidth,
82
+ ]);
83
+ };
@@ -1,3 +1,4 @@
1
1
  export * from "./chartColors";
2
2
  export * from "./chartExport";
3
3
  export * from "./chartMath";
4
+ export * from "./chartSizing";
@@ -1,3 +1,4 @@
1
1
  export * from "./chartColors";
2
2
  export * from "./chartExport";
3
3
  export * from "./chartMath";
4
+ export * from "./chartSizing";
@@ -22,14 +22,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
22
22
  import { forwardRef, useEffect, useId, useImperativeHandle, useMemo, useRef, useState, } from "react";
23
23
  import { useTheme } from "styled-components";
24
24
  import { ChartExportControl } from "../ChartPrimitives";
25
- import { DEFAULT_CHART_EXPORT_FORMATS, copyChartImage, downloadChartImage, } from "../ChartUtils";
25
+ import { DEFAULT_CHART_EXPORT_FORMATS, copyChartImage, downloadChartImage, useChartResponsiveSize, } from "../ChartUtils";
26
26
  import { buildHeatMapCells, clamp, easeOutCubic, formatDefaultValue, formatDefaultWeekdayLabel, getHeatMapColor, getHeatMapDateRange, getMonthLabels, } from "./HeatMap.lib";
27
27
  import { StyledCell, StyledChartActions, StyledChartFrame, StyledChartScroller, StyledContainer, StyledLegend, StyledLegendCell, StyledLegendScale, StyledMonthLabel, StyledSvg, StyledTooltip, StyledTooltipHeader, StyledTooltipMeta, StyledTooltipSwatch, StyledWeekdayLabel, } from "./HeatMap.styled";
28
28
  const HeatMapInner = (_a, ref) => {
29
- var { data, startDate, endDate, cellSize = 12, cellGap = 4, cellRadius = 2, emptyColor, colors, minValue = 0, maxValue, weekStartsOn = 0, showMonthLabels = true, showWeekdayLabels = true, showLegend = true, animateOnRender = false, animationDuration = 350, animationStagger = 1, showExportButton = false, exportFileName = "heat-map", exportFormats = DEFAULT_CHART_EXPORT_FORMATS, exportScale = 2, exportBackgroundColor, showTooltips = false, ariaLabel = "Heat map", valueFormatter, monthLabelFormatter, weekdayLabelFormatter, tooltipFormatter, onCellClick, className } = _a, props = __rest(_a, ["data", "startDate", "endDate", "cellSize", "cellGap", "cellRadius", "emptyColor", "colors", "minValue", "maxValue", "weekStartsOn", "showMonthLabels", "showWeekdayLabels", "showLegend", "animateOnRender", "animationDuration", "animationStagger", "showExportButton", "exportFileName", "exportFormats", "exportScale", "exportBackgroundColor", "showTooltips", "ariaLabel", "valueFormatter", "monthLabelFormatter", "weekdayLabelFormatter", "tooltipFormatter", "onCellClick", "className"]);
29
+ var { data, width, responsive = false, startDate, endDate, cellSize = 12, minCellSize = 6, cellGap = 4, cellRadius = 2, emptyColor, colors, minValue = 0, maxValue, weekStartsOn = 0, showMonthLabels = true, showWeekdayLabels = true, showLegend = true, animateOnRender = false, animationDuration = 350, animationStagger = 1, showExportButton = false, exportFileName = "heat-map", exportFormats = DEFAULT_CHART_EXPORT_FORMATS, exportScale = 2, exportBackgroundColor, showTooltips = false, ariaLabel = "Heat map", valueFormatter, monthLabelFormatter, weekdayLabelFormatter, tooltipFormatter, onCellClick, className } = _a, props = __rest(_a, ["data", "width", "responsive", "startDate", "endDate", "cellSize", "minCellSize", "cellGap", "cellRadius", "emptyColor", "colors", "minValue", "maxValue", "weekStartsOn", "showMonthLabels", "showWeekdayLabels", "showLegend", "animateOnRender", "animationDuration", "animationStagger", "showExportButton", "exportFileName", "exportFormats", "exportScale", "exportBackgroundColor", "showTooltips", "ariaLabel", "valueFormatter", "monthLabelFormatter", "weekdayLabelFormatter", "tooltipFormatter", "onCellClick", "className"]);
30
30
  const descriptionId = useId();
31
31
  const theme = useTheme();
32
32
  const containerRef = useRef(null);
33
+ const chartSizeRef = useRef(null);
33
34
  const svgRef = useRef(null);
34
35
  const [activeCellKey, setActiveCellKey] = useState(null);
35
36
  const [activeTooltip, setActiveTooltip] = useState(null);
@@ -73,12 +74,12 @@ const HeatMapInner = (_a, ref) => {
73
74
  .map((datum) => datum.value)
74
75
  .filter((value) => Number.isFinite(value));
75
76
  const resolvedMaxValue = maxValue !== null && maxValue !== void 0 ? maxValue : Math.max(...values, minValue, 1);
76
- const safeCellSize = Math.max(cellSize, 1);
77
+ const preferredCellSize = Math.max(cellSize, 1);
78
+ const safeMinCellSize = Math.max(minCellSize, 1);
77
79
  const safeCellGap = Math.max(cellGap, 0);
78
80
  const safeCellRadius = Math.max(cellRadius, 0);
79
81
  const labelWidth = showWeekdayLabels ? 28 : 0;
80
82
  const monthLabelHeight = showMonthLabels ? 18 : 0;
81
- const step = safeCellSize + safeCellGap;
82
83
  const cells = useMemo(() => buildHeatMapCells({
83
84
  data,
84
85
  startDate: resolvedStartDate,
@@ -100,8 +101,28 @@ const HeatMapInner = (_a, ref) => {
100
101
  weekStartsOn,
101
102
  ]);
102
103
  const weekCount = cells.length > 0 ? Math.max(...cells.map((cell) => cell.weekIndex)) + 1 : 1;
103
- const width = labelWidth + weekCount * step - safeCellGap;
104
- const height = monthLabelHeight + 7 * step - safeCellGap;
104
+ const preferredStep = preferredCellSize + safeCellGap;
105
+ const preferredWidth = labelWidth + weekCount * preferredStep - safeCellGap;
106
+ const preferredHeight = monthLabelHeight + 7 * preferredStep - safeCellGap;
107
+ const chartSize = useChartResponsiveSize(chartSizeRef, {
108
+ width,
109
+ responsive,
110
+ defaultWidth: preferredWidth,
111
+ defaultHeight: preferredHeight,
112
+ minWidth: 1,
113
+ minHeight: 1,
114
+ });
115
+ const shouldFitWidth = responsive || width != null;
116
+ const targetCellSize = (chartSize.width - labelWidth + safeCellGap) / weekCount - safeCellGap;
117
+ const safeCellSize = shouldFitWidth
118
+ ? Math.max(targetCellSize, safeMinCellSize)
119
+ : preferredCellSize;
120
+ const step = safeCellSize + safeCellGap;
121
+ const chartWidth = labelWidth + weekCount * step - safeCellGap;
122
+ const chartHeight = monthLabelHeight + 7 * step - safeCellGap;
123
+ const chartWidthStyle = typeof width === "number" && Number.isFinite(width)
124
+ ? `${chartSize.width}px`
125
+ : chartSize.widthStyle;
105
126
  const formatValue = (cell) => { var _a; return (_a = valueFormatter === null || valueFormatter === void 0 ? void 0 : valueFormatter(cell.value, cell.datum)) !== null && _a !== void 0 ? _a : formatDefaultValue(cell.value); };
106
127
  const getCellFill = (cell) => {
107
128
  if (!cell.datum)
@@ -172,7 +193,7 @@ const HeatMapInner = (_a, ref) => {
172
193
  const elapsed = animationElapsed - index * safeAnimationStagger;
173
194
  return easeOutCubic(clamp(elapsed / safeAnimationDuration, 0, 1));
174
195
  };
175
- return (_jsxs(StyledContainer, Object.assign({ ref: containerRef, className: className }, props, { children: [_jsx(StyledChartScroller, { children: _jsxs(StyledChartFrame, { children: [showExportButton && exportFormats.length > 0 && (_jsx(StyledChartActions, { "data-chart-export-ignore": "true", children: _jsx(ChartExportControl, { rootRef: containerRef, svgRef: svgRef, fileName: exportFileName, formats: exportFormats, scale: exportScale, backgroundColor: resolvedExportBackgroundColor }) })), _jsxs(StyledSvg, { ref: svgRef, width: width, height: height, viewBox: `0 0 ${width} ${height}`, role: "img", "aria-label": ariaLabel, "aria-describedby": descriptionId, children: [_jsx("desc", { id: descriptionId, children: description }), showMonthLabels &&
196
+ return (_jsxs(StyledContainer, Object.assign({ ref: containerRef, className: className, "$fillAvailableWidth": chartSize.fillAvailableWidth }, props, { children: [_jsx(StyledChartScroller, { ref: chartSizeRef, "$width": chartWidthStyle, children: _jsxs(StyledChartFrame, { children: [showExportButton && exportFormats.length > 0 && (_jsx(StyledChartActions, { "data-chart-export-ignore": "true", children: _jsx(ChartExportControl, { rootRef: containerRef, svgRef: svgRef, fileName: exportFileName, formats: exportFormats, scale: exportScale, backgroundColor: resolvedExportBackgroundColor }) })), _jsxs(StyledSvg, { ref: svgRef, width: chartWidth, height: chartHeight, viewBox: `0 0 ${chartWidth} ${chartHeight}`, role: "img", "aria-label": ariaLabel, "aria-describedby": descriptionId, children: [_jsx("desc", { id: descriptionId, children: description }), showMonthLabels &&
176
197
  monthLabels.map((monthLabel) => (_jsx(StyledMonthLabel, { x: labelWidth + monthLabel.weekIndex * step, y: 10, children: monthLabel.label }, `${monthLabel.label}-${monthLabel.weekIndex}`))), showWeekdayLabels &&
177
198
  Array.from({ length: 7 }, (_, dayIndex) => {
178
199
  var _a;
@@ -1,6 +1,10 @@
1
1
  import { StyledChartActions } from "../ChartPrimitives";
2
- export declare const StyledContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
3
- export declare const StyledChartScroller: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
2
+ export declare const StyledContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
3
+ $fillAvailableWidth: boolean;
4
+ }>> & string;
5
+ export declare const StyledChartScroller: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
6
+ $width?: string;
7
+ }>> & string;
4
8
  export declare const StyledChartFrame: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
5
9
  export { StyledChartActions };
6
10
  export declare const StyledSvg: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").SVGProps<SVGSVGElement>, never>> & string;
@@ -9,16 +9,19 @@ export const StyledContainer = styled.div `
9
9
  display: inline-flex;
10
10
  flex-direction: column;
11
11
  gap: 10px;
12
+ width: ${({ $fillAvailableWidth }) => $fillAvailableWidth ? "100%" : "fit-content"};
12
13
  max-width: 100%;
13
14
  color: ${({ theme }) => theme.palette.text.primary};
14
15
  overflow: visible;
15
16
  `;
16
17
  export const StyledChartScroller = styled.div `
17
18
  display: flex;
19
+ width: ${({ $width }) => $width !== null && $width !== void 0 ? $width : "auto"};
18
20
  max-width: 100%;
19
21
  overflow-x: auto;
20
22
  overflow-y: visible;
21
23
  padding-bottom: 2px;
24
+ box-sizing: border-box;
22
25
  `;
23
26
  export const StyledChartFrame = styled.div `
24
27
  position: relative;
@@ -1,5 +1,5 @@
1
1
  import React, { HTMLAttributes } from "react";
2
- import type { ChartExportOptions } from "../ChartUtils";
2
+ import type { ChartDimension, ChartExportOptions } from "../ChartUtils";
3
3
  export type HeatMapDatum<TData = unknown> = {
4
4
  /** Date represented by this cell. ISO yyyy-mm-dd strings are recommended. */
5
5
  date: Date | string;
@@ -31,12 +31,18 @@ export type HeatMapTooltipState = {
31
31
  export type HeatMapProps<TData = unknown> = HTMLAttributes<HTMLDivElement> & ChartExportOptions & {
32
32
  /** Values rendered by the heatmap. Missing dates render as empty cells. */
33
33
  data: HeatMapDatum<TData>[];
34
+ /** Target heatmap width in pixels or any CSS length measured from the chart frame. */
35
+ width?: ChartDimension;
36
+ /** Measures the chart frame and resizes cells to fit the available width. Defaults to false. */
37
+ responsive?: boolean;
34
38
  /** First date to render. Defaults to the earliest date in data. */
35
39
  startDate?: Date | string;
36
40
  /** Last date to render. Defaults to the latest date in data. */
37
41
  endDate?: Date | string;
38
42
  /** Size of each square cell in pixels. Defaults to 12. */
39
43
  cellSize?: number;
44
+ /** Minimum rendered cell size in pixels when responsive sizing is active. Defaults to 6. */
45
+ minCellSize?: number;
40
46
  /** Gap between cells in pixels. Defaults to 4. */
41
47
  cellGap?: number;
42
48
  /** Cell corner radius in pixels. Defaults to 2. */