@fluentui/react-charts 0.0.0-nightly-20251216-0407.1 → 0.0.0-nightly-20251218-0407.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.
- package/CHANGELOG.md +38 -13
- package/dist/index.d.ts +11 -1
- package/lib/components/AreaChart/AreaChart.js +1 -28
- package/lib/components/AreaChart/AreaChart.js.map +1 -1
- package/lib/components/AreaChart/useAreaChartStyles.styles.js +1 -2
- package/lib/components/AreaChart/useAreaChartStyles.styles.js.map +1 -1
- package/lib/components/ChartTable/ChartTable.js +6 -1
- package/lib/components/ChartTable/ChartTable.js.map +1 -1
- package/lib/components/CommonComponents/CartesianChart.js +42 -31
- package/lib/components/CommonComponents/CartesianChart.js.map +1 -1
- package/lib/components/CommonComponents/CartesianChart.types.js.map +1 -1
- package/lib/components/CommonComponents/useCartesianChartStyles.styles.js +5 -5
- package/lib/components/CommonComponents/useCartesianChartStyles.styles.js.map +1 -1
- package/lib/components/CommonComponents/useCartesianChartStyles.styles.raw.js +4 -3
- package/lib/components/CommonComponents/useCartesianChartStyles.styles.raw.js.map +1 -1
- package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js +12 -10
- package/lib/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
- package/lib/components/DonutChart/DonutChart.js +6 -3
- package/lib/components/DonutChart/DonutChart.js.map +1 -1
- package/lib/components/FunnelChart/FunnelChart.js +6 -3
- package/lib/components/FunnelChart/FunnelChart.js.map +1 -1
- package/lib/components/GaugeChart/GaugeChart.js +6 -3
- package/lib/components/GaugeChart/GaugeChart.js.map +1 -1
- package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +2 -17
- package/lib/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -1
- package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +1 -2
- package/lib/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -1
- package/lib/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js +2 -4
- package/lib/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js.map +1 -1
- package/lib/components/Legends/Legends.js +3 -4
- package/lib/components/Legends/Legends.js.map +1 -1
- package/lib/components/LineChart/LineChart.js +1 -23
- package/lib/components/LineChart/LineChart.js.map +1 -1
- package/lib/components/LineChart/useLineChartStyles.styles.js +1 -2
- package/lib/components/LineChart/useLineChartStyles.styles.js.map +1 -1
- package/lib/components/SankeyChart/SankeyChart.js +1 -1
- package/lib/components/SankeyChart/SankeyChart.js.map +1 -1
- package/lib/components/SankeyChart/useSankeyChartStyles.styles.js +1 -2
- package/lib/components/SankeyChart/useSankeyChartStyles.styles.js.map +1 -1
- package/lib/components/ScatterChart/ScatterChart.js +1 -23
- package/lib/components/ScatterChart/ScatterChart.js.map +1 -1
- package/lib/components/ScatterChart/useScatterChartStyles.styles.js +1 -2
- package/lib/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -1
- package/lib/components/VerticalBarChart/VerticalBarChart.js +1 -73
- package/lib/components/VerticalBarChart/VerticalBarChart.js.map +1 -1
- package/lib/components/VerticalBarChart/useVerticalBarChartStyles.styles.js +1 -2
- package/lib/components/VerticalBarChart/useVerticalBarChartStyles.styles.js.map +1 -1
- package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js +8 -28
- package/lib/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
- package/lib/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js +1 -2
- package/lib/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js.map +1 -1
- package/lib/utilities/Common.styles.js +0 -1
- package/lib/utilities/Common.styles.js.map +1 -1
- package/lib/utilities/Common.styles.raw.js +0 -1
- package/lib/utilities/Common.styles.raw.js.map +1 -1
- package/lib/utilities/image-export-utils.js +4 -4
- package/lib/utilities/image-export-utils.js.map +1 -1
- package/lib/utilities/utilities.js +200 -67
- package/lib/utilities/utilities.js.map +1 -1
- package/lib-commonjs/components/AreaChart/AreaChart.js +0 -26
- package/lib-commonjs/components/AreaChart/AreaChart.js.map +1 -1
- package/lib-commonjs/components/AreaChart/useAreaChartStyles.styles.js +0 -2
- package/lib-commonjs/components/AreaChart/useAreaChartStyles.styles.js.map +1 -1
- package/lib-commonjs/components/ChartTable/ChartTable.js +6 -1
- package/lib-commonjs/components/ChartTable/ChartTable.js.map +1 -1
- package/lib-commonjs/components/CommonComponents/CartesianChart.js +41 -30
- package/lib-commonjs/components/CommonComponents/CartesianChart.js.map +1 -1
- package/lib-commonjs/components/CommonComponents/CartesianChart.types.js.map +1 -1
- package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.js +3 -4
- package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.js.map +1 -1
- package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.raw.js +3 -2
- package/lib-commonjs/components/CommonComponents/useCartesianChartStyles.styles.raw.js.map +1 -1
- package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js +12 -10
- package/lib-commonjs/components/DeclarativeChart/PlotlySchemaAdapter.js.map +1 -1
- package/lib-commonjs/components/DonutChart/DonutChart.js +5 -2
- package/lib-commonjs/components/DonutChart/DonutChart.js.map +1 -1
- package/lib-commonjs/components/FunnelChart/FunnelChart.js +5 -2
- package/lib-commonjs/components/FunnelChart/FunnelChart.js.map +1 -1
- package/lib-commonjs/components/GaugeChart/GaugeChart.js +5 -2
- package/lib-commonjs/components/GaugeChart/GaugeChart.js.map +1 -1
- package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js +0 -15
- package/lib-commonjs/components/GroupedVerticalBarChart/GroupedVerticalBarChart.js.map +1 -1
- package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js +0 -2
- package/lib-commonjs/components/GroupedVerticalBarChart/useGroupedVerticalBarChartStyles.styles.js.map +1 -1
- package/lib-commonjs/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js +2 -4
- package/lib-commonjs/components/HorizontalBarChartWithAxis/HorizontalBarChartWithAxis.js.map +1 -1
- package/lib-commonjs/components/Legends/Legends.js +3 -4
- package/lib-commonjs/components/Legends/Legends.js.map +1 -1
- package/lib-commonjs/components/LineChart/LineChart.js +0 -22
- package/lib-commonjs/components/LineChart/LineChart.js.map +1 -1
- package/lib-commonjs/components/LineChart/useLineChartStyles.styles.js +0 -2
- package/lib-commonjs/components/LineChart/useLineChartStyles.styles.js.map +1 -1
- package/lib-commonjs/components/SankeyChart/SankeyChart.js +1 -1
- package/lib-commonjs/components/SankeyChart/SankeyChart.js.map +1 -1
- package/lib-commonjs/components/SankeyChart/useSankeyChartStyles.styles.js +0 -2
- package/lib-commonjs/components/SankeyChart/useSankeyChartStyles.styles.js.map +1 -1
- package/lib-commonjs/components/ScatterChart/ScatterChart.js +0 -22
- package/lib-commonjs/components/ScatterChart/ScatterChart.js.map +1 -1
- package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js +0 -2
- package/lib-commonjs/components/ScatterChart/useScatterChartStyles.styles.js.map +1 -1
- package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.js +0 -72
- package/lib-commonjs/components/VerticalBarChart/VerticalBarChart.js.map +1 -1
- package/lib-commonjs/components/VerticalBarChart/useVerticalBarChartStyles.styles.js +0 -2
- package/lib-commonjs/components/VerticalBarChart/useVerticalBarChartStyles.styles.js.map +1 -1
- package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js +7 -27
- package/lib-commonjs/components/VerticalStackedBarChart/VerticalStackedBarChart.js.map +1 -1
- package/lib-commonjs/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js +0 -2
- package/lib-commonjs/components/VerticalStackedBarChart/useVerticalStackedBarChartStyles.styles.js.map +1 -1
- package/lib-commonjs/utilities/Common.styles.js +0 -1
- package/lib-commonjs/utilities/Common.styles.js.map +1 -1
- package/lib-commonjs/utilities/Common.styles.raw.js +0 -1
- package/lib-commonjs/utilities/Common.styles.raw.js.map +1 -1
- package/lib-commonjs/utilities/image-export-utils.js +3 -3
- package/lib-commonjs/utilities/image-export-utils.js.map +1 -1
- package/lib-commonjs/utilities/utilities.js +212 -70
- package/lib-commonjs/utilities/utilities.js.map +1 -1
- package/package.json +12 -12
- package/lib/components/DeclarativeChart/imageExporter.js +0 -223
- package/lib/components/DeclarativeChart/imageExporter.js.map +0 -1
- package/lib-commonjs/components/DeclarativeChart/imageExporter.js +0 -233
- package/lib-commonjs/components/DeclarativeChart/imageExporter.js.map +0 -1
|
@@ -268,8 +268,8 @@ function cloneLegendsToSVG(legends, svgWidth, config, legendContainer) {
|
|
|
268
268
|
const noLegendsSelected = Object.keys(selectedLegends).length === 0;
|
|
269
269
|
for(let i = 0; i < legends.length; i++){
|
|
270
270
|
const textOffset = _useLegendsStylesstyles.LEGEND_PADDING + _useLegendsStylesstyles.LEGEND_SHAPE_SIZE + _useLegendsStylesstyles.LEGEND_SHAPE_MARGIN_END;
|
|
271
|
-
const legendText = (0, _index.
|
|
272
|
-
const legendWidth = textOffset + legendText.
|
|
271
|
+
const legendText = (0, _index.measureTextWithDOM)(legends[i].title, `.${textClassName}`, legendContainer);
|
|
272
|
+
const legendWidth = textOffset + legendText.width + _useLegendsStylesstyles.LEGEND_PADDING;
|
|
273
273
|
const legendItem = legendGroup.append('g');
|
|
274
274
|
legendLine.push({
|
|
275
275
|
elem: legendItem,
|
|
@@ -290,7 +290,7 @@ function cloneLegendsToSVG(legends, svgWidth, config, legendContainer) {
|
|
|
290
290
|
}
|
|
291
291
|
const isLegendActive = selectedLegends[legends[i].title] || noLegendsSelected;
|
|
292
292
|
legendItem.append('rect').attr('x', legendX + (isRTL ? legendWidth - _useLegendsStylesstyles.LEGEND_PADDING - _useLegendsStylesstyles.LEGEND_SHAPE_SIZE : _useLegendsStylesstyles.LEGEND_PADDING)).attr('y', legendY + _useLegendsStylesstyles.LEGEND_PADDING).attr('width', _useLegendsStylesstyles.LEGEND_SHAPE_SIZE).attr('height', _useLegendsStylesstyles.LEGEND_SHAPE_SIZE).style('fill', isLegendActive ? legends[i].color : 'transparent').style('stroke-width', _useLegendsStylesstyles.LEGEND_SHAPE_BORDER).style('stroke', legends[i].color);
|
|
293
|
-
legendItem.append('text').attr('x', legendX + (isRTL ? legendWidth - textOffset : textOffset)).attr('y', legendY + _useLegendsStylesstyles.LEGEND_PADDING).attr('dominant-baseline', 'hanging').style('opacity', isLegendActive ? 1 : _useLegendsStylesstyles.INACTIVE_LEGEND_TEXT_OPACITY).text(legends[i].title).call((selection)=>(0, _index.copyStyle)(LEGEND_TEXT_STYLE_PROPERTIES_MAP, legendText, selection.node()));
|
|
293
|
+
legendItem.append('text').attr('x', legendX + (isRTL ? legendWidth - textOffset : textOffset)).attr('y', legendY + _useLegendsStylesstyles.LEGEND_PADDING).attr('dominant-baseline', 'hanging').style('opacity', isLegendActive ? 1 : _useLegendsStylesstyles.INACTIVE_LEGEND_TEXT_OPACITY).text(legends[i].title).call((selection)=>(0, _index.copyStyle)(LEGEND_TEXT_STYLE_PROPERTIES_MAP, legendText.node, selection.node()));
|
|
294
294
|
legendX += legendWidth;
|
|
295
295
|
}
|
|
296
296
|
legendLines.push(legendLine);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utilities/image-export-utils.ts"],"sourcesContent":["'use client';\n\nimport { create as d3Create, select as d3Select, Selection } from 'd3-selection';\nimport { isHTMLElement } from '@fluentui/react-utilities';\nimport { copyStyle, createMeasurementSpan } from './index';\nimport { ImageExportOptions } from '../types/index';\nimport { Legend, LegendContainer } from '../Legends';\nimport {\n LEGEND_CONTAINER_MARGIN_TOP,\n LEGEND_CONTAINER_MARGIN_START,\n LEGEND_PADDING,\n LEGEND_HEIGHT,\n LEGEND_SHAPE_BORDER,\n LEGEND_SHAPE_SIZE,\n LEGEND_SHAPE_MARGIN_END,\n INACTIVE_LEGEND_TEXT_OPACITY,\n} from '../components/Legends/useLegendsStyles.styles';\n\nexport type GridChart = {\n container: HTMLElement | null | undefined;\n row?: number;\n col?: number;\n};\n\ntype SvgImage = {\n dataUrl: string;\n width: number;\n height: number;\n};\n\nexport async function exportChartsAsImage(\n charts: GridChart[],\n legendsToSvg?: LegendContainer['toSVG'],\n isRTL: boolean = false,\n opts: ImageExportOptions = {},\n): Promise<string> {\n if (charts.length === 0 && !legendsToSvg) {\n throw new Error('No charts or legends to export');\n }\n\n const chartImages = await Promise.all(\n charts.map(chart => {\n return new Promise<SvgImage>(resolve => {\n const svg = cloneStyledSVG(chart.container, isRTL);\n const svgDataUrl = svgToBase64(svg.node);\n resolve({ dataUrl: svgDataUrl, width: svg.width, height: svg.height });\n });\n }),\n );\n\n const grid: SvgImage[][] = []; // Sparse 2D array\n charts.forEach((chart, i) => {\n const row = chart.row || 0;\n const col = chart.col || 0;\n if (!grid[row]) {\n grid[row] = [];\n }\n grid[row][col] = chartImages[i];\n });\n\n if (legendsToSvg) {\n let totalWidth = 0;\n grid.forEach(row => {\n let rowWidth = 0;\n row.forEach(item => {\n rowWidth += item.width;\n });\n totalWidth = Math.max(totalWidth, rowWidth);\n });\n\n const svg = legendsToSvg(totalWidth, isRTL);\n if (svg.node) {\n const svgDataUrl = svgToBase64(svg.node);\n grid.push([{ dataUrl: svgDataUrl, width: svg.width, height: svg.height }]);\n }\n }\n\n return svgToPng(grid, opts);\n}\n\nconst SVG_STYLE_PROPERTIES = [\n 'display',\n 'fill',\n 'fill-opacity',\n 'opacity',\n 'stroke',\n 'stroke-width',\n 'transform',\n 'border-collapse',\n];\nconst SVG_TEXT_STYLE_PROPERTIES = [\n 'font-family',\n 'font-size',\n 'font-weight',\n 'text-anchor',\n 'background-color',\n 'color',\n 'padding',\n 'text-align',\n 'border',\n];\n\nconst ANNOTATION_HTML_STYLE_PROPERTIES = [\n 'align-items',\n 'background',\n 'background-color',\n 'border',\n 'border-radius',\n 'box-shadow',\n 'box-sizing',\n 'color',\n 'column-gap',\n 'display',\n 'flex',\n 'flex-direction',\n 'font-family',\n 'font-size',\n 'font-style',\n 'font-weight',\n 'gap',\n 'height',\n 'justify-content',\n 'letter-spacing',\n 'line-height',\n 'margin',\n 'max-height',\n 'max-width',\n 'min-height',\n 'min-width',\n 'opacity',\n 'overflow',\n 'padding',\n 'pointer-events',\n 'position',\n 'row-gap',\n 'text-align',\n 'text-decoration',\n 'text-transform',\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'visibility',\n 'white-space',\n 'width',\n 'z-index',\n];\nconst ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES = ['overflow', 'pointer-events'];\n\nfunction cloneStyledSVG(chartContainer: HTMLElement | null | undefined, isRTL: boolean) {\n if (!chartContainer) {\n throw new Error('Chart container is not defined');\n }\n\n const svg = chartContainer.querySelector<SVGSVGElement>('svg');\n if (!svg) {\n throw new Error('SVG not found');\n }\n\n let clonedSvg = d3Select(svg.cloneNode(true) as SVGSVGElement)\n .attr('width', null)\n .attr('height', null)\n .attr('viewBox', null);\n let svgElements = svg.getElementsByTagName('*');\n let clonedSvgElements = clonedSvg.node()!.getElementsByTagName('*');\n\n const TEXT_ELEMENTS = ['text'];\n const TABLE_ELEMENTS = ['table', 'thead', 'tbody', 'tr', 'th', 'td'];\n\n for (let i = 0; i < svgElements.length; i++) {\n const tag = svgElements[i].tagName.toLowerCase();\n\n if (TEXT_ELEMENTS.includes(tag) || TABLE_ELEMENTS.includes(tag)) {\n copyStyle([...SVG_STYLE_PROPERTIES, ...SVG_TEXT_STYLE_PROPERTIES], svgElements[i], clonedSvgElements[i]);\n } else {\n copyStyle(SVG_STYLE_PROPERTIES, svgElements[i], clonedSvgElements[i]);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n svgElements = null as any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n clonedSvgElements = null as any;\n\n const originalForeignObjects = svg.querySelectorAll('foreignObject');\n const clonedForeignObjects = clonedSvg.node()!.querySelectorAll('foreignObject');\n\n originalForeignObjects.forEach((originalFo, index) => {\n const clonedFo = clonedForeignObjects[index];\n if (!clonedFo) {\n return;\n }\n\n const originalRoot = originalFo.firstElementChild as HTMLElement | null;\n const clonedRoot = clonedFo.firstElementChild as HTMLElement | null;\n\n if (originalRoot && clonedRoot) {\n copyStyle(ANNOTATION_HTML_STYLE_PROPERTIES, originalRoot, clonedRoot);\n }\n\n const originalHtmlElements = originalFo.querySelectorAll<HTMLElement>('*');\n const clonedHtmlElements = clonedFo.querySelectorAll<HTMLElement>('*');\n\n originalHtmlElements.forEach((originalEl, elementIndex) => {\n const clonedEl = clonedHtmlElements[elementIndex];\n if (clonedEl) {\n copyStyle(ANNOTATION_HTML_STYLE_PROPERTIES, originalEl, clonedEl);\n }\n });\n });\n\n const annotationSvg = chartContainer.querySelector<SVGSVGElement>('[data-chart-annotation-svg=\"true\"]');\n let annotationClone: SVGSVGElement | null = null;\n\n if (annotationSvg) {\n annotationClone = annotationSvg.cloneNode(true) as SVGSVGElement;\n copyStyle(SVG_STYLE_PROPERTIES, annotationSvg, annotationClone);\n\n const annotationElements = annotationSvg.getElementsByTagName('*');\n const clonedAnnotationElements = annotationClone.getElementsByTagName('*');\n\n for (let i = 0; i < annotationElements.length; i++) {\n const original = annotationElements[i];\n const cloned = clonedAnnotationElements[i];\n const tag = original.tagName.toLowerCase();\n const isSvgElement = original instanceof SVGElement;\n const isTextElement = tag === 'text';\n const isHtmlElement = isHTMLElement(original);\n\n if (isSvgElement) {\n if (isTextElement) {\n copyStyle([...SVG_STYLE_PROPERTIES, ...SVG_TEXT_STYLE_PROPERTIES], original, cloned);\n } else {\n copyStyle(SVG_STYLE_PROPERTIES, original, cloned);\n }\n }\n\n if (isHtmlElement) {\n copyStyle(ANNOTATION_HTML_STYLE_PROPERTIES, original, cloned);\n }\n\n if (tag === 'foreignobject') {\n copyStyle(ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES, original, cloned);\n }\n }\n }\n\n const { width, height } = svg.getBoundingClientRect();\n\n clonedSvg\n .attr('width', width)\n .attr('height', height)\n .attr('viewBox', `0 0 ${width} ${height}`)\n .attr('direction', isRTL ? 'rtl' : 'ltr');\n\n if (annotationClone) {\n clonedSvg.selectAll('[data-chart-annotation-layer=\"true\"]').remove();\n d3Select(annotationClone).attr('x', 0).attr('y', 0).attr('width', width).attr('height', height);\n clonedSvg.append(() => annotationClone as SVGSVGElement);\n }\n const result = {\n node: clonedSvg.node(),\n width,\n height,\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n clonedSvg = null as any;\n\n return result;\n}\n\nconst LEGEND_TEXT_STYLE_PROPERTIES_MAP = {\n color: 'fill',\n 'font-family': 'font-family',\n 'font-size': 'font-size',\n 'font-weight': 'font-weight',\n};\n\nexport function cloneLegendsToSVG(\n legends: Legend[],\n svgWidth: number,\n config: {\n selectedLegends: Record<string, boolean>;\n centerLegends: boolean;\n textClassName: string;\n isRTL: boolean;\n },\n legendContainer?: HTMLElement | null,\n): {\n node: SVGSVGElement | null;\n width: number;\n height: number;\n} {\n if (legends.length === 0) {\n return {\n node: null,\n width: 0,\n height: 0,\n };\n }\n\n const { selectedLegends, centerLegends, textClassName, isRTL } = config;\n const legendGroup = d3Create<SVGGElement>('svg:g');\n let legendX = centerLegends ? 0 : LEGEND_CONTAINER_MARGIN_START;\n let legendY = LEGEND_CONTAINER_MARGIN_TOP;\n let legendLine: { elem: Selection<SVGGElement, unknown, null, undefined>; width: number }[] = [];\n const legendLines: (typeof legendLine)[] = [];\n const legendLineWidths: number[] = [];\n const noLegendsSelected = Object.keys(selectedLegends).length === 0;\n\n for (let i = 0; i < legends.length; i++) {\n const textOffset = LEGEND_PADDING + LEGEND_SHAPE_SIZE + LEGEND_SHAPE_MARGIN_END;\n const legendText = createMeasurementSpan(legends[i].title, textClassName, legendContainer);\n const legendWidth = textOffset + legendText.getBoundingClientRect().width + LEGEND_PADDING;\n const legendItem = legendGroup.append('g');\n\n legendLine.push({ elem: legendItem, width: legendWidth });\n if (legendX + legendWidth > svgWidth && legendLine.length > 1) {\n legendLine.pop();\n legendLines.push(legendLine);\n legendLineWidths.push(legendX);\n\n legendLine = [{ elem: legendItem, width: legendWidth }];\n legendX = centerLegends ? 0 : LEGEND_CONTAINER_MARGIN_START;\n legendY += LEGEND_HEIGHT;\n }\n\n const isLegendActive = selectedLegends[legends[i].title] || noLegendsSelected;\n\n legendItem\n .append('rect')\n .attr('x', legendX + (isRTL ? legendWidth - LEGEND_PADDING - LEGEND_SHAPE_SIZE : LEGEND_PADDING))\n .attr('y', legendY + LEGEND_PADDING)\n .attr('width', LEGEND_SHAPE_SIZE)\n .attr('height', LEGEND_SHAPE_SIZE)\n .style('fill', isLegendActive ? legends[i].color : 'transparent')\n .style('stroke-width', LEGEND_SHAPE_BORDER)\n .style('stroke', legends[i].color);\n\n legendItem\n .append('text')\n .attr('x', legendX + (isRTL ? legendWidth - textOffset : textOffset))\n .attr('y', legendY + LEGEND_PADDING)\n .attr('dominant-baseline', 'hanging')\n .style('opacity', isLegendActive ? 1 : INACTIVE_LEGEND_TEXT_OPACITY)\n .text(legends[i].title)\n .call(selection => copyStyle(LEGEND_TEXT_STYLE_PROPERTIES_MAP, legendText, selection.node()!));\n\n legendX += legendWidth;\n }\n\n legendLines.push(legendLine);\n legendLineWidths.push(legendX);\n legendY += LEGEND_HEIGHT;\n\n if (centerLegends) {\n legendLines.forEach((ln, idx) => {\n const lineOffsetX = Math.max((svgWidth - legendLineWidths[idx]) / 2, 0);\n let remLineWidth = legendLineWidths[idx];\n let itemOffsetX = 0;\n ln.forEach(item => {\n const newOffsetX = lineOffsetX + (isRTL ? remLineWidth - item.width - itemOffsetX : 0);\n item.elem.attr('transform', `translate(${newOffsetX}, 0)`);\n remLineWidth -= item.width;\n itemOffsetX += item.width;\n });\n });\n } else if (isRTL) {\n const w1 = Math.max(svgWidth, ...legendLineWidths);\n legendLines.forEach(ln => {\n let remLineWidth = w1 - LEGEND_CONTAINER_MARGIN_START;\n let itemOffsetX = LEGEND_CONTAINER_MARGIN_START;\n ln.forEach(item => {\n const newOffsetX = remLineWidth - item.width - itemOffsetX;\n item.elem.attr('transform', `translate(${newOffsetX}, 0)`);\n remLineWidth -= item.width;\n itemOffsetX += item.width;\n });\n });\n }\n\n const w1 = Math.max(svgWidth, ...legendLineWidths);\n const h1 = legendY;\n const svg = d3Create<SVGSVGElement>('svg').attr('width', w1).attr('height', h1).attr('viewBox', `0 0 ${w1} ${h1}`);\n svg.append(() => legendGroup.node()!);\n\n return {\n node: svg.node(),\n width: w1,\n height: h1,\n };\n}\n\ntype PositionedImage = SvgImage & {\n x: number;\n y: number;\n};\n\nasync function svgToPng(grid: SvgImage[][], opts: ImageExportOptions = {}): Promise<string> {\n let totalWidth = 0;\n let totalHeight = 0;\n\n const positionedImages: PositionedImage[] = grid\n .map(row => {\n let rowWidth = 0;\n let rowHeight = 0;\n\n const items = row.map(item => {\n const positioned = { ...item, x: rowWidth, y: totalHeight };\n rowWidth += item.width;\n rowHeight = Math.max(rowHeight, item.height);\n return positioned;\n });\n\n totalWidth = Math.max(totalWidth, rowWidth);\n totalHeight += rowHeight;\n\n return items;\n })\n .flat();\n\n const scale = opts.scale || 1;\n const w0 = opts.width || totalWidth;\n const h0 = opts.height || totalHeight;\n const scaleX = (scale * w0) / totalWidth;\n const scaleY = (scale * h0) / totalHeight;\n totalWidth = scaleX * totalWidth;\n totalHeight = scaleY * totalHeight;\n\n const canvas = document.createElement('canvas');\n canvas.width = totalWidth;\n canvas.height = totalHeight;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas context is null');\n }\n\n ctx.fillStyle = opts.background || 'transparent';\n ctx.fillRect(0, 0, totalWidth, totalHeight);\n\n await Promise.all(\n positionedImages.map(\n item =>\n new Promise<void>((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, scaleX * item.x, scaleY * item.y, scaleX * item.width, scaleY * item.height);\n resolve();\n };\n img.onerror = reject;\n img.src = item.dataUrl;\n }),\n ),\n );\n\n return canvas.toDataURL('image/png');\n}\n\nfunction svgToBase64(svgNode: SVGSVGElement | null) {\n if (!svgNode) {\n throw new Error('SVG node is null');\n }\n\n const svgData = new XMLSerializer().serializeToString(svgNode);\n const svgDataUrl = 'data:image/svg+xml;base64,' + btoa(unescapePonyfill(encodeURIComponent(svgData)));\n return svgDataUrl;\n}\n\nconst hex2 = /^[\\da-f]{2}$/i;\nconst hex4 = /^[\\da-f]{4}$/i;\n\n/**\n * A ponyfill for the deprecated `unescape` method, taken from the `core-js` library.\n *\n * Source: {@link https://github.com/zloirock/core-js/blob/167136f479d3b8519953f2e4c534ecdd1031d3cf/packages/core-js/modules/es.unescape.js core-js/packages/core-js/modules/es.unescape.js}\n */\nfunction unescapePonyfill(str: string) {\n let result = '';\n const length = str.length;\n let index = 0;\n let chr;\n let part;\n while (index < length) {\n chr = str.charAt(index++);\n if (chr === '%') {\n if (str.charAt(index) === 'u') {\n part = str.slice(index + 1, index + 5);\n if (hex4.exec(part)) {\n result += String.fromCharCode(parseInt(part, 16));\n index += 5;\n continue;\n }\n } else {\n part = str.slice(index, index + 2);\n if (hex2.exec(part)) {\n result += String.fromCharCode(parseInt(part, 16));\n index += 2;\n continue;\n }\n }\n }\n result += chr;\n }\n return result;\n}\n"],"names":["create","d3Create","select","d3Select","isHTMLElement","copyStyle","createMeasurementSpan","LEGEND_CONTAINER_MARGIN_TOP","LEGEND_CONTAINER_MARGIN_START","LEGEND_PADDING","LEGEND_HEIGHT","LEGEND_SHAPE_BORDER","LEGEND_SHAPE_SIZE","LEGEND_SHAPE_MARGIN_END","INACTIVE_LEGEND_TEXT_OPACITY","exportChartsAsImage","charts","legendsToSvg","isRTL","opts","length","Error","chartImages","Promise","all","map","chart","resolve","svg","cloneStyledSVG","container","svgDataUrl","svgToBase64","node","dataUrl","width","height","grid","forEach","i","row","col","totalWidth","rowWidth","item","Math","max","push","svgToPng","SVG_STYLE_PROPERTIES","SVG_TEXT_STYLE_PROPERTIES","ANNOTATION_HTML_STYLE_PROPERTIES","ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES","chartContainer","querySelector","clonedSvg","cloneNode","attr","svgElements","getElementsByTagName","clonedSvgElements","TEXT_ELEMENTS","TABLE_ELEMENTS","tag","tagName","toLowerCase","includes","originalForeignObjects","querySelectorAll","clonedForeignObjects","originalFo","index","clonedFo","originalRoot","firstElementChild","clonedRoot","originalHtmlElements","clonedHtmlElements","originalEl","elementIndex","clonedEl","annotationSvg","annotationClone","annotationElements","clonedAnnotationElements","original","cloned","isSvgElement","SVGElement","isTextElement","isHtmlElement","getBoundingClientRect","selectAll","remove","append","result","LEGEND_TEXT_STYLE_PROPERTIES_MAP","color","cloneLegendsToSVG","legends","svgWidth","config","legendContainer","selectedLegends","centerLegends","textClassName","legendGroup","legendX","legendY","legendLine","legendLines","legendLineWidths","noLegendsSelected","Object","keys","textOffset","legendText","title","legendWidth","legendItem","elem","pop","isLegendActive","style","text","call","selection","ln","idx","lineOffsetX","remLineWidth","itemOffsetX","newOffsetX","w1","h1","totalHeight","positionedImages","rowHeight","items","positioned","x","y","flat","scale","w0","h0","scaleX","scaleY","canvas","document","createElement","ctx","getContext","fillStyle","background","fillRect","reject","img","Image","onload","drawImage","onerror","src","toDataURL","svgNode","svgData","XMLSerializer","serializeToString","btoa","unescapePonyfill","encodeURIComponent","hex2","hex4","str","chr","part","charAt","slice","exec","String","fromCharCode","parseInt"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/utilities/image-export-utils.ts"],"sourcesContent":["'use client';\n\nimport { create as d3Create, select as d3Select, Selection } from 'd3-selection';\nimport { isHTMLElement } from '@fluentui/react-utilities';\nimport { copyStyle, measureTextWithDOM } from './index';\nimport { ImageExportOptions } from '../types/index';\nimport { Legend, LegendContainer } from '../Legends';\nimport {\n LEGEND_CONTAINER_MARGIN_TOP,\n LEGEND_CONTAINER_MARGIN_START,\n LEGEND_PADDING,\n LEGEND_HEIGHT,\n LEGEND_SHAPE_BORDER,\n LEGEND_SHAPE_SIZE,\n LEGEND_SHAPE_MARGIN_END,\n INACTIVE_LEGEND_TEXT_OPACITY,\n} from '../components/Legends/useLegendsStyles.styles';\n\nexport type GridChart = {\n container: HTMLElement | null | undefined;\n row?: number;\n col?: number;\n};\n\ntype SvgImage = {\n dataUrl: string;\n width: number;\n height: number;\n};\n\nexport async function exportChartsAsImage(\n charts: GridChart[],\n legendsToSvg?: LegendContainer['toSVG'],\n isRTL: boolean = false,\n opts: ImageExportOptions = {},\n): Promise<string> {\n if (charts.length === 0 && !legendsToSvg) {\n throw new Error('No charts or legends to export');\n }\n\n const chartImages = await Promise.all(\n charts.map(chart => {\n return new Promise<SvgImage>(resolve => {\n const svg = cloneStyledSVG(chart.container, isRTL);\n const svgDataUrl = svgToBase64(svg.node);\n resolve({ dataUrl: svgDataUrl, width: svg.width, height: svg.height });\n });\n }),\n );\n\n const grid: SvgImage[][] = []; // Sparse 2D array\n charts.forEach((chart, i) => {\n const row = chart.row || 0;\n const col = chart.col || 0;\n if (!grid[row]) {\n grid[row] = [];\n }\n grid[row][col] = chartImages[i];\n });\n\n if (legendsToSvg) {\n let totalWidth = 0;\n grid.forEach(row => {\n let rowWidth = 0;\n row.forEach(item => {\n rowWidth += item.width;\n });\n totalWidth = Math.max(totalWidth, rowWidth);\n });\n\n const svg = legendsToSvg(totalWidth, isRTL);\n if (svg.node) {\n const svgDataUrl = svgToBase64(svg.node);\n grid.push([{ dataUrl: svgDataUrl, width: svg.width, height: svg.height }]);\n }\n }\n\n return svgToPng(grid, opts);\n}\n\nconst SVG_STYLE_PROPERTIES = [\n 'display',\n 'fill',\n 'fill-opacity',\n 'opacity',\n 'stroke',\n 'stroke-width',\n 'transform',\n 'border-collapse',\n];\nconst SVG_TEXT_STYLE_PROPERTIES = [\n 'font-family',\n 'font-size',\n 'font-weight',\n 'text-anchor',\n 'background-color',\n 'color',\n 'padding',\n 'text-align',\n 'border',\n];\n\nconst ANNOTATION_HTML_STYLE_PROPERTIES = [\n 'align-items',\n 'background',\n 'background-color',\n 'border',\n 'border-radius',\n 'box-shadow',\n 'box-sizing',\n 'color',\n 'column-gap',\n 'display',\n 'flex',\n 'flex-direction',\n 'font-family',\n 'font-size',\n 'font-style',\n 'font-weight',\n 'gap',\n 'height',\n 'justify-content',\n 'letter-spacing',\n 'line-height',\n 'margin',\n 'max-height',\n 'max-width',\n 'min-height',\n 'min-width',\n 'opacity',\n 'overflow',\n 'padding',\n 'pointer-events',\n 'position',\n 'row-gap',\n 'text-align',\n 'text-decoration',\n 'text-transform',\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'visibility',\n 'white-space',\n 'width',\n 'z-index',\n];\nconst ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES = ['overflow', 'pointer-events'];\n\nfunction cloneStyledSVG(chartContainer: HTMLElement | null | undefined, isRTL: boolean) {\n if (!chartContainer) {\n throw new Error('Chart container is not defined');\n }\n\n const svg = chartContainer.querySelector<SVGSVGElement>('svg');\n if (!svg) {\n throw new Error('SVG not found');\n }\n\n let clonedSvg = d3Select(svg.cloneNode(true) as SVGSVGElement)\n .attr('width', null)\n .attr('height', null)\n .attr('viewBox', null);\n let svgElements = svg.getElementsByTagName('*');\n let clonedSvgElements = clonedSvg.node()!.getElementsByTagName('*');\n\n const TEXT_ELEMENTS = ['text'];\n const TABLE_ELEMENTS = ['table', 'thead', 'tbody', 'tr', 'th', 'td'];\n\n for (let i = 0; i < svgElements.length; i++) {\n const tag = svgElements[i].tagName.toLowerCase();\n\n if (TEXT_ELEMENTS.includes(tag) || TABLE_ELEMENTS.includes(tag)) {\n copyStyle([...SVG_STYLE_PROPERTIES, ...SVG_TEXT_STYLE_PROPERTIES], svgElements[i], clonedSvgElements[i]);\n } else {\n copyStyle(SVG_STYLE_PROPERTIES, svgElements[i], clonedSvgElements[i]);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n svgElements = null as any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n clonedSvgElements = null as any;\n\n const originalForeignObjects = svg.querySelectorAll('foreignObject');\n const clonedForeignObjects = clonedSvg.node()!.querySelectorAll('foreignObject');\n\n originalForeignObjects.forEach((originalFo, index) => {\n const clonedFo = clonedForeignObjects[index];\n if (!clonedFo) {\n return;\n }\n\n const originalRoot = originalFo.firstElementChild as HTMLElement | null;\n const clonedRoot = clonedFo.firstElementChild as HTMLElement | null;\n\n if (originalRoot && clonedRoot) {\n copyStyle(ANNOTATION_HTML_STYLE_PROPERTIES, originalRoot, clonedRoot);\n }\n\n const originalHtmlElements = originalFo.querySelectorAll<HTMLElement>('*');\n const clonedHtmlElements = clonedFo.querySelectorAll<HTMLElement>('*');\n\n originalHtmlElements.forEach((originalEl, elementIndex) => {\n const clonedEl = clonedHtmlElements[elementIndex];\n if (clonedEl) {\n copyStyle(ANNOTATION_HTML_STYLE_PROPERTIES, originalEl, clonedEl);\n }\n });\n });\n\n const annotationSvg = chartContainer.querySelector<SVGSVGElement>('[data-chart-annotation-svg=\"true\"]');\n let annotationClone: SVGSVGElement | null = null;\n\n if (annotationSvg) {\n annotationClone = annotationSvg.cloneNode(true) as SVGSVGElement;\n copyStyle(SVG_STYLE_PROPERTIES, annotationSvg, annotationClone);\n\n const annotationElements = annotationSvg.getElementsByTagName('*');\n const clonedAnnotationElements = annotationClone.getElementsByTagName('*');\n\n for (let i = 0; i < annotationElements.length; i++) {\n const original = annotationElements[i];\n const cloned = clonedAnnotationElements[i];\n const tag = original.tagName.toLowerCase();\n const isSvgElement = original instanceof SVGElement;\n const isTextElement = tag === 'text';\n const isHtmlElement = isHTMLElement(original);\n\n if (isSvgElement) {\n if (isTextElement) {\n copyStyle([...SVG_STYLE_PROPERTIES, ...SVG_TEXT_STYLE_PROPERTIES], original, cloned);\n } else {\n copyStyle(SVG_STYLE_PROPERTIES, original, cloned);\n }\n }\n\n if (isHtmlElement) {\n copyStyle(ANNOTATION_HTML_STYLE_PROPERTIES, original, cloned);\n }\n\n if (tag === 'foreignobject') {\n copyStyle(ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES, original, cloned);\n }\n }\n }\n\n const { width, height } = svg.getBoundingClientRect();\n\n clonedSvg\n .attr('width', width)\n .attr('height', height)\n .attr('viewBox', `0 0 ${width} ${height}`)\n .attr('direction', isRTL ? 'rtl' : 'ltr');\n\n if (annotationClone) {\n clonedSvg.selectAll('[data-chart-annotation-layer=\"true\"]').remove();\n d3Select(annotationClone).attr('x', 0).attr('y', 0).attr('width', width).attr('height', height);\n clonedSvg.append(() => annotationClone as SVGSVGElement);\n }\n const result = {\n node: clonedSvg.node(),\n width,\n height,\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n clonedSvg = null as any;\n\n return result;\n}\n\nconst LEGEND_TEXT_STYLE_PROPERTIES_MAP = {\n color: 'fill',\n 'font-family': 'font-family',\n 'font-size': 'font-size',\n 'font-weight': 'font-weight',\n};\n\nexport function cloneLegendsToSVG(\n legends: Legend[],\n svgWidth: number,\n config: {\n selectedLegends: Record<string, boolean>;\n centerLegends: boolean;\n textClassName: string;\n isRTL: boolean;\n },\n legendContainer?: HTMLElement | null,\n): {\n node: SVGSVGElement | null;\n width: number;\n height: number;\n} {\n if (legends.length === 0) {\n return {\n node: null,\n width: 0,\n height: 0,\n };\n }\n\n const { selectedLegends, centerLegends, textClassName, isRTL } = config;\n const legendGroup = d3Create<SVGGElement>('svg:g');\n let legendX = centerLegends ? 0 : LEGEND_CONTAINER_MARGIN_START;\n let legendY = LEGEND_CONTAINER_MARGIN_TOP;\n let legendLine: { elem: Selection<SVGGElement, unknown, null, undefined>; width: number }[] = [];\n const legendLines: (typeof legendLine)[] = [];\n const legendLineWidths: number[] = [];\n const noLegendsSelected = Object.keys(selectedLegends).length === 0;\n\n for (let i = 0; i < legends.length; i++) {\n const textOffset = LEGEND_PADDING + LEGEND_SHAPE_SIZE + LEGEND_SHAPE_MARGIN_END;\n const legendText = measureTextWithDOM(legends[i].title, `.${textClassName}`, legendContainer);\n const legendWidth = textOffset + legendText.width + LEGEND_PADDING;\n const legendItem = legendGroup.append('g');\n\n legendLine.push({ elem: legendItem, width: legendWidth });\n if (legendX + legendWidth > svgWidth && legendLine.length > 1) {\n legendLine.pop();\n legendLines.push(legendLine);\n legendLineWidths.push(legendX);\n\n legendLine = [{ elem: legendItem, width: legendWidth }];\n legendX = centerLegends ? 0 : LEGEND_CONTAINER_MARGIN_START;\n legendY += LEGEND_HEIGHT;\n }\n\n const isLegendActive = selectedLegends[legends[i].title] || noLegendsSelected;\n\n legendItem\n .append('rect')\n .attr('x', legendX + (isRTL ? legendWidth - LEGEND_PADDING - LEGEND_SHAPE_SIZE : LEGEND_PADDING))\n .attr('y', legendY + LEGEND_PADDING)\n .attr('width', LEGEND_SHAPE_SIZE)\n .attr('height', LEGEND_SHAPE_SIZE)\n .style('fill', isLegendActive ? legends[i].color : 'transparent')\n .style('stroke-width', LEGEND_SHAPE_BORDER)\n .style('stroke', legends[i].color);\n\n legendItem\n .append('text')\n .attr('x', legendX + (isRTL ? legendWidth - textOffset : textOffset))\n .attr('y', legendY + LEGEND_PADDING)\n .attr('dominant-baseline', 'hanging')\n .style('opacity', isLegendActive ? 1 : INACTIVE_LEGEND_TEXT_OPACITY)\n .text(legends[i].title)\n .call(selection => copyStyle(LEGEND_TEXT_STYLE_PROPERTIES_MAP, legendText.node, selection.node()!));\n\n legendX += legendWidth;\n }\n\n legendLines.push(legendLine);\n legendLineWidths.push(legendX);\n legendY += LEGEND_HEIGHT;\n\n if (centerLegends) {\n legendLines.forEach((ln, idx) => {\n const lineOffsetX = Math.max((svgWidth - legendLineWidths[idx]) / 2, 0);\n let remLineWidth = legendLineWidths[idx];\n let itemOffsetX = 0;\n ln.forEach(item => {\n const newOffsetX = lineOffsetX + (isRTL ? remLineWidth - item.width - itemOffsetX : 0);\n item.elem.attr('transform', `translate(${newOffsetX}, 0)`);\n remLineWidth -= item.width;\n itemOffsetX += item.width;\n });\n });\n } else if (isRTL) {\n const w1 = Math.max(svgWidth, ...legendLineWidths);\n legendLines.forEach(ln => {\n let remLineWidth = w1 - LEGEND_CONTAINER_MARGIN_START;\n let itemOffsetX = LEGEND_CONTAINER_MARGIN_START;\n ln.forEach(item => {\n const newOffsetX = remLineWidth - item.width - itemOffsetX;\n item.elem.attr('transform', `translate(${newOffsetX}, 0)`);\n remLineWidth -= item.width;\n itemOffsetX += item.width;\n });\n });\n }\n\n const w1 = Math.max(svgWidth, ...legendLineWidths);\n const h1 = legendY;\n const svg = d3Create<SVGSVGElement>('svg').attr('width', w1).attr('height', h1).attr('viewBox', `0 0 ${w1} ${h1}`);\n svg.append(() => legendGroup.node()!);\n\n return {\n node: svg.node(),\n width: w1,\n height: h1,\n };\n}\n\ntype PositionedImage = SvgImage & {\n x: number;\n y: number;\n};\n\nasync function svgToPng(grid: SvgImage[][], opts: ImageExportOptions = {}): Promise<string> {\n let totalWidth = 0;\n let totalHeight = 0;\n\n const positionedImages: PositionedImage[] = grid\n .map(row => {\n let rowWidth = 0;\n let rowHeight = 0;\n\n const items = row.map(item => {\n const positioned = { ...item, x: rowWidth, y: totalHeight };\n rowWidth += item.width;\n rowHeight = Math.max(rowHeight, item.height);\n return positioned;\n });\n\n totalWidth = Math.max(totalWidth, rowWidth);\n totalHeight += rowHeight;\n\n return items;\n })\n .flat();\n\n const scale = opts.scale || 1;\n const w0 = opts.width || totalWidth;\n const h0 = opts.height || totalHeight;\n const scaleX = (scale * w0) / totalWidth;\n const scaleY = (scale * h0) / totalHeight;\n totalWidth = scaleX * totalWidth;\n totalHeight = scaleY * totalHeight;\n\n const canvas = document.createElement('canvas');\n canvas.width = totalWidth;\n canvas.height = totalHeight;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas context is null');\n }\n\n ctx.fillStyle = opts.background || 'transparent';\n ctx.fillRect(0, 0, totalWidth, totalHeight);\n\n await Promise.all(\n positionedImages.map(\n item =>\n new Promise<void>((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n ctx.drawImage(img, scaleX * item.x, scaleY * item.y, scaleX * item.width, scaleY * item.height);\n resolve();\n };\n img.onerror = reject;\n img.src = item.dataUrl;\n }),\n ),\n );\n\n return canvas.toDataURL('image/png');\n}\n\nfunction svgToBase64(svgNode: SVGSVGElement | null) {\n if (!svgNode) {\n throw new Error('SVG node is null');\n }\n\n const svgData = new XMLSerializer().serializeToString(svgNode);\n const svgDataUrl = 'data:image/svg+xml;base64,' + btoa(unescapePonyfill(encodeURIComponent(svgData)));\n return svgDataUrl;\n}\n\nconst hex2 = /^[\\da-f]{2}$/i;\nconst hex4 = /^[\\da-f]{4}$/i;\n\n/**\n * A ponyfill for the deprecated `unescape` method, taken from the `core-js` library.\n *\n * Source: {@link https://github.com/zloirock/core-js/blob/167136f479d3b8519953f2e4c534ecdd1031d3cf/packages/core-js/modules/es.unescape.js core-js/packages/core-js/modules/es.unescape.js}\n */\nfunction unescapePonyfill(str: string) {\n let result = '';\n const length = str.length;\n let index = 0;\n let chr;\n let part;\n while (index < length) {\n chr = str.charAt(index++);\n if (chr === '%') {\n if (str.charAt(index) === 'u') {\n part = str.slice(index + 1, index + 5);\n if (hex4.exec(part)) {\n result += String.fromCharCode(parseInt(part, 16));\n index += 5;\n continue;\n }\n } else {\n part = str.slice(index, index + 2);\n if (hex2.exec(part)) {\n result += String.fromCharCode(parseInt(part, 16));\n index += 2;\n continue;\n }\n }\n }\n result += chr;\n }\n return result;\n}\n"],"names":["create","d3Create","select","d3Select","isHTMLElement","copyStyle","measureTextWithDOM","LEGEND_CONTAINER_MARGIN_TOP","LEGEND_CONTAINER_MARGIN_START","LEGEND_PADDING","LEGEND_HEIGHT","LEGEND_SHAPE_BORDER","LEGEND_SHAPE_SIZE","LEGEND_SHAPE_MARGIN_END","INACTIVE_LEGEND_TEXT_OPACITY","exportChartsAsImage","charts","legendsToSvg","isRTL","opts","length","Error","chartImages","Promise","all","map","chart","resolve","svg","cloneStyledSVG","container","svgDataUrl","svgToBase64","node","dataUrl","width","height","grid","forEach","i","row","col","totalWidth","rowWidth","item","Math","max","push","svgToPng","SVG_STYLE_PROPERTIES","SVG_TEXT_STYLE_PROPERTIES","ANNOTATION_HTML_STYLE_PROPERTIES","ANNOTATION_FOREIGN_OBJECT_STYLE_PROPERTIES","chartContainer","querySelector","clonedSvg","cloneNode","attr","svgElements","getElementsByTagName","clonedSvgElements","TEXT_ELEMENTS","TABLE_ELEMENTS","tag","tagName","toLowerCase","includes","originalForeignObjects","querySelectorAll","clonedForeignObjects","originalFo","index","clonedFo","originalRoot","firstElementChild","clonedRoot","originalHtmlElements","clonedHtmlElements","originalEl","elementIndex","clonedEl","annotationSvg","annotationClone","annotationElements","clonedAnnotationElements","original","cloned","isSvgElement","SVGElement","isTextElement","isHtmlElement","getBoundingClientRect","selectAll","remove","append","result","LEGEND_TEXT_STYLE_PROPERTIES_MAP","color","cloneLegendsToSVG","legends","svgWidth","config","legendContainer","selectedLegends","centerLegends","textClassName","legendGroup","legendX","legendY","legendLine","legendLines","legendLineWidths","noLegendsSelected","Object","keys","textOffset","legendText","title","legendWidth","legendItem","elem","pop","isLegendActive","style","text","call","selection","ln","idx","lineOffsetX","remLineWidth","itemOffsetX","newOffsetX","w1","h1","totalHeight","positionedImages","rowHeight","items","positioned","x","y","flat","scale","w0","h0","scaleX","scaleY","canvas","document","createElement","ctx","getContext","fillStyle","background","fillRect","reject","img","Image","onload","drawImage","onerror","src","toDataURL","svgNode","svgData","XMLSerializer","serializeToString","btoa","unescapePonyfill","encodeURIComponent","hex2","hex4","str","chr","part","charAt","slice","exec","String","fromCharCode","parseInt"],"mappings":"AAAA;;;;;;;;;;;;qBAsRgBkG;eAAAA;;IAxPMnF,mBAAAA;;;;6BA5B4C,eAAe;gCACnD,4BAA4B;uBACZ,UAAU;wCAYjD,gDAAgD;AAchD,mCACLC,MAAmB,EACnBC,YAAuC,EACvCC,QAAiB,KAAK,EACtBC,OAA2B,CAAC,CAAC;IAE7B,IAAIH,OAAOI,MAAM,KAAK,KAAK,CAACH,cAAc;QACxC,MAAM,IAAII,MAAM;IAClB;IAEA,MAAMC,cAAc,MAAMC,QAAQC,GAAG,CACnCR,OAAOS,GAAG,CAACC,CAAAA;QACT,OAAO,IAAIH,QAAkBI,CAAAA;YAC3B,MAAMC,MAAMC,eAAeH,MAAMI,SAAS,EAAEZ;YAC5C,MAAMa,aAAaC,YAAYJ,IAAIK,IAAI;YACvCN,QAAQ;gBAAEO,SAASH;gBAAYI,OAAOP,IAAIO,KAAK;gBAAEC,QAAQR,IAAIQ,MAAM;YAAC;QACtE;IACF;IAGF,MAAMC,OAAqB,EAAE,EAAE,kBAAkB;IACjDrB,OAAOsB,OAAO,CAAC,CAACZ,OAAOa;QACrB,MAAMC,MAAMd,MAAMc,GAAG,IAAI;QACzB,MAAMC,MAAMf,MAAMe,GAAG,IAAI;QACzB,IAAI,CAACJ,IAAI,CAACG,IAAI,EAAE;YACdH,IAAI,CAACG,IAAI,GAAG,EAAE;QAChB;QACAH,IAAI,CAACG,IAAI,CAACC,IAAI,GAAGnB,WAAW,CAACiB,EAAE;IACjC;IAEA,IAAItB,cAAc;QAChB,IAAIyB,aAAa;QACjBL,KAAKC,OAAO,CAACE,CAAAA;YACX,IAAIG,WAAW;YACfH,IAAIF,OAAO,CAACM,CAAAA;gBACVD,YAAYC,KAAKT,KAAK;YACxB;YACAO,aAAaG,KAAKC,GAAG,CAACJ,YAAYC;QACpC;QAEA,MAAMf,MAAMX,aAAayB,YAAYxB;QACrC,IAAIU,IAAIK,IAAI,EAAE;YACZ,MAAMF,aAAaC,YAAYJ,IAAIK,IAAI;YACvCI,KAAKU,IAAI,CAAC;gBAAC;oBAAEb,SAASH;oBAAYI,OAAOP,IAAIO,KAAK;oBAAEC,QAAQR,IAAIQ,MAAM;gBAAC;aAAE;QAC3E;IACF;IAEA,OAAOY,SAASX,MAAMlB;AACxB;AAEA,MAAM8B,uBAAuB;IAC3B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AACD,MAAMC,4BAA4B;IAChC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,MAAMC,mCAAmC;IACvC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AACD,MAAMC,6CAA6C;IAAC;IAAY;CAAiB;AAEjF,SAASvB,eAAewB,cAA8C,EAAEnC,KAAc;IACpF,IAAI,CAACmC,gBAAgB;QACnB,MAAM,IAAIhC,MAAM;IAClB;IAEA,MAAMO,MAAMyB,eAAeC,aAAa,CAAgB;IACxD,IAAI,CAAC1B,KAAK;QACR,MAAM,IAAIP,MAAM;IAClB;IAEA,IAAIkC,gBAAYpD,mBAAAA,EAASyB,IAAI4B,SAAS,CAAC,OACpCC,IAAI,CAAC,SAAS,MACdA,IAAI,CAAC,UAAU,MACfA,IAAI,CAAC,WAAW;IACnB,IAAIC,cAAc9B,IAAI+B,oBAAoB,CAAC;IAC3C,IAAIC,oBAAoBL,UAAUtB,IAAI,GAAI0B,oBAAoB,CAAC;IAE/D,MAAME,gBAAgB;QAAC;KAAO;IAC9B,MAAMC,iBAAiB;QAAC;QAAS;QAAS;QAAS;QAAM;QAAM;KAAK;IAEpE,IAAK,IAAIvB,IAAI,GAAGA,IAAImB,YAAYtC,MAAM,EAAEmB,IAAK;QAC3C,MAAMwB,MAAML,WAAW,CAACnB,EAAE,CAACyB,OAAO,CAACC,WAAW;QAE9C,IAAIJ,cAAcK,QAAQ,CAACH,QAAQD,eAAeI,QAAQ,CAACH,MAAM;gBAC/D1D,gBAAAA,EAAU;mBAAI4C;mBAAyBC;aAA0B,EAAEQ,WAAW,CAACnB,EAAE,EAAEqB,iBAAiB,CAACrB,EAAE;QACzG,OAAO;gBACLlC,gBAAAA,EAAU4C,sBAAsBS,WAAW,CAACnB,EAAE,EAAEqB,iBAAiB,CAACrB,EAAE;QACtE;IACF;IAEA,8DAA8D;IAC9DmB,cAAc;IACd,8DAA8D;IAC9DE,oBAAoB;IAEpB,MAAMO,yBAAyBvC,IAAIwC,gBAAgB,CAAC;IACpD,MAAMC,uBAAuBd,UAAUtB,IAAI,GAAImC,gBAAgB,CAAC;IAEhED,uBAAuB7B,OAAO,CAAC,CAACgC,YAAYC;QAC1C,MAAMC,WAAWH,oBAAoB,CAACE,MAAM;QAC5C,IAAI,CAACC,UAAU;YACb;QACF;QAEA,MAAMC,eAAeH,WAAWI,iBAAiB;QACjD,MAAMC,aAAaH,SAASE,iBAAiB;QAE7C,IAAID,gBAAgBE,YAAY;gBAC9BtE,gBAAAA,EAAU8C,kCAAkCsB,cAAcE;QAC5D;QAEA,MAAMC,uBAAuBN,WAAWF,gBAAgB,CAAc;QACtE,MAAMS,qBAAqBL,SAASJ,gBAAgB,CAAc;QAElEQ,qBAAqBtC,OAAO,CAAC,CAACwC,YAAYC;YACxC,MAAMC,WAAWH,kBAAkB,CAACE,aAAa;YACjD,IAAIC,UAAU;gBACZ3E,oBAAAA,EAAU8C,kCAAkC2B,YAAYE;YAC1D;QACF;IACF;IAEA,MAAMC,gBAAgB5B,eAAeC,aAAa,CAAgB;IAClE,IAAI4B,kBAAwC;IAE5C,IAAID,eAAe;QACjBC,kBAAkBD,cAAczB,SAAS,CAAC;YAC1CnD,gBAAAA,EAAU4C,sBAAsBgC,eAAeC;QAE/C,MAAMC,qBAAqBF,cAActB,oBAAoB,CAAC;QAC9D,MAAMyB,2BAA2BF,gBAAgBvB,oBAAoB,CAAC;QAEtE,IAAK,IAAIpB,IAAI,GAAGA,IAAI4C,mBAAmB/D,MAAM,EAAEmB,IAAK;YAClD,MAAM8C,WAAWF,kBAAkB,CAAC5C,EAAE;YACtC,MAAM+C,SAASF,wBAAwB,CAAC7C,EAAE;YAC1C,MAAMwB,MAAMsB,SAASrB,OAAO,CAACC,WAAW;YACxC,MAAMsB,eAAeF,oBAAoBG;YACzC,MAAMC,gBAAgB1B,QAAQ;YAC9B,MAAM2B,oBAAgBtF,6BAAAA,EAAciF;YAEpC,IAAIE,cAAc;gBAChB,IAAIE,eAAe;oBACjBpF,oBAAAA,EAAU;2BAAI4C;2BAAyBC;qBAA0B,EAAEmC,UAAUC;gBAC/E,OAAO;wBACLjF,gBAAAA,EAAU4C,sBAAsBoC,UAAUC;gBAC5C;YACF;YAEA,IAAII,eAAe;oBACjBrF,gBAAAA,EAAU8C,kCAAkCkC,UAAUC;YACxD;YAEA,IAAIvB,QAAQ,iBAAiB;oBAC3B1D,gBAAAA,EAAU+C,4CAA4CiC,UAAUC;YAClE;QACF;IACF;IAEA,MAAM,EAAEnD,KAAK,EAAEC,MAAM,EAAE,GAAGR,IAAI+D,qBAAqB;IAEnDpC,UACGE,IAAI,CAAC,SAAStB,OACdsB,IAAI,CAAC,UAAUrB,QACfqB,IAAI,CAAC,WAAW,CAAC,IAAI,EAAEtB,MAAM,CAAC,EAAEC,QAAQ,EACxCqB,IAAI,CAAC,aAAavC,QAAQ,QAAQ;IAErC,IAAIgE,iBAAiB;QACnB3B,UAAUqC,SAAS,CAAC,wCAAwCC,MAAM;YAClE1F,mBAAAA,EAAS+E,iBAAiBzB,IAAI,CAAC,KAAK,GAAGA,IAAI,CAAC,KAAK,GAAGA,IAAI,CAAC,SAAStB,OAAOsB,IAAI,CAAC,UAAUrB;QACxFmB,UAAUuC,MAAM,CAAC,IAAMZ;IACzB;IACA,MAAMa,SAAS;QACb9D,MAAMsB,UAAUtB,IAAI;QACpBE;QACAC;IACF;IACA,8DAA8D;IAC9DmB,YAAY;IAEZ,OAAOwC;AACT;AAEA,MAAMC,mCAAmC;IACvCC,OAAO;IACP,eAAe;IACf,aAAa;IACb,eAAe;AACjB;AAEO,2BACLE,OAAiB,EACjBC,QAAgB,EAChBC,MAKC,EACDC,eAAoC;IAMpC,IAAIH,QAAQ/E,MAAM,KAAK,GAAG;QACxB,OAAO;YACLa,MAAM;YACNE,OAAO;YACPC,QAAQ;QACV;IACF;IAEA,MAAM,EAAEmE,eAAe,EAAEC,aAAa,EAAEC,aAAa,EAAEvF,KAAK,EAAE,GAAGmF;IACjE,MAAMK,kBAAczG,mBAAAA,EAAsB;IAC1C,IAAI0G,UAAUH,gBAAgB,IAAIhG,qDAAAA;IAClC,IAAIoG,UAAUrG,mDAAAA;IACd,IAAIsG,aAA0F,EAAE;IAChG,MAAMC,cAAqC,EAAE;IAC7C,MAAMC,mBAA6B,EAAE;IACrC,MAAMC,oBAAoBC,OAAOC,IAAI,CAACX,iBAAiBnF,MAAM,KAAK;IAElE,IAAK,IAAImB,IAAI,GAAGA,IAAI4D,QAAQ/E,MAAM,EAAEmB,IAAK;QACvC,MAAM4E,aAAa1G,sCAAAA,GAAiBG,yCAAAA,GAAoBC,+CAAAA;QACxD,MAAMuG,iBAAa9G,yBAAAA,EAAmB6F,OAAO,CAAC5D,EAAE,CAAC8E,KAAK,EAAE,CAAC,CAAC,EAAEZ,eAAe,EAAEH;QAC7E,MAAMgB,cAAcH,aAAaC,WAAWjF,KAAK,GAAG1B,sCAAAA;QACpD,MAAM8G,aAAab,YAAYZ,MAAM,CAAC;QAEtCe,WAAW9D,IAAI,CAAC;YAAEyE,MAAMD;YAAYpF,OAAOmF;QAAY;QACvD,IAAIX,UAAUW,cAAclB,YAAYS,WAAWzF,MAAM,GAAG,GAAG;YAC7DyF,WAAWY,GAAG;YACdX,YAAY/D,IAAI,CAAC8D;YACjBE,iBAAiBhE,IAAI,CAAC4D;YAEtBE,aAAa;gBAAC;oBAAEW,MAAMD;oBAAYpF,OAAOmF;gBAAY;aAAE;YACvDX,UAAUH,gBAAgB,IAAIhG,qDAAAA;YAC9BoG,WAAWlG,qCAAAA;QACb;QAEA,MAAMgH,iBAAiBnB,eAAe,CAACJ,OAAO,CAAC5D,EAAE,CAAC8E,KAAK,CAAC,IAAIL;QAE5DO,WACGzB,MAAM,CAAC,QACPrC,IAAI,CAAC,KAAKkD,UAAWzF,CAAAA,QAAQoG,cAAc7G,sCAAAA,GAAiBG,yCAAAA,GAAoBH,sCAAAA,AAAa,GAC7FgD,IAAI,CAAC,KAAKmD,UAAUnG,sCAAAA,EACpBgD,IAAI,CAAC,SAAS7C,yCAAAA,EACd6C,IAAI,CAAC,UAAU7C,yCAAAA,EACf+G,KAAK,CAAC,QAAQD,iBAAiBvB,OAAO,CAAC5D,EAAE,CAAC0D,KAAK,GAAG,eAClD0B,KAAK,CAAC,gBAAgBhH,2CAAAA,EACtBgH,KAAK,CAAC,UAAUxB,OAAO,CAAC5D,EAAE,CAAC0D,KAAK;QAEnCsB,WACGzB,MAAM,CAAC,QACPrC,IAAI,CAAC,KAAKkD,UAAWzF,CAAAA,QAAQoG,cAAcH,aAAaA,UAAAA,CAAS,EACjE1D,IAAI,CAAC,KAAKmD,UAAUnG,sCAAAA,EACpBgD,IAAI,CAAC,qBAAqB,WAC1BkE,KAAK,CAAC,WAAWD,iBAAiB,IAAI5G,oDAAAA,EACtC8G,IAAI,CAACzB,OAAO,CAAC5D,EAAE,CAAC8E,KAAK,EACrBQ,IAAI,CAACC,CAAAA,gBAAazH,gBAAAA,EAAU2F,kCAAkCoB,WAAWnF,IAAI,EAAE6F,UAAU7F,IAAI;QAEhG0E,WAAWW;IACb;IAEAR,YAAY/D,IAAI,CAAC8D;IACjBE,iBAAiBhE,IAAI,CAAC4D;IACtBC,WAAWlG,qCAAAA;IAEX,IAAI8F,eAAe;QACjBM,YAAYxE,OAAO,CAAC,CAACyF,IAAIC;YACvB,MAAMC,cAAcpF,KAAKC,GAAG,CAAEsD,CAAAA,WAAWW,gBAAgB,CAACiB,IAAAA,AAAG,IAAK,GAAG;YACrE,IAAIE,eAAenB,gBAAgB,CAACiB,IAAI;YACxC,IAAIG,cAAc;YAClBJ,GAAGzF,OAAO,CAACM,CAAAA;gBACT,MAAMwF,aAAaH,cAAe/G,CAAAA,QAAQgH,eAAetF,KAAKT,KAAK,GAAGgG,eAAc,CAAA;gBACpFvF,KAAK4E,IAAI,CAAC/D,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE2E,WAAW,IAAI,CAAC;gBACzDF,gBAAgBtF,KAAKT,KAAK;gBAC1BgG,eAAevF,KAAKT,KAAK;YAC3B;QACF;IACF,OAAO,IAAIjB,OAAO;QAChB,MAAMmH,KAAKxF,KAAKC,GAAG,CAACsD,aAAaW;QACjCD,YAAYxE,OAAO,CAACyF,CAAAA;YAClB,IAAIG,eAAeG,KAAK7H,qDAAAA;YACxB,IAAI2H,cAAc3H,qDAAAA;YAClBuH,GAAGzF,OAAO,CAACM,CAAAA;gBACT,MAAMwF,aAAaF,eAAetF,KAAKT,KAAK,GAAGgG;gBAC/CvF,KAAK4E,IAAI,CAAC/D,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE2E,WAAW,IAAI,CAAC;gBACzDF,gBAAgBtF,KAAKT,KAAK;gBAC1BgG,eAAevF,KAAKT,KAAK;YAC3B;QACF;IACF;IAEA,MAAMkG,KAAKxF,KAAKC,GAAG,CAACsD,aAAaW;IACjC,MAAMuB,KAAK1B;IACX,MAAMhF,UAAM3B,mBAAAA,EAAwB,OAAOwD,IAAI,CAAC,SAAS4E,IAAI5E,IAAI,CAAC,UAAU6E,IAAI7E,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE4E,GAAG,CAAC,EAAEC,IAAI;IACjH1G,IAAIkE,MAAM,CAAC,IAAMY,YAAYzE,IAAI;IAEjC,OAAO;QACLA,MAAML,IAAIK,IAAI;QACdE,OAAOkG;QACPjG,QAAQkG;IACV;AACF;AAOA,eAAetF,SAASX,IAAkB,EAAElB,OAA2B,CAAC,CAAC;IACvE,IAAIuB,aAAa;IACjB,IAAI6F,cAAc;IAElB,MAAMC,mBAAsCnG,KACzCZ,GAAG,CAACe,CAAAA;QACH,IAAIG,WAAW;QACf,IAAI8F,YAAY;QAEhB,MAAMC,QAAQlG,IAAIf,GAAG,CAACmB,CAAAA;YACpB,MAAM+F,aAAa;gBAAE,GAAG/F,IAAI;gBAAEgG,GAAGjG;gBAAUkG,GAAGN;YAAY;YAC1D5F,YAAYC,KAAKT,KAAK;YACtBsG,YAAY5F,KAAKC,GAAG,CAAC2F,WAAW7F,KAAKR,MAAM;YAC3C,OAAOuG;QACT;QAEAjG,aAAaG,KAAKC,GAAG,CAACJ,YAAYC;QAClC4F,eAAeE;QAEf,OAAOC;IACT,GACCI,IAAI;IAEP,MAAMC,QAAQ5H,KAAK4H,KAAK,IAAI;IAC5B,MAAMC,KAAK7H,KAAKgB,KAAK,IAAIO;IACzB,MAAMuG,KAAK9H,KAAKiB,MAAM,IAAImG;IAC1B,MAAMW,SAAUH,QAAQC,KAAMtG;IAC9B,MAAMyG,SAAUJ,QAAQE,KAAMV;IAC9B7F,aAAawG,SAASxG;IACtB6F,cAAcY,SAASZ;IAEvB,MAAMa,SAASC,SAASC,aAAa,CAAC;IACtCF,OAAOjH,KAAK,GAAGO;IACf0G,OAAOhH,MAAM,GAAGmG;IAEhB,MAAMgB,MAAMH,OAAOI,UAAU,CAAC;IAC9B,IAAI,CAACD,KAAK;QACR,MAAM,IAAIlI,MAAM;IAClB;IAEAkI,IAAIE,SAAS,GAAGtI,KAAKuI,UAAU,IAAI;IACnCH,IAAII,QAAQ,CAAC,GAAG,GAAGjH,YAAY6F;IAE/B,MAAMhH,QAAQC,GAAG,CACfgH,iBAAiB/G,GAAG,CAClBmB,CAAAA,OACE,IAAIrB,QAAc,CAACI,SAASiI;YAC1B,MAAMC,MAAM,IAAIC;YAChBD,IAAIE,MAAM,GAAG;gBACXR,IAAIS,SAAS,CAACH,KAAKX,SAAStG,KAAKgG,CAAC,EAAEO,SAASvG,KAAKiG,CAAC,EAAEK,SAAStG,KAAKT,KAAK,EAAEgH,SAASvG,KAAKR,MAAM;gBAC9FT;YACF;YACAkI,IAAII,OAAO,GAAGL;YACdC,IAAIK,GAAG,GAAGtH,KAAKV,OAAO;QACxB;IAIN,OAAOkH,OAAOe,SAAS,CAAC;AAC1B;AAEA,SAASnI,YAAYoI,OAA6B;IAChD,IAAI,CAACA,SAAS;QACZ,MAAM,IAAI/I,MAAM;IAClB;IAEA,MAAMgJ,UAAU,IAAIC,gBAAgBC,iBAAiB,CAACH;IACtD,MAAMrI,aAAa,+BAA+ByI,KAAKC,iBAAiBC,mBAAmBL;IAC3F,OAAOtI;AACT;AAEA,MAAM4I,OAAO;AACb,MAAMC,OAAO;AAEb;;;;CAIC,GACD,SAASH,iBAAiBI,GAAW;IACnC,IAAI9E,SAAS;IACb,MAAM3E,SAASyJ,IAAIzJ,MAAM;IACzB,IAAImD,QAAQ;IACZ,IAAIuG;IACJ,IAAIC;IACJ,MAAOxG,QAAQnD,OAAQ;QACrB0J,MAAMD,IAAIG,MAAM,CAACzG;QACjB,IAAIuG,QAAQ,KAAK;YACf,IAAID,IAAIG,MAAM,CAACzG,WAAW,KAAK;gBAC7BwG,OAAOF,IAAII,KAAK,CAAC1G,QAAQ,GAAGA,QAAQ;gBACpC,IAAIqG,KAAKM,IAAI,CAACH,OAAO;oBACnBhF,UAAUoF,OAAOC,YAAY,CAACC,SAASN,MAAM;oBAC7CxG,SAAS;oBACT;gBACF;YACF,OAAO;gBACLwG,OAAOF,IAAII,KAAK,CAAC1G,OAAOA,QAAQ;gBAChC,IAAIoG,KAAKO,IAAI,CAACH,OAAO;oBACnBhF,UAAUoF,OAAOC,YAAY,CAACC,SAASN,MAAM;oBAC7CxG,SAAS;oBACT;gBACF;YACF;QACF;QACAwB,UAAU+E;IACZ;IACA,OAAO/E;AACT"}
|
|
@@ -10,6 +10,9 @@ function _export(target, all) {
|
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
12
|
_export(exports, {
|
|
13
|
+
CARTESIAN_XAXIS_CLASSNAME: function() {
|
|
14
|
+
return CARTESIAN_XAXIS_CLASSNAME;
|
|
15
|
+
},
|
|
13
16
|
ChartTypes: function() {
|
|
14
17
|
return ChartTypes;
|
|
15
18
|
},
|
|
@@ -49,6 +52,9 @@ _export(exports, {
|
|
|
49
52
|
areArraysEqual: function() {
|
|
50
53
|
return areArraysEqual;
|
|
51
54
|
},
|
|
55
|
+
autoLayoutXAxisLabels: function() {
|
|
56
|
+
return autoLayoutXAxisLabels;
|
|
57
|
+
},
|
|
52
58
|
calculateLongestLabelWidth: function() {
|
|
53
59
|
return calculateLongestLabelWidth;
|
|
54
60
|
},
|
|
@@ -67,9 +73,6 @@ _export(exports, {
|
|
|
67
73
|
createDateXAxis: function() {
|
|
68
74
|
return createDateXAxis;
|
|
69
75
|
},
|
|
70
|
-
createMeasurementSpan: function() {
|
|
71
|
-
return createMeasurementSpan;
|
|
72
|
-
},
|
|
73
76
|
createNumericXAxis: function() {
|
|
74
77
|
return createNumericXAxis;
|
|
75
78
|
},
|
|
@@ -175,6 +178,9 @@ _export(exports, {
|
|
|
175
178
|
getSecureProps: function() {
|
|
176
179
|
return getSecureProps;
|
|
177
180
|
},
|
|
181
|
+
getTextSize: function() {
|
|
182
|
+
return getTextSize;
|
|
183
|
+
},
|
|
178
184
|
getTypeOfAxis: function() {
|
|
179
185
|
return getTypeOfAxis;
|
|
180
186
|
},
|
|
@@ -202,6 +208,9 @@ _export(exports, {
|
|
|
202
208
|
isValidDomainValue: function() {
|
|
203
209
|
return isValidDomainValue;
|
|
204
210
|
},
|
|
211
|
+
measureTextWithDOM: function() {
|
|
212
|
+
return measureTextWithDOM;
|
|
213
|
+
},
|
|
205
214
|
pointTypes: function() {
|
|
206
215
|
return pointTypes;
|
|
207
216
|
},
|
|
@@ -252,6 +261,8 @@ const _chartutilities = require("@fluentui/chart-utilities");
|
|
|
252
261
|
const MIN_DOMAIN_MARGIN = 8;
|
|
253
262
|
const MIN_DONUT_RADIUS = 1;
|
|
254
263
|
const DEFAULT_DATE_STRING = '2000-01-01';
|
|
264
|
+
const CARTESIAN_XAXIS_CLASSNAME = 'fui-cart__xAxis';
|
|
265
|
+
const CARTESIAN_XAXIS_TEXT_SELECTOR = `.${CARTESIAN_XAXIS_CLASSNAME} text`;
|
|
255
266
|
var ChartTypes = /*#__PURE__*/ function(ChartTypes) {
|
|
256
267
|
ChartTypes[ChartTypes["AreaChart"] = 0] = "AreaChart";
|
|
257
268
|
ChartTypes[ChartTypes["LineChart"] = 1] = "LineChart";
|
|
@@ -321,7 +332,7 @@ function createNumericXAxis(xAxisParams, tickParams, chartType, culture, scaleTy
|
|
|
321
332
|
const xAxisValue = typeof domainValue === 'number' ? domainValue : domainValue.valueOf();
|
|
322
333
|
return (defaultFormat === null || defaultFormat === void 0 ? void 0 : defaultFormat(xAxisValue)) === '' ? '' : (0, _chartutilities.formatToLocaleString)(xAxisValue, culture);
|
|
323
334
|
};
|
|
324
|
-
if (hideTickOverlap
|
|
335
|
+
if (hideTickOverlap) {
|
|
325
336
|
const longestLabelWidth = calcMaxLabelWidth(xAxisScale.ticks().map((v, i)=>tickFormat(v, i))) + 20;
|
|
326
337
|
const [start, end] = xAxisScale.range();
|
|
327
338
|
tickCount = Math.min(Math.max(1, Math.floor(Math.abs(end - start) / longestLabelWidth)), 10);
|
|
@@ -345,10 +356,12 @@ function createNumericXAxis(xAxisParams, tickParams, chartType, culture, scaleTy
|
|
|
345
356
|
if (xAxisElement) {
|
|
346
357
|
(0, _d3selection.select)(xAxisElement).call(xAxis).selectAll('text').attr('aria-hidden', 'true').style('direction', 'ltr').style('unicode-bidi', 'isolate');
|
|
347
358
|
}
|
|
348
|
-
const tickValues =
|
|
359
|
+
const tickValues = customTickValues !== null && customTickValues !== void 0 ? customTickValues : xAxisScale.ticks(tickCount);
|
|
360
|
+
const tickLabels = tickValues.map(xAxis.tickFormat());
|
|
349
361
|
return {
|
|
350
362
|
xScale: xAxisScale,
|
|
351
|
-
tickValues
|
|
363
|
+
tickValues,
|
|
364
|
+
tickLabels
|
|
352
365
|
};
|
|
353
366
|
}
|
|
354
367
|
/**
|
|
@@ -536,7 +549,7 @@ function getDateFormatLevel(date, useUTC) {
|
|
|
536
549
|
return (_matchedFormat_formatLevel = matchedFormat === null || matchedFormat === void 0 ? void 0 : matchedFormat.formatLevel) !== null && _matchedFormat_formatLevel !== void 0 ? _matchedFormat_formatLevel : 7;
|
|
537
550
|
}
|
|
538
551
|
function createDateXAxis(xAxisParams, tickParams, culture, options, timeFormatLocale, customDateTimeFormatter, useUTC, chartType) {
|
|
539
|
-
const { domainNRangeValues, xAxisElement, tickPadding = 6, xAxistickSize = 6, xAxisCount, calcMaxLabelWidth, tickStep, tick0, tickText } = xAxisParams;
|
|
552
|
+
const { domainNRangeValues, xAxisElement, tickPadding = 6, xAxistickSize = 6, xAxisCount, hideTickOverlap, calcMaxLabelWidth, tickStep, tick0, tickText } = xAxisParams;
|
|
540
553
|
const isUtcSet = useUTC === true || useUTC === 'utc';
|
|
541
554
|
const xAxisScale = isUtcSet ? (0, _d3scale.scaleUtc)() : (0, _d3scale.scaleTime)();
|
|
542
555
|
xAxisScale.domain([
|
|
@@ -580,10 +593,11 @@ function createDateXAxis(xAxisParams, tickParams, culture, options, timeFormatLo
|
|
|
580
593
|
}
|
|
581
594
|
return (0, _chartutilities.formatDateToLocaleString)(domainValue, culture, useUTC ? true : false, false, formatOptions);
|
|
582
595
|
};
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
596
|
+
if (hideTickOverlap) {
|
|
597
|
+
const longestLabelWidth = calcMaxLabelWidth(xAxisScale.ticks().map(tickFormat)) + 40;
|
|
598
|
+
const [start, end] = xAxisScale.range();
|
|
599
|
+
tickCount = Math.max(1, Math.floor(Math.abs(end - start) / longestLabelWidth));
|
|
600
|
+
}
|
|
587
601
|
const xAxis = (0, _d3axis.axisBottom)(xAxisScale).tickSize(xAxistickSize).tickPadding(tickPadding).ticks(tickCount).tickFormat(tickFormat);
|
|
588
602
|
if ([
|
|
589
603
|
8
|
|
@@ -602,10 +616,12 @@ function createDateXAxis(xAxisParams, tickParams, culture, options, timeFormatLo
|
|
|
602
616
|
if (xAxisElement) {
|
|
603
617
|
(0, _d3selection.select)(xAxisElement).call(xAxis).selectAll('text').attr('aria-hidden', 'true');
|
|
604
618
|
}
|
|
605
|
-
const tickValues =
|
|
619
|
+
const tickValues = customTickValues !== null && customTickValues !== void 0 ? customTickValues : xAxisScale.ticks(tickCount);
|
|
620
|
+
const tickLabels = tickValues.map(xAxis.tickFormat());
|
|
606
621
|
return {
|
|
607
622
|
xScale: xAxisScale,
|
|
608
|
-
tickValues
|
|
623
|
+
tickValues,
|
|
624
|
+
tickLabels
|
|
609
625
|
};
|
|
610
626
|
}
|
|
611
627
|
function createStringXAxis(xAxisParams, tickParams, dataset, culture, _useRtl) {
|
|
@@ -654,7 +670,8 @@ function createStringXAxis(xAxisParams, tickParams, dataset, culture, _useRtl) {
|
|
|
654
670
|
}
|
|
655
671
|
return {
|
|
656
672
|
xScale: xAxisScale,
|
|
657
|
-
tickValues
|
|
673
|
+
tickValues,
|
|
674
|
+
tickLabels: tickValues.map(xAxis.tickFormat())
|
|
658
675
|
};
|
|
659
676
|
}
|
|
660
677
|
function useRtl() {
|
|
@@ -949,14 +966,14 @@ function silceOrAppendToArray(array, value) {
|
|
|
949
966
|
}
|
|
950
967
|
const DEFAULT_WRAP_WIDTH = 10;
|
|
951
968
|
function createWrapOfXLabels(wrapLabelProps) {
|
|
952
|
-
const { node, xAxis, noOfCharsToTruncate, showXAxisLablesTooltip, width = DEFAULT_WRAP_WIDTH } = wrapLabelProps;
|
|
969
|
+
const { node, xAxis, noOfCharsToTruncate, showXAxisLablesTooltip, width = DEFAULT_WRAP_WIDTH, container } = wrapLabelProps;
|
|
953
970
|
if (node === null) {
|
|
954
971
|
return;
|
|
955
972
|
}
|
|
956
973
|
const axisNode = (0, _d3selection.select)(node).call(xAxis);
|
|
957
974
|
let removeVal = 0;
|
|
958
975
|
let maxLines = 1;
|
|
959
|
-
axisNode.selectAll('.tick text').each(function() {
|
|
976
|
+
axisNode.selectAll('.tick text').each(function(_, tickIndex) {
|
|
960
977
|
const text = (0, _d3selection.select)(this);
|
|
961
978
|
const totalWord = text.text();
|
|
962
979
|
const truncatedWord = `${text.text().slice(0, noOfCharsToTruncate)}...`;
|
|
@@ -968,33 +985,33 @@ function createWrapOfXLabels(wrapLabelProps) {
|
|
|
968
985
|
const lineHeight = 1.1; // ems
|
|
969
986
|
const y = text.attr('y');
|
|
970
987
|
const dy = parseFloat(text.attr('dy'));
|
|
971
|
-
let tspan = text.text(null).append('tspan').attr('x', 0).attr('y', y).attr('
|
|
972
|
-
if (showXAxisLablesTooltip
|
|
973
|
-
tspan
|
|
974
|
-
} else if (showXAxisLablesTooltip && totalWordLength <= noOfCharsToTruncate) {
|
|
975
|
-
tspan = text.append('tspan').attr('id', 'LessLength').attr('x', 0).attr('y', y).attr('dy', dy + 'em').text(totalWord);
|
|
988
|
+
let tspan = text.text(null).attr('data-full', totalWord).append('tspan').attr('x', 0).attr('y', y).attr('dy', dy + 'em');
|
|
989
|
+
if (showXAxisLablesTooltip) {
|
|
990
|
+
tspan.text(totalWordLength > noOfCharsToTruncate ? truncatedWord : totalWord);
|
|
976
991
|
} else {
|
|
992
|
+
const maxWidth = Array.isArray(width) ? width[tickIndex] : width;
|
|
977
993
|
while(word = words.pop()){
|
|
978
994
|
line.push(word);
|
|
979
|
-
|
|
980
|
-
|
|
995
|
+
const label = line.join(' ');
|
|
996
|
+
tspan.text(label);
|
|
997
|
+
const labelWidth = getTextSize(label, CARTESIAN_XAXIS_TEXT_SELECTOR, container).width;
|
|
998
|
+
if (labelWidth > maxWidth && line.length > 1) {
|
|
981
999
|
line.pop();
|
|
982
1000
|
tspan.text(line.join(' '));
|
|
983
1001
|
line = [
|
|
984
1002
|
word
|
|
985
1003
|
];
|
|
986
|
-
tspan = text.append('tspan').attr('
|
|
1004
|
+
tspan = text.append('tspan').attr('x', 0).attr('y', y).attr('dy', ++lineNumber * lineHeight + dy + 'em').text(word);
|
|
987
1005
|
}
|
|
988
1006
|
}
|
|
989
1007
|
}
|
|
990
1008
|
maxLines = Math.max(maxLines, lineNumber + 1);
|
|
991
1009
|
});
|
|
992
1010
|
if (!showXAxisLablesTooltip) {
|
|
1011
|
+
var _querySelector;
|
|
993
1012
|
let maxHeight = 12; // intial value to render corretly first time
|
|
994
|
-
|
|
995
|
-
const
|
|
996
|
-
const BoxCordinates = outerHTMLElement && outerHTMLElement.getBoundingClientRect();
|
|
997
|
-
const boxHeight = BoxCordinates && BoxCordinates.height;
|
|
1013
|
+
var _querySelector_getBoundingClientRect_height;
|
|
1014
|
+
const boxHeight = (_querySelector_getBoundingClientRect_height = (_querySelector = (container !== null && container !== void 0 ? container : document).querySelector(`.${CARTESIAN_XAXIS_CLASSNAME} tspan`)) === null || _querySelector === void 0 ? void 0 : _querySelector.getBoundingClientRect().height) !== null && _querySelector_getBoundingClientRect_height !== void 0 ? _querySelector_getBoundingClientRect_height : 0;
|
|
998
1015
|
if (boxHeight > maxHeight) {
|
|
999
1016
|
maxHeight = boxHeight;
|
|
1000
1017
|
}
|
|
@@ -1006,24 +1023,18 @@ function createYAxisLabels(node, yAxis, noOfCharsToTruncate, truncateLabel, isRt
|
|
|
1006
1023
|
if (node === null) {
|
|
1007
1024
|
return;
|
|
1008
1025
|
}
|
|
1009
|
-
let tickIndex = 0;
|
|
1010
1026
|
const axisNode = (0, _d3selection.select)(node).call(yAxis);
|
|
1011
1027
|
axisNode.selectAll('.tick text').each(function() {
|
|
1012
1028
|
const text = (0, _d3selection.select)(this);
|
|
1013
1029
|
const totalWord = text.text();
|
|
1014
1030
|
const truncatedWord = isRtl ? `...${text.text().slice(0, noOfCharsToTruncate)}` : `${text.text().slice(0, noOfCharsToTruncate)}...`;
|
|
1015
1031
|
const totalWordLength = text.text().length;
|
|
1016
|
-
const padding = 0; // ems
|
|
1017
1032
|
const y = text.attr('y');
|
|
1018
1033
|
const x = text.attr('x');
|
|
1019
1034
|
const dy = parseFloat(text.attr('dy'));
|
|
1020
|
-
const
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
if (truncateLabel && totalWordLength > noOfCharsToTruncate) {
|
|
1024
|
-
text.append('tspan').attr('id', `showDots-${uid}`).attr('x', x).attr('y', y).attr('dy', dy + 'em').attr('dx', padding + dx + 'em').text(truncatedWord);
|
|
1025
|
-
} else {
|
|
1026
|
-
text.append('tspan').attr('id', `LessLength-${uid}`).attr('x', x).attr('y', y).attr('dx', padding + dx + 'em').text(totalWord);
|
|
1035
|
+
const tspan = text.text(null).attr('data-full', totalWord).append('tspan').attr('x', x).attr('y', y).attr('dy', dy + 'em');
|
|
1036
|
+
if (truncateLabel) {
|
|
1037
|
+
tspan.text(totalWordLength > noOfCharsToTruncate ? truncatedWord : totalWord);
|
|
1027
1038
|
}
|
|
1028
1039
|
});
|
|
1029
1040
|
}
|
|
@@ -1065,30 +1076,30 @@ const calculateLongestLabelWidth = (labels, query = 'none')=>{
|
|
|
1065
1076
|
return maxLabelWidth;
|
|
1066
1077
|
};
|
|
1067
1078
|
function tooltipOfAxislabels(axistooltipProps) {
|
|
1068
|
-
const { tooltipCls, axis, id } = axistooltipProps;
|
|
1079
|
+
const { tooltipCls, axis, id, container } = axistooltipProps;
|
|
1069
1080
|
if (axis === null) {
|
|
1070
1081
|
return null;
|
|
1071
1082
|
}
|
|
1072
|
-
const div = (0, _d3selection.select)('body').append('div').attr('id', id).attr('class', tooltipCls).style('opacity', 0);
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
const tickObjectLength = tickObject && Object.keys(tickObject).length;
|
|
1082
|
-
for(let i = 0; i < tickObjectLength; i++){
|
|
1083
|
-
const d1 = tickObject[i];
|
|
1084
|
-
(0, _d3selection.select)(d1) // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1083
|
+
const div = (container ? (0, _d3selection.select)(container) : (0, _d3selection.select)('body')).append('div').attr('id', id).attr('class', tooltipCls).style('opacity', 0);
|
|
1084
|
+
axis.selectAll('.tick text').each(function() {
|
|
1085
|
+
const tickSelection = (0, _d3selection.select)(this);
|
|
1086
|
+
const fullLabel = tickSelection.attr('data-full');
|
|
1087
|
+
if (tickSelection.text() === fullLabel) {
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
const tickEl = this;
|
|
1091
|
+
tickSelection // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1085
1092
|
.on('mouseover', (event, d)=>{
|
|
1086
|
-
|
|
1087
|
-
|
|
1093
|
+
const containerBounds = container === null || container === void 0 ? void 0 : container.getBoundingClientRect();
|
|
1094
|
+
const tickBounds = tickEl.getBoundingClientRect();
|
|
1095
|
+
const tooltipBottom = containerBounds ? containerBounds.bottom - (tickBounds.top - 4) : tickBounds.top - 4;
|
|
1096
|
+
var _containerBounds_left;
|
|
1097
|
+
const tooltipLeft = (tickBounds.left + tickBounds.right) / 2 - ((_containerBounds_left = containerBounds === null || containerBounds === void 0 ? void 0 : containerBounds.left) !== null && _containerBounds_left !== void 0 ? _containerBounds_left : 0);
|
|
1098
|
+
div.text(fullLabel).style('bottom', `${tooltipBottom}px`).style('left', `${tooltipLeft}px`).style('transform', 'translateX(-50%)').style('opacity', 0.9);
|
|
1088
1099
|
}).on('mouseout', (d)=>{
|
|
1089
1100
|
div.style('opacity', 0);
|
|
1090
1101
|
});
|
|
1091
|
-
}
|
|
1102
|
+
});
|
|
1092
1103
|
}
|
|
1093
1104
|
function getXAxisType(points) {
|
|
1094
1105
|
let isXAxisDateType = false;
|
|
@@ -1513,8 +1524,8 @@ function areArraysEqual(arr1, arr2) {
|
|
|
1513
1524
|
return true;
|
|
1514
1525
|
}
|
|
1515
1526
|
const cssVarRegExp = /var\((--[a-zA-Z0-9\-]+)\)/g;
|
|
1516
|
-
function resolveCSSVariables(
|
|
1517
|
-
const containerStyles = getComputedStyle(
|
|
1527
|
+
function resolveCSSVariables(container, styleRules) {
|
|
1528
|
+
const containerStyles = getComputedStyle(container);
|
|
1518
1529
|
return styleRules.replace(cssVarRegExp, (match, group1)=>{
|
|
1519
1530
|
return containerStyles.getPropertyValue(group1);
|
|
1520
1531
|
});
|
|
@@ -1614,11 +1625,6 @@ function copyStyle(properties, fromEl, toEl) {
|
|
|
1614
1625
|
});
|
|
1615
1626
|
}
|
|
1616
1627
|
}
|
|
1617
|
-
let measurementSpanCounter = 0;
|
|
1618
|
-
function getUniqueMeasurementSpanId() {
|
|
1619
|
-
measurementSpanCounter++;
|
|
1620
|
-
return `measurement_span_${measurementSpanCounter}`;
|
|
1621
|
-
}
|
|
1622
1628
|
const MEASUREMENT_SPAN_STYLE = {
|
|
1623
1629
|
position: 'absolute',
|
|
1624
1630
|
visibility: 'hidden',
|
|
@@ -1629,23 +1635,60 @@ const MEASUREMENT_SPAN_STYLE = {
|
|
|
1629
1635
|
border: 'none',
|
|
1630
1636
|
whiteSpace: 'pre'
|
|
1631
1637
|
};
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1638
|
+
const MEASUREMENT_SPAN_ID = 'fui_measurement_span';
|
|
1639
|
+
const TEXT_STYLE_PROPERTIES = [
|
|
1640
|
+
'font-size',
|
|
1641
|
+
'font-family',
|
|
1642
|
+
'font-weight',
|
|
1643
|
+
'font-style',
|
|
1644
|
+
'letter-spacing',
|
|
1645
|
+
'text-transform'
|
|
1646
|
+
];
|
|
1647
|
+
const measureTextWithDOM = (text, cssSelector, container)=>{
|
|
1634
1648
|
let measurementSpan = document.getElementById(MEASUREMENT_SPAN_ID);
|
|
1635
1649
|
if (!measurementSpan) {
|
|
1636
1650
|
measurementSpan = document.createElement('span');
|
|
1637
1651
|
measurementSpan.setAttribute('id', MEASUREMENT_SPAN_ID);
|
|
1638
1652
|
measurementSpan.setAttribute('aria-hidden', 'true');
|
|
1639
|
-
|
|
1640
|
-
parentElement.appendChild(measurementSpan);
|
|
1641
|
-
} else {
|
|
1642
|
-
document.body.appendChild(measurementSpan);
|
|
1643
|
-
}
|
|
1653
|
+
(container !== null && container !== void 0 ? container : document.body).appendChild(measurementSpan);
|
|
1644
1654
|
}
|
|
1645
|
-
measurementSpan.setAttribute('class', className);
|
|
1646
1655
|
Object.assign(measurementSpan.style, MEASUREMENT_SPAN_STYLE);
|
|
1656
|
+
const refEl = (container !== null && container !== void 0 ? container : document).querySelector(cssSelector);
|
|
1657
|
+
if (refEl) {
|
|
1658
|
+
copyStyle(TEXT_STYLE_PROPERTIES, refEl, measurementSpan);
|
|
1659
|
+
}
|
|
1647
1660
|
measurementSpan.textContent = `${text}`;
|
|
1648
|
-
|
|
1661
|
+
const rect = measurementSpan.getBoundingClientRect();
|
|
1662
|
+
return {
|
|
1663
|
+
node: measurementSpan,
|
|
1664
|
+
width: rect.width,
|
|
1665
|
+
height: rect.height
|
|
1666
|
+
};
|
|
1667
|
+
};
|
|
1668
|
+
const CACHE_SIZE = 2000;
|
|
1669
|
+
const textSizeCache = new Map();
|
|
1670
|
+
const getTextSize = (text, cssSelector, container)=>{
|
|
1671
|
+
const cacheKey = `${text}|${cssSelector}`;
|
|
1672
|
+
const cachedResult = textSizeCache.get(cacheKey);
|
|
1673
|
+
if (cachedResult) {
|
|
1674
|
+
return cachedResult;
|
|
1675
|
+
}
|
|
1676
|
+
const { width, height } = measureTextWithDOM(text, cssSelector, container);
|
|
1677
|
+
// TODO: Improve cache eviction strategy if needed (e.g., LRU)
|
|
1678
|
+
if (textSizeCache.size >= CACHE_SIZE) {
|
|
1679
|
+
const firstKey = textSizeCache.keys().next().value;
|
|
1680
|
+
if (!(0, _chartutilities.isInvalidValue)(firstKey)) {
|
|
1681
|
+
textSizeCache.delete(firstKey);
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
textSizeCache.set(cacheKey, {
|
|
1685
|
+
width,
|
|
1686
|
+
height
|
|
1687
|
+
});
|
|
1688
|
+
return {
|
|
1689
|
+
width,
|
|
1690
|
+
height
|
|
1691
|
+
};
|
|
1649
1692
|
};
|
|
1650
1693
|
function isScatterPolarSeries(points) {
|
|
1651
1694
|
return points.some((item)=>{
|
|
@@ -1842,3 +1885,102 @@ const findCalloutPoints = (calloutPointsByX, x)=>{
|
|
|
1842
1885
|
values: calloutPointsByX[key]
|
|
1843
1886
|
};
|
|
1844
1887
|
};
|
|
1888
|
+
const autoLayoutXAxisLabels = (tickValues, tickLabels, scale, axisNode, containerWidth, container)=>{
|
|
1889
|
+
let requiresWrap = false;
|
|
1890
|
+
let requiresTruncate = false;
|
|
1891
|
+
const maxWidths = [];
|
|
1892
|
+
const [rangeStart, rangeEnd] = scale.range();
|
|
1893
|
+
const isRTL = rangeEnd - rangeStart < 0;
|
|
1894
|
+
const start = isRTL ? containerWidth : 0;
|
|
1895
|
+
const end = isRTL ? 0 : containerWidth;
|
|
1896
|
+
const getTickPosition = (index)=>{
|
|
1897
|
+
var _scale;
|
|
1898
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1899
|
+
return ((_scale = scale(tickValues[index])) !== null && _scale !== void 0 ? _scale : 0) + ('bandwidth' in scale ? scale.bandwidth() / 2 : 0);
|
|
1900
|
+
};
|
|
1901
|
+
const getLabelWidth = (text)=>{
|
|
1902
|
+
return getTextSize(text, CARTESIAN_XAXIS_TEXT_SELECTOR, container).width;
|
|
1903
|
+
};
|
|
1904
|
+
for(let i = 0; i < tickValues.length; i++){
|
|
1905
|
+
const position = getTickPosition(i);
|
|
1906
|
+
const leftSpace = Math.abs(i > 0 ? (position - getTickPosition(i - 1)) / 2 : position - start);
|
|
1907
|
+
const rightSpace = Math.abs(i + 1 < tickValues.length ? (getTickPosition(i + 1) - position) / 2 : end - position);
|
|
1908
|
+
const maxAvailableWidth = Math.min(leftSpace, rightSpace) * 2 - 8; // 4px padding on both sides
|
|
1909
|
+
const label = tickLabels[i];
|
|
1910
|
+
const labelWidth = getLabelWidth(label);
|
|
1911
|
+
maxWidths.push(maxAvailableWidth);
|
|
1912
|
+
if (labelWidth > maxAvailableWidth) {
|
|
1913
|
+
const longestWordWidth = Math.max(...label.split(/\s+/).map((word)=>getLabelWidth(word)));
|
|
1914
|
+
if (longestWordWidth <= maxAvailableWidth) {
|
|
1915
|
+
requiresWrap = true;
|
|
1916
|
+
} else {
|
|
1917
|
+
requiresTruncate = true;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
if (requiresTruncate) {
|
|
1922
|
+
return truncateAndStaggerXAxisLabels(tickValues, tickLabels, scale, axisNode, containerWidth, container);
|
|
1923
|
+
}
|
|
1924
|
+
if (requiresWrap) {
|
|
1925
|
+
var _createWrapOfXLabels;
|
|
1926
|
+
return (_createWrapOfXLabels = createWrapOfXLabels({
|
|
1927
|
+
node: axisNode,
|
|
1928
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1929
|
+
xAxis: scale,
|
|
1930
|
+
noOfCharsToTruncate: 100,
|
|
1931
|
+
showXAxisLablesTooltip: false,
|
|
1932
|
+
width: maxWidths,
|
|
1933
|
+
container
|
|
1934
|
+
})) !== null && _createWrapOfXLabels !== void 0 ? _createWrapOfXLabels : 0;
|
|
1935
|
+
}
|
|
1936
|
+
return 0;
|
|
1937
|
+
};
|
|
1938
|
+
const truncateAndStaggerXAxisLabels = (tickValues, tickLabels, scale, axisNode, containerWidth, container)=>{
|
|
1939
|
+
if (!axisNode) {
|
|
1940
|
+
return 0;
|
|
1941
|
+
}
|
|
1942
|
+
let maxHeight = 12;
|
|
1943
|
+
const [rangeStart, rangeEnd] = scale.range();
|
|
1944
|
+
const isRTL = rangeEnd - rangeStart < 0;
|
|
1945
|
+
const start = isRTL ? containerWidth : 0;
|
|
1946
|
+
const end = isRTL ? 0 : containerWidth;
|
|
1947
|
+
const getTickPosition = (index)=>{
|
|
1948
|
+
var _scale;
|
|
1949
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1950
|
+
return ((_scale = scale(tickValues[index])) !== null && _scale !== void 0 ? _scale : 0) + ('bandwidth' in scale ? scale.bandwidth() / 2 : 0);
|
|
1951
|
+
};
|
|
1952
|
+
const getLabelSize = (text)=>{
|
|
1953
|
+
return getTextSize(text, CARTESIAN_XAXIS_TEXT_SELECTOR, container);
|
|
1954
|
+
};
|
|
1955
|
+
(0, _d3selection.select)(axisNode).selectAll('.tick text').each(function(_, i) {
|
|
1956
|
+
const position = getTickPosition(i);
|
|
1957
|
+
const leftSpace = Math.abs(i > 0 ? position - getTickPosition(i - 1) : position - start);
|
|
1958
|
+
const rightSpace = Math.abs(i + 1 < tickValues.length ? getTickPosition(i + 1) - position : end - position);
|
|
1959
|
+
const maxAvailableWidth = Math.min(leftSpace, rightSpace) * 2 - 8; // 4px padding on both sides
|
|
1960
|
+
const label = tickLabels[i];
|
|
1961
|
+
const textNode = (0, _d3selection.select)(this).text(null).attr('data-full', label);
|
|
1962
|
+
const lineHeight = 1.1; // ems
|
|
1963
|
+
const y = textNode.attr('y');
|
|
1964
|
+
const dy = parseFloat(textNode.attr('dy'));
|
|
1965
|
+
textNode.append('tspan').attr('x', 0).attr('y', y).attr('dy', (i % 2 === 1 ? lineHeight : 0) + dy + 'em').text(truncateTextToFitWidth(label, maxAvailableWidth, (s)=>getLabelSize(s).width));
|
|
1966
|
+
maxHeight = Math.max(maxHeight, getLabelSize(label).height);
|
|
1967
|
+
});
|
|
1968
|
+
return tickValues.length > 1 ? maxHeight : 0;
|
|
1969
|
+
};
|
|
1970
|
+
const truncateTextToFitWidth = (text, maxWidth, measure)=>{
|
|
1971
|
+
if (measure(text) <= maxWidth) {
|
|
1972
|
+
return text;
|
|
1973
|
+
}
|
|
1974
|
+
let lo = 1;
|
|
1975
|
+
let hi = text.length;
|
|
1976
|
+
while(lo < hi){
|
|
1977
|
+
const mid = Math.floor((lo + hi + 1) / 2);
|
|
1978
|
+
const candidate = text.slice(0, mid) + '...';
|
|
1979
|
+
if (measure(candidate) <= maxWidth) {
|
|
1980
|
+
lo = mid;
|
|
1981
|
+
} else {
|
|
1982
|
+
hi = mid - 1;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
return text.slice(0, lo) + '...';
|
|
1986
|
+
};
|