@rowsncolumns/charts 28.1.17 → 28.1.19
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/Readme.md +18 -1
- package/dist/cjs/basic-chart/basic-chart.d.ts +1 -1
- package/dist/cjs/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/cjs/basic-chart/basic-chart.js +371 -242
- package/dist/cjs/basic-chart/helpers.d.ts +7 -3
- package/dist/cjs/basic-chart/helpers.d.ts.map +1 -1
- package/dist/cjs/basic-chart/helpers.js +30 -4
- package/dist/cjs/basic-chart/index.d.ts +7 -0
- package/dist/cjs/basic-chart/index.d.ts.map +1 -1
- package/dist/cjs/basic-chart/index.js +19 -2
- package/dist/cjs/components/editors/chart-editor.d.ts +7 -1
- package/dist/cjs/components/editors/chart-editor.d.ts.map +1 -1
- package/dist/cjs/components/editors/chart-editor.js +24 -14
- package/dist/cjs/components/editors/fields/axis-options-fields.d.ts +6 -3
- package/dist/cjs/components/editors/fields/axis-options-fields.d.ts.map +1 -1
- package/dist/cjs/components/editors/fields/axis-options-fields.js +69 -7
- package/dist/cjs/components/editors/fields/chart-elements-fields.d.ts +15 -0
- package/dist/cjs/components/editors/fields/chart-elements-fields.d.ts.map +1 -0
- package/dist/cjs/components/editors/fields/chart-elements-fields.js +23 -0
- package/dist/cjs/components/editors/fields/series-format-fields.d.ts.map +1 -1
- package/dist/cjs/components/editors/fields/series-format-fields.js +16 -2
- package/dist/cjs/config.d.ts +10 -0
- package/dist/cjs/config.d.ts.map +1 -1
- package/dist/cjs/config.js +45 -10
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +10 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/utils/chart-lines.d.ts +36 -0
- package/dist/cjs/utils/chart-lines.d.ts.map +1 -0
- package/dist/cjs/utils/chart-lines.js +111 -0
- package/dist/cjs/utils/data-table.d.ts +31 -0
- package/dist/cjs/utils/data-table.d.ts.map +1 -0
- package/dist/cjs/utils/data-table.js +61 -0
- package/dist/cjs/utils/echarts-gl-loader.d.ts +6 -0
- package/dist/cjs/utils/echarts-gl-loader.d.ts.map +1 -1
- package/dist/cjs/utils/echarts-gl-loader.js +42 -1
- package/dist/cjs/utils/excel-axis-scale.d.ts +35 -0
- package/dist/cjs/utils/excel-axis-scale.d.ts.map +1 -0
- package/dist/cjs/utils/excel-axis-scale.js +210 -0
- package/dist/cjs/utils/overrides.d.ts +24 -3
- package/dist/cjs/utils/overrides.d.ts.map +1 -1
- package/dist/cjs/utils/overrides.js +119 -14
- package/dist/cjs/utils/three-d.d.ts +12 -1
- package/dist/cjs/utils/three-d.d.ts.map +1 -1
- package/dist/cjs/utils/three-d.js +4 -1
- package/dist/esm/basic-chart/basic-chart.d.ts +1 -1
- package/dist/esm/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/esm/basic-chart/basic-chart.js +237 -73
- package/dist/esm/basic-chart/helpers.d.ts +7 -3
- package/dist/esm/basic-chart/helpers.d.ts.map +1 -1
- package/dist/esm/basic-chart/helpers.js +26 -3
- package/dist/esm/basic-chart/index.d.ts +7 -0
- package/dist/esm/basic-chart/index.d.ts.map +1 -1
- package/dist/esm/basic-chart/index.js +15 -1
- package/dist/esm/components/editors/chart-editor.d.ts +7 -1
- package/dist/esm/components/editors/chart-editor.d.ts.map +1 -1
- package/dist/esm/components/editors/chart-editor.js +16 -4
- package/dist/esm/components/editors/fields/axis-options-fields.d.ts +6 -3
- package/dist/esm/components/editors/fields/axis-options-fields.d.ts.map +1 -1
- package/dist/esm/components/editors/fields/axis-options-fields.js +56 -5
- package/dist/esm/components/editors/fields/chart-elements-fields.d.ts +15 -0
- package/dist/esm/components/editors/fields/chart-elements-fields.d.ts.map +1 -0
- package/dist/esm/components/editors/fields/chart-elements-fields.js +17 -0
- package/dist/esm/components/editors/fields/series-format-fields.d.ts.map +1 -1
- package/dist/esm/components/editors/fields/series-format-fields.js +9 -1
- package/dist/esm/config.d.ts +10 -0
- package/dist/esm/config.d.ts.map +1 -1
- package/dist/esm/config.js +20 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +10 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils/chart-lines.d.ts +36 -0
- package/dist/esm/utils/chart-lines.d.ts.map +1 -0
- package/dist/esm/utils/chart-lines.js +121 -0
- package/dist/esm/utils/data-table.d.ts +31 -0
- package/dist/esm/utils/data-table.d.ts.map +1 -0
- package/dist/esm/utils/data-table.js +48 -0
- package/dist/esm/utils/echarts-gl-loader.d.ts +6 -0
- package/dist/esm/utils/echarts-gl-loader.d.ts.map +1 -1
- package/dist/esm/utils/echarts-gl-loader.js +40 -0
- package/dist/esm/utils/excel-axis-scale.d.ts +35 -0
- package/dist/esm/utils/excel-axis-scale.d.ts.map +1 -0
- package/dist/esm/utils/excel-axis-scale.js +122 -0
- package/dist/esm/utils/overrides.d.ts +24 -3
- package/dist/esm/utils/overrides.d.ts.map +1 -1
- package/dist/esm/utils/overrides.js +111 -10
- package/dist/esm/utils/three-d.d.ts +12 -1
- package/dist/esm/utils/three-d.d.ts.map +1 -1
- package/dist/esm/utils/three-d.js +4 -1
- package/package.json +7 -7
|
@@ -16,20 +16,23 @@ import { computeBoxplotSummary } from "../utils/boxplot";
|
|
|
16
16
|
import { createBubbleSizeScale, prepareBubbleSeriesData, } from "../utils/bubble";
|
|
17
17
|
import { echartsGroupedCategoryAxes, resolveCategoryLevels, } from "../utils/category-levels";
|
|
18
18
|
import { dataUrlToBlob } from "../utils/chart-image";
|
|
19
|
+
import { buildChartLineSeries, CHART_LINE_SERIES_PREFIX, } from "../utils/chart-lines";
|
|
19
20
|
import { canSwitchRowColumn, cellLabelGetterFromRangeReader, switchRowColumn, } from "../utils/chart-orientation";
|
|
20
21
|
import { coerceCalculatedLabel, getChartDataRanges, } from "../utils/chart-spec-utils";
|
|
21
22
|
import { getChartPalette } from "../utils/chart-styles";
|
|
23
|
+
import { dataTableAxes, } from "../utils/data-table";
|
|
22
24
|
import { clampDoughnutHole, doughnutRings } from "../utils/doughnut";
|
|
23
|
-
import { getEchartsGlState, loadEchartsGl, } from "../utils/echarts-gl-loader";
|
|
25
|
+
import { getEchartsGlState, loadEchartsGl, markEchartsGlFailed, } from "../utils/echarts-gl-loader";
|
|
24
26
|
import { buildEchartsOverlaySeries } from "../utils/echarts-overlays";
|
|
25
27
|
import { applyEmptyCellsPolicy, connectsAcrossEmptyCells, isLineLikeChartType, isolatedPointIndexes, } from "../utils/empty-cells";
|
|
28
|
+
import { excelAutoAxisScale, valueAxisExtentValues } from "../utils/excel-axis-scale";
|
|
26
29
|
import { gradientToEcharts } from "../utils/gradient";
|
|
27
30
|
import { buildHierarchyTree, contrastTextColor, extractHierarchyRows, getHierarchyHeaderTitle, } from "../utils/hierarchy";
|
|
28
31
|
import { aggregateByCategory, binHistogram, computePareto, isParetoSpec, } from "../utils/histogram";
|
|
29
32
|
import { categoryAxisNameGap, legendLabelsFrom, reserveEchartsLegendBand, } from "../utils/legend-layout";
|
|
30
33
|
import { clampSecondPieSize, isOfPieChartSpec, otherSliceHalfAngle, resolveOfPieType, splitOfPie, } from "../utils/of-pie";
|
|
31
34
|
import { applyAxisOverrides, applyLegendOverrides, buildSeriesLabelOption, dataLabelFormatter, resolveSeriesDataLabels, } from "../utils/overrides";
|
|
32
|
-
import { themedTextStyle } from "../utils/overrides";
|
|
35
|
+
import { CHART_TEXT_PX, CHART_TITLE_PX, fontSizePx, pointsToPixels, themedTextStyle, } from "../utils/overrides";
|
|
33
36
|
import { explosionOffsetPx, pieRadiusPx, resolveExplosion, } from "../utils/pie-explosion";
|
|
34
37
|
import { buildRadarIndicators, buildRadarSeriesData } from "../utils/radar";
|
|
35
38
|
import { buildRegionMapData, buildSequentialColorRamp, isRegionMapSpec, resolveGeoScope, warnOnceForUnmatchedRegions, } from "../utils/region-map";
|
|
@@ -40,7 +43,7 @@ import { STOCK_ROLES, toCandlestick, toLineSeries, toVolumeSeries, } from "../ut
|
|
|
40
43
|
import { buildBar3DData, buildContourData, buildLine3DSeries, buildSurfaceData, getCategoryCount, getValueExtent, isContourSpec, resolve3DRenderKind, SURFACE_COLOR_RAMP, } from "../utils/three-d";
|
|
41
44
|
import { computeWaterfall } from "../utils/waterfall";
|
|
42
45
|
import { isWebGLAvailable } from "../utils/webgl";
|
|
43
|
-
import { chartTypeToEchartsType, circularLegendEntries, getEchartsSeriesStyle, isCircularChartType, mapMarkerSymbolToEcharts, showXAxis, } from "./helpers";
|
|
46
|
+
import { automaticMarkerSymbol, chartTypeToEchartsType, circularLegendEntries, getEchartsSeriesStyle, isCircularChartType, mapMarkerSymbolToEcharts, showXAxis, } from "./helpers";
|
|
44
47
|
// Excel error values that should be treated as null in charts
|
|
45
48
|
const EXCEL_ERROR_VALUES = new Set([
|
|
46
49
|
"#N/A",
|
|
@@ -248,9 +251,33 @@ const defaultLegendConfig = {
|
|
|
248
251
|
};
|
|
249
252
|
/** Category-axis title gap: clears one row of tick labels (#986). */
|
|
250
253
|
const CATEGORY_AXIS_NAME_GAP = categoryAxisNameGap();
|
|
251
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Excel's chart text colour: Text 1 at 65% (`<a:schemeClr val="tx1"><a:lumMod
|
|
256
|
+
* val="65000"/><a:lumOff val="35000"/>`, #595959 on the light theme) — RD-24.
|
|
257
|
+
*/
|
|
258
|
+
const chartTextColor = (theme, isDarkMode) => getStringifiedColor({ theme: 1, tint: isDarkMode ? 1 : 0.35 }, theme);
|
|
259
|
+
/** The theme's body (minor) font, which Excel's chart text uses. */
|
|
260
|
+
const chartFontFamily = (theme) => theme?.primaryFontFamily ? `${theme.primaryFontFamily}, sans-serif` : "sans-serif";
|
|
261
|
+
/** Chart types whose value axes take Excel's automatic bounds and major unit. */
|
|
262
|
+
const AUTO_SCALE_CHART_TYPES = new Set([
|
|
263
|
+
"column",
|
|
264
|
+
"bar",
|
|
265
|
+
"line",
|
|
266
|
+
"area",
|
|
267
|
+
"combo",
|
|
268
|
+
]);
|
|
269
|
+
export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, readonly, getDomainValuesFromRange, getSeriesValuesFromRange, getFormattingFromRange, onDeleteChart, onUpdateChart, onRequestEdit, onRequestCalculate, isSelected, fieldButtons, locale, enable3D, }) => {
|
|
252
270
|
const spec = chart.spec;
|
|
253
|
-
|
|
271
|
+
// A title linked to a cell shows the cell's text (FT-08); `title` is its last copy.
|
|
272
|
+
const titleSource = chart.spec.titleSource;
|
|
273
|
+
const linkedTitleValue = titleSource
|
|
274
|
+
? getDomainValuesFromRange(titleSource)?.[0]
|
|
275
|
+
: undefined;
|
|
276
|
+
const explicitChartTitle = (linkedTitleValue !== undefined && linkedTitleValue !== null && linkedTitleValue !== ""
|
|
277
|
+
? String(linkedTitleValue)
|
|
278
|
+
: undefined) ??
|
|
279
|
+
chart.spec.title ??
|
|
280
|
+
undefined;
|
|
254
281
|
const hierarchyTitleRef = useRef(explicitChartTitle);
|
|
255
282
|
const title = explicitChartTitle ?? hierarchyTitleRef.current;
|
|
256
283
|
const el = useRef(null);
|
|
@@ -428,7 +455,7 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
428
455
|
// SSR, import failure, PIE_3D) the 2-D fallback renders untouched.
|
|
429
456
|
// The 3-D and region-map gates key off disjoint sourceChartType
|
|
430
457
|
// tokens, so a spec can never satisfy both.
|
|
431
|
-
const threeDRenderKind = resolve3DRenderKind(spec.sourceChartType);
|
|
458
|
+
const threeDRenderKind = resolve3DRenderKind(spec.sourceChartType, { enable3D });
|
|
432
459
|
const canRender3D = threeDRenderKind !== null && isWebGLAvailable();
|
|
433
460
|
const willRender3D = canRender3D && getEchartsGlState() === "ready";
|
|
434
461
|
if (canRender3D && !willRender3D && getEchartsGlState() !== "failed") {
|
|
@@ -790,20 +817,19 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
790
817
|
visible: bubbleLegend.show !== false,
|
|
791
818
|
labels: preparedSeries.map((entry) => entry.name),
|
|
792
819
|
legendFontSize: bubbleLegend.textStyle?.fontSize ??
|
|
793
|
-
spec.legend?.textFormat?.fontSize
|
|
794
|
-
12,
|
|
820
|
+
fontSizePx(spec.legend?.textFormat?.fontSize, CHART_TEXT_PX),
|
|
795
821
|
legendItemWidth: defaultLegendConfig.itemWidth,
|
|
796
822
|
width: width ?? 0,
|
|
797
823
|
height: height ?? 0,
|
|
798
824
|
hasTitle: Boolean(explicitChartTitle),
|
|
799
|
-
titleFontSize: spec.titleTextFormat?.fontSize
|
|
825
|
+
titleFontSize: fontSizePx(spec.titleTextFormat?.fontSize, CHART_TITLE_PX),
|
|
800
826
|
hasBottomAxisTitle: Boolean(spec.horizontalAxisTitle),
|
|
801
827
|
bottomAxisNameGap: 30,
|
|
802
828
|
hasLeftAxisTitle: Boolean(spec.verticalAxisTitle),
|
|
803
829
|
});
|
|
804
830
|
chartRef.current?.setOption({
|
|
805
831
|
xAxis: [
|
|
806
|
-
applyAxisOverrides({ ...xAxisConfig }, spec.categoryAxisOptions),
|
|
832
|
+
applyAxisOverrides({ ...xAxisConfig }, spec.categoryAxisOptions, undefined, undefined, "x"),
|
|
807
833
|
],
|
|
808
834
|
yAxis: [
|
|
809
835
|
applyAxisOverrides({
|
|
@@ -936,13 +962,12 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
936
962
|
visible: legendShown && hierarchyData.length > 0,
|
|
937
963
|
labels: hierarchyData.map((node) => node.name),
|
|
938
964
|
legendFontSize: hierarchyLegend.textStyle?.fontSize ??
|
|
939
|
-
spec.legend?.textFormat?.fontSize
|
|
940
|
-
12,
|
|
965
|
+
fontSizePx(spec.legend?.textFormat?.fontSize, CHART_TEXT_PX),
|
|
941
966
|
legendItemWidth: defaultLegendConfig.itemWidth,
|
|
942
967
|
width: width ?? 0,
|
|
943
968
|
height: height ?? 0,
|
|
944
969
|
hasTitle: Boolean(explicitChartTitle ?? headerTitle),
|
|
945
|
-
titleFontSize: spec.titleTextFormat?.fontSize
|
|
970
|
+
titleFontSize: fontSizePx(spec.titleTextFormat?.fontSize, CHART_TITLE_PX),
|
|
946
971
|
hasBottomAxisTitle: false,
|
|
947
972
|
bottomAxisNameGap: 0,
|
|
948
973
|
hasLeftAxisTitle: false,
|
|
@@ -1327,38 +1352,63 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1327
1352
|
inRange: { color: [...SURFACE_COLOR_RAMP] },
|
|
1328
1353
|
};
|
|
1329
1354
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1355
|
+
// echarts-gl builds its GL scene inside setOption, and that can
|
|
1356
|
+
// throw after the module loaded fine — claygl compiles compositor
|
|
1357
|
+
// sizes with `new Function`, which a CSP without 'unsafe-eval'
|
|
1358
|
+
// blocks (rowsncolumns/spreadsheet#1187). Latch the failure so no
|
|
1359
|
+
// chart retries 3-D, drop the half-built instance and draw the 2-D
|
|
1360
|
+
// fallback instead of leaving the chart blank.
|
|
1361
|
+
try {
|
|
1362
|
+
chartRef.current?.setOption({
|
|
1363
|
+
tooltip: {
|
|
1364
|
+
textStyle: { fontSize: 12 },
|
|
1365
|
+
formatter: threeDTooltipFormatter,
|
|
1366
|
+
},
|
|
1367
|
+
legend: threeDRenderKind === "line3D" || stackedBar3D
|
|
1368
|
+
? applyLegendOverrides({
|
|
1369
|
+
...defaultLegendConfig,
|
|
1370
|
+
show: seriesNames.length > 1,
|
|
1371
|
+
data: seriesNames,
|
|
1372
|
+
}, spec.legend)
|
|
1373
|
+
: { show: false },
|
|
1374
|
+
xAxis3D: { ...xAxis3D, name: spec.horizontalAxisTitle ?? "" },
|
|
1375
|
+
yAxis3D: { ...yAxis3D, name: "" },
|
|
1376
|
+
zAxis3D: { type: "value", name: spec.verticalAxisTitle ?? "" },
|
|
1377
|
+
grid3D: {
|
|
1378
|
+
boxDepth: Math.max(20, Math.min(100, seriesNames.length * 20)),
|
|
1379
|
+
viewControl: { autoRotate: false },
|
|
1380
|
+
},
|
|
1381
|
+
...(visualMap ? { visualMap: [visualMap] } : {}),
|
|
1382
|
+
series: threeDSeries,
|
|
1383
|
+
}, {
|
|
1384
|
+
replaceMerge: [
|
|
1385
|
+
"series",
|
|
1386
|
+
"xAxis3D",
|
|
1387
|
+
"yAxis3D",
|
|
1388
|
+
"zAxis3D",
|
|
1389
|
+
"visualMap",
|
|
1390
|
+
"legend",
|
|
1391
|
+
"tooltip",
|
|
1392
|
+
],
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
catch (error) {
|
|
1396
|
+
markEchartsGlFailed(error);
|
|
1397
|
+
try {
|
|
1398
|
+
chartRef.current?.dispose();
|
|
1399
|
+
}
|
|
1400
|
+
catch {
|
|
1401
|
+
// A GL instance that threw mid-build may not dispose cleanly.
|
|
1402
|
+
}
|
|
1403
|
+
chartRef.current = undefined;
|
|
1404
|
+
renderedIn3D.current = false;
|
|
1405
|
+
previousChartType.current = undefined;
|
|
1406
|
+
previousSeriesCount.current = undefined;
|
|
1407
|
+
initializeChart();
|
|
1408
|
+
applyThemeOptions();
|
|
1409
|
+
await updateChart();
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1362
1412
|
// Re-apply theme-derived title / palette / tooltip colors — lost
|
|
1363
1413
|
// when the instance was re-initialized on entry into 3-D.
|
|
1364
1414
|
renderedIn3D.current = true;
|
|
@@ -1420,13 +1470,12 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1420
1470
|
visible: radarLegend.show !== false,
|
|
1421
1471
|
labels: radarData.map((d) => d.name),
|
|
1422
1472
|
legendFontSize: radarLegend.textStyle?.fontSize ??
|
|
1423
|
-
spec.legend?.textFormat?.fontSize
|
|
1424
|
-
12,
|
|
1473
|
+
fontSizePx(spec.legend?.textFormat?.fontSize, CHART_TEXT_PX),
|
|
1425
1474
|
legendItemWidth: defaultLegendConfig.itemWidth,
|
|
1426
1475
|
width: width ?? 0,
|
|
1427
1476
|
height: height ?? 0,
|
|
1428
1477
|
hasTitle: Boolean(explicitChartTitle),
|
|
1429
|
-
titleFontSize: spec.titleTextFormat?.fontSize
|
|
1478
|
+
titleFontSize: fontSizePx(spec.titleTextFormat?.fontSize, CHART_TITLE_PX),
|
|
1430
1479
|
hasBottomAxisTitle: false,
|
|
1431
1480
|
bottomAxisNameGap: 0,
|
|
1432
1481
|
hasLeftAxisTitle: false,
|
|
@@ -1727,6 +1776,13 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1727
1776
|
return;
|
|
1728
1777
|
}
|
|
1729
1778
|
const isStacked = spec.stackedType && spec.stackedType !== "UNSTACKED";
|
|
1779
|
+
// Tick labels and axis titles in Excel's chart text style (RD-24): 9 pt
|
|
1780
|
+
// labels, 10 pt titles, Text 1 at 65%. An axis' `<c:txPr>` overrides it.
|
|
1781
|
+
const axisTextColor = chartTextColor(theme, isDarkMode);
|
|
1782
|
+
const axisTextStyle = {
|
|
1783
|
+
axisLabel: { color: axisTextColor, fontSize: CHART_TEXT_PX },
|
|
1784
|
+
nameTextStyle: { color: axisTextColor, fontSize: pointsToPixels(10) },
|
|
1785
|
+
};
|
|
1730
1786
|
const isCircularChart = spec.chartType === "pie" || spec.chartType === "doughnut";
|
|
1731
1787
|
// Pie-of-pie / bar-of-pie composite. The of-pie branch below fills
|
|
1732
1788
|
// `ofPieLayout` so the grid/axis assembly at the bottom can add the
|
|
@@ -1753,7 +1809,7 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1753
1809
|
show: showAxis,
|
|
1754
1810
|
axisLine: { show: true },
|
|
1755
1811
|
axisTick: { show: true },
|
|
1756
|
-
splitLine: { show:
|
|
1812
|
+
splitLine: { show: false },
|
|
1757
1813
|
name: isHorizontalBarChart
|
|
1758
1814
|
? spec.verticalAxisTitle ?? ""
|
|
1759
1815
|
: spec.horizontalAxisTitle ?? "",
|
|
@@ -1777,12 +1833,15 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1777
1833
|
: spec.horizontalAxisTitle ?? ""
|
|
1778
1834
|
: undefined;
|
|
1779
1835
|
chartDomains.push({
|
|
1836
|
+
...axisTextStyle,
|
|
1780
1837
|
type: "category",
|
|
1781
1838
|
data: axisData,
|
|
1782
1839
|
show: showAxis && !isCircularChart,
|
|
1783
1840
|
axisLine: { show: !isCircularChart },
|
|
1784
1841
|
axisTick: { show: !isCircularChart },
|
|
1785
|
-
|
|
1842
|
+
// Excel draws vertical (category) gridlines only when the axis asks
|
|
1843
|
+
// for them (`<c:catAx><c:majorGridlines/>`) — LV-05.
|
|
1844
|
+
splitLine: { show: false },
|
|
1786
1845
|
name: axisTitle,
|
|
1787
1846
|
nameLocation: "middle",
|
|
1788
1847
|
nameGap: CATEGORY_AXIS_NAME_GAP,
|
|
@@ -1790,11 +1849,12 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1790
1849
|
});
|
|
1791
1850
|
if (chartDomains.length === 0 && !isCircularChart) {
|
|
1792
1851
|
chartDomains.push({
|
|
1852
|
+
...axisTextStyle,
|
|
1793
1853
|
type: "category",
|
|
1794
1854
|
show: showAxis,
|
|
1795
1855
|
axisLine: { show: true },
|
|
1796
1856
|
axisTick: { show: true },
|
|
1797
|
-
splitLine: { show:
|
|
1857
|
+
splitLine: { show: false },
|
|
1798
1858
|
gridIndex: 0,
|
|
1799
1859
|
name: isHorizontalBarChart
|
|
1800
1860
|
? spec.verticalAxisTitle ?? ""
|
|
@@ -1964,8 +2024,9 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1964
2024
|
seriesEntry.showSymbol = wantsMarkers || labelsWithoutMarkers;
|
|
1965
2025
|
if (wantsMarkers) {
|
|
1966
2026
|
seriesEntry.symbol =
|
|
1967
|
-
mapMarkerSymbolToEcharts(markerSymbol) ?? "circle";
|
|
1968
|
-
|
|
2027
|
+
mapMarkerSymbolToEcharts(markerSymbol ?? automaticMarkerSymbol(specSeriesIndex)) ?? "circle";
|
|
2028
|
+
// Excel's automatic marker is 5 pt (7 px); an authored size is points too.
|
|
2029
|
+
seriesEntry.symbolSize = Math.round(((seriesAny.marker?.size ?? 5) * 4) / 3);
|
|
1969
2030
|
}
|
|
1970
2031
|
else {
|
|
1971
2032
|
if (labelsWithoutMarkers) {
|
|
@@ -2694,18 +2755,41 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2694
2755
|
}
|
|
2695
2756
|
legend.data = [];
|
|
2696
2757
|
}
|
|
2758
|
+
// Add Chart Element → Lines / Up/Down Bars (FT-08): over the primary
|
|
2759
|
+
// axis' line series, in spec order.
|
|
2760
|
+
const lineElementOptions = spec;
|
|
2761
|
+
if (!isCircularChart &&
|
|
2762
|
+
(lineElementOptions.dropLines ||
|
|
2763
|
+
(spec.chartType === "line" &&
|
|
2764
|
+
(lineElementOptions.hiLowLines || lineElementOptions.upDownBars)))) {
|
|
2765
|
+
const lineData = chartSeries
|
|
2766
|
+
.filter((s) => s?.type === "line" &&
|
|
2767
|
+
s.yAxisIndex !== 1 &&
|
|
2768
|
+
chartSeriesSpecIndex(s.id) !== undefined &&
|
|
2769
|
+
Array.isArray(s.data))
|
|
2770
|
+
.map((s) => s.data);
|
|
2771
|
+
chartSeries.push(...buildChartLineSeries({
|
|
2772
|
+
dropLines: lineElementOptions.dropLines &&
|
|
2773
|
+
(spec.chartType === "line" || spec.chartType === "area"),
|
|
2774
|
+
hiLowLines: lineElementOptions.hiLowLines,
|
|
2775
|
+
upDownBars: lineElementOptions.upDownBars,
|
|
2776
|
+
}, lineData, { isDarkMode }));
|
|
2777
|
+
}
|
|
2697
2778
|
// Only redraw chart
|
|
2698
2779
|
// if chart type has changed
|
|
2699
2780
|
// if series count has changed. Use the rendered series count
|
|
2700
2781
|
// (`chartSeries.length`) rather than `spec.series.length` because
|
|
2701
2782
|
// trendline / error-bar overlays add extra series; comparing the
|
|
2702
2783
|
// raw spec count would miss those and skip the structural redraw.
|
|
2703
|
-
|
|
2784
|
+
// A data table's rows are extra x axes: turning it on or off is a
|
|
2785
|
+
// structural change too, so it shifts the count the redraw compares.
|
|
2786
|
+
const renderedSeriesCount = chartSeries.length + (spec.dataTable ? 10_000 : 0);
|
|
2704
2787
|
const replaceMerge = previousChartType.current !== spec.chartType ||
|
|
2705
2788
|
previousSeriesCount.current !== renderedSeriesCount
|
|
2706
2789
|
? ["series", "xAxis", "yAxis", "legend", "grid", "tooltip"]
|
|
2707
2790
|
: [];
|
|
2708
2791
|
const valueAxisBase = {
|
|
2792
|
+
...axisTextStyle,
|
|
2709
2793
|
type: "value",
|
|
2710
2794
|
show: !isCircularChart,
|
|
2711
2795
|
// echarts draws the value axis line at the zero of a value-type x
|
|
@@ -2785,13 +2869,12 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2785
2869
|
visible: finalLegend.show !== false,
|
|
2786
2870
|
labels: legendLabelsFrom(finalLegend.data, chartSeries.map((s) => s?.name)),
|
|
2787
2871
|
legendFontSize: finalLegend.textStyle?.fontSize ??
|
|
2788
|
-
spec.legend?.textFormat?.fontSize
|
|
2789
|
-
12,
|
|
2872
|
+
fontSizePx(spec.legend?.textFormat?.fontSize, CHART_TEXT_PX),
|
|
2790
2873
|
legendItemWidth: defaultLegendConfig.itemWidth,
|
|
2791
2874
|
width: width ?? 0,
|
|
2792
2875
|
height: height ?? 0,
|
|
2793
2876
|
hasTitle: Boolean(title),
|
|
2794
|
-
titleFontSize: spec.titleTextFormat?.fontSize
|
|
2877
|
+
titleFontSize: fontSizePx(spec.titleTextFormat?.fontSize, CHART_TITLE_PX),
|
|
2795
2878
|
hasBottomAxisTitle: !isCircularChart && Boolean(spec.horizontalAxisTitle),
|
|
2796
2879
|
bottomAxisNameGap,
|
|
2797
2880
|
hasLeftAxisTitle: !isCircularChart && Boolean(spec.verticalAxisTitle),
|
|
@@ -2822,12 +2905,20 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2822
2905
|
const seriesLabelOptionFor = (s) => {
|
|
2823
2906
|
const specIndex = chartSeriesSpecIndex(s?.id);
|
|
2824
2907
|
const dataLabelOptions = resolveSeriesDataLabels(chartDataLabels, specIndex === undefined ? undefined : spec.series?.[specIndex]);
|
|
2825
|
-
|
|
2908
|
+
const withFormat = dataLabelOptions && !dataLabelOptions.numberFormatPattern
|
|
2826
2909
|
? {
|
|
2827
2910
|
...dataLabelOptions,
|
|
2828
2911
|
numberFormatPattern: seriesNumberFormatFor(s),
|
|
2829
2912
|
}
|
|
2830
|
-
: dataLabelOptions
|
|
2913
|
+
: dataLabelOptions;
|
|
2914
|
+
// Value From Cells: the label range's cells, point by point.
|
|
2915
|
+
const cellRange = withFormat?.valueFromCells;
|
|
2916
|
+
return buildSeriesLabelOption(cellRange
|
|
2917
|
+
? {
|
|
2918
|
+
...withFormat,
|
|
2919
|
+
cellLabels: getDomainValuesFromRange(cellRange, spec.hiddenDimensionStrategy) ?? [],
|
|
2920
|
+
}
|
|
2921
|
+
: withFormat, s?.type, locale);
|
|
2831
2922
|
};
|
|
2832
2923
|
// For doughnut, surface the inner-radius hole on each pie series.
|
|
2833
2924
|
// Excel persists `holeSize` as a 0-90 percentage; we normalize to a
|
|
@@ -2893,7 +2984,8 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2893
2984
|
}
|
|
2894
2985
|
const seriesWithLabels = chartSeries.map((s) => {
|
|
2895
2986
|
const next = { ...s };
|
|
2896
|
-
if (DECORATION_SERIES_IDS.has(s?.id)
|
|
2987
|
+
if (DECORATION_SERIES_IDS.has(s?.id) ||
|
|
2988
|
+
String(s?.id ?? "").startsWith(CHART_LINE_SERIES_PREFIX)) {
|
|
2897
2989
|
return next;
|
|
2898
2990
|
}
|
|
2899
2991
|
const seriesLabelOption = seriesLabelOptionFor(s);
|
|
@@ -2961,6 +3053,66 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2961
3053
|
}
|
|
2962
3054
|
return next;
|
|
2963
3055
|
});
|
|
3056
|
+
// A chart with no category range (`<c:ser>` without `<c:cat>`) labels its
|
|
3057
|
+
// points 1, 2, 3… like Excel — echarts' bare category axis would number
|
|
3058
|
+
// them from 0 (LV-05).
|
|
3059
|
+
const bareCategoryAxis = chartDomains[0];
|
|
3060
|
+
if (!isCircularChart &&
|
|
3061
|
+
!categoryLevels &&
|
|
3062
|
+
!spec.domains?.length &&
|
|
3063
|
+
bareCategoryAxis &&
|
|
3064
|
+
bareCategoryAxis.data === undefined) {
|
|
3065
|
+
const pointCount = seriesWithLabels.reduce((count, s) => (s?.type === "bar" || s?.type === "line") && Array.isArray(s.data)
|
|
3066
|
+
? Math.max(count, s.data.length)
|
|
3067
|
+
: count, 0);
|
|
3068
|
+
bareCategoryAxis.data = Array.from({ length: pointCount }, (_, i) => String(i + 1));
|
|
3069
|
+
}
|
|
3070
|
+
// Add Chart Element → Data Table (FT-08): a row per plotted series under
|
|
3071
|
+
// the category axis, values in the series' own number format.
|
|
3072
|
+
const dataTableOptions = spec.dataTable;
|
|
3073
|
+
const dataTableRows = dataTableOptions && !isCircularChart && !isHorizontalBarChart && !isOfPie
|
|
3074
|
+
? seriesWithLabels
|
|
3075
|
+
.filter((s) => (s?.type === "line" || s?.type === "bar") &&
|
|
3076
|
+
chartSeriesSpecIndex(s?.id) !== undefined &&
|
|
3077
|
+
Array.isArray(s.data))
|
|
3078
|
+
.map((s) => {
|
|
3079
|
+
const specIndex = chartSeriesSpecIndex(s.id);
|
|
3080
|
+
const pattern = seriesNumberFormatFor(s);
|
|
3081
|
+
return {
|
|
3082
|
+
name: String(s.name ?? ""),
|
|
3083
|
+
color: typeof s.itemStyle?.color === "string"
|
|
3084
|
+
? s.itemStyle.color
|
|
3085
|
+
: spec.series?.[specIndex]?.color ?? paletteColorAt(specIndex),
|
|
3086
|
+
values: s.data.map((d) => {
|
|
3087
|
+
const v = d !== null && typeof d === "object"
|
|
3088
|
+
? d.originalValue ?? d.value
|
|
3089
|
+
: d;
|
|
3090
|
+
return v === null || v === undefined ? "" : formatAxisValue(pattern, v, locale);
|
|
3091
|
+
}),
|
|
3092
|
+
};
|
|
3093
|
+
})
|
|
3094
|
+
: [];
|
|
3095
|
+
const dataTableAxisList = dataTableRows.length
|
|
3096
|
+
? dataTableAxes(dataTableRows, dataTableOptions ?? {}, {
|
|
3097
|
+
textColor: axisTextColor,
|
|
3098
|
+
fontSize: CHART_TEXT_PX,
|
|
3099
|
+
borderColor: isDarkMode ? "rgba(255,255,255,0.3)" : "#D9D9D9",
|
|
3100
|
+
})
|
|
3101
|
+
: [];
|
|
3102
|
+
// Excel's automatic bounds and major unit on the cartesian value axes
|
|
3103
|
+
// (LV-05: echarts' own nicing drew steps of 3 where Excel draws 2).
|
|
3104
|
+
const autoScaleEligible = !isCircularChart &&
|
|
3105
|
+
!isOfPie &&
|
|
3106
|
+
AUTO_SCALE_CHART_TYPES.has(spec.chartType) &&
|
|
3107
|
+
!spec.sourceChartType &&
|
|
3108
|
+
spec.stackedType !== "PERCENT_STACKED";
|
|
3109
|
+
const withExcelAutoScale = (axis, opts, axisIndex) => {
|
|
3110
|
+
if (!autoScaleEligible || axis?.type === "log" || opts?.logarithmic) {
|
|
3111
|
+
return axis;
|
|
3112
|
+
}
|
|
3113
|
+
const scale = excelAutoAxisScale(valueAxisExtentValues(seriesWithLabels, axisIndex), { min: opts?.min, max: opts?.max, majorUnit: opts?.majorUnit });
|
|
3114
|
+
return scale ? { ...axis, ...scale } : axis;
|
|
3115
|
+
};
|
|
2964
3116
|
// Update charts
|
|
2965
3117
|
chartRef.current?.setOption({
|
|
2966
3118
|
xAxis: (() => {
|
|
@@ -3005,10 +3157,10 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
3005
3157
|
}
|
|
3006
3158
|
if (isHorizontalBarChart) {
|
|
3007
3159
|
return [
|
|
3008
|
-
applyAxisOverrides({
|
|
3160
|
+
withExcelAutoScale(applyAxisOverrides({
|
|
3009
3161
|
...valueAxisBase,
|
|
3010
3162
|
name: spec.horizontalAxisTitle ?? "",
|
|
3011
|
-
}, spec.valueAxisOptions, primaryAxisNumberFormat, locale),
|
|
3163
|
+
}, spec.valueAxisOptions, primaryAxisNumberFormat, locale, "x"), spec.valueAxisOptions, 0),
|
|
3012
3164
|
];
|
|
3013
3165
|
}
|
|
3014
3166
|
const base = chartDomains.length > 0
|
|
@@ -3019,14 +3171,18 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
3019
3171
|
show: showAxis,
|
|
3020
3172
|
axisLine: { show: true },
|
|
3021
3173
|
axisTick: { show: true },
|
|
3022
|
-
splitLine: { show:
|
|
3174
|
+
splitLine: { show: false },
|
|
3023
3175
|
name: spec.horizontalAxisTitle ?? "",
|
|
3024
3176
|
nameLocation: "middle",
|
|
3025
3177
|
nameGap: CATEGORY_AXIS_NAME_GAP,
|
|
3026
3178
|
},
|
|
3027
3179
|
];
|
|
3028
3180
|
const axes = base.map((axis) => applyAxisOverrides(axis, spec.categoryAxisOptions));
|
|
3029
|
-
return
|
|
3181
|
+
return [
|
|
3182
|
+
...axes,
|
|
3183
|
+
...(boxplotOverlayAxis ? [boxplotOverlayAxis] : []),
|
|
3184
|
+
...dataTableAxisList,
|
|
3185
|
+
];
|
|
3030
3186
|
})(),
|
|
3031
3187
|
yAxis: (() => {
|
|
3032
3188
|
if (isOfPie) {
|
|
@@ -3075,13 +3231,13 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
3075
3231
|
show: showAxis,
|
|
3076
3232
|
axisLine: { show: true },
|
|
3077
3233
|
axisTick: { show: true },
|
|
3078
|
-
splitLine: { show:
|
|
3234
|
+
splitLine: { show: false },
|
|
3079
3235
|
name: spec.verticalAxisTitle ?? "",
|
|
3080
3236
|
nameLocation: "middle",
|
|
3081
3237
|
nameGap: CATEGORY_AXIS_NAME_GAP,
|
|
3082
3238
|
},
|
|
3083
3239
|
];
|
|
3084
|
-
return base.map((axis) => applyAxisOverrides(axis, spec.categoryAxisOptions));
|
|
3240
|
+
return base.map((axis) => applyAxisOverrides(axis, spec.categoryAxisOptions, undefined, undefined, "y"));
|
|
3085
3241
|
}
|
|
3086
3242
|
const axes = [
|
|
3087
3243
|
applyAxisOverrides({
|
|
@@ -3100,6 +3256,7 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
3100
3256
|
}),
|
|
3101
3257
|
}, spec.valueAxisOptions, primaryAxisNumberFormat, locale),
|
|
3102
3258
|
];
|
|
3259
|
+
axes[0] = withExcelAutoScale(axes[0], spec.valueAxisOptions, 0);
|
|
3103
3260
|
if (hasSecondaryAxis) {
|
|
3104
3261
|
axes.push(applyAxisOverrides({
|
|
3105
3262
|
...valueAxisBase,
|
|
@@ -3114,6 +3271,9 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
3114
3271
|
}
|
|
3115
3272
|
: {}),
|
|
3116
3273
|
}, spec.secondaryValueAxisOptions, secondaryAxisNumberFormat, locale));
|
|
3274
|
+
if (!isPareto) {
|
|
3275
|
+
axes[1] = withExcelAutoScale(axes[1], spec.secondaryValueAxisOptions, 1);
|
|
3276
|
+
}
|
|
3117
3277
|
}
|
|
3118
3278
|
return axes;
|
|
3119
3279
|
})(),
|
|
@@ -3160,10 +3320,8 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
3160
3320
|
// re-apply these.
|
|
3161
3321
|
const applyThemeOptions = () => {
|
|
3162
3322
|
if (chartRef.current) {
|
|
3163
|
-
const textColor =
|
|
3164
|
-
|
|
3165
|
-
tint: isDarkMode ? 1 : 0,
|
|
3166
|
-
}, theme);
|
|
3323
|
+
const textColor = chartTextColor(theme, isDarkMode);
|
|
3324
|
+
const fontFamily = chartFontFamily(theme);
|
|
3167
3325
|
const bgColor = getStringifiedColor({ theme: 0, tint: isDarkMode ? -1 : 1 }, theme);
|
|
3168
3326
|
const showAxis = showXAxis(chart.spec.chartType);
|
|
3169
3327
|
// Authored chart-level text formats override the theme-derived
|
|
@@ -3179,18 +3337,24 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
3179
3337
|
// Every key is written (echarts merges setOption calls, so a key
|
|
3180
3338
|
// left out keeps its previous value — turning bold off used to
|
|
3181
3339
|
// leave the title bold, rowsncolumns/spreadsheet#1105).
|
|
3340
|
+
left: "center",
|
|
3182
3341
|
textStyle: themedTextStyle(authoredTitleFmt, {
|
|
3183
3342
|
color: textColor,
|
|
3184
|
-
fontSize:
|
|
3185
|
-
|
|
3343
|
+
fontSize: CHART_TITLE_PX,
|
|
3344
|
+
fontFamily,
|
|
3345
|
+
fontWeight: "normal",
|
|
3186
3346
|
}),
|
|
3187
3347
|
},
|
|
3188
3348
|
legend: {
|
|
3189
3349
|
textStyle: themedTextStyle(authoredLegendFmt, {
|
|
3190
3350
|
color: textColor,
|
|
3191
|
-
fontSize:
|
|
3351
|
+
fontSize: CHART_TEXT_PX,
|
|
3352
|
+
fontFamily,
|
|
3192
3353
|
}),
|
|
3193
3354
|
},
|
|
3355
|
+
// Every other chart text (tick labels, axis titles, data labels)
|
|
3356
|
+
// inherits the theme body font.
|
|
3357
|
+
textStyle: { fontFamily },
|
|
3194
3358
|
axisLabel: {
|
|
3195
3359
|
color: authoredDataLabelFmt?.color ?? textColor,
|
|
3196
3360
|
},
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { EmbeddedChart } from "@rowsncolumns/spreadsheet";
|
|
2
2
|
export declare const chartTypeToEchartsType: (type: EmbeddedChart["spec"]["chartType"]) => "bar" | "line" | "pie" | "radar" | "boxplot" | "funnel" | "treemap" | "sunburst" | "scatter" | "map";
|
|
3
|
+
export declare const mapMarkerSymbolToEcharts: (symbol: string | undefined | null) => string | undefined;
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* The marker Excel draws for a "Line with Markers" series that names no
|
|
6
|
+
* symbol of its own (`<c:lineChart><c:marker val="1"/>` with no
|
|
7
|
+
* `<c:ser><c:marker>`): the automatic cycle by series index — diamond,
|
|
8
|
+
* square, triangle, x, star, circle, plus (LV-05).
|
|
6
9
|
*/
|
|
7
|
-
export declare const
|
|
10
|
+
export declare const EXCEL_AUTOMATIC_MARKERS: readonly ["diamond", "square", "triangle", "x", "star", "circle", "plus"];
|
|
11
|
+
export declare const automaticMarkerSymbol: (seriesIndex: number) => "x" | "plus" | "circle" | "square" | "diamond" | "triangle" | "star";
|
|
8
12
|
/** Pie and doughnut — the pie-family types whose points are slices. */
|
|
9
13
|
export declare const isCircularChartType: (type: EmbeddedChart["spec"]["chartType"] | undefined) => boolean;
|
|
10
14
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../basic-chart/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,eAAO,MAAM,sBAAsB,GACjC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,yGA6DzC,CAAC;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../basic-chart/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,eAAO,MAAM,sBAAsB,GACjC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,yGA6DzC,CAAC;AAcF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,GAAG,SAAS,GAAG,IAAI,KAChC,MAAM,GAAG,SAqBX,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,2EAQ1B,CAAC;AAEX,eAAO,MAAM,qBAAqB,GAAI,aAAa,MAAM,yEAKtD,CAAC;AAEJ,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,GAC9B,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,GAAG,SAAS,KACnD,OAAgD,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,aAAa,CAAC,OAAO,CAAC,KAC7B,MAAM,EAmBR,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC;;aASzC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,YAmBjE,CAAC"}
|
|
@@ -50,6 +50,13 @@ export const chartTypeToEchartsType = (type) => {
|
|
|
50
50
|
* Map OOXML `<c:marker><c:symbol>` values to echarts symbol names.
|
|
51
51
|
* Returns undefined for "auto" / unknown — caller defaults to "circle".
|
|
52
52
|
*/
|
|
53
|
+
/** Excel's x / plus / asterisk / dash markers as echarts path symbols (filled outlines). */
|
|
54
|
+
const MARKER_PATHS = {
|
|
55
|
+
x: "path://M2,0L5,3L8,0L10,2L7,5L10,8L8,10L5,7L2,10L0,8L3,5L0,2Z",
|
|
56
|
+
plus: "path://M4,0H6V4H10V6H6V10H4V6H0V4H4Z",
|
|
57
|
+
star: "path://M4.3,0H5.7V3.8L9,1.9L9.7,3.1L6.4,5L9.7,6.9L9,8.1L5.7,6.2V10H4.3V6.2L1,8.1L0.3,6.9L3.6,5L0.3,3.1L1,1.9L4.3,3.8Z",
|
|
58
|
+
dash: "path://M0,4H10V6H0Z",
|
|
59
|
+
};
|
|
53
60
|
export const mapMarkerSymbolToEcharts = (symbol) => {
|
|
54
61
|
switch (symbol) {
|
|
55
62
|
case "circle":
|
|
@@ -63,17 +70,33 @@ export const mapMarkerSymbolToEcharts = (symbol) => {
|
|
|
63
70
|
return "triangle";
|
|
64
71
|
case "x":
|
|
65
72
|
case "plus":
|
|
66
|
-
return "pin";
|
|
67
73
|
case "star":
|
|
68
|
-
return "diamond";
|
|
69
74
|
case "dash":
|
|
70
|
-
return
|
|
75
|
+
return MARKER_PATHS[symbol];
|
|
71
76
|
case "none":
|
|
72
77
|
return "none";
|
|
73
78
|
default:
|
|
74
79
|
return undefined;
|
|
75
80
|
}
|
|
76
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* The marker Excel draws for a "Line with Markers" series that names no
|
|
84
|
+
* symbol of its own (`<c:lineChart><c:marker val="1"/>` with no
|
|
85
|
+
* `<c:ser><c:marker>`): the automatic cycle by series index — diamond,
|
|
86
|
+
* square, triangle, x, star, circle, plus (LV-05).
|
|
87
|
+
*/
|
|
88
|
+
export const EXCEL_AUTOMATIC_MARKERS = [
|
|
89
|
+
"diamond",
|
|
90
|
+
"square",
|
|
91
|
+
"triangle",
|
|
92
|
+
"x",
|
|
93
|
+
"star",
|
|
94
|
+
"circle",
|
|
95
|
+
"plus",
|
|
96
|
+
];
|
|
97
|
+
export const automaticMarkerSymbol = (seriesIndex) => EXCEL_AUTOMATIC_MARKERS[((seriesIndex % EXCEL_AUTOMATIC_MARKERS.length) +
|
|
98
|
+
EXCEL_AUTOMATIC_MARKERS.length) %
|
|
99
|
+
EXCEL_AUTOMATIC_MARKERS.length];
|
|
77
100
|
/** Pie and doughnut — the pie-family types whose points are slices. */
|
|
78
101
|
export const isCircularChartType = (type) => type === "pie" || type === "doughnut";
|
|
79
102
|
/**
|