@extend-ai/react-xlsx 0.12.2 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -22,6 +22,170 @@ var SERIES_COLORS = [
22
22
  "#636363",
23
23
  "#997300"
24
24
  ];
25
+ function quoteSeriesFormulaString(value) {
26
+ return `"${value.replace(/"/g, '""')}"`;
27
+ }
28
+ function unquoteSeriesFormulaString(value) {
29
+ const trimmed = value.trim();
30
+ if (trimmed.length < 2 || !trimmed.startsWith('"') || !trimmed.endsWith('"')) {
31
+ return null;
32
+ }
33
+ return trimmed.slice(1, -1).replace(/""/g, '"');
34
+ }
35
+ function splitTopLevelSeriesArguments(value) {
36
+ const args = [];
37
+ let current = "";
38
+ let doubleQuoted = false;
39
+ let singleQuoted = false;
40
+ let depth = 0;
41
+ for (let index = 0; index < value.length; index += 1) {
42
+ const char = value[index] ?? "";
43
+ const next = value[index + 1] ?? "";
44
+ if (doubleQuoted) {
45
+ current += char;
46
+ if (char === '"' && next === '"') {
47
+ current += next;
48
+ index += 1;
49
+ } else if (char === '"') {
50
+ doubleQuoted = false;
51
+ }
52
+ continue;
53
+ }
54
+ if (singleQuoted) {
55
+ current += char;
56
+ if (char === "'" && next === "'") {
57
+ current += next;
58
+ index += 1;
59
+ } else if (char === "'") {
60
+ singleQuoted = false;
61
+ }
62
+ continue;
63
+ }
64
+ if (char === '"') {
65
+ doubleQuoted = true;
66
+ current += char;
67
+ continue;
68
+ }
69
+ if (char === "'") {
70
+ singleQuoted = true;
71
+ current += char;
72
+ continue;
73
+ }
74
+ if (char === "(") {
75
+ depth += 1;
76
+ current += char;
77
+ continue;
78
+ }
79
+ if (char === ")") {
80
+ depth = Math.max(0, depth - 1);
81
+ current += char;
82
+ continue;
83
+ }
84
+ if (char === "," && depth === 0) {
85
+ args.push(current.trim());
86
+ current = "";
87
+ continue;
88
+ }
89
+ current += char;
90
+ }
91
+ args.push(current.trim());
92
+ return args;
93
+ }
94
+ function readSeriesNameFormula(series) {
95
+ const raw = series.raw && typeof series.raw === "object" ? series.raw : null;
96
+ return typeof raw?.name === "string" && raw.name.length > 0 ? raw.name : null;
97
+ }
98
+ function buildChartSeriesFormula(chart, seriesIndex) {
99
+ const series = chart?.series[seriesIndex];
100
+ if (!chart || !series) {
101
+ return "";
102
+ }
103
+ const nameFormula = readSeriesNameFormula(series);
104
+ const nameArgument = nameFormula ?? quoteSeriesFormulaString(series.name ?? `Series ${seriesIndex + 1}`);
105
+ const categoryArgument = series.categoriesRef?.formula ?? "";
106
+ const valueArgument = series.valuesRef?.formula ?? "";
107
+ const orderArgument = String(seriesIndex + 1);
108
+ const bubbleArgument = series.bubbleSizeRef?.formula;
109
+ return [
110
+ `=SERIES(${nameArgument}`,
111
+ categoryArgument,
112
+ valueArgument,
113
+ orderArgument,
114
+ ...chart.chartType === "Bubble" || bubbleArgument ? [bubbleArgument ?? ""] : []
115
+ ].join(",") + ")";
116
+ }
117
+ function parseChartSeriesFormula(formula, chart) {
118
+ const trimmed = formula.trim();
119
+ const withoutEquals = trimmed.startsWith("=") ? trimmed.slice(1).trim() : trimmed;
120
+ const match = /^SERIES\s*\(([\s\S]*)\)$/i.exec(withoutEquals);
121
+ if (!match) {
122
+ return null;
123
+ }
124
+ const args = splitTopLevelSeriesArguments(match[1]);
125
+ const isBubble = chart?.chartType === "Bubble";
126
+ if (args.length < 4 || args.length > 5 || isBubble && args.length !== 5) {
127
+ return null;
128
+ }
129
+ const [nameArg = "", categoryFormula = "", valueFormula = "", orderArg = "", bubbleSizeFormula] = args;
130
+ if (!categoryFormula || !valueFormula) {
131
+ return null;
132
+ }
133
+ const parsedOrder = Number(orderArg);
134
+ if (!Number.isFinite(parsedOrder)) {
135
+ return null;
136
+ }
137
+ const nameLiteral = unquoteSeriesFormulaString(nameArg);
138
+ return {
139
+ bubbleSizeFormula: bubbleSizeFormula && bubbleSizeFormula.length > 0 ? bubbleSizeFormula : void 0,
140
+ categoryFormula,
141
+ nameFormula: nameLiteral == null && nameArg.length > 0 ? nameArg : void 0,
142
+ nameLiteral: nameLiteral ?? void 0,
143
+ order: parsedOrder,
144
+ valueFormula
145
+ };
146
+ }
147
+ function applyChartSeriesFormula(chart, seriesIndex, formula, workbook) {
148
+ const parsed = parseChartSeriesFormula(formula, chart);
149
+ const currentSeries = chart.series[seriesIndex];
150
+ if (!parsed || !currentSeries) {
151
+ return null;
152
+ }
153
+ const categoriesRef = {
154
+ ...currentSeries.categoriesRef ?? {},
155
+ formula: parsed.categoryFormula
156
+ };
157
+ const valuesRef = {
158
+ ...currentSeries.valuesRef ?? {},
159
+ formula: parsed.valueFormula
160
+ };
161
+ const bubbleSizeRef = chart.chartType === "Bubble" || parsed.bubbleSizeFormula ? {
162
+ ...currentSeries.bubbleSizeRef ?? {},
163
+ formula: parsed.bubbleSizeFormula
164
+ } : currentSeries.bubbleSizeRef ?? null;
165
+ const raw = {
166
+ ...currentSeries.raw ?? {}
167
+ };
168
+ if (parsed.nameFormula) {
169
+ raw.name = parsed.nameFormula;
170
+ } else {
171
+ delete raw.name;
172
+ }
173
+ const nextSeries = {
174
+ ...currentSeries,
175
+ bubbleSizeRef,
176
+ bubbleSizes: workbook && bubbleSizeRef?.formula ? resolveReferenceValues(workbook, chart.workbookSheetIndex, bubbleSizeRef, "value").map((value) => typeof value === "number" && Number.isFinite(value) ? value : null) : currentSeries.bubbleSizes,
177
+ categories: workbook ? resolveReferenceValues(workbook, chart.workbookSheetIndex, categoriesRef, "category") : currentSeries.categories,
178
+ categoriesRef,
179
+ name: parsed.nameLiteral ?? (parsed.nameFormula && workbook ? resolveSeriesName(workbook, chart.workbookSheetIndex, parsed.nameFormula) : parsed.nameFormula ?? currentSeries.name),
180
+ raw,
181
+ values: workbook ? resolveReferenceValues(workbook, chart.workbookSheetIndex, valuesRef, "value").map((value) => typeof value === "number" && Number.isFinite(value) ? value : null) : currentSeries.values,
182
+ valuesRef
183
+ };
184
+ return {
185
+ ...chart,
186
+ series: chart.series.map((series, index) => index === seriesIndex ? nextSeries : series)
187
+ };
188
+ }
25
189
  function normalizeWorksheetVisibility(value) {
26
190
  return value === "hidden" || value === "veryHidden" ? value : "visible";
27
191
  }
@@ -1588,6 +1752,9 @@ function getLocalChildren(parent, localName) {
1588
1752
  (node) => node.nodeType === Node.ELEMENT_NODE && node.localName === localName
1589
1753
  );
1590
1754
  }
1755
+ function removeLocalChildren(parent, localName) {
1756
+ getLocalChildren(parent, localName).forEach((node) => node.parentNode?.removeChild(node));
1757
+ }
1591
1758
  function getLocalDescendants(parent, localName) {
1592
1759
  return Array.from(parent.getElementsByTagName("*")).filter(
1593
1760
  (node) => node.localName === localName
@@ -3046,34 +3213,52 @@ function setChartTitle(chartNode, value) {
3046
3213
  }
3047
3214
  function setRefFormula(parent, refNodeName, formula) {
3048
3215
  if (!formula) {
3216
+ removeLocalChildren(parent, refNodeName);
3049
3217
  return;
3050
3218
  }
3051
3219
  const refNode = ensureChild(parent, refNodeName);
3052
3220
  setLeafValue(refNode, "f", formula);
3053
3221
  }
3054
- function updateSeriesNodes(chartTypeNode, chart) {
3222
+ function setSeriesText(seriesNode, series) {
3223
+ const raw = series.raw && typeof series.raw === "object" ? series.raw : null;
3224
+ const nameFormula = typeof raw?.name === "string" && raw.name.length > 0 ? raw.name : void 0;
3225
+ if (!nameFormula && series.name === void 0) {
3226
+ return;
3227
+ }
3228
+ const tx = ensureChild(seriesNode, "tx");
3229
+ removeLocalChildren(tx, "strRef");
3230
+ removeLocalChildren(tx, "v");
3231
+ if (nameFormula) {
3232
+ const strRef = ensureChild(tx, "strRef");
3233
+ setLeafValue(strRef, "f", nameFormula);
3234
+ return;
3235
+ }
3236
+ setLeafValue(tx, "v", series.name ?? "");
3237
+ }
3238
+ function updateSeriesNodes(plotAreaNode, chart) {
3055
3239
  if (!chart.series) {
3056
3240
  return;
3057
3241
  }
3058
- const seriesNodes = getLocalDescendants(chartTypeNode, "ser");
3242
+ const seriesNodes = getLocalDescendants(plotAreaNode, "ser");
3059
3243
  chart.series.forEach((series, index) => {
3060
3244
  const seriesNode = seriesNodes[index];
3061
3245
  if (!seriesNode) {
3062
3246
  return;
3063
3247
  }
3064
- if (series.name !== void 0) {
3065
- const tx = ensureChild(seriesNode, "tx");
3066
- const strRef = ensureChild(tx, "strRef");
3067
- setLeafValue(strRef, "f", series.name);
3068
- }
3248
+ setSeriesText(seriesNode, series);
3069
3249
  if (series.categoriesRef?.formula) {
3070
- const target = chart.chartType === "Scatter" || chart.chartType === "ScatterLines" || chart.chartType === "ScatterSmooth" ? ensureChild(seriesNode, "xVal") : ensureChild(seriesNode, "cat");
3071
- setRefFormula(target, "strRef", series.categoriesRef.formula);
3250
+ const target = getFirstLocalChild(seriesNode, "xVal") ?? getFirstLocalChild(seriesNode, "cat") ?? (chart.chartType === "Scatter" || chart.chartType === "ScatterLines" || chart.chartType === "ScatterSmooth" || chart.chartType === "Bubble" ? ensureChild(seriesNode, "xVal") : ensureChild(seriesNode, "cat"));
3251
+ const categoryRefName = target.localName === "xVal" || getFirstLocalChild(target, "numRef") ? "numRef" : "strRef";
3252
+ setRefFormula(target, categoryRefName, series.categoriesRef.formula);
3072
3253
  }
3073
3254
  if (series.valuesRef?.formula) {
3074
- const target = chart.chartType === "Scatter" || chart.chartType === "ScatterLines" || chart.chartType === "ScatterSmooth" ? ensureChild(seriesNode, "yVal") : ensureChild(seriesNode, "val");
3255
+ const target = getFirstLocalChild(seriesNode, "yVal") ?? getFirstLocalChild(seriesNode, "val") ?? (chart.chartType === "Scatter" || chart.chartType === "ScatterLines" || chart.chartType === "ScatterSmooth" || chart.chartType === "Bubble" ? ensureChild(seriesNode, "yVal") : ensureChild(seriesNode, "val"));
3075
3256
  setRefFormula(target, "numRef", series.valuesRef.formula);
3076
3257
  }
3258
+ if (series.bubbleSizeRef) {
3259
+ const target = getFirstLocalChild(seriesNode, "bubbleSize") ?? ensureChild(seriesNode, "bubbleSize");
3260
+ setRefFormula(target, "numRef", series.bubbleSizeRef.formula);
3261
+ }
3077
3262
  if (series.invertIfNegative !== void 0) {
3078
3263
  setBooleanValue(seriesNode, "invertIfNegative", series.invertIfNegative);
3079
3264
  }
@@ -3222,7 +3407,7 @@ function updateWorkbookChartDefinition(imageAssets, chartAssets, chartId, patch)
3222
3407
  if (patch.dataLabels) {
3223
3408
  updateDataLabels(chartTypeNode, patch.dataLabels);
3224
3409
  }
3225
- updateSeriesNodes(chartTypeNode, patch);
3410
+ updateSeriesNodes(plotAreaNode, patch);
3226
3411
  updateAxisNode(
3227
3412
  getLocalChildren(plotAreaNode, "catAx")[0] ?? getLocalChildren(plotAreaNode, "dateAx")[0] ?? getLocalChildren(plotAreaNode, "serAx")[0] ?? null,
3228
3413
  patch.categoryAxis
@@ -3458,6 +3643,85 @@ function sheetColumnWidthToPixels(width, columnCharacterWidthPx = DEFAULT_COLUMN
3458
3643
  const pixels = width < 1 ? Math.floor(width * (digitWidth + 5) + 0.5) : Math.floor((256 * width + Math.floor(128 / digitWidth)) / 256 * digitWidth);
3459
3644
  return Math.max(MIN_COL_WIDTH_PX, pixels);
3460
3645
  }
3646
+ function resolveWorksheetDefaultColumnWidthPixels(worksheet, columnCharacterWidthPx = DEFAULT_COLUMN_CHARACTER_WIDTH_PX, fallbackPx = sheetColumnWidthToPixels(8.43, columnCharacterWidthPx)) {
3647
+ const width = typeof worksheet.defaultColumnWidth === "number" ? worksheet.defaultColumnWidth : Number.NaN;
3648
+ return Number.isFinite(width) && width > 0 ? sheetColumnWidthToPixels(width, columnCharacterWidthPx) : fallbackPx;
3649
+ }
3650
+ function resolveWorksheetDefaultRowHeightPixels(worksheet, fallbackPx = Math.max(MIN_ROW_HEIGHT_PX, Math.round(15 * 1.33))) {
3651
+ const height = typeof worksheet.defaultRowHeight === "number" ? worksheet.defaultRowHeight : Number.NaN;
3652
+ return Number.isFinite(height) && height > 0 ? Math.max(MIN_ROW_HEIGHT_PX, Math.round(height * 1.33)) : fallbackPx;
3653
+ }
3654
+ function resolveWorksheetHiddenRows(worksheet, maxRow) {
3655
+ if (!Number.isFinite(maxRow) || maxRow < 0 || typeof worksheet.isRowHidden !== "function") {
3656
+ return [];
3657
+ }
3658
+ const hiddenRows = [];
3659
+ for (let row = 0; row <= maxRow; row += 1) {
3660
+ if (worksheet.isRowHidden(row)) {
3661
+ hiddenRows.push(row);
3662
+ }
3663
+ }
3664
+ return hiddenRows;
3665
+ }
3666
+ function resolveWorksheetHiddenCols(worksheet, maxCol) {
3667
+ if (!Number.isFinite(maxCol) || maxCol < 0 || typeof worksheet.isColumnHidden !== "function") {
3668
+ return [];
3669
+ }
3670
+ const hiddenCols = [];
3671
+ for (let col = 0; col <= maxCol; col += 1) {
3672
+ if (worksheet.isColumnHidden(col)) {
3673
+ hiddenCols.push(col);
3674
+ }
3675
+ }
3676
+ return hiddenCols;
3677
+ }
3678
+ function resolveWorksheetMergeMetadata(worksheet) {
3679
+ const mergeMetadata = {
3680
+ hasHorizontalMerges: false,
3681
+ hasVerticalMerges: false,
3682
+ maxHorizontalMergeEndCol: -1,
3683
+ maxVerticalMergeEndRow: -1
3684
+ };
3685
+ const mergedRegions = Array.isArray(worksheet.mergedRegions) ? worksheet.mergedRegions : [];
3686
+ for (const rawRegion of mergedRegions) {
3687
+ let range = null;
3688
+ if (typeof rawRegion === "string") {
3689
+ range = parseA1RangeReference(rawRegion);
3690
+ } else if (rawRegion && typeof rawRegion === "object") {
3691
+ const region = rawRegion;
3692
+ const startRow = typeof region.startRow === "number" ? region.startRow : Number.NaN;
3693
+ const startCol = typeof region.startCol === "number" ? region.startCol : Number.NaN;
3694
+ const endRow = typeof region.endRow === "number" ? region.endRow : Number.NaN;
3695
+ const endCol = typeof region.endCol === "number" ? region.endCol : Number.NaN;
3696
+ if ([startRow, startCol, endRow, endCol].every((value) => Number.isFinite(value) && value >= 0)) {
3697
+ range = {
3698
+ end: {
3699
+ col: Math.max(startCol, endCol),
3700
+ row: Math.max(startRow, endRow)
3701
+ },
3702
+ start: {
3703
+ col: Math.min(startCol, endCol),
3704
+ row: Math.min(startRow, endRow)
3705
+ }
3706
+ };
3707
+ } else if (typeof region.range === "string") {
3708
+ range = parseA1RangeReference(region.range);
3709
+ }
3710
+ }
3711
+ if (!range) {
3712
+ continue;
3713
+ }
3714
+ if (range.end.col > range.start.col) {
3715
+ mergeMetadata.hasHorizontalMerges = true;
3716
+ mergeMetadata.maxHorizontalMergeEndCol = Math.max(mergeMetadata.maxHorizontalMergeEndCol, range.end.col);
3717
+ }
3718
+ if (range.end.row > range.start.row) {
3719
+ mergeMetadata.hasVerticalMerges = true;
3720
+ mergeMetadata.maxVerticalMergeEndRow = Math.max(mergeMetadata.maxVerticalMergeEndRow, range.end.row);
3721
+ }
3722
+ }
3723
+ return mergeMetadata;
3724
+ }
3461
3725
  function buildThemePalette(theme) {
3462
3726
  const themeOrder = ["lt1", "dk1", "lt2", "dk2", "accent1", "accent2", "accent3", "accent4", "accent5", "accent6", "hlink", "folHlink"];
3463
3727
  const colorsByIndex = {};
@@ -4189,67 +4453,6 @@ function parseWorkbookStyles(archive) {
4189
4453
  tableStyleByName
4190
4454
  };
4191
4455
  }
4192
- function parseWorkbookTableMetadata(archive, workbookSheets) {
4193
- return workbookSheets.map((sheet) => {
4194
- const sheetRelationships = parseRelationships(archive, relsPathForDocument(sheet.path), sheet.path);
4195
- const sheetXml = readArchiveText2(archive, sheet.path);
4196
- if (!sheetXml) {
4197
- return [];
4198
- }
4199
- const sheetDocument = parseXml2(sheetXml);
4200
- if (!sheetDocument) {
4201
- return [];
4202
- }
4203
- return getLocalElements(sheetDocument, "tablePart").flatMap((tablePartNode) => {
4204
- const relationshipId = getRelationshipId(tablePartNode);
4205
- if (!relationshipId) {
4206
- return [];
4207
- }
4208
- const relationship = sheetRelationships.get(relationshipId);
4209
- if (!relationship) {
4210
- return [];
4211
- }
4212
- const tableXml = readArchiveText2(archive, relationship.target);
4213
- if (!tableXml) {
4214
- return [];
4215
- }
4216
- const tableDocument = parseXml2(tableXml);
4217
- const tableNode = tableDocument?.documentElement;
4218
- if (!tableNode || tableNode.localName !== "table") {
4219
- return [];
4220
- }
4221
- return [{
4222
- displayName: tableNode.getAttribute("displayName") ?? void 0,
4223
- headerRowCount: parseWorkbookTableCount(tableNode.getAttribute("headerRowCount"), 1),
4224
- headerRowCellStyle: tableNode.getAttribute("headerRowCellStyle") ?? void 0,
4225
- name: tableNode.getAttribute("name") ?? void 0,
4226
- reference: tableNode.getAttribute("ref") ?? void 0,
4227
- totalsRowCount: parseWorkbookTableCount(tableNode.getAttribute("totalsRowCount"), 0),
4228
- totalsRowShown: parseWorkbookTableBoolean(tableNode.getAttribute("totalsRowShown"), false)
4229
- }];
4230
- });
4231
- });
4232
- }
4233
- function parseWorkbookTableCount(value, fallback) {
4234
- if (value === null) {
4235
- return fallback;
4236
- }
4237
- const parsed = Number.parseInt(value, 10);
4238
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
4239
- }
4240
- function parseWorkbookTableBoolean(value, fallback) {
4241
- if (value === null) {
4242
- return fallback;
4243
- }
4244
- const normalized = value.trim().toLowerCase();
4245
- if (normalized === "0" || normalized === "false" || normalized === "") {
4246
- return false;
4247
- }
4248
- if (normalized === "1" || normalized === "true") {
4249
- return true;
4250
- }
4251
- return fallback;
4252
- }
4253
4456
  function parseSqrefRanges(sqref) {
4254
4457
  if (!sqref) {
4255
4458
  return [];
@@ -4521,12 +4724,6 @@ function parseSheetState(archive, path, options) {
4521
4724
  const colWidthOverridesPx = {};
4522
4725
  const rowStyleIds = {};
4523
4726
  const colStyleIds = {};
4524
- const hiddenRows = /* @__PURE__ */ new Set();
4525
- const hiddenCols = /* @__PURE__ */ new Set();
4526
- let hasHorizontalMerges = false;
4527
- let hasVerticalMerges = false;
4528
- let maxHorizontalMergeEndCol = -1;
4529
- let maxVerticalMergeEndRow = -1;
4530
4727
  let minContentCol = Number.POSITIVE_INFINITY;
4531
4728
  let minContentRow = Number.POSITIVE_INFINITY;
4532
4729
  let maxContentCol = -1;
@@ -4567,16 +4764,12 @@ function parseSheetState(archive, path, options) {
4567
4764
  const rowIndex = Number(rowNode.getAttribute("r") ?? 0) - 1;
4568
4765
  const height = Number(rowNode.getAttribute("ht") ?? Number.NaN);
4569
4766
  const styleId = Number(rowNode.getAttribute("s") ?? Number.NaN);
4570
- const isHidden = (rowNode.getAttribute("hidden") ?? "0") === "1";
4571
4767
  if (rowIndex >= 0 && Number.isFinite(height)) {
4572
4768
  rowHeightOverridesPx[rowIndex] = Math.max(MIN_ROW_HEIGHT_PX, Math.round(height * 1.33));
4573
4769
  }
4574
4770
  if (rowIndex >= 0 && Number.isFinite(styleId)) {
4575
4771
  rowStyleIds[rowIndex] = styleId;
4576
4772
  }
4577
- if (rowIndex >= 0 && isHidden) {
4578
- hiddenRows.add(rowIndex);
4579
- }
4580
4773
  getChildElements(rowNode, "c").forEach((cellNode) => {
4581
4774
  const cellRef = cellNode.getAttribute("r");
4582
4775
  if (isMeaningfulCellNode(cellNode)) {
@@ -4591,28 +4784,12 @@ function parseSheetState(archive, path, options) {
4591
4784
  }
4592
4785
  });
4593
4786
  });
4594
- getLocalElements(document2, "mergeCell").forEach((mergeNode) => {
4595
- const reference = mergeNode.getAttribute("ref");
4596
- const range = reference ? parseA1RangeReference(reference) : null;
4597
- if (!range) {
4598
- return;
4599
- }
4600
- if (range.end.col > range.start.col) {
4601
- hasHorizontalMerges = true;
4602
- maxHorizontalMergeEndCol = Math.max(maxHorizontalMergeEndCol, range.end.col);
4603
- }
4604
- if (range.end.row > range.start.row) {
4605
- hasVerticalMerges = true;
4606
- maxVerticalMergeEndRow = Math.max(maxVerticalMergeEndRow, range.end.row);
4607
- }
4608
- });
4609
- const maxMetadataCol = Math.max(maxContentCol, maxHorizontalMergeEndCol, 0) + 256;
4787
+ const maxMetadataCol = Math.max(maxContentCol, 0) + 256;
4610
4788
  getLocalElements(document2, "col").forEach((colNode) => {
4611
4789
  const min = Number(colNode.getAttribute("min") ?? 0) - 1;
4612
4790
  const max = Number(colNode.getAttribute("max") ?? 0) - 1;
4613
4791
  const width = Number(colNode.getAttribute("width") ?? Number.NaN);
4614
4792
  const styleId = Number(colNode.getAttribute("style") ?? Number.NaN);
4615
- const isHidden = (colNode.getAttribute("hidden") ?? "0") === "1";
4616
4793
  if (!Number.isFinite(width)) {
4617
4794
  if (!Number.isFinite(styleId)) {
4618
4795
  return;
@@ -4627,9 +4804,6 @@ function parseSheetState(archive, path, options) {
4627
4804
  if (Number.isFinite(styleId)) {
4628
4805
  colStyleIds[col] = styleId;
4629
4806
  }
4630
- if (isHidden) {
4631
- hiddenCols.add(col);
4632
- }
4633
4807
  }
4634
4808
  }
4635
4809
  });
@@ -4641,16 +4815,16 @@ function parseSheetState(archive, path, options) {
4641
4815
  conditionalFormatRules,
4642
4816
  defaultColWidthPx: sheetColumnWidthToPixels(defaultColWidth, columnWidthCharacterWidthPx),
4643
4817
  defaultRowHeightPx: Math.max(MIN_ROW_HEIGHT_PX, Math.round(defaultRowHeight * 1.33)),
4644
- hasHorizontalMerges,
4645
- hasVerticalMerges,
4646
- maxHorizontalMergeEndCol,
4647
- maxVerticalMergeEndRow,
4818
+ hasHorizontalMerges: false,
4819
+ hasVerticalMerges: false,
4820
+ maxHorizontalMergeEndCol: -1,
4821
+ maxVerticalMergeEndRow: -1,
4648
4822
  maxContentCol,
4649
4823
  maxContentRow,
4650
4824
  minContentCol: Number.isFinite(minContentCol) ? minContentCol : -1,
4651
4825
  minContentRow: Number.isFinite(minContentRow) ? minContentRow : -1,
4652
- hiddenCols: [...hiddenCols].sort((left, right) => left - right),
4653
- hiddenRows: [...hiddenRows].sort((left, right) => left - right),
4826
+ hiddenCols: [],
4827
+ hiddenRows: [],
4654
4828
  rowHeightOverridesPx,
4655
4829
  rowStyleIds,
4656
4830
  showGridLines: (sheetViewNode?.getAttribute("showGridLines") ?? "1") !== "0",
@@ -5820,7 +5994,6 @@ function parseWorkbookStructureAssetsFromArchive(archive, options) {
5820
5994
  const theme = parseWorkbookTheme(archive);
5821
5995
  const themePalette = buildThemePalette(theme);
5822
5996
  const { defaultFont, namedCellStyleByName, styleById, tableStyleByName } = parseWorkbookStyles(archive);
5823
- const tableMetadataByWorkbookSheetIndex = parseWorkbookTableMetadata(archive, workbookSheets);
5824
5997
  return {
5825
5998
  contentTypes,
5826
5999
  namedCellStyleByName,
@@ -5830,7 +6003,7 @@ function parseWorkbookStructureAssetsFromArchive(archive, options) {
5830
6003
  themePalette
5831
6004
  })),
5832
6005
  styleById,
5833
- tableMetadataByWorkbookSheetIndex,
6006
+ tableMetadataByWorkbookSheetIndex: workbookSheets.map(() => []),
5834
6007
  tableStyleByName,
5835
6008
  theme,
5836
6009
  themePalette,
@@ -6726,16 +6899,20 @@ function resolveDisplayFileName(src, fileName) {
6726
6899
  }
6727
6900
  function resolveSheetDisplayUsedRange(usedRange, sheetState) {
6728
6901
  const [minRow, minCol, maxRow, maxCol] = usedRange;
6729
- const maxMeaningfulRow = Math.max(sheetState?.maxContentRow ?? -1, sheetState?.maxVerticalMergeEndRow ?? -1);
6730
- const maxMeaningfulCol = Math.max(sheetState?.maxContentCol ?? -1, sheetState?.maxHorizontalMergeEndCol ?? -1);
6902
+ const maxContentRow = sheetState?.maxContentRow ?? -1;
6903
+ const maxContentCol = sheetState?.maxContentCol ?? -1;
6904
+ const maxVerticalMergeEndRow = sheetState?.maxVerticalMergeEndRow ?? -1;
6905
+ const maxHorizontalMergeEndCol = sheetState?.maxHorizontalMergeEndCol ?? -1;
6906
+ const maxMeaningfulRow = Math.max(maxContentRow, maxVerticalMergeEndRow);
6907
+ const maxMeaningfulCol = Math.max(maxContentCol, maxHorizontalMergeEndCol);
6731
6908
  if (maxMeaningfulRow < 0 && maxMeaningfulCol < 0) {
6732
6909
  return usedRange;
6733
6910
  }
6734
6911
  return [
6735
6912
  sheetState?.minContentRow !== void 0 && sheetState.minContentRow >= 0 ? Math.min(minRow, sheetState.minContentRow) : minRow,
6736
6913
  sheetState?.minContentCol !== void 0 && sheetState.minContentCol >= 0 ? Math.min(minCol, sheetState.minContentCol) : minCol,
6737
- maxMeaningfulRow >= 0 ? Math.min(maxRow, maxMeaningfulRow) : maxRow,
6738
- maxMeaningfulCol >= 0 ? Math.min(maxCol, maxMeaningfulCol) : maxCol
6914
+ maxMeaningfulRow >= 0 ? maxContentRow >= 0 ? Math.min(maxRow, maxMeaningfulRow) : Math.max(maxRow, maxMeaningfulRow) : maxRow,
6915
+ maxMeaningfulCol >= 0 ? maxContentCol >= 0 ? Math.min(maxCol, maxMeaningfulCol) : Math.max(maxCol, maxMeaningfulCol) : maxCol
6739
6916
  ];
6740
6917
  }
6741
6918
  function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette, styleById, namedCellStyleByName, tableStyleByName, showHiddenSheets = false) {
@@ -6743,6 +6920,20 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6743
6920
  for (let index = 0; index < workbook.sheetCount; index += 1) {
6744
6921
  const worksheet = workbook.getSheet(index);
6745
6922
  const sheetState = sheetStatesByWorkbookSheetIndex?.[index] ?? null;
6923
+ const mergeMetadata = resolveWorksheetMergeMetadata(worksheet);
6924
+ const effectiveSheetState = {
6925
+ ...sheetState,
6926
+ ...mergeMetadata
6927
+ };
6928
+ const defaultColWidthPx = resolveWorksheetDefaultColumnWidthPixels(
6929
+ worksheet,
6930
+ sheetState?.columnWidthCharacterWidthPx,
6931
+ sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH
6932
+ );
6933
+ const defaultRowHeightPx = resolveWorksheetDefaultRowHeightPixels(
6934
+ worksheet,
6935
+ sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT
6936
+ );
6746
6937
  const visibility = normalizeWorksheetVisibility2(worksheet.visibility);
6747
6938
  if (!showHiddenSheets && visibility !== "visible") {
6748
6939
  continue;
@@ -6752,14 +6943,14 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6752
6943
  if (width !== void 0 && width !== null) {
6753
6944
  return resolveSheetColumnWidthPixels(width, sheetState?.columnWidthCharacterWidthPx);
6754
6945
  }
6755
- return sheetState?.colWidthOverridesPx?.[col] ?? sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH;
6946
+ return sheetState?.colWidthOverridesPx?.[col] ?? defaultColWidthPx;
6756
6947
  };
6757
6948
  const resolveRowHeightPx = (row) => {
6758
6949
  const height = worksheet.getRowHeight(row);
6759
6950
  if (height !== void 0 && height !== null) {
6760
6951
  return Math.max(Math.round(height * 1.33), MIN_ROW_HEIGHT_PX2);
6761
6952
  }
6762
- return sheetState?.rowHeightOverridesPx?.[row] ?? sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT;
6953
+ return sheetState?.rowHeightOverridesPx?.[row] ?? defaultRowHeightPx;
6763
6954
  };
6764
6955
  const usedRange = worksheet.usedRange();
6765
6956
  if (!usedRange) {
@@ -6770,15 +6961,15 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6770
6961
  colStyleIds: sheetState?.colStyleIds ?? {},
6771
6962
  conditionalFormatRules: sheetState?.conditionalFormatRules ?? [],
6772
6963
  dataValidations: parseWorksheetDataValidations(worksheet),
6773
- defaultColWidthPx: sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH,
6774
- defaultRowHeightPx: sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT,
6964
+ defaultColWidthPx,
6965
+ defaultRowHeightPx,
6775
6966
  freezePanes: parseWorksheetFreezePanes(worksheet),
6776
- hasHorizontalMerges: sheetState?.hasHorizontalMerges ?? false,
6777
- hasVerticalMerges: sheetState?.hasVerticalMerges ?? false,
6778
- maxHorizontalMergeEndCol: sheetState?.maxHorizontalMergeEndCol ?? -1,
6779
- maxVerticalMergeEndRow: sheetState?.maxVerticalMergeEndRow ?? -1,
6780
- hiddenCols: sheetState?.hiddenCols ?? [],
6781
- hiddenRows: sheetState?.hiddenRows ?? [],
6967
+ hasHorizontalMerges: mergeMetadata.hasHorizontalMerges,
6968
+ hasVerticalMerges: mergeMetadata.hasVerticalMerges,
6969
+ maxHorizontalMergeEndCol: mergeMetadata.maxHorizontalMergeEndCol,
6970
+ maxVerticalMergeEndRow: mergeMetadata.maxVerticalMergeEndRow,
6971
+ hiddenCols: [],
6972
+ hiddenRows: [],
6782
6973
  minUsedCol: -1,
6783
6974
  minUsedRow: -1,
6784
6975
  maxUsedCol: -1,
@@ -6804,7 +6995,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6804
6995
  });
6805
6996
  continue;
6806
6997
  }
6807
- const [minRow, minCol, maxRow, maxCol] = resolveSheetDisplayUsedRange(usedRange, sheetState);
6998
+ const [minRow, minCol, maxRow, maxCol] = resolveSheetDisplayUsedRange(usedRange, effectiveSheetState);
6808
6999
  let visibleRowsCache = null;
6809
7000
  let visibleColsCache = null;
6810
7001
  let rowHeightsCache = null;
@@ -6856,15 +7047,15 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6856
7047
  colStyleIds: sheetState?.colStyleIds ?? {},
6857
7048
  conditionalFormatRules: sheetState?.conditionalFormatRules ?? [],
6858
7049
  dataValidations: parseWorksheetDataValidations(worksheet),
6859
- defaultColWidthPx: sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH,
6860
- defaultRowHeightPx: sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT,
7050
+ defaultColWidthPx,
7051
+ defaultRowHeightPx,
6861
7052
  freezePanes: parseWorksheetFreezePanes(worksheet),
6862
- hasHorizontalMerges: sheetState?.hasHorizontalMerges ?? false,
6863
- hasVerticalMerges: sheetState?.hasVerticalMerges ?? false,
6864
- maxHorizontalMergeEndCol: sheetState?.maxHorizontalMergeEndCol ?? -1,
6865
- maxVerticalMergeEndRow: sheetState?.maxVerticalMergeEndRow ?? -1,
6866
- hiddenCols: sheetState?.hiddenCols ?? [],
6867
- hiddenRows: sheetState?.hiddenRows ?? [],
7053
+ hasHorizontalMerges: mergeMetadata.hasHorizontalMerges,
7054
+ hasVerticalMerges: mergeMetadata.hasVerticalMerges,
7055
+ maxHorizontalMergeEndCol: mergeMetadata.maxHorizontalMergeEndCol,
7056
+ maxVerticalMergeEndRow: mergeMetadata.maxVerticalMergeEndRow,
7057
+ hiddenCols: resolveWorksheetHiddenCols(worksheet, maxCol),
7058
+ hiddenRows: resolveWorksheetHiddenRows(worksheet, maxRow),
6868
7059
  minUsedCol: minCol,
6869
7060
  minUsedRow: minRow,
6870
7061
  maxUsedCol: maxCol,
@@ -7023,17 +7214,14 @@ function rangeContainsCell(range, cell) {
7023
7214
  const normalized = normalizeRange(range);
7024
7215
  return cell.row >= normalized.start.row && cell.row <= normalized.end.row && cell.col >= normalized.start.col && cell.col <= normalized.end.col;
7025
7216
  }
7026
- function mapWorksheetTables(worksheet, metadataForSheet) {
7217
+ function mapWorksheetTables(worksheet) {
7027
7218
  const rawTables = worksheet?.tables ?? [];
7028
7219
  return rawTables.flatMap((table, index) => {
7029
7220
  const rawColumns = Array.isArray(table.columns) ? table.columns : [];
7030
7221
  const rawName = typeof table.name === "string" ? table.name : `Table${index + 1}`;
7031
7222
  const rawDisplayName = typeof table.displayName === "string" ? table.displayName : typeof table.name === "string" ? table.name : `Table ${index + 1}`;
7032
- const metadata = metadataForSheet?.find(
7033
- (entry) => entry.name && entry.name === rawName || entry.displayName && entry.displayName === rawDisplayName || entry.reference && entry.reference === table.reference
7034
- );
7035
7223
  const rawReference = typeof table.reference === "string" ? table.reference : "";
7036
- const reference = metadata?.reference ?? rawReference;
7224
+ const reference = rawReference;
7037
7225
  const parsedRange = parseA1RangeReference2(reference);
7038
7226
  if (!parsedRange) {
7039
7227
  return [];
@@ -7046,14 +7234,14 @@ function mapWorksheetTables(worksheet, metadataForSheet) {
7046
7234
  })),
7047
7235
  displayName: rawDisplayName,
7048
7236
  end: parsedRange.end,
7049
- headerRowCount: metadata?.headerRowCount ?? resolveWorkbookTableCount(table.headerRowCount, 1),
7050
- headerRowCellStyle: metadata?.headerRowCellStyle,
7237
+ headerRowCount: resolveWorkbookTableCount(table.headerRowCount, 1),
7238
+ headerRowCellStyle: typeof table.headerRowCellStyle === "string" ? table.headerRowCellStyle : void 0,
7051
7239
  name: rawName,
7052
7240
  reference,
7053
7241
  start: parsedRange.start,
7054
7242
  styleInfo: table.styleInfo,
7055
- totalsRowCount: metadata?.totalsRowCount ?? resolveWorkbookTableCount(table.totalsRowCount, 0),
7056
- totalsRowShown: metadata?.totalsRowShown ?? resolveWorkbookTableBoolean(table.totalsRowShown)
7243
+ totalsRowCount: resolveWorkbookTableCount(table.totalsRowCount, 0),
7244
+ totalsRowShown: resolveWorkbookTableBoolean(table.totalsRowShown)
7057
7245
  }];
7058
7246
  });
7059
7247
  }
@@ -7835,6 +8023,7 @@ function useXlsxViewerController(options) {
7835
8023
  const [activeCell, setActiveCell] = React.useState(null);
7836
8024
  const [selection, setSelection] = React.useState(null);
7837
8025
  const [selectedChartId, setSelectedChartId] = React.useState(null);
8026
+ const [selectedChartElement, setSelectedChartElement] = React.useState(null);
7838
8027
  const [selectedImageId, setSelectedImageId] = React.useState(null);
7839
8028
  const [revision, setRevision] = React.useState(0);
7840
8029
  const selectionAnchorRef = React.useRef(null);
@@ -8107,6 +8296,7 @@ function useXlsxViewerController(options) {
8107
8296
  setActiveCell(null);
8108
8297
  setSelection(null);
8109
8298
  setSelectedChartId(null);
8299
+ setSelectedChartElement(null);
8110
8300
  setSelectedImageId(null);
8111
8301
  selectionAnchorRef.current = null;
8112
8302
  undoStackRef.current = [];
@@ -8135,6 +8325,7 @@ function useXlsxViewerController(options) {
8135
8325
  setActiveCell(null);
8136
8326
  setSelection(null);
8137
8327
  setSelectedChartId(null);
8328
+ setSelectedChartElement(null);
8138
8329
  setSelectedImageId(null);
8139
8330
  selectionAnchorRef.current = null;
8140
8331
  undoStackRef.current = [];
@@ -8286,6 +8477,7 @@ function useXlsxViewerController(options) {
8286
8477
  setActiveCell(null);
8287
8478
  setSelection(null);
8288
8479
  setSelectedChartId(null);
8480
+ setSelectedChartElement(null);
8289
8481
  setSelectedImageId(null);
8290
8482
  selectionAnchorRef.current = null;
8291
8483
  setSortState(null);
@@ -8528,10 +8720,9 @@ function useXlsxViewerController(options) {
8528
8720
  }
8529
8721
  return workbook.getSheet(activeSheet.workbookSheetIndex);
8530
8722
  }, [activeSheet, workbook]);
8531
- const activeTableMetadata = imageAssetsRef.current?.tableMetadataByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? null;
8532
8723
  const tables = React.useMemo(
8533
- () => isWorkerBacked ? workerTablesByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? [] : mapWorksheetTables(getActiveWorksheet(), activeTableMetadata),
8534
- [activeSheet?.workbookSheetIndex, activeTableMetadata, getActiveWorksheet, isWorkerBacked, revision, workerTablesByWorkbookSheetIndex]
8724
+ () => isWorkerBacked ? workerTablesByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? [] : mapWorksheetTables(getActiveWorksheet()),
8725
+ [activeSheet?.workbookSheetIndex, getActiveWorksheet, isWorkerBacked, revision, workerTablesByWorkbookSheetIndex]
8535
8726
  );
8536
8727
  const getCellSnapshotAsync = React.useCallback((workbookSheetIndex, row, col) => {
8537
8728
  if (!isWorkerBacked) {
@@ -8608,12 +8799,49 @@ function useXlsxViewerController(options) {
8608
8799
  () => selectedChartId ? getChartById(selectedChartId) : null,
8609
8800
  [getChartById, selectedChartId]
8610
8801
  );
8802
+ React.useEffect(() => {
8803
+ if (!selectedChartId) {
8804
+ if (selectedChartElement) {
8805
+ setSelectedChartElement(null);
8806
+ }
8807
+ return;
8808
+ }
8809
+ if (!selectedChart) {
8810
+ setSelectedChartId(null);
8811
+ setSelectedChartElement(null);
8812
+ return;
8813
+ }
8814
+ if (!selectedChartElement) {
8815
+ setSelectedChartElement({ chartId: selectedChartId, kind: "chart" });
8816
+ return;
8817
+ }
8818
+ if (selectedChartElement.chartId !== selectedChartId) {
8819
+ setSelectedChartElement({ chartId: selectedChartId, kind: "chart" });
8820
+ return;
8821
+ }
8822
+ if (selectedChartElement.kind !== "chart") {
8823
+ const selectedSeries = selectedChart.series[selectedChartElement.seriesIndex];
8824
+ if (!selectedSeries || selectedSeries.id !== selectedChartElement.seriesId) {
8825
+ setSelectedChartElement({ chartId: selectedChartId, kind: "chart" });
8826
+ }
8827
+ }
8828
+ }, [selectedChart, selectedChartElement, selectedChartId]);
8611
8829
  const selectChart = React.useCallback((id) => {
8612
8830
  setSelectedImageId(null);
8613
8831
  setSelectedChartId(id);
8832
+ setSelectedChartElement(id ? { chartId: id, kind: "chart" } : null);
8614
8833
  }, []);
8615
8834
  const clearSelectedChart = React.useCallback(() => {
8616
8835
  setSelectedChartId(null);
8836
+ setSelectedChartElement(null);
8837
+ }, []);
8838
+ const clearSelectedChartElement = React.useCallback(() => {
8839
+ setSelectedChartElement(selectedChartId ? { chartId: selectedChartId, kind: "chart" } : null);
8840
+ }, [selectedChartId]);
8841
+ const selectChartElement = React.useCallback((selection2) => {
8842
+ setSelectedImageId(null);
8843
+ setSelectedChartId(selection2?.chartId ?? null);
8844
+ setSelectedChartElement(selection2);
8617
8845
  }, []);
8618
8846
  const getSheetImages = React.useCallback((sheetIndex = activeSheetIndex) => {
8619
8847
  const targetSheet = sheets[sheetIndex];
@@ -8660,6 +8888,7 @@ function useXlsxViewerController(options) {
8660
8888
  );
8661
8889
  const selectImage = React.useCallback((id) => {
8662
8890
  setSelectedChartId(null);
8891
+ setSelectedChartElement(null);
8663
8892
  setSelectedImageId(id);
8664
8893
  }, []);
8665
8894
  const clearSelectedImage = React.useCallback(() => {
@@ -8884,10 +9113,32 @@ function useXlsxViewerController(options) {
8884
9113
  () => getCellDisplayValue2(deferredMetadataCell),
8885
9114
  [deferredMetadataCell, getCellDisplayValue2, revision, workerCellSnapshotRevision]
8886
9115
  );
8887
- const selectedFormula = React.useMemo(
9116
+ const selectedCellFormula = React.useMemo(
8888
9117
  () => getCellFormula(deferredMetadataCell),
8889
9118
  [deferredMetadataCell, getCellFormula, revision, workerCellSnapshotRevision]
8890
9119
  );
9120
+ const getChartSeriesFormula = React.useCallback((chartId, seriesIndex) => buildChartSeriesFormula(getChartById(chartId), seriesIndex), [getChartById]);
9121
+ const selectedChartFormula = React.useMemo(() => {
9122
+ if (!selectedChartElement || selectedChartElement.kind === "chart" || selectedChartElement.seriesIndex < 0) {
9123
+ return null;
9124
+ }
9125
+ return getChartSeriesFormula(selectedChartElement.chartId, selectedChartElement.seriesIndex);
9126
+ }, [getChartSeriesFormula, selectedChartElement]);
9127
+ const selectedFormulaTarget = React.useMemo(() => {
9128
+ if (selectedChartFormula && selectedChartElement && selectedChartElement.kind !== "chart") {
9129
+ return {
9130
+ chartId: selectedChartElement.chartId,
9131
+ kind: "chartSeries",
9132
+ seriesId: selectedChartElement.seriesId,
9133
+ seriesIndex: selectedChartElement.seriesIndex
9134
+ };
9135
+ }
9136
+ return {
9137
+ cell: deferredMetadataCell,
9138
+ kind: "cell"
9139
+ };
9140
+ }, [deferredMetadataCell, selectedChartElement, selectedChartFormula]);
9141
+ const selectedFormula = selectedChartFormula ?? selectedCellFormula;
8891
9142
  const isLoadDeferred = deferredLoadFileSize !== null;
8892
9143
  const canLoadDeferred = !isLoading && isLoadDeferred;
8893
9144
  const canUndo = !readOnly && undoStackRef.current.length > 0;
@@ -9430,8 +9681,32 @@ function useXlsxViewerController(options) {
9430
9681
  setChartsByWorkbookSheetIndex((current) => current.map((sheetCharts) => sheetCharts.map((chart) => chart.id === id ? { ...chart, ...patch } : chart)));
9431
9682
  setRevision((current) => current + 1);
9432
9683
  }, [ensureChartAssetsHydrated, getChartById, readOnly, recordHistoryBeforeMutation, sheets, workbook]);
9684
+ const setChartSeriesFormula = React.useCallback((chartId, seriesIndex, formula) => {
9685
+ if (readOnly) {
9686
+ return false;
9687
+ }
9688
+ const chart = getChartById(chartId);
9689
+ if (!chart || chart.editable === false) {
9690
+ return false;
9691
+ }
9692
+ const nextChart = applyChartSeriesFormula(chart, seriesIndex, formula, workbook);
9693
+ if (!nextChart) {
9694
+ return false;
9695
+ }
9696
+ updateChart(chartId, { series: nextChart.series });
9697
+ const selectedSeries = nextChart.series[seriesIndex];
9698
+ if (selectedSeries) {
9699
+ setSelectedChartElement((current) => current && current.chartId === chartId && current.kind !== "chart" ? {
9700
+ ...current,
9701
+ seriesId: selectedSeries.id,
9702
+ seriesIndex
9703
+ } : current);
9704
+ }
9705
+ return true;
9706
+ }, [getChartById, readOnly, updateChart, workbook]);
9433
9707
  const selectCell = React.useCallback((cell, options2) => {
9434
9708
  setSelectedChartId(null);
9709
+ setSelectedChartElement(null);
9435
9710
  setSelectedImageId(null);
9436
9711
  setActiveCell(cell);
9437
9712
  if (options2?.extend && selectionAnchorRef.current) {
@@ -9444,6 +9719,7 @@ function useXlsxViewerController(options) {
9444
9719
  const selectRange = React.useCallback((range) => {
9445
9720
  const normalized = normalizeRange(range);
9446
9721
  setSelectedChartId(null);
9722
+ setSelectedChartElement(null);
9447
9723
  setSelectedImageId(null);
9448
9724
  selectionAnchorRef.current = normalized.start;
9449
9725
  setActiveCell(normalized.end);
@@ -9454,6 +9730,7 @@ function useXlsxViewerController(options) {
9454
9730
  setActiveCell(null);
9455
9731
  setSelection(null);
9456
9732
  setSelectedChartId(null);
9733
+ setSelectedChartElement(null);
9457
9734
  setSelectedImageId(null);
9458
9735
  }, []);
9459
9736
  const clearSelectedCells = React.useCallback(() => {
@@ -9571,6 +9848,16 @@ function useXlsxViewerController(options) {
9571
9848
  }
9572
9849
  setCellFormula(activeCell, formula);
9573
9850
  }, [activeCell, setCellFormula]);
9851
+ const setSelectedFormula = React.useCallback((formula) => {
9852
+ if (selectedFormulaTarget?.kind === "chartSeries") {
9853
+ return setChartSeriesFormula(selectedFormulaTarget.chartId, selectedFormulaTarget.seriesIndex, formula);
9854
+ }
9855
+ if (!activeCell) {
9856
+ return false;
9857
+ }
9858
+ setCellFormula(activeCell, formula);
9859
+ return true;
9860
+ }, [activeCell, selectedFormulaTarget, setCellFormula, setChartSeriesFormula]);
9574
9861
  const setSelectedCellStyle = React.useCallback((style) => {
9575
9862
  if (!activeCell) {
9576
9863
  return;
@@ -10047,6 +10334,7 @@ function useXlsxViewerController(options) {
10047
10334
  charts,
10048
10335
  chartsheets,
10049
10336
  clearSelectedChart,
10337
+ clearSelectedChartElement,
10050
10338
  clearSelectedCells,
10051
10339
  clearSelectedImage,
10052
10340
  clearSelection,
@@ -10063,6 +10351,7 @@ function useXlsxViewerController(options) {
10063
10351
  fillSelection,
10064
10352
  formControls,
10065
10353
  getChartById,
10354
+ getChartSeriesFormula,
10066
10355
  getChartsheetById,
10067
10356
  getImageById,
10068
10357
  getSheetCharts,
@@ -10103,18 +10392,25 @@ function useXlsxViewerController(options) {
10103
10392
  setCellStyle,
10104
10393
  setCellValue,
10105
10394
  setRangeStyle,
10395
+ setSelectedFormula,
10106
10396
  setZoomScale,
10107
10397
  setChartRect,
10398
+ setChartSeriesFormula,
10108
10399
  setImageRect,
10109
10400
  selectedChart,
10401
+ selectedChartElement,
10402
+ selectedChartFormula,
10110
10403
  selectedChartId,
10404
+ selectedCellFormula,
10111
10405
  selectedFormula,
10406
+ selectedFormulaTarget,
10112
10407
  selectedImage,
10113
10408
  selectedImageId,
10114
10409
  selectedRangeAddress,
10115
10410
  selectedValue,
10116
10411
  selectCell,
10117
10412
  selectChart,
10413
+ selectChartElement,
10118
10414
  selectImage,
10119
10415
  selectRange,
10120
10416
  selection,
@@ -10154,6 +10450,7 @@ function useXlsxViewerController(options) {
10154
10450
  charts,
10155
10451
  chartsheets,
10156
10452
  clearSelectedChart,
10453
+ clearSelectedChartElement,
10157
10454
  clearSelectedCells,
10158
10455
  clearSelectedImage,
10159
10456
  continueDeferredLoad,
@@ -10170,6 +10467,7 @@ function useXlsxViewerController(options) {
10170
10467
  fillSelection,
10171
10468
  formControls,
10172
10469
  getChartById,
10470
+ getChartSeriesFormula,
10173
10471
  getChartsheetById,
10174
10472
  getImageById,
10175
10473
  getSheetCharts,
@@ -10208,18 +10506,25 @@ function useXlsxViewerController(options) {
10208
10506
  setCellStyle,
10209
10507
  setCellValue,
10210
10508
  setRangeStyle,
10509
+ setSelectedFormula,
10211
10510
  setZoomScale,
10212
10511
  setChartRect,
10512
+ setChartSeriesFormula,
10213
10513
  setImageRect,
10214
10514
  selectedChart,
10515
+ selectedChartElement,
10516
+ selectedChartFormula,
10215
10517
  selectedChartId,
10518
+ selectedCellFormula,
10216
10519
  selectedFormula,
10520
+ selectedFormulaTarget,
10217
10521
  selectedImage,
10218
10522
  selectedImageId,
10219
10523
  selectedRangeAddress,
10220
10524
  selectedValue,
10221
10525
  selectCell,
10222
10526
  selectChart,
10527
+ selectChartElement,
10223
10528
  selectImage,
10224
10529
  selectRange,
10225
10530
  selection,
@@ -11024,6 +11329,8 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11024
11329
  chart,
11025
11330
  fontFamily,
11026
11331
  layout,
11332
+ onDoubleClick,
11333
+ onPointerDown,
11027
11334
  overlay,
11028
11335
  palette,
11029
11336
  fallback
@@ -11219,7 +11526,7 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11219
11526
  fontFamily,
11220
11527
  height: "100%",
11221
11528
  overflow: "hidden",
11222
- pointerEvents: "none",
11529
+ pointerEvents: "auto",
11223
11530
  position: "relative",
11224
11531
  width: "100%"
11225
11532
  },
@@ -11240,6 +11547,8 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11240
11547
  /* @__PURE__ */ jsxs(
11241
11548
  "svg",
11242
11549
  {
11550
+ onDoubleClick,
11551
+ onPointerDown,
11243
11552
  style: { display: "block", height: "100%", inset: 0, position: "absolute", width: "100%" },
11244
11553
  viewBox: `0 0 ${layout.width} ${layout.height}`,
11245
11554
  children: [
@@ -11251,10 +11560,104 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11251
11560
  ]
11252
11561
  }
11253
11562
  );
11254
- }, (prev, next) => prev.chart === next.chart && prev.palette === next.palette && prev.background === next.background && prev.borderColor === next.borderColor && prev.fontFamily === next.fontFamily && prev.layout.width === next.layout.width && prev.layout.height === next.layout.height && prev.layout.plot.left === next.layout.plot.left && prev.layout.plot.top === next.layout.plot.top && prev.layout.plot.width === next.layout.plot.width && prev.layout.plot.height === next.layout.plot.height && prev.overlay === next.overlay && prev.fallback === next.fallback);
11563
+ }, (prev, next) => prev.chart === next.chart && prev.palette === next.palette && prev.background === next.background && prev.borderColor === next.borderColor && prev.fontFamily === next.fontFamily && prev.onDoubleClick === next.onDoubleClick && prev.onPointerDown === next.onPointerDown && prev.layout.width === next.layout.width && prev.layout.height === next.layout.height && prev.layout.plot.left === next.layout.plot.left && prev.layout.plot.top === next.layout.plot.top && prev.layout.plot.width === next.layout.plot.width && prev.layout.plot.height === next.layout.plot.height && prev.overlay === next.overlay && prev.fallback === next.fallback);
11255
11564
 
11256
11565
  // src/chart-renderer.tsx
11257
11566
  import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
11567
+ import { createElement } from "react";
11568
+ function chartElementDataProps(seriesIndex, pointIndex, options) {
11569
+ return {
11570
+ "data-xlsx-chart-point-index": typeof pointIndex === "number" ? String(pointIndex) : void 0,
11571
+ "data-xlsx-chart-selection-mode": options?.selectionMode,
11572
+ "data-xlsx-chart-series-index": String(seriesIndex),
11573
+ style: {
11574
+ cursor: "pointer",
11575
+ pointerEvents: "all"
11576
+ }
11577
+ };
11578
+ }
11579
+ function barChartElementDataProps(seriesIndex, pointIndex) {
11580
+ return chartElementDataProps(seriesIndex, pointIndex, { selectionMode: "seriesFirst" });
11581
+ }
11582
+ function resolveChartElementTarget(target) {
11583
+ if (!(target instanceof Element)) {
11584
+ return null;
11585
+ }
11586
+ return target.closest("[data-xlsx-chart-series-index]");
11587
+ }
11588
+ function resolveChartSelectionFromTarget(chart, target, selectedChartElement) {
11589
+ const element = resolveChartElementTarget(target);
11590
+ if (!element) {
11591
+ return selectedChartElement?.chartId === chart.id ? { chartId: chart.id, kind: "chart" } : { chartId: chart.id, kind: "chart" };
11592
+ }
11593
+ const seriesIndex = Number(element.dataset.xlsxChartSeriesIndex);
11594
+ if (!Number.isInteger(seriesIndex) || seriesIndex < 0 || seriesIndex >= chart.series.length) {
11595
+ return null;
11596
+ }
11597
+ const series = chart.series[seriesIndex];
11598
+ if (!series) {
11599
+ return null;
11600
+ }
11601
+ const rawPointIndex = element.dataset.xlsxChartPointIndex;
11602
+ const rawElementKind = element.dataset.xlsxChartElementKind;
11603
+ const selectionMode = element.dataset.xlsxChartSelectionMode;
11604
+ const pointIndex = rawPointIndex == null || rawPointIndex === "" ? null : Number(rawPointIndex);
11605
+ const hasPoint = pointIndex != null && Number.isInteger(pointIndex) && pointIndex >= 0;
11606
+ const sameSelectedSeries = selectedChartElement?.chartId === chart.id && selectedChartElement.kind !== "chart" && selectedChartElement.seriesIndex === seriesIndex;
11607
+ if (hasPoint && (selectionMode !== "seriesFirst" || sameSelectedSeries)) {
11608
+ return {
11609
+ chartId: chart.id,
11610
+ kind: "point",
11611
+ pointIndex,
11612
+ seriesId: series.id,
11613
+ seriesIndex
11614
+ };
11615
+ }
11616
+ return {
11617
+ chartId: chart.id,
11618
+ kind: rawElementKind === "legendEntry" ? "legendEntry" : "series",
11619
+ seriesId: series.id,
11620
+ seriesIndex
11621
+ };
11622
+ }
11623
+ function isSelectedChartSeries(selectedChartElement, chartId, seriesIndex) {
11624
+ return selectedChartElement?.chartId === chartId && selectedChartElement.kind !== "chart" && selectedChartElement.seriesIndex === seriesIndex;
11625
+ }
11626
+ function isSelectedChartPoint(selectedChartElement, chartId, seriesIndex, pointIndex) {
11627
+ return selectedChartElement?.chartId === chartId && selectedChartElement.kind === "point" && selectedChartElement.seriesIndex === seriesIndex && selectedChartElement.pointIndex === pointIndex;
11628
+ }
11629
+ function isSelectedChartPointOrSeries(selectedChartElement, chartId, seriesIndex, pointIndex) {
11630
+ return isSelectedChartPoint(selectedChartElement, chartId, seriesIndex, pointIndex) || isSelectedChartSeries(selectedChartElement, chartId, seriesIndex) && selectedChartElement?.kind !== "point";
11631
+ }
11632
+ function renderSelectionRectHandles(key, left, top, width, height, color = "#64748b") {
11633
+ return renderSelectionPointHandles(
11634
+ key,
11635
+ [
11636
+ { x: left, y: top },
11637
+ { x: left + width, y: top },
11638
+ { x: left, y: top + height },
11639
+ { x: left + width, y: top + height }
11640
+ ],
11641
+ color
11642
+ );
11643
+ }
11644
+ function renderSelectionPointHandles(key, points, color = "#64748b") {
11645
+ const radius = 3;
11646
+ return /* @__PURE__ */ jsx2("g", { pointerEvents: "none", children: points.map((point, index) => /* @__PURE__ */ jsx2(
11647
+ "circle",
11648
+ {
11649
+ cx: point.x,
11650
+ cy: point.y,
11651
+ fill: "#ffffff",
11652
+ r: radius,
11653
+ stroke: color,
11654
+ strokeWidth: 1.1,
11655
+ style: { filter: "drop-shadow(0 1px 2px rgba(15, 23, 42, 0.18))" },
11656
+ vectorEffect: "non-scaling-stroke"
11657
+ },
11658
+ `${key}-handle-${index}`
11659
+ )) }, key);
11660
+ }
11258
11661
  var WORLD_COUNTRY_FEATURES = topojsonFeature(
11259
11662
  countries_50m_default,
11260
11663
  countries_50m_default.objects.countries
@@ -12952,10 +13355,17 @@ function renderLegend(chart, layout, palette) {
12952
13355
  const startY = layout.plot.top + 6;
12953
13356
  return /* @__PURE__ */ jsx2("g", { children: items.map((item, index) => {
12954
13357
  const y = startY + index * 18;
12955
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${x}, ${y})`, children: [
13358
+ return /* @__PURE__ */ createElement(
13359
+ "g",
13360
+ {
13361
+ ...index < chart.series.length ? chartElementDataProps(index) : {},
13362
+ "data-xlsx-chart-element-kind": index < chart.series.length ? "legendEntry" : void 0,
13363
+ key: `legend-${index}`,
13364
+ transform: `translate(${x}, ${y})`
13365
+ },
12956
13366
  /* @__PURE__ */ jsx2("rect", { fill: item.color, height: swatchSize, rx: 1.2, ry: 1.2, width: swatchSize, x: 0, y: -7 }),
12957
13367
  /* @__PURE__ */ jsx2("text", { fill: textColor, fontSize: 10, x: textOffset, y: 0, children: item.label })
12958
- ] }, `legend-${index}`);
13368
+ );
12959
13369
  }) });
12960
13370
  }
12961
13371
  const rowY = legendPos === "top" ? layout.titleHeight + 12 : layout.height - 8;
@@ -12963,10 +13373,17 @@ function renderLegend(chart, layout, palette) {
12963
13373
  let cursorX = Math.max(8, (layout.width - totalWidth) / 2);
12964
13374
  return /* @__PURE__ */ jsx2("g", { children: items.map((item, index) => {
12965
13375
  const labelWidth = Math.min(96, item.label.length * 5.4);
12966
- const node = /* @__PURE__ */ jsxs2("g", { transform: `translate(${cursorX}, ${rowY})`, children: [
13376
+ const node = /* @__PURE__ */ createElement(
13377
+ "g",
13378
+ {
13379
+ ...index < chart.series.length ? chartElementDataProps(index) : {},
13380
+ "data-xlsx-chart-element-kind": index < chart.series.length ? "legendEntry" : void 0,
13381
+ key: `legend-${index}`,
13382
+ transform: `translate(${cursorX}, ${rowY})`
13383
+ },
12967
13384
  /* @__PURE__ */ jsx2("rect", { fill: item.color, height: swatchSize, rx: 1.2, ry: 1.2, width: swatchSize, x: 0, y: -7 }),
12968
13385
  /* @__PURE__ */ jsx2("text", { fill: textColor, fontSize: 10, x: textOffset, y: 0, children: item.label })
12969
- ] }, `legend-${index}`);
13386
+ );
12970
13387
  cursorX += 24 + labelWidth;
12971
13388
  return node;
12972
13389
  }) });
@@ -13293,7 +13710,7 @@ function projectCartesian3dPoint2(x, y, z, rotXRad, rotYRad, usePerspective, per
13293
13710
  y: y1 * perspective
13294
13711
  };
13295
13712
  }
13296
- function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPointsBySeries, minValue, maxValue, isAreaChart, isStackedSeries) {
13713
+ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPointsBySeries, minValue, maxValue, isAreaChart, isStackedSeries, selectedChartElement) {
13297
13714
  const plot = layout.plot;
13298
13715
  const valueDomain = resolveAxisDomainWithChartOverrides(
13299
13716
  chart.valueAxis,
@@ -13360,6 +13777,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13360
13777
  return {
13361
13778
  bottom,
13362
13779
  bottomBack,
13780
+ categoryIndex,
13363
13781
  defined: point.defined,
13364
13782
  depth: top.depth,
13365
13783
  depthBack: topBack?.depth ?? top.depth,
@@ -13395,6 +13813,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13395
13813
  points: series.map((point) => ({
13396
13814
  bottom: toScreenPoint(point.bottom),
13397
13815
  bottomBack: point.bottomBack ? toScreenPoint(point.bottomBack) : null,
13816
+ categoryIndex: point.categoryIndex,
13398
13817
  defined: point.defined,
13399
13818
  top: toScreenPoint(point.top),
13400
13819
  topBack: point.topBack ? toScreenPoint(point.topBack) : null
@@ -13499,6 +13918,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13499
13918
  /* @__PURE__ */ jsx2(
13500
13919
  "path",
13501
13920
  {
13921
+ ...chartElementDataProps(seriesIndex),
13502
13922
  d: topFace,
13503
13923
  fill: lightenColor2(fillColor, 0.08),
13504
13924
  fillOpacity: 0.8,
@@ -13509,6 +13929,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13509
13929
  /* @__PURE__ */ jsx2(
13510
13930
  "path",
13511
13931
  {
13932
+ ...chartElementDataProps(seriesIndex),
13512
13933
  d: bottomFace,
13513
13934
  fill: darkenColor2(fillColor, 0.2),
13514
13935
  fillOpacity: 0.34,
@@ -13536,6 +13957,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13536
13957
  isAreaChart && isStackedSeries && areaBackPoints.length >= 3 ? /* @__PURE__ */ jsx2(
13537
13958
  "path",
13538
13959
  {
13960
+ ...chartElementDataProps(seriesIndex),
13539
13961
  d: buildLinearSvgPath(areaBackPoints, true),
13540
13962
  fill: darkenColor2(fillColor, 0.18),
13541
13963
  fillOpacity: 0.44,
@@ -13547,6 +13969,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13547
13969
  startCap ? /* @__PURE__ */ jsx2(
13548
13970
  "path",
13549
13971
  {
13972
+ ...chartElementDataProps(seriesIndex),
13550
13973
  d: startCap,
13551
13974
  fill: darkenColor2(fillColor, 0.24),
13552
13975
  fillOpacity: 0.54,
@@ -13557,6 +13980,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13557
13980
  endCap ? /* @__PURE__ */ jsx2(
13558
13981
  "path",
13559
13982
  {
13983
+ ...chartElementDataProps(seriesIndex),
13560
13984
  d: endCap,
13561
13985
  fill: darkenColor2(fillColor, 0.14),
13562
13986
  fillOpacity: 0.6,
@@ -13567,6 +13991,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13567
13991
  isAreaChart && areaPoints.length >= 3 ? /* @__PURE__ */ jsx2(
13568
13992
  "path",
13569
13993
  {
13994
+ ...chartElementDataProps(seriesIndex),
13570
13995
  d: buildLinearSvgPath(areaPoints, true),
13571
13996
  fill: fillColor,
13572
13997
  fillOpacity: 0.74,
@@ -13590,6 +14015,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13590
14015
  /* @__PURE__ */ jsx2(
13591
14016
  "path",
13592
14017
  {
14018
+ ...chartElementDataProps(seriesIndex),
13593
14019
  d: buildLinearSvgPath(linePoints),
13594
14020
  fill: "none",
13595
14021
  stroke: strokeColor,
@@ -13604,6 +14030,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13604
14030
  children: /* @__PURE__ */ jsx2(
13605
14031
  "path",
13606
14032
  {
14033
+ ...chartElementDataProps(seriesIndex, point.categoryIndex),
13607
14034
  d: markerPath,
13608
14035
  fill: chart.series[seriesIndex]?.markerColor ?? fillColor,
13609
14036
  stroke: chart.series[seriesIndex]?.markerLineColor ?? chart.chartAreaFillColor ?? palette.surface,
@@ -13612,7 +14039,23 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13612
14039
  )
13613
14040
  },
13614
14041
  `line3d-marker-${seriesIndex}-${pointIndex}`
13615
- )) : null
14042
+ )) : null,
14043
+ definedPoints.map((point) => /* @__PURE__ */ createElement(
14044
+ "circle",
14045
+ {
14046
+ ...chartElementDataProps(seriesIndex, point.categoryIndex),
14047
+ cx: point.top.x,
14048
+ cy: point.top.y,
14049
+ fill: "transparent",
14050
+ key: `line3d-hit-${seriesIndex}-${point.categoryIndex}`,
14051
+ r: 7,
14052
+ stroke: "none"
14053
+ }
14054
+ )),
14055
+ definedPoints.map((point) => isSelectedChartPointOrSeries(selectedChartElement, chart.id, seriesIndex, point.categoryIndex) ? renderSelectionPointHandles(
14056
+ `line3d-selection-${seriesIndex}-${point.categoryIndex}`,
14057
+ [{ x: point.top.x, y: point.top.y }]
14058
+ ) : null)
13616
14059
  ] }, `line3d-series-${seriesIndex}`);
13617
14060
  }),
13618
14061
  yLabelPoints.map(({ point, tick }) => /* @__PURE__ */ jsx2(
@@ -13641,7 +14084,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13641
14084
  ))
13642
14085
  ] });
13643
14086
  }
13644
- function renderBarChart(chart, palette, layout, chartType) {
14087
+ function renderBarChart(chart, palette, layout, chartType, selectedChartElement) {
13645
14088
  if (chart.series.length === 0) {
13646
14089
  return null;
13647
14090
  }
@@ -14022,9 +14465,11 @@ function renderBarChart(chart, palette, layout, chartType) {
14022
14465
  axisNode,
14023
14466
  frameNode,
14024
14467
  depthAxisNode,
14025
- chart.is3d ? sortedBars.map((bar) => renderExtrudedRect(bar)) : renderedBars.map((bar) => /* @__PURE__ */ jsx2(
14468
+ chart.is3d ? sortedBars.map((bar) => /* @__PURE__ */ jsx2("g", { ...barChartElementDataProps(bar.seriesIndex, bar.categoryIndex), children: renderExtrudedRect(bar) }, `bar-hit-${bar.key}`)) : renderedBars.map((bar) => /* @__PURE__ */ createElement(
14026
14469
  "rect",
14027
14470
  {
14471
+ ...barChartElementDataProps(bar.seriesIndex, bar.categoryIndex),
14472
+ key: bar.key,
14028
14473
  fill: bar.color,
14029
14474
  height: bar.height,
14030
14475
  stroke: isHistogramLike ? "none" : bar.stroke,
@@ -14032,12 +14477,12 @@ function renderBarChart(chart, palette, layout, chartType) {
14032
14477
  width: bar.width,
14033
14478
  x: bar.left,
14034
14479
  y: bar.top
14035
- },
14036
- bar.key
14037
- ))
14480
+ }
14481
+ )),
14482
+ renderedBars.map((bar) => isSelectedChartPoint(selectedChartElement, chart.id, bar.seriesIndex, bar.categoryIndex) || isSelectedChartSeries(selectedChartElement, chart.id, bar.seriesIndex) && selectedChartElement?.kind !== "point" ? renderSelectionRectHandles(`bar-selection-${bar.key}`, bar.left, bar.top, bar.width, bar.height) : null)
14038
14483
  ] });
14039
14484
  }
14040
- function renderLineOrAreaChart(chart, palette, layout, chartType) {
14485
+ function renderLineOrAreaChart(chart, palette, layout, chartType, selectedChartElement) {
14041
14486
  if (chart.series.length === 0) {
14042
14487
  return null;
14043
14488
  }
@@ -14148,7 +14593,8 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14148
14593
  minValue,
14149
14594
  maxValue,
14150
14595
  isAreaChart,
14151
- isStackedSeries
14596
+ isStackedSeries,
14597
+ selectedChartElement
14152
14598
  );
14153
14599
  }
14154
14600
  const rawRecord = chart.raw && typeof chart.raw === "object" ? chart.raw : null;
@@ -14237,6 +14683,7 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14237
14683
  isAreaChart ? /* @__PURE__ */ jsx2(
14238
14684
  "path",
14239
14685
  {
14686
+ ...chartElementDataProps(seriesIndex),
14240
14687
  d: areaPath,
14241
14688
  fill: seriesFillColor,
14242
14689
  fillOpacity: 1,
@@ -14246,6 +14693,7 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14246
14693
  /* @__PURE__ */ jsx2(
14247
14694
  "path",
14248
14695
  {
14696
+ ...chartElementDataProps(seriesIndex),
14249
14697
  d: linePath,
14250
14698
  fill: "none",
14251
14699
  stroke: chartSeriesStrokeColor(chart, seriesIndex),
@@ -14254,23 +14702,31 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14254
14702
  strokeWidth: Math.max(1.5, series.lineWidthPx ?? 2)
14255
14703
  }
14256
14704
  ),
14257
- points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ jsx2(
14705
+ points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ createElement(
14258
14706
  "circle",
14259
14707
  {
14708
+ ...chartElementDataProps(seriesIndex, pointIndex),
14709
+ key: `line-marker-${seriesIndex}-${pointIndex}`,
14260
14710
  cx: point.x,
14261
14711
  cy: yScale(point.y),
14262
14712
  fill: series.markerColor ?? chartSeriesColor(chart, seriesIndex),
14263
14713
  r: Math.max(2, (series.markerSize ?? 6) * 0.25),
14264
14714
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? chartSeriesStrokeColor(chart, seriesIndex),
14265
14715
  strokeWidth: 1
14266
- },
14267
- `line-marker-${seriesIndex}-${pointIndex}`
14268
- ))
14716
+ }
14717
+ )),
14718
+ points.map((point, pointIndex) => point.y != null && (isSelectedChartPoint(selectedChartElement, chart.id, seriesIndex, pointIndex) || isSelectedChartSeries(selectedChartElement, chart.id, seriesIndex) && selectedChartElement?.kind !== "point") ? isAreaChart ? renderSelectionPointHandles(`area-selection-${seriesIndex}-${pointIndex}`, [{ x: point.x, y: yScale(point.y) }]) : renderSelectionRectHandles(
14719
+ `line-selection-${seriesIndex}-${pointIndex}`,
14720
+ point.x - 4,
14721
+ yScale(point.y) - 4,
14722
+ 8,
14723
+ 8
14724
+ ) : null)
14269
14725
  ] }, `line-series-${seriesIndex}`);
14270
14726
  })
14271
14727
  ] });
14272
14728
  }
14273
- function renderComboChart(chart, palette, layout) {
14729
+ function renderComboChart(chart, palette, layout, selectedChartElement) {
14274
14730
  const groups = buildComboGroups(chart);
14275
14731
  const columnGroup = groups.find((group) => group.chartType.startsWith("Column"));
14276
14732
  const lineGroup = groups.find((group) => group.chartType.startsWith("Line"));
@@ -14297,6 +14753,10 @@ function renderComboChart(chart, palette, layout) {
14297
14753
  const categoryScale = scaleBand().domain(categories).range([plot.left, plot.left + plot.width]).paddingInner(categoryBandPadding.inner).paddingOuter(categoryBandPadding.outer);
14298
14754
  const seriesScale = scaleBand().domain(Array.from({ length: columnGroup.series.length }, (_, index) => String(index))).range([0, categoryScale.bandwidth()]).paddingInner(histogramColumns ? 0 : 0.16).paddingOuter(histogramColumns ? 0 : 0.08);
14299
14755
  const categoryPositions = categories.map((category) => (categoryScale(category) ?? plot.left) + categoryScale.bandwidth() / 2);
14756
+ const resolveGlobalSeriesIndex = (series) => {
14757
+ const index = chart.series.findIndex((candidate) => candidate.id === series.id);
14758
+ return index >= 0 ? index : 0;
14759
+ };
14300
14760
  const primaryValues = columnGroup.series.flatMap((series) => series.values.map((value) => safeNumber2(value)).filter((value) => value != null));
14301
14761
  const secondaryValues = lineGroup.series.flatMap((series) => series.values.map((value) => safeNumber2(value)).filter((value) => value != null));
14302
14762
  if (primaryValues.length === 0 || secondaryValues.length === 0) {
@@ -14356,6 +14816,7 @@ function renderComboChart(chart, palette, layout) {
14356
14816
  }
14357
14817
  ),
14358
14818
  columnGroup.series.flatMap((series, seriesIndex) => categories.map((category, categoryIndex) => {
14819
+ const globalSeriesIndex = resolveGlobalSeriesIndex(series);
14359
14820
  const value = safeNumber2(series.values[categoryIndex]) ?? 0;
14360
14821
  const categoryStart = categoryScale(category) ?? plot.left;
14361
14822
  const barWidth = Math.max(1, histogramColumns ? categoryScale.bandwidth() : seriesScale.bandwidth());
@@ -14363,21 +14824,32 @@ function renderComboChart(chart, palette, layout) {
14363
14824
  const y = primaryScale(Math.max(0, value));
14364
14825
  const zeroY = primaryScale(0);
14365
14826
  const height = Math.max(1, Math.abs(zeroY - primaryScale(value)));
14366
- return /* @__PURE__ */ jsx2(
14367
- "rect",
14368
- {
14369
- fill: series.color ?? series.lineColor ?? chartSeriesColor(primaryChart, seriesIndex),
14370
- height,
14371
- stroke: histogramColumns ? "none" : series.lineColor ?? series.color ?? chartSeriesStrokeColor(primaryChart, seriesIndex),
14372
- strokeWidth: histogramColumns ? 0 : 1,
14373
- width: barWidth,
14827
+ const selected = isSelectedChartPoint(selectedChartElement, chart.id, globalSeriesIndex, categoryIndex) || isSelectedChartSeries(selectedChartElement, chart.id, globalSeriesIndex) && selectedChartElement?.kind !== "point";
14828
+ return /* @__PURE__ */ jsxs2(React3.Fragment, { children: [
14829
+ /* @__PURE__ */ jsx2(
14830
+ "rect",
14831
+ {
14832
+ ...barChartElementDataProps(globalSeriesIndex, categoryIndex),
14833
+ fill: series.color ?? series.lineColor ?? chartSeriesColor(primaryChart, seriesIndex),
14834
+ height,
14835
+ stroke: selected ? "#64748b" : histogramColumns ? "none" : series.lineColor ?? series.color ?? chartSeriesStrokeColor(primaryChart, seriesIndex),
14836
+ strokeWidth: selected ? 2 : histogramColumns ? 0 : 1,
14837
+ width: barWidth,
14838
+ x,
14839
+ y: Math.min(y, zeroY)
14840
+ }
14841
+ ),
14842
+ selected ? renderSelectionRectHandles(
14843
+ `combo-bar-selection-${globalSeriesIndex}-${categoryIndex}`,
14374
14844
  x,
14375
- y: Math.min(y, zeroY)
14376
- },
14377
- `combo-bar-${seriesIndex}-${categoryIndex}`
14378
- );
14845
+ Math.min(y, zeroY),
14846
+ barWidth,
14847
+ height
14848
+ ) : null
14849
+ ] }, `combo-bar-${seriesIndex}-${categoryIndex}`);
14379
14850
  })),
14380
14851
  lineGroup.series.map((series, seriesIndex) => {
14852
+ const globalSeriesIndex = resolveGlobalSeriesIndex(series);
14381
14853
  const points = categories.map((category, categoryIndex) => ({
14382
14854
  x: (categoryScale(category) ?? plot.left) + categoryScale.bandwidth() / 2,
14383
14855
  y: safeNumber2(series.values[categoryIndex])
@@ -14388,6 +14860,7 @@ function renderComboChart(chart, palette, layout) {
14388
14860
  /* @__PURE__ */ jsx2(
14389
14861
  "path",
14390
14862
  {
14863
+ ...chartElementDataProps(globalSeriesIndex),
14391
14864
  d: path,
14392
14865
  fill: "none",
14393
14866
  stroke: series.lineColor ?? series.color ?? chartSeriesStrokeColor(chart, columnGroup.series.length + seriesIndex),
@@ -14396,22 +14869,30 @@ function renderComboChart(chart, palette, layout) {
14396
14869
  strokeWidth: Math.max(1.5, series.lineWidthPx ?? 2)
14397
14870
  }
14398
14871
  ),
14399
- points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ jsx2(
14872
+ points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ createElement(
14400
14873
  "path",
14401
14874
  {
14875
+ ...chartElementDataProps(globalSeriesIndex, pointIndex),
14402
14876
  d: markerSymbolPath(normalizeChartMarkerSymbol(series.markerSymbol), Math.max(4, series.markerSize ?? 7)) || markerSymbolPath("circle", 7),
14403
14877
  fill: series.markerColor ?? series.color ?? series.lineColor ?? chartSeriesColor(chart, columnGroup.series.length + seriesIndex),
14878
+ key: `combo-line-marker-${seriesIndex}-${pointIndex}`,
14404
14879
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? "#ffffff",
14405
14880
  strokeWidth: 1,
14406
14881
  transform: `translate(${point.x}, ${secondaryScale(point.y)})`
14407
- },
14408
- `combo-line-marker-${seriesIndex}-${pointIndex}`
14409
- ))
14882
+ }
14883
+ )),
14884
+ points.map((point, pointIndex) => point.y != null && isSelectedChartPointOrSeries(selectedChartElement, chart.id, globalSeriesIndex, pointIndex) ? renderSelectionRectHandles(
14885
+ `combo-line-selection-${globalSeriesIndex}-${pointIndex}`,
14886
+ point.x - 4,
14887
+ secondaryScale(point.y) - 4,
14888
+ 8,
14889
+ 8
14890
+ ) : null)
14410
14891
  ] }, `combo-line-${seriesIndex}`);
14411
14892
  })
14412
14893
  ] });
14413
14894
  }
14414
- function renderScatterChart(chart, palette, layout, smooth) {
14895
+ function renderScatterChart(chart, palette, layout, smooth, selectedChartElement) {
14415
14896
  const plot = layout.plot;
14416
14897
  const rawRecord = chart.raw && typeof chart.raw === "object" ? chart.raw : null;
14417
14898
  const normalizedTitle = typeof chart.title === "string" ? chart.title.trim().toLowerCase() : "";
@@ -14597,6 +15078,7 @@ function renderScatterChart(chart, palette, layout, smooth) {
14597
15078
  shouldDrawLine && linePath.length > 0 ? /* @__PURE__ */ jsx2(
14598
15079
  "path",
14599
15080
  {
15081
+ ...chartElementDataProps(seriesIndex),
14600
15082
  d: linePath,
14601
15083
  fill: "none",
14602
15084
  stroke: series.lineColor ?? chartSeriesStrokeColor(chart, seriesIndex),
@@ -14616,6 +15098,7 @@ function renderScatterChart(chart, palette, layout, smooth) {
14616
15098
  children: /* @__PURE__ */ jsx2(
14617
15099
  "path",
14618
15100
  {
15101
+ ...chartElementDataProps(seriesIndex, pointIndex, { selectionMode: "seriesFirst" }),
14619
15102
  d: markerPath,
14620
15103
  fill: markerFill,
14621
15104
  stroke: "none",
@@ -14625,12 +15108,16 @@ function renderScatterChart(chart, palette, layout, smooth) {
14625
15108
  },
14626
15109
  `scatter-point-${seriesIndex}-${pointIndex}`
14627
15110
  );
14628
- })
15111
+ }),
15112
+ seriesPoints.points.map((point, pointIndex) => isSelectedChartPoint(selectedChartElement, chart.id, seriesIndex, pointIndex) || isSelectedChartSeries(selectedChartElement, chart.id, seriesIndex) && selectedChartElement?.kind !== "point" ? renderSelectionPointHandles(
15113
+ `scatter-selection-${seriesIndex}-${pointIndex}`,
15114
+ [{ x: xScale(point.x), y: yScale(point.y) }]
15115
+ ) : null)
14629
15116
  ] }, `scatter-series-${seriesIndex}`);
14630
15117
  })
14631
15118
  ] });
14632
15119
  }
14633
- function renderBubbleChart(chart, palette, layout) {
15120
+ function renderBubbleChart(chart, palette, layout, selectedChartElement) {
14634
15121
  const plot = layout.plot;
14635
15122
  const pointsBySeries = chart.series.map((series) => series.values.map((value, index) => {
14636
15123
  const x = safeNumber2(series.categories[index]);
@@ -14750,6 +15237,7 @@ function renderBubbleChart(chart, palette, layout) {
14750
15237
  /* @__PURE__ */ jsx2(
14751
15238
  "circle",
14752
15239
  {
15240
+ ...chartElementDataProps(seriesIndex, point.index, { selectionMode: "seriesFirst" }),
14753
15241
  cx: xScale(point.x),
14754
15242
  cy: yScale(point.y),
14755
15243
  fill: isBubble3d ? `url(#bubble3d-grad-${chart.id}-${seriesIndex})` : baseColor,
@@ -14759,6 +15247,13 @@ function renderBubbleChart(chart, palette, layout) {
14759
15247
  strokeWidth: isBubble3d ? 1.2 : 1
14760
15248
  }
14761
15249
  ),
15250
+ isSelectedChartPoint(selectedChartElement, chart.id, seriesIndex, point.index) || isSelectedChartSeries(selectedChartElement, chart.id, seriesIndex) && selectedChartElement?.kind !== "point" ? renderSelectionRectHandles(
15251
+ `bubble-selection-${seriesIndex}-${point.index}`,
15252
+ xScale(point.x) - radius,
15253
+ yScale(point.y) - radius,
15254
+ radius * 2,
15255
+ radius * 2
15256
+ ) : null,
14762
15257
  isBubble3d ? /* @__PURE__ */ jsx2(
14763
15258
  "ellipse",
14764
15259
  {
@@ -14786,7 +15281,7 @@ function renderBubbleChart(chart, palette, layout) {
14786
15281
  ] }, `bubble-series-${seriesIndex}`))
14787
15282
  ] });
14788
15283
  }
14789
- function renderRadarChart(chart, palette, layout) {
15284
+ function renderRadarChart(chart, palette, layout, selectedChartElement) {
14790
15285
  if (chart.series.length === 0) {
14791
15286
  return null;
14792
15287
  }
@@ -14865,12 +15360,14 @@ function renderRadarChart(chart, palette, layout) {
14865
15360
  if (rawValue == null) {
14866
15361
  return {
14867
15362
  defined: false,
15363
+ pointIndex: categoryIndex,
14868
15364
  ...radialPoint(categoryIndex, 0)
14869
15365
  };
14870
15366
  }
14871
15367
  const ratio = clamp2((rawValue - minValue) / (safeMax - minValue), 0, 1);
14872
15368
  return {
14873
15369
  defined: true,
15370
+ pointIndex: categoryIndex,
14874
15371
  ...radialPoint(categoryIndex, ratio)
14875
15372
  };
14876
15373
  });
@@ -14889,6 +15386,7 @@ function renderRadarChart(chart, palette, layout) {
14889
15386
  definedPoints.length >= 2 ? /* @__PURE__ */ jsx2(
14890
15387
  "path",
14891
15388
  {
15389
+ ...chartElementDataProps(seriesIndex),
14892
15390
  d: polygon,
14893
15391
  fill: filled && !hasGap && definedPoints.length >= 3 ? color : "none",
14894
15392
  fillOpacity: filled ? 0.26 : 0,
@@ -14896,13 +15394,14 @@ function renderRadarChart(chart, palette, layout) {
14896
15394
  strokeWidth: 1.8
14897
15395
  }
14898
15396
  ) : null,
14899
- showMarkers ? definedPoints.map((point, pointIndex) => /* @__PURE__ */ jsx2(
15397
+ showMarkers ? definedPoints.map((point) => /* @__PURE__ */ jsx2(
14900
15398
  "g",
14901
15399
  {
14902
15400
  transform: `translate(${point.x}, ${point.y})`,
14903
15401
  children: /* @__PURE__ */ jsx2(
14904
15402
  "path",
14905
15403
  {
15404
+ ...chartElementDataProps(seriesIndex, point.pointIndex),
14906
15405
  d: markerPath,
14907
15406
  fill: series.markerColor ?? color,
14908
15407
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? palette.surface,
@@ -14910,13 +15409,17 @@ function renderRadarChart(chart, palette, layout) {
14910
15409
  }
14911
15410
  )
14912
15411
  },
14913
- `radar-point-${seriesIndex}-${pointIndex}`
14914
- )) : null
15412
+ `radar-point-${seriesIndex}-${point.pointIndex}`
15413
+ )) : null,
15414
+ definedPoints.map((point) => isSelectedChartPoint(selectedChartElement, chart.id, seriesIndex, point.pointIndex) || isSelectedChartSeries(selectedChartElement, chart.id, seriesIndex) && selectedChartElement?.kind !== "point" ? renderSelectionPointHandles(
15415
+ `radar-selection-${seriesIndex}-${point.pointIndex}`,
15416
+ [{ x: point.x, y: point.y }]
15417
+ ) : null)
14915
15418
  ] }, `radar-series-${seriesIndex}`);
14916
15419
  })
14917
15420
  ] });
14918
15421
  }
14919
- function renderPieChart(chart, palette, layout, chartType) {
15422
+ function renderPieChart(chart, palette, layout, chartType, selectedChartElement) {
14920
15423
  const pieSeriesIndex = selectPrimaryPieSeriesIndex(chart);
14921
15424
  const pieSeries = chart.series[pieSeriesIndex];
14922
15425
  const pieData = buildPieEntries(chart, pieSeriesIndex);
@@ -15068,6 +15571,16 @@ function renderPieChart(chart, palette, layout, chartType) {
15068
15571
  const midAngle = (arc.startAngle + arc.endAngle) / 2;
15069
15572
  const explodeX = Math.sin(midAngle) * explosion;
15070
15573
  const explodeY = -Math.cos(midAngle) * explosion * (isPie3d ? tilt : 1);
15574
+ const isSliceSelected = isSelectedChartPoint(selectedChartElement, chart.id, pieSeriesIndex, arc.data.index) || isSelectedChartSeries(selectedChartElement, chart.id, pieSeriesIndex) && selectedChartElement?.kind !== "point";
15575
+ const sliceHandlePoints = isSliceSelected ? [
15576
+ pieEllipsePoint(centerX, centerY, outerRadius, isPie3d ? tilt : 1, arc.startAngle),
15577
+ pieEllipsePoint(centerX, centerY, outerRadius, isPie3d ? tilt : 1, midAngle),
15578
+ pieEllipsePoint(centerX, centerY, outerRadius, isPie3d ? tilt : 1, arc.endAngle),
15579
+ innerRadius > 0 ? pieEllipsePoint(centerX, centerY, innerRadius, isPie3d ? tilt : 1, midAngle) : { x: centerX, y: centerY }
15580
+ ].map((point) => ({
15581
+ x: point.x + explodeX,
15582
+ y: point.y + explodeY
15583
+ })) : [];
15071
15584
  const labelRadius = outerRadius + (chartType === "PieExploded" ? 8 : 12);
15072
15585
  const labelX = centerX + Math.sin(midAngle) * labelRadius + explodeX;
15073
15586
  const labelY = centerY - Math.cos(midAngle) * labelRadius * (isPie3d ? tilt : 1) + explodeY;
@@ -15101,14 +15614,16 @@ function renderPieChart(chart, palette, layout, chartType) {
15101
15614
  /* @__PURE__ */ jsx2("g", { transform: `translate(${explodeX}, ${explodeY})`, children: /* @__PURE__ */ jsx2(
15102
15615
  "path",
15103
15616
  {
15617
+ ...chartElementDataProps(pieSeriesIndex, arc.data.index),
15104
15618
  d: arcPath(arc) ?? "",
15105
15619
  fill: arc.data.color,
15106
- stroke: sliceSeparatorColor,
15107
- strokeWidth: sliceSeparatorWidth,
15108
- transform: `translate(${centerX}, ${centerY})${isPie3d ? ` scale(1, ${tilt})` : ""}`,
15109
- filter: isPie3d ? `url(#${shadowId})` : void 0
15620
+ filter: isPie3d ? `url(#${shadowId})` : void 0,
15621
+ stroke: isSliceSelected ? "#64748b" : sliceSeparatorColor,
15622
+ strokeWidth: isSliceSelected ? Math.max(2, sliceSeparatorWidth) : sliceSeparatorWidth,
15623
+ transform: `translate(${centerX}, ${centerY})${isPie3d ? ` scale(1, ${tilt})` : ""}`
15110
15624
  }
15111
15625
  ) }),
15626
+ isSliceSelected ? renderSelectionPointHandles(`pie-selection-${arc.data.index}`, sliceHandlePoints) : null,
15112
15627
  dataLabelsEnabled && truncatedLabelText.length > 0 ? /* @__PURE__ */ jsx2(
15113
15628
  "text",
15114
15629
  {
@@ -15136,7 +15651,7 @@ function renderPieChart(chart, palette, layout, chartType) {
15136
15651
  ) : null
15137
15652
  ] });
15138
15653
  }
15139
- function renderBarOfPieChart(chart, palette, layout) {
15654
+ function renderBarOfPieChart(chart, palette, layout, selectedChartElement) {
15140
15655
  const pieSeriesIndex = selectPrimaryPieSeriesIndex(chart);
15141
15656
  const pieSeries = chart.series[pieSeriesIndex];
15142
15657
  const categories = getCategoryLabels(chart);
@@ -15153,10 +15668,11 @@ function renderBarOfPieChart(chart, palette, layout) {
15153
15668
  }
15154
15669
  const secondarySet = new Set(secondaryIndices);
15155
15670
  const secondaryTotal = secondaryIndices.reduce((sum, index) => sum + (values[index] ?? 0), 0);
15156
- const primaryData = values.flatMap((value, index) => secondarySet.has(index) ? [] : [{ color: chartPointColor(chart, index, pieSeriesIndex), label: categories[index], value }]);
15671
+ const primaryData = values.flatMap((value, index) => secondarySet.has(index) ? [] : [{ color: chartPointColor(chart, index, pieSeriesIndex), index, label: categories[index], value }]);
15157
15672
  if (secondaryTotal > 0) {
15158
15673
  primaryData.push({
15159
15674
  color: chartPointColor(chart, secondaryIndices[0] ?? 0, pieSeriesIndex),
15675
+ index: secondaryIndices[0] ?? 0,
15160
15676
  label: "Other",
15161
15677
  value: secondaryTotal
15162
15678
  });
@@ -15171,6 +15687,7 @@ function renderBarOfPieChart(chart, palette, layout) {
15171
15687
  const connectorTargetX = layout.plot.left + layout.plot.width * 0.69;
15172
15688
  const secondaryData = secondaryIndices.map((index) => ({
15173
15689
  color: chartPointColor(chart, index, pieSeriesIndex),
15690
+ index,
15174
15691
  label: categories[index] ?? "",
15175
15692
  value: values[index] ?? 0
15176
15693
  }));
@@ -15186,17 +15703,25 @@ function renderBarOfPieChart(chart, palette, layout) {
15186
15703
  const secondaryTotalSafe = Math.max(1e-6, secondaryTotal);
15187
15704
  let stackCursor = stackedBarTop;
15188
15705
  return /* @__PURE__ */ jsxs2("g", { children: [
15189
- pieArcs.map((entry, index) => /* @__PURE__ */ jsx2(
15190
- "path",
15191
- {
15192
- d: arc(entry) ?? "",
15193
- fill: entry.data.color,
15194
- stroke: chart.chartAreaFillColor ?? palette.surface,
15195
- strokeWidth: 1,
15196
- transform: `translate(${pieCenterX}, ${pieCenterY})`
15197
- },
15198
- `bar-of-pie-main-${index}`
15199
- )),
15706
+ pieArcs.map((entry, index) => {
15707
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, pieSeriesIndex, entry.data.index);
15708
+ const midAngle = (entry.startAngle + entry.endAngle) / 2;
15709
+ const dot = pieEllipsePoint(pieCenterX, pieCenterY, pieRadius * 0.62, 1, midAngle);
15710
+ return /* @__PURE__ */ jsxs2(React3.Fragment, { children: [
15711
+ /* @__PURE__ */ jsx2(
15712
+ "path",
15713
+ {
15714
+ ...chartElementDataProps(pieSeriesIndex, entry.data.index),
15715
+ d: arc(entry) ?? "",
15716
+ fill: entry.data.color,
15717
+ stroke: selected ? "#64748b" : chart.chartAreaFillColor ?? palette.surface,
15718
+ strokeWidth: selected ? 2 : 1,
15719
+ transform: `translate(${pieCenterX}, ${pieCenterY})`
15720
+ }
15721
+ ),
15722
+ selected ? renderSelectionPointHandles(`bar-of-pie-main-selection-${index}`, [dot]) : null
15723
+ ] }, `bar-of-pie-main-${index}`);
15724
+ }),
15200
15725
  /* @__PURE__ */ jsx2(
15201
15726
  "line",
15202
15727
  {
@@ -15219,33 +15744,50 @@ function renderBarOfPieChart(chart, palette, layout) {
15219
15744
  y2: layout.plot.top + layout.plot.height - 10
15220
15745
  }
15221
15746
  ),
15222
- ofPieType === "pie" ? secondaryPieArcs.map((entry, index) => /* @__PURE__ */ jsx2(
15223
- "path",
15224
- {
15225
- d: secondaryArc(entry) ?? "",
15226
- fill: entry.data.color,
15227
- stroke: chart.chartAreaFillColor ?? palette.surface,
15228
- strokeWidth: 1,
15229
- transform: `translate(${secondaryCenterX}, ${secondaryCenterY})`
15230
- },
15231
- `bar-of-pie-secondary-pie-${index}`
15232
- )) : secondaryData.map((entry, index) => {
15747
+ ofPieType === "pie" ? secondaryPieArcs.map((entry, index) => {
15748
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, pieSeriesIndex, entry.data.index);
15749
+ const midAngle = (entry.startAngle + entry.endAngle) / 2;
15750
+ const dot = pieEllipsePoint(secondaryCenterX, secondaryCenterY, secondaryRadius * 0.62, 1, midAngle);
15751
+ return /* @__PURE__ */ jsxs2(React3.Fragment, { children: [
15752
+ /* @__PURE__ */ jsx2(
15753
+ "path",
15754
+ {
15755
+ ...chartElementDataProps(pieSeriesIndex, entry.data.index),
15756
+ d: secondaryArc(entry) ?? "",
15757
+ fill: entry.data.color,
15758
+ stroke: selected ? "#64748b" : chart.chartAreaFillColor ?? palette.surface,
15759
+ strokeWidth: selected ? 2 : 1,
15760
+ transform: `translate(${secondaryCenterX}, ${secondaryCenterY})`
15761
+ }
15762
+ ),
15763
+ selected ? renderSelectionPointHandles(`bar-of-pie-secondary-pie-selection-${index}`, [dot]) : null
15764
+ ] }, `bar-of-pie-secondary-pie-${index}`);
15765
+ }) : secondaryData.map((entry, index) => {
15233
15766
  const segmentHeight = index === secondaryData.length - 1 ? Math.max(1, stackedBarTop + stackedBarHeight - stackCursor) : Math.max(1, entry.value / secondaryTotalSafe * stackedBarHeight);
15234
15767
  const y = stackCursor;
15235
15768
  stackCursor += segmentHeight;
15769
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, pieSeriesIndex, entry.index);
15236
15770
  return /* @__PURE__ */ jsxs2("g", { children: [
15237
15771
  /* @__PURE__ */ jsx2(
15238
15772
  "rect",
15239
15773
  {
15774
+ ...chartElementDataProps(pieSeriesIndex, entry.index),
15240
15775
  fill: entry.color,
15241
15776
  height: segmentHeight,
15242
- stroke: chart.chartAreaFillColor ?? palette.surface,
15243
- strokeWidth: 1,
15777
+ stroke: selected ? "#64748b" : chart.chartAreaFillColor ?? palette.surface,
15778
+ strokeWidth: selected ? 2 : 1,
15244
15779
  width: stackedBarWidth,
15245
15780
  x: stackedBarLeft,
15246
15781
  y
15247
15782
  }
15248
15783
  ),
15784
+ selected ? renderSelectionRectHandles(
15785
+ `bar-of-pie-secondary-bar-selection-${index}`,
15786
+ stackedBarLeft,
15787
+ y,
15788
+ stackedBarWidth,
15789
+ segmentHeight
15790
+ ) : null,
15249
15791
  /* @__PURE__ */ jsx2(
15250
15792
  "text",
15251
15793
  {
@@ -15261,7 +15803,7 @@ function renderBarOfPieChart(chart, palette, layout) {
15261
15803
  })
15262
15804
  ] });
15263
15805
  }
15264
- function renderSurfaceChart(chart, palette, layout) {
15806
+ function renderSurfaceChart(chart, palette, layout, selectedChartElement) {
15265
15807
  const plot = resolveSurfacePlotRect(chart, layout);
15266
15808
  const categories = getCategoryLabels(chart);
15267
15809
  const rows = chart.series.length;
@@ -15786,11 +16328,51 @@ function renderSurfaceChart(chart, palette, layout) {
15786
16328
  ) : null
15787
16329
  ] });
15788
16330
  }
16331
+ function renderSurfaceHitOverlay(chart, layout, selectedChartElement) {
16332
+ const plot = resolveSurfacePlotRect(chart, layout);
16333
+ const categories = getCategoryLabels(chart);
16334
+ const rows = chart.series.length;
16335
+ const cols = Math.max(
16336
+ categories.length,
16337
+ chart.series.reduce((max, series) => Math.max(max, series.values.length), 0)
16338
+ );
16339
+ if (rows === 0 || cols === 0) {
16340
+ return null;
16341
+ }
16342
+ const cellWidth = plot.width / cols;
16343
+ const cellHeight = plot.height / rows;
16344
+ return /* @__PURE__ */ jsx2("g", { children: chart.series.flatMap((_, seriesIndex) => Array.from({ length: cols }, (_2, pointIndex) => {
16345
+ const left = plot.left + pointIndex * cellWidth;
16346
+ const top = plot.top + seriesIndex * cellHeight;
16347
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, seriesIndex, pointIndex);
16348
+ return /* @__PURE__ */ jsxs2(React3.Fragment, { children: [
16349
+ /* @__PURE__ */ jsx2(
16350
+ "rect",
16351
+ {
16352
+ ...chartElementDataProps(seriesIndex, pointIndex),
16353
+ fill: "transparent",
16354
+ height: cellHeight,
16355
+ stroke: "none",
16356
+ width: cellWidth,
16357
+ x: left,
16358
+ y: top
16359
+ }
16360
+ ),
16361
+ selected ? renderSelectionRectHandles(
16362
+ `surface-selection-${seriesIndex}-${pointIndex}`,
16363
+ left,
16364
+ top,
16365
+ cellWidth,
16366
+ cellHeight
16367
+ ) : null
16368
+ ] }, `surface-hit-${seriesIndex}-${pointIndex}`);
16369
+ })) });
16370
+ }
15789
16371
  function indexByName(series, matcher) {
15790
16372
  const index = series.findIndex((entry) => matcher.test((entry.name ?? "").toLowerCase()));
15791
16373
  return index >= 0 ? index : null;
15792
16374
  }
15793
- function renderStockChart(chart, palette, layout) {
16375
+ function renderStockChart(chart, palette, layout, selectedChartElement) {
15794
16376
  const categories = getCategoryLabels(chart);
15795
16377
  if (categories.length === 0 || chart.series.length < 2) {
15796
16378
  return null;
@@ -15893,7 +16475,13 @@ function renderStockChart(chart, palette, layout) {
15893
16475
  const closeY = yScale(entry.close);
15894
16476
  const highY = yScale(entry.high);
15895
16477
  const lowY = yScale(entry.low);
15896
- return /* @__PURE__ */ jsxs2("g", { children: [
16478
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, closeIndex, index);
16479
+ return /* @__PURE__ */ createElement(
16480
+ "g",
16481
+ {
16482
+ ...chartElementDataProps(closeIndex, index),
16483
+ key: `stock-point-${index}`
16484
+ },
15897
16485
  hasVolume && entry.volume != null ? /* @__PURE__ */ jsx2(
15898
16486
  "rect",
15899
16487
  {
@@ -15919,12 +16507,13 @@ function renderStockChart(chart, palette, layout) {
15919
16507
  y: Math.min(openY, closeY)
15920
16508
  }
15921
16509
  ) : /* @__PURE__ */ jsx2("line", { stroke, strokeWidth: 1.6, x1: bodyLeft, x2: bodyLeft + candleWidth, y1: closeY, y2: closeY }) : /* @__PURE__ */ jsx2("line", { stroke: closeTickColor, strokeWidth: 1.8, x1: x, x2: x + 7, y1: closeY, y2: closeY }),
15922
- entry.open != null && openY != null ? /* @__PURE__ */ jsx2("line", { stroke: openTickColor, strokeWidth: 1.8, x1: x - 7, x2: x, y1: openY, y2: openY }) : null
15923
- ] }, `stock-point-${index}`);
16510
+ entry.open != null && openY != null ? /* @__PURE__ */ jsx2("line", { stroke: openTickColor, strokeWidth: 1.8, x1: x - 7, x2: x, y1: openY, y2: openY }) : null,
16511
+ selected ? renderSelectionPointHandles(`stock-selection-${index}`, [{ x, y: closeY }]) : null
16512
+ );
15924
16513
  })
15925
16514
  ] });
15926
16515
  }
15927
- function renderWaterfallChart(chart, palette, layout) {
16516
+ function renderWaterfallChart(chart, palette, layout, selectedChartElement) {
15928
16517
  const stages = buildChartStages(chart);
15929
16518
  if (stages.length === 0) {
15930
16519
  return null;
@@ -15979,6 +16568,7 @@ function renderWaterfallChart(chart, palette, layout) {
15979
16568
  const fill = bar.isSubtotal ? darkenColor2(bar.color, 0.18) : bar.value >= 0 ? bar.color : lightenColor2(bar.color, 0.22);
15980
16569
  const connectorStart = index > 0 ? bars[index - 1] : null;
15981
16570
  const connectorY = connectorStart ? yScale(connectorStart.end) : 0;
16571
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
15982
16572
  return /* @__PURE__ */ jsxs2("g", { children: [
15983
16573
  connectorStart ? /* @__PURE__ */ jsx2(
15984
16574
  "line",
@@ -15995,17 +16585,19 @@ function renderWaterfallChart(chart, palette, layout) {
15995
16585
  /* @__PURE__ */ jsx2(
15996
16586
  "rect",
15997
16587
  {
16588
+ ...chartElementDataProps(0, index),
15998
16589
  fill,
15999
16590
  rx: 2,
16000
16591
  ry: 2,
16001
- stroke: darkenColor2(fill, 0.22),
16002
- strokeWidth: 1,
16592
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.22),
16593
+ strokeWidth: selected ? 2 : 1,
16003
16594
  x: bandLeft,
16004
16595
  y: top,
16005
16596
  width: bandWidth,
16006
16597
  height
16007
16598
  }
16008
16599
  ),
16600
+ selected ? renderSelectionRectHandles(`waterfall-selection-${index}`, bandLeft, top, bandWidth, height) : null,
16009
16601
  /* @__PURE__ */ jsx2(
16010
16602
  "text",
16011
16603
  {
@@ -16032,7 +16624,7 @@ function renderWaterfallChart(chart, palette, layout) {
16032
16624
  })
16033
16625
  ] });
16034
16626
  }
16035
- function renderFunnelChart(chart, palette, layout) {
16627
+ function renderFunnelChart(chart, palette, layout, selectedChartElement) {
16036
16628
  const stages = buildChartStages(chart).map((stage) => ({ ...stage, value: Math.max(0, stage.value) })).filter((stage) => stage.value > 0);
16037
16629
  if (stages.length === 0) {
16038
16630
  return null;
@@ -16049,21 +16641,24 @@ function renderFunnelChart(chart, palette, layout) {
16049
16641
  const left = centerX - stageWidth * 0.5;
16050
16642
  const fill = stage.isSubtotal ? darkenColor2(stage.color, 0.14) : stage.color;
16051
16643
  const labelFitsInside = stageWidth > 90;
16644
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16052
16645
  return /* @__PURE__ */ jsxs2("g", { children: [
16053
16646
  /* @__PURE__ */ jsx2(
16054
16647
  "rect",
16055
16648
  {
16649
+ ...chartElementDataProps(0, index),
16056
16650
  fill,
16057
16651
  height: stageHeight,
16058
16652
  rx: 0,
16059
16653
  ry: 0,
16060
- stroke: darkenColor2(fill, 0.2),
16061
- strokeWidth: 1,
16654
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.2),
16655
+ strokeWidth: selected ? 2 : 1,
16062
16656
  width: stageWidth,
16063
16657
  x: left,
16064
16658
  y: topY
16065
16659
  }
16066
16660
  ),
16661
+ selected ? renderSelectionRectHandles(`funnel-selection-${index}`, left, topY, stageWidth, stageHeight) : null,
16067
16662
  /* @__PURE__ */ jsx2(
16068
16663
  "text",
16069
16664
  {
@@ -16078,7 +16673,7 @@ function renderFunnelChart(chart, palette, layout) {
16078
16673
  ] }, `funnel-stage-${index}`);
16079
16674
  }) });
16080
16675
  }
16081
- function renderSunburstChart(chart, palette, layout) {
16676
+ function renderSunburstChart(chart, palette, layout, selectedChartElement) {
16082
16677
  const hierarchyData = buildHierarchyData(chart);
16083
16678
  if (!hierarchyData) {
16084
16679
  return null;
@@ -16105,16 +16700,19 @@ function renderSunburstChart(chart, palette, layout) {
16105
16700
  const arcSpan = node.x1 - node.x0;
16106
16701
  const canShowLabel = arcSpan * labelRadius > 26;
16107
16702
  const fill = resolveHierarchyNodeColor(chart, node);
16703
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16108
16704
  return /* @__PURE__ */ jsxs2("g", { children: [
16109
16705
  /* @__PURE__ */ jsx2(
16110
16706
  "path",
16111
16707
  {
16708
+ ...chartElementDataProps(0, index),
16112
16709
  d: path,
16113
16710
  fill,
16114
- stroke: palette.surface,
16115
- strokeWidth: 1
16711
+ stroke: selected ? "#64748b" : palette.surface,
16712
+ strokeWidth: selected ? 2 : 1
16116
16713
  }
16117
16714
  ),
16715
+ selected ? renderSelectionPointHandles(`sunburst-selection-${index}`, [{ x: labelX, y: labelY }]) : null,
16118
16716
  canShowLabel ? /* @__PURE__ */ jsx2(
16119
16717
  "text",
16120
16718
  {
@@ -16130,7 +16728,7 @@ function renderSunburstChart(chart, palette, layout) {
16130
16728
  /* @__PURE__ */ jsx2("circle", { fill: chart.chartAreaFillColor ?? palette.surface, r: holeRadius - 2 })
16131
16729
  ] });
16132
16730
  }
16133
- function renderTreemapChart(chart, palette, layout) {
16731
+ function renderTreemapChart(chart, palette, layout, selectedChartElement) {
16134
16732
  const hierarchyData = buildHierarchyData(chart);
16135
16733
  if (!hierarchyData) {
16136
16734
  return null;
@@ -16142,21 +16740,24 @@ function renderTreemapChart(chart, palette, layout) {
16142
16740
  const width = Math.max(0, leaf.x1 - leaf.x0);
16143
16741
  const height = Math.max(0, leaf.y1 - leaf.y0);
16144
16742
  const canShowLabel = width > 48 && height > 22;
16743
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16145
16744
  return /* @__PURE__ */ jsxs2("g", { children: [
16146
16745
  /* @__PURE__ */ jsx2(
16147
16746
  "rect",
16148
16747
  {
16748
+ ...chartElementDataProps(0, index),
16149
16749
  fill,
16150
16750
  rx: 3,
16151
16751
  ry: 3,
16152
- stroke: palette.surface,
16153
- strokeWidth: 1,
16752
+ stroke: selected ? "#64748b" : palette.surface,
16753
+ strokeWidth: selected ? 2 : 1,
16154
16754
  x: leaf.x0,
16155
16755
  y: leaf.y0,
16156
16756
  width,
16157
16757
  height
16158
16758
  }
16159
16759
  ),
16760
+ selected ? renderSelectionRectHandles(`treemap-selection-${index}`, leaf.x0, leaf.y0, width, height) : null,
16160
16761
  canShowLabel ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
16161
16762
  /* @__PURE__ */ jsx2(
16162
16763
  "text",
@@ -16183,7 +16784,7 @@ function renderTreemapChart(chart, palette, layout) {
16183
16784
  ] }, `treemap-leaf-${index}`);
16184
16785
  }) });
16185
16786
  }
16186
- function renderBoxWhiskerChart(chart, palette, layout) {
16787
+ function renderBoxWhiskerChart(chart, palette, layout, selectedChartElement) {
16187
16788
  const visibleSeries = chart.series.filter((series) => series.hidden !== true);
16188
16789
  if (visibleSeries.length === 0) {
16189
16790
  return null;
@@ -16289,146 +16890,145 @@ function renderBoxWhiskerChart(chart, palette, layout) {
16289
16890
  const meanY = yScale(entry.stats.mean);
16290
16891
  const visiblePoints = entry.visibility.nonoutliers ? entry.stats.visiblePoints : [];
16291
16892
  const outliers = entry.visibility.outliers ? entry.stats.outliers : [];
16292
- return /* @__PURE__ */ jsxs2("g", { children: [
16293
- /* @__PURE__ */ jsx2(
16294
- "line",
16295
- {
16296
- stroke: entry.lineColor,
16297
- strokeWidth: 1.5,
16298
- x1: x,
16299
- x2: x,
16300
- y1: upperWhiskerY,
16301
- y2: boxTop
16302
- }
16303
- ),
16893
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, index, index);
16894
+ return /* @__PURE__ */ createElement("g", { ...chartElementDataProps(index), key: `box-whisker-series-${index}` }, /* @__PURE__ */ jsx2(
16895
+ "line",
16896
+ {
16897
+ stroke: entry.lineColor,
16898
+ strokeWidth: 1.5,
16899
+ x1: x,
16900
+ x2: x,
16901
+ y1: upperWhiskerY,
16902
+ y2: boxTop
16903
+ }
16904
+ ), /* @__PURE__ */ jsx2(
16905
+ "line",
16906
+ {
16907
+ stroke: entry.lineColor,
16908
+ strokeWidth: 1.5,
16909
+ x1: x,
16910
+ x2: x,
16911
+ y1: boxBottom,
16912
+ y2: lowerWhiskerY
16913
+ }
16914
+ ), /* @__PURE__ */ jsx2(
16915
+ "line",
16916
+ {
16917
+ stroke: entry.lineColor,
16918
+ strokeWidth: 1.5,
16919
+ x1: x - capWidth * 0.5,
16920
+ x2: x + capWidth * 0.5,
16921
+ y1: upperWhiskerY,
16922
+ y2: upperWhiskerY
16923
+ }
16924
+ ), /* @__PURE__ */ jsx2(
16925
+ "line",
16926
+ {
16927
+ stroke: entry.lineColor,
16928
+ strokeWidth: 1.5,
16929
+ x1: x - capWidth * 0.5,
16930
+ x2: x + capWidth * 0.5,
16931
+ y1: lowerWhiskerY,
16932
+ y2: lowerWhiskerY
16933
+ }
16934
+ ), /* @__PURE__ */ jsx2(
16935
+ "rect",
16936
+ {
16937
+ ...chartElementDataProps(index, index),
16938
+ fill: lightenColor2(entry.color, 0.35),
16939
+ fillOpacity: 0.72,
16940
+ height: Math.max(1, boxBottom - boxTop),
16941
+ stroke: selected ? "#64748b" : entry.lineColor,
16942
+ strokeWidth: selected ? 2 : 1.5,
16943
+ width: boxWidth,
16944
+ x: x - boxWidth * 0.5,
16945
+ y: boxTop
16946
+ }
16947
+ ), selected ? renderSelectionRectHandles(
16948
+ `box-whisker-selection-${index}`,
16949
+ x - boxWidth * 0.5,
16950
+ boxTop,
16951
+ boxWidth,
16952
+ Math.max(1, boxBottom - boxTop)
16953
+ ) : null, /* @__PURE__ */ jsx2(
16954
+ "line",
16955
+ {
16956
+ stroke: darkenColor2(entry.lineColor, 0.15),
16957
+ strokeWidth: 2,
16958
+ x1: x - boxWidth * 0.5,
16959
+ x2: x + boxWidth * 0.5,
16960
+ y1: medianY,
16961
+ y2: medianY
16962
+ }
16963
+ ), entry.visibility.meanMarker ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
16304
16964
  /* @__PURE__ */ jsx2(
16305
16965
  "line",
16306
16966
  {
16307
- stroke: entry.lineColor,
16308
- strokeWidth: 1.5,
16309
- x1: x,
16310
- x2: x,
16311
- y1: boxBottom,
16312
- y2: lowerWhiskerY
16967
+ stroke: darkenColor2(entry.lineColor, 0.18),
16968
+ strokeWidth: 1.2,
16969
+ x1: x - 4,
16970
+ x2: x + 4,
16971
+ y1: meanY - 4,
16972
+ y2: meanY + 4
16313
16973
  }
16314
16974
  ),
16315
16975
  /* @__PURE__ */ jsx2(
16316
16976
  "line",
16317
16977
  {
16318
- stroke: entry.lineColor,
16319
- strokeWidth: 1.5,
16320
- x1: x - capWidth * 0.5,
16321
- x2: x + capWidth * 0.5,
16322
- y1: upperWhiskerY,
16323
- y2: upperWhiskerY
16978
+ stroke: darkenColor2(entry.lineColor, 0.18),
16979
+ strokeWidth: 1.2,
16980
+ x1: x - 4,
16981
+ x2: x + 4,
16982
+ y1: meanY + 4,
16983
+ y2: meanY - 4
16324
16984
  }
16325
- ),
16326
- /* @__PURE__ */ jsx2(
16327
- "line",
16985
+ )
16986
+ ] }) : null, visiblePoints.map((value, pointIndex) => {
16987
+ const y = yScale(value);
16988
+ const jitter = (pointIndex % 7 - 3) * (boxWidth / 16);
16989
+ return /* @__PURE__ */ createElement(
16990
+ "circle",
16328
16991
  {
16329
- stroke: entry.lineColor,
16330
- strokeWidth: 1.5,
16331
- x1: x - capWidth * 0.5,
16332
- x2: x + capWidth * 0.5,
16333
- y1: lowerWhiskerY,
16334
- y2: lowerWhiskerY
16992
+ ...chartElementDataProps(index, pointIndex),
16993
+ key: `box-whisker-visible-${index}-${pointIndex}`,
16994
+ cx: x + jitter,
16995
+ cy: y,
16996
+ fill: entry.color,
16997
+ fillOpacity: 0.45,
16998
+ r: 2,
16999
+ stroke: "none"
16335
17000
  }
16336
- ),
16337
- /* @__PURE__ */ jsx2(
16338
- "rect",
17001
+ );
17002
+ }), outliers.map((value, pointIndex) => {
17003
+ const y = yScale(value);
17004
+ return /* @__PURE__ */ createElement(
17005
+ "circle",
16339
17006
  {
16340
- fill: lightenColor2(entry.color, 0.35),
16341
- fillOpacity: 0.72,
16342
- height: Math.max(1, boxBottom - boxTop),
17007
+ ...chartElementDataProps(index, pointIndex),
17008
+ key: `box-whisker-outlier-${index}-${pointIndex}`,
17009
+ cx: x,
17010
+ cy: y,
17011
+ fill: "#ffffff",
17012
+ r: 3,
16343
17013
  stroke: entry.lineColor,
16344
- strokeWidth: 1.5,
16345
- width: boxWidth,
16346
- x: x - boxWidth * 0.5,
16347
- y: boxTop
16348
- }
16349
- ),
16350
- /* @__PURE__ */ jsx2(
16351
- "line",
16352
- {
16353
- stroke: darkenColor2(entry.lineColor, 0.15),
16354
- strokeWidth: 2,
16355
- x1: x - boxWidth * 0.5,
16356
- x2: x + boxWidth * 0.5,
16357
- y1: medianY,
16358
- y2: medianY
16359
- }
16360
- ),
16361
- entry.visibility.meanMarker ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
16362
- /* @__PURE__ */ jsx2(
16363
- "line",
16364
- {
16365
- stroke: darkenColor2(entry.lineColor, 0.18),
16366
- strokeWidth: 1.2,
16367
- x1: x - 4,
16368
- x2: x + 4,
16369
- y1: meanY - 4,
16370
- y2: meanY + 4
16371
- }
16372
- ),
16373
- /* @__PURE__ */ jsx2(
16374
- "line",
16375
- {
16376
- stroke: darkenColor2(entry.lineColor, 0.18),
16377
- strokeWidth: 1.2,
16378
- x1: x - 4,
16379
- x2: x + 4,
16380
- y1: meanY + 4,
16381
- y2: meanY - 4
16382
- }
16383
- )
16384
- ] }) : null,
16385
- visiblePoints.map((value, pointIndex) => {
16386
- const y = yScale(value);
16387
- const jitter = (pointIndex % 7 - 3) * (boxWidth / 16);
16388
- return /* @__PURE__ */ jsx2(
16389
- "circle",
16390
- {
16391
- cx: x + jitter,
16392
- cy: y,
16393
- fill: entry.color,
16394
- fillOpacity: 0.45,
16395
- r: 2,
16396
- stroke: "none"
16397
- },
16398
- `box-whisker-visible-${index}-${pointIndex}`
16399
- );
16400
- }),
16401
- outliers.map((value, pointIndex) => {
16402
- const y = yScale(value);
16403
- return /* @__PURE__ */ jsx2(
16404
- "circle",
16405
- {
16406
- cx: x,
16407
- cy: y,
16408
- fill: "#ffffff",
16409
- r: 3,
16410
- stroke: entry.lineColor,
16411
- strokeWidth: 1.2
16412
- },
16413
- `box-whisker-outlier-${index}-${pointIndex}`
16414
- );
16415
- }),
16416
- /* @__PURE__ */ jsx2(
16417
- "text",
16418
- {
16419
- fill: labelColor,
16420
- fontSize: 10,
16421
- textAnchor: "middle",
16422
- x,
16423
- y: layout.plot.top + layout.plot.height + 14,
16424
- children: entry.label
17014
+ strokeWidth: 1.2
16425
17015
  }
16426
- )
16427
- ] }, `box-whisker-series-${index}`);
17016
+ );
17017
+ }), /* @__PURE__ */ jsx2(
17018
+ "text",
17019
+ {
17020
+ fill: labelColor,
17021
+ fontSize: 10,
17022
+ textAnchor: "middle",
17023
+ x,
17024
+ y: layout.plot.top + layout.plot.height + 14,
17025
+ children: entry.label
17026
+ }
17027
+ ));
16428
17028
  })
16429
17029
  ] });
16430
17030
  }
16431
- function renderRegionMapChart(chart, palette, layout) {
17031
+ function renderRegionMapChart(chart, palette, layout, selectedChartElement) {
16432
17032
  const primarySeriesIndex = Math.max(0, chart.series.findIndex((series) => series.hidden !== true));
16433
17033
  const primarySeries = chart.series[primarySeriesIndex] ?? null;
16434
17034
  if (!primarySeries) {
@@ -16508,17 +17108,23 @@ function renderRegionMapChart(chart, palette, layout) {
16508
17108
  const ratio = maxValue <= minValue ? 1 : (entry.value - minValue) / Math.max(1e-6, maxValue - minValue);
16509
17109
  return resolveRegionMapValueColor(chart, primarySeriesIndex, ratio);
16510
17110
  })() : categoricalColorByLabel?.get(entry.colorLabel ?? "") ?? resolveRegionMapDataColor(chart, primarySeriesIndex);
16511
- return /* @__PURE__ */ jsx2(
16512
- "path",
16513
- {
16514
- d,
16515
- fill,
16516
- stroke: darkenColor2(fill, 0.18),
16517
- strokeLinejoin: "round",
16518
- strokeWidth: 0.85
16519
- },
16520
- `region-map-value-${entry.key || index}`
16521
- );
17111
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, primarySeriesIndex, index);
17112
+ const centroid = path.centroid(entry.feature);
17113
+ const canShowSelectionDot = Number.isFinite(centroid[0]) && Number.isFinite(centroid[1]);
17114
+ return /* @__PURE__ */ jsxs2(React3.Fragment, { children: [
17115
+ /* @__PURE__ */ jsx2(
17116
+ "path",
17117
+ {
17118
+ ...chartElementDataProps(primarySeriesIndex, index),
17119
+ d,
17120
+ fill,
17121
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.18),
17122
+ strokeLinejoin: "round",
17123
+ strokeWidth: selected ? 1.8 : 0.85
17124
+ }
17125
+ ),
17126
+ selected && canShowSelectionDot ? renderSelectionPointHandles(`region-map-selection-${index}`, [{ x: centroid[0], y: centroid[1] }]) : null
17127
+ ] }, `region-map-value-${entry.key || index}`);
16522
17128
  }),
16523
17129
  showRegionLabels ? entries.map((entry, index) => {
16524
17130
  const bounds = path.bounds(entry.feature);
@@ -16575,64 +17181,71 @@ function renderUnsupported(chart, palette, layout, chartType) {
16575
17181
  )
16576
17182
  ] });
16577
17183
  }
16578
- function renderChartPlot(chart, palette, layout, chartType) {
17184
+ function renderChartPlot(chart, palette, layout, chartType, selectedChartElement) {
16579
17185
  if (isComboChart(chart)) {
16580
- return renderComboChart(chart, palette, layout) ?? renderUnsupported(chart, palette, layout, "Combo");
17186
+ return renderComboChart(chart, palette, layout, selectedChartElement) ?? renderUnsupported(chart, palette, layout, "Combo");
16581
17187
  }
16582
17188
  if (chartType === "ColumnClustered" || chartType === "ColumnStacked" || chartType === "ColumnPercentStacked" || chartType === "BarClustered" || chartType === "BarStacked" || chartType === "BarPercentStacked") {
16583
- return renderBarChart(chart, palette, layout, chartType);
17189
+ return renderBarChart(chart, palette, layout, chartType, selectedChartElement);
16584
17190
  }
16585
17191
  if (chartType === "Line" || chartType === "LineStacked" || chartType === "LinePercentStacked" || chartType === "Area" || chartType === "AreaStacked" || chartType === "AreaPercentStacked") {
16586
- return renderLineOrAreaChart(chart, palette, layout, chartType);
17192
+ return renderLineOrAreaChart(chart, palette, layout, chartType, selectedChartElement);
16587
17193
  }
16588
17194
  if (chartType === "Scatter") {
16589
- return renderScatterChart(chart, palette, layout, false);
17195
+ return renderScatterChart(chart, palette, layout, false, selectedChartElement);
16590
17196
  }
16591
17197
  if (chartType === "ScatterLines") {
16592
- return renderScatterChart(chart, palette, layout, false);
17198
+ return renderScatterChart(chart, palette, layout, false, selectedChartElement);
16593
17199
  }
16594
17200
  if (chartType === "ScatterSmooth") {
16595
- return renderScatterChart(chart, palette, layout, true);
17201
+ return renderScatterChart(chart, palette, layout, true, selectedChartElement);
16596
17202
  }
16597
17203
  if (chartType === "Bubble") {
16598
- return renderBubbleChart(chart, palette, layout);
17204
+ return renderBubbleChart(chart, palette, layout, selectedChartElement);
16599
17205
  }
16600
17206
  if (chartType === "Radar") {
16601
- return renderRadarChart(chart, palette, layout);
17207
+ return renderRadarChart(chart, palette, layout, selectedChartElement);
16602
17208
  }
16603
17209
  if (chartType === "Pie" || chartType === "Pie3D" || chartType === "PieExploded" || chartType === "Doughnut") {
16604
- return renderPieChart(chart, palette, layout, chartType);
17210
+ return renderPieChart(chart, palette, layout, chartType, selectedChartElement);
16605
17211
  }
16606
17212
  if (chartType === "BarOfPie") {
16607
- return renderBarOfPieChart(chart, palette, layout);
17213
+ return renderBarOfPieChart(chart, palette, layout, selectedChartElement);
16608
17214
  }
16609
17215
  if (chartType === "Surface") {
16610
- return renderSurfaceChart(chart, palette, layout);
17216
+ return renderSurfaceChart(chart, palette, layout, selectedChartElement);
16611
17217
  }
16612
17218
  if (chartType === "Stock") {
16613
- return renderStockChart(chart, palette, layout);
17219
+ return renderStockChart(chart, palette, layout, selectedChartElement);
16614
17220
  }
16615
17221
  if (chartType === "Waterfall") {
16616
- return renderWaterfallChart(chart, palette, layout);
17222
+ return renderWaterfallChart(chart, palette, layout, selectedChartElement);
16617
17223
  }
16618
17224
  if (chartType === "Funnel") {
16619
- return renderFunnelChart(chart, palette, layout);
17225
+ return renderFunnelChart(chart, palette, layout, selectedChartElement);
16620
17226
  }
16621
17227
  if (chartType === "BoxWhisker") {
16622
- return renderBoxWhiskerChart(chart, palette, layout);
17228
+ return renderBoxWhiskerChart(chart, palette, layout, selectedChartElement);
16623
17229
  }
16624
17230
  if (chartType === "Sunburst") {
16625
- return renderSunburstChart(chart, palette, layout);
17231
+ return renderSunburstChart(chart, palette, layout, selectedChartElement);
16626
17232
  }
16627
17233
  if (chartType === "Treemap") {
16628
- return renderTreemapChart(chart, palette, layout);
17234
+ return renderTreemapChart(chart, palette, layout, selectedChartElement);
16629
17235
  }
16630
17236
  if (chartType === "RegionMap") {
16631
- return renderRegionMapChart(chart, palette, layout);
17237
+ return renderRegionMapChart(chart, palette, layout, selectedChartElement);
16632
17238
  }
16633
17239
  return renderUnsupported(chart, palette, layout, chartType);
16634
17240
  }
16635
- var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect }) {
17241
+ var MemoChartSvg = React3.memo(function MemoChartSvg2({
17242
+ chart,
17243
+ onChartElementDoubleClick,
17244
+ onChartElementPointerDown,
17245
+ palette,
17246
+ rect,
17247
+ selectedChartElement
17248
+ }) {
16636
17249
  const renderChartType = normalizeRenderableChartType(chart);
16637
17250
  const legendItems = getLegendItems(chart, renderChartType, palette);
16638
17251
  const layout = buildLayout(chart, rect, legendItems);
@@ -16644,6 +17257,26 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16644
17257
  const normalizedBorderColor = borderColor.trim().toLowerCase();
16645
17258
  const hideBackgroundRect = normalizedBackground === "transparent" && normalizedBorderColor === "transparent";
16646
17259
  const fontFamily = buildChartFontFamily(chart.fontFamily);
17260
+ const handlePointerDown = React3.useCallback((event) => {
17261
+ const selection = resolveChartSelectionFromTarget(chart, event.target, selectedChartElement);
17262
+ if (!selection) {
17263
+ return;
17264
+ }
17265
+ if (resolveChartElementTarget(event.target)) {
17266
+ event.stopPropagation();
17267
+ }
17268
+ onChartElementPointerDown?.(selection, event);
17269
+ }, [chart, onChartElementPointerDown, selectedChartElement]);
17270
+ const handleDoubleClick = React3.useCallback((event) => {
17271
+ const selection = resolveChartSelectionFromTarget(chart, event.target, selectedChartElement);
17272
+ if (!selection) {
17273
+ return;
17274
+ }
17275
+ if (resolveChartElementTarget(event.target)) {
17276
+ event.stopPropagation();
17277
+ }
17278
+ onChartElementDoubleClick?.(selection, event);
17279
+ }, [chart, onChartElementDoubleClick, selectedChartElement]);
16647
17280
  if (renderChartType === "Surface") {
16648
17281
  return /* @__PURE__ */ jsx2(
16649
17282
  MemoSurfaceChartComposite,
@@ -16651,10 +17284,13 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16651
17284
  background,
16652
17285
  borderColor,
16653
17286
  chart,
16654
- fallback: renderSurfaceChart(chart, palette, layout),
17287
+ fallback: renderSurfaceChart(chart, palette, layout, selectedChartElement),
16655
17288
  fontFamily,
16656
17289
  layout,
17290
+ onDoubleClick: handleDoubleClick,
17291
+ onPointerDown: handlePointerDown,
16657
17292
  overlay: /* @__PURE__ */ jsxs2(Fragment2, { children: [
17293
+ renderSurfaceHitOverlay(chart, layout, selectedChartElement),
16658
17294
  renderSurfaceAxes(chart, layout),
16659
17295
  renderTitle(chart, layout, palette),
16660
17296
  renderLegend(chart, layout, palette)
@@ -16667,18 +17303,20 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16667
17303
  "svg",
16668
17304
  {
16669
17305
  "aria-label": chart.title ?? chart.name ?? "Chart",
17306
+ onDoubleClick: handleDoubleClick,
17307
+ onPointerDown: handlePointerDown,
16670
17308
  role: "img",
16671
- style: { display: "block", fontFamily, height: "100%", pointerEvents: "none", width: "100%" },
17309
+ style: { display: "block", fontFamily, height: "100%", pointerEvents: "auto", width: "100%" },
16672
17310
  viewBox: `0 0 ${layout.width} ${layout.height}`,
16673
17311
  children: [
16674
17312
  hideBackgroundRect ? null : /* @__PURE__ */ jsx2("rect", { fill: background, height: layout.height, stroke: borderColor, strokeWidth: 1, width: layout.width, x: 0, y: 0 }),
16675
17313
  renderTitle(chart, layout, palette),
16676
17314
  renderLegend(chart, layout, palette),
16677
- renderChartPlot(chart, palette, layout, renderChartType)
17315
+ renderChartPlot(chart, palette, layout, renderChartType, selectedChartElement)
16678
17316
  ]
16679
17317
  }
16680
17318
  );
16681
- }, (prev, next) => prev.chart === next.chart && prev.palette === next.palette && prev.rect.height === next.rect.height && prev.rect.width === next.rect.width && prev.rect.left === next.rect.left && prev.rect.top === next.rect.top);
17319
+ }, (prev, next) => prev.chart === next.chart && prev.onChartElementDoubleClick === next.onChartElementDoubleClick && prev.onChartElementPointerDown === next.onChartElementPointerDown && prev.palette === next.palette && prev.rect.height === next.rect.height && prev.rect.width === next.rect.width && prev.rect.left === next.rect.left && prev.rect.top === next.rect.top && prev.selectedChartElement === next.selectedChartElement);
16682
17320
 
16683
17321
  // src/XlsxViewer.tsx
16684
17322
  import { Fragment as Fragment4, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
@@ -16721,6 +17359,13 @@ var LIVE_ZOOM_COMMIT_IDLE_MS = 48;
16721
17359
  var WHEEL_ZOOM_SENSITIVITY = 25e-5;
16722
17360
  var WHEEL_LINE_DELTA_PX = 16;
16723
17361
  var CHART_SOURCE_HIGHLIGHT_COLORS = ["#2563eb", "#dc2626", "#7c3aed", "#059669", "#ea580c", "#db2777"];
17362
+ var CHART_SOURCE_HIGHLIGHT_COLOR_BY_ROLE = {
17363
+ bubble: CHART_SOURCE_HIGHLIGHT_COLORS[3] ?? "#059669",
17364
+ category: CHART_SOURCE_HIGHLIGHT_COLORS[2] ?? "#7c3aed",
17365
+ name: CHART_SOURCE_HIGHLIGHT_COLORS[0] ?? "#2563eb",
17366
+ point: CHART_SOURCE_HIGHLIGHT_COLORS[5] ?? "#db2777",
17367
+ value: CHART_SOURCE_HIGHLIGHT_COLORS[4] ?? "#ea580c"
17368
+ };
16724
17369
  var SHEET_SURFACE = "#ffffff";
16725
17370
  var DRAWING_SELECTION_STROKE = "#64748b";
16726
17371
  var DRAWING_SELECTION_HANDLE_FILL = "#ffffff";
@@ -19655,23 +20300,57 @@ function resolveChartFormulaRange(formula, fallbackSheetIndex, sheets, workbook)
19655
20300
  workbookSheetIndex
19656
20301
  };
19657
20302
  }
19658
- function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
20303
+ function resolveRangePointCell(range, pointIndex) {
20304
+ const normalized = normalizeRange2(range);
20305
+ const rowCount = normalized.end.row - normalized.start.row + 1;
20306
+ const colCount = normalized.end.col - normalized.start.col + 1;
20307
+ const cellCount = rowCount * colCount;
20308
+ if (pointIndex < 0 || pointIndex >= cellCount) {
20309
+ return null;
20310
+ }
20311
+ const rowOffset = Math.floor(pointIndex / colCount);
20312
+ const colOffset = pointIndex % colCount;
20313
+ const cell = {
20314
+ col: normalized.start.col + colOffset,
20315
+ row: normalized.start.row + rowOffset
20316
+ };
20317
+ return { start: cell, end: cell };
20318
+ }
20319
+ function collectChartRangeHighlights(chart, selectedElement, sheets, workbook, isDark) {
19659
20320
  if (!chart) {
19660
20321
  return [];
19661
20322
  }
19662
20323
  const highlights = [];
19663
20324
  const seenRanges = /* @__PURE__ */ new Set();
19664
- const references = chart.series.flatMap((series) => [
19665
- series.categoriesRef?.formula,
19666
- typeof series.raw?.name === "string" ? series.raw.name : void 0,
19667
- series.valuesRef?.formula,
19668
- series.bubbleSizeRef?.formula
20325
+ const selectedSeriesIndex = selectedElement?.chartId === chart.id && selectedElement.kind !== "chart" ? selectedElement.seriesIndex : null;
20326
+ const seriesEntries = chart.series.map((series, seriesIndex) => ({ series, seriesIndex })).filter(({ series, seriesIndex }) => series.hidden !== true && (selectedSeriesIndex == null || seriesIndex === selectedSeriesIndex));
20327
+ const references = seriesEntries.flatMap(({ series, seriesIndex }) => [
20328
+ {
20329
+ formula: typeof series.raw?.name === "string" ? series.raw.name : void 0,
20330
+ role: "name",
20331
+ seriesIndex
20332
+ },
20333
+ {
20334
+ formula: series.categoriesRef?.formula,
20335
+ role: "category",
20336
+ seriesIndex
20337
+ },
20338
+ {
20339
+ formula: series.valuesRef?.formula,
20340
+ role: "value",
20341
+ seriesIndex
20342
+ },
20343
+ {
20344
+ formula: series.bubbleSizeRef?.formula,
20345
+ role: "bubble",
20346
+ seriesIndex
20347
+ }
19669
20348
  ]);
19670
- references.forEach((formula) => {
19671
- if (!formula) {
20349
+ references.forEach((reference) => {
20350
+ if (!reference.formula) {
19672
20351
  return;
19673
20352
  }
19674
- const resolved = resolveChartFormulaRange(formula, chart.workbookSheetIndex, sheets, workbook);
20353
+ const resolved = resolveChartFormulaRange(reference.formula, chart.workbookSheetIndex, sheets, workbook);
19675
20354
  if (!resolved) {
19676
20355
  return;
19677
20356
  }
@@ -19686,7 +20365,7 @@ function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
19686
20365
  return;
19687
20366
  }
19688
20367
  seenRanges.add(key);
19689
- const strokeColor = CHART_SOURCE_HIGHLIGHT_COLORS[highlights.length % CHART_SOURCE_HIGHLIGHT_COLORS.length] ?? "#2563eb";
20368
+ const strokeColor = CHART_SOURCE_HIGHLIGHT_COLOR_BY_ROLE[reference.role];
19690
20369
  highlights.push({
19691
20370
  fillColor: applyAlphaToColor(strokeColor, isDark ? 0.24 : 0.14),
19692
20371
  range: resolved.range,
@@ -19694,6 +20373,28 @@ function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
19694
20373
  workbookSheetIndex: resolved.workbookSheetIndex
19695
20374
  });
19696
20375
  });
20376
+ if (selectedElement?.chartId === chart.id && selectedElement.kind === "point") {
20377
+ references.forEach((reference) => {
20378
+ if (!reference.formula || reference.role === "name") {
20379
+ return;
20380
+ }
20381
+ const resolved = resolveChartFormulaRange(reference.formula, chart.workbookSheetIndex, sheets, workbook);
20382
+ if (!resolved) {
20383
+ return;
20384
+ }
20385
+ const range = resolveRangePointCell(resolved.range, selectedElement.pointIndex);
20386
+ if (!range) {
20387
+ return;
20388
+ }
20389
+ const strokeColor = CHART_SOURCE_HIGHLIGHT_COLOR_BY_ROLE.point;
20390
+ highlights.push({
20391
+ fillColor: applyAlphaToColor(strokeColor, isDark ? 0.34 : 0.22),
20392
+ range,
20393
+ strokeColor,
20394
+ workbookSheetIndex: resolved.workbookSheetIndex
20395
+ });
20396
+ });
20397
+ }
19697
20398
  return highlights;
19698
20399
  }
19699
20400
  function clampSparklineValue(value, min, max) {
@@ -21751,11 +22452,13 @@ function XlsxGrid({
21751
22452
  redo,
21752
22453
  revision,
21753
22454
  selectedChart,
22455
+ selectedChartElement,
21754
22456
  selectedChartId,
21755
22457
  selectedImage,
21756
22458
  selectedImageId,
21757
22459
  selectCell,
21758
22460
  selectChart,
22461
+ selectChartElement,
21759
22462
  selectImage,
21760
22463
  selectRange,
21761
22464
  selection,
@@ -23664,8 +24367,8 @@ function XlsxGrid({
23664
24367
  return map;
23665
24368
  }, [activeSheet?.sparklines]);
23666
24369
  const chartRangeHighlights = React4.useMemo(
23667
- () => collectChartRangeHighlights(selectedChart, sheets, workbook, paletteIsDark(palette)),
23668
- [palette, selectedChart, sheets, workbook]
24370
+ () => collectChartRangeHighlights(selectedChart, selectedChartElement, sheets, workbook, paletteIsDark(palette)),
24371
+ [palette, selectedChart, selectedChartElement, sheets, workbook]
23669
24372
  );
23670
24373
  const activeSheetChartHighlights = React4.useMemo(
23671
24374
  () => activeSheet ? chartRangeHighlights.filter((highlight) => highlight.workbookSheetIndex === activeSheet.workbookSheetIndex) : [],
@@ -23680,6 +24383,7 @@ function XlsxGrid({
23680
24383
  getCellStyle,
23681
24384
  palette,
23682
24385
  revision,
24386
+ selectedChartElement,
23683
24387
  selectedChartId,
23684
24388
  viewportRowBatch,
23685
24389
  worksheet,
@@ -23693,6 +24397,7 @@ function XlsxGrid({
23693
24397
  getCellStyle,
23694
24398
  palette,
23695
24399
  revision,
24400
+ selectedChartElement,
23696
24401
  selectedChartId,
23697
24402
  viewportRowBatch,
23698
24403
  worksheet,
@@ -26888,6 +27593,13 @@ function XlsxGrid({
26888
27593
  }
26889
27594
  selectChart(chart.id);
26890
27595
  }, [selectChart]);
27596
+ const handleChartElementPointerDown = React4.useCallback((selection2) => {
27597
+ skipNextChartClickRef.current = selection2.chartId;
27598
+ selectChartElement(selection2);
27599
+ }, [selectChartElement]);
27600
+ const handleChartElementDoubleClick = React4.useCallback((selection2) => {
27601
+ selectChartElement(selection2);
27602
+ }, [selectChartElement]);
26891
27603
  if (isLoading) {
26892
27604
  return /* @__PURE__ */ jsx3(Fragment4, { children: renderLoading(loadingComponent, loadingState, palette) });
26893
27605
  }
@@ -26937,7 +27649,17 @@ function XlsxGrid({
26937
27649
  },
26938
27650
  children: charts.length > 0 ? charts.map((chart) => {
26939
27651
  const chartsheetRect = { height: 320, left: 0, top: 0, width: 640 };
26940
- return /* @__PURE__ */ jsx3("div", { style: { minHeight: 320, position: "relative" }, children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, chartsheetRect) : /* @__PURE__ */ jsx3(MemoChartSvg, { chart, palette, rect: chartsheetRect }) }, chart.id);
27652
+ return /* @__PURE__ */ jsx3("div", { style: { minHeight: 320, position: "relative" }, children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, chartsheetRect) : /* @__PURE__ */ jsx3(
27653
+ MemoChartSvg,
27654
+ {
27655
+ chart,
27656
+ onChartElementDoubleClick: handleChartElementDoubleClick,
27657
+ onChartElementPointerDown: handleChartElementPointerDown,
27658
+ palette,
27659
+ rect: chartsheetRect,
27660
+ selectedChartElement
27661
+ }
27662
+ ) }, chart.id);
26941
27663
  }) : /* @__PURE__ */ jsx3(
26942
27664
  "div",
26943
27665
  {
@@ -27611,7 +28333,6 @@ function XlsxGrid({
27611
28333
  }
27612
28334
  ) : null;
27613
28335
  return /* @__PURE__ */ jsxs3(React4.Fragment, { children: [
27614
- /* @__PURE__ */ jsx3("div", { style, children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, rect) : /* @__PURE__ */ jsx3(MemoChartSvg, { chart, palette, rect }) }),
27615
28336
  /* @__PURE__ */ jsx3(
27616
28337
  "div",
27617
28338
  {
@@ -27619,11 +28340,20 @@ function XlsxGrid({
27619
28340
  onPointerDown: (event) => startChartMove(event, chart, rect),
27620
28341
  style: {
27621
28342
  ...style,
27622
- background: "transparent",
27623
28343
  cursor: canEditChart && selectedChartId === chart.id ? "move" : "cell",
27624
- pointerEvents: "auto",
27625
- zIndex: isFrozenDrawing ? chart.zIndex + 21 : chart.zIndex + 1
27626
- }
28344
+ pointerEvents: "auto"
28345
+ },
28346
+ children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, rect) : /* @__PURE__ */ jsx3(
28347
+ MemoChartSvg,
28348
+ {
28349
+ chart,
28350
+ onChartElementDoubleClick: handleChartElementDoubleClick,
28351
+ onChartElementPointerDown: handleChartElementPointerDown,
28352
+ palette,
28353
+ rect,
28354
+ selectedChartElement
28355
+ }
28356
+ )
27627
28357
  }
27628
28358
  ),
27629
28359
  selectionNode
@@ -27706,7 +28436,7 @@ function XlsxGrid({
27706
28436
  };
27707
28437
  const drawingViewportCacheSignature = `${Math.floor(drawingViewport.left / CANVAS_VIEWPORT_OVERSCAN_PX)}:${Math.floor(drawingViewport.top / CANVAS_VIEWPORT_OVERSCAN_PX)}:${drawingViewport.width}:${drawingViewport.height}`;
27708
28438
  const previousPaneDrawingNodes = paneDrawingNodesCacheRef.current;
27709
- const canReusePaneDrawingNodes = previousPaneDrawingNodes !== null && previousPaneDrawingNodes.showImages === showImages && previousPaneDrawingNodes.chartRects === chartRects && previousPaneDrawingNodes.formControlRects === domFormControlRects && previousPaneDrawingNodes.shapeRects === domShapeRects && previousPaneDrawingNodes.imageRects === domImageRects && previousPaneDrawingNodes.selectedChartId === selectedChartId && previousPaneDrawingNodes.selectedImageId === selectedImageId && previousPaneDrawingNodes.readOnly === readOnly && previousPaneDrawingNodes.selectionStroke === selectionStroke && previousPaneDrawingNodes.renderChartLoading === renderChartLoading && previousPaneDrawingNodes.renderImage === renderImage && previousPaneDrawingNodes.renderImageSelection === renderImageSelection && previousPaneDrawingNodes.isChartsLoading === isChartsLoading && previousPaneDrawingNodes.palette === palette && previousPaneDrawingNodes.drawingViewportSignature === drawingViewportCacheSignature;
28439
+ const canReusePaneDrawingNodes = previousPaneDrawingNodes !== null && previousPaneDrawingNodes.showImages === showImages && previousPaneDrawingNodes.chartRects === chartRects && previousPaneDrawingNodes.formControlRects === domFormControlRects && previousPaneDrawingNodes.shapeRects === domShapeRects && previousPaneDrawingNodes.imageRects === domImageRects && previousPaneDrawingNodes.selectedChartId === selectedChartId && previousPaneDrawingNodes.selectedImageId === selectedImageId && previousPaneDrawingNodes.readOnly === readOnly && previousPaneDrawingNodes.selectionStroke === selectionStroke && previousPaneDrawingNodes.renderChartLoading === renderChartLoading && previousPaneDrawingNodes.renderImage === renderImage && previousPaneDrawingNodes.renderImageSelection === renderImageSelection && previousPaneDrawingNodes.isChartsLoading === isChartsLoading && previousPaneDrawingNodes.selectedChartElement === selectedChartElement && previousPaneDrawingNodes.palette === palette && previousPaneDrawingNodes.drawingViewportSignature === drawingViewportCacheSignature;
27710
28440
  const paneDrawingNodes = canReusePaneDrawingNodes ? previousPaneDrawingNodes.value : !showImages ? {
27711
28441
  corner: null,
27712
28442
  left: null,
@@ -27750,6 +28480,7 @@ function XlsxGrid({
27750
28480
  renderChartLoading,
27751
28481
  renderImage,
27752
28482
  renderImageSelection,
28483
+ selectedChartElement,
27753
28484
  selectedChartId,
27754
28485
  selectedImageId,
27755
28486
  selectionStroke,
@@ -29166,12 +29897,16 @@ function useXlsxViewerEditing() {
29166
29897
  removeActiveSheet,
29167
29898
  readOnly,
29168
29899
  redo,
29900
+ selectedCellFormula,
29901
+ selectedChartFormula,
29169
29902
  selectedFormula,
29903
+ selectedFormulaTarget,
29170
29904
  selectedValue,
29171
29905
  setCellFormula,
29172
29906
  setCellStyle,
29173
29907
  setCellValue,
29174
29908
  setRangeStyle,
29909
+ setSelectedFormula,
29175
29910
  setSelectedCellFormula,
29176
29911
  setSelectedCellStyle,
29177
29912
  setSelectedCellValue,
@@ -29197,12 +29932,16 @@ function useXlsxViewerEditing() {
29197
29932
  removeActiveSheet,
29198
29933
  readOnly,
29199
29934
  redo,
29935
+ selectedCellFormula,
29936
+ selectedChartFormula,
29200
29937
  selectedFormula,
29938
+ selectedFormulaTarget,
29201
29939
  selectedValue,
29202
29940
  setCellFormula,
29203
29941
  setCellStyle,
29204
29942
  setCellValue,
29205
29943
  setRangeStyle,
29944
+ setSelectedFormula,
29206
29945
  setSelectedCellFormula,
29207
29946
  setSelectedCellStyle,
29208
29947
  setSelectedCellValue,
@@ -29227,12 +29966,16 @@ function useXlsxViewerEditing() {
29227
29966
  removeActiveSheet,
29228
29967
  readOnly,
29229
29968
  redo,
29969
+ selectedCellFormula,
29970
+ selectedChartFormula,
29230
29971
  selectedFormula,
29972
+ selectedFormulaTarget,
29231
29973
  selectedValue,
29232
29974
  setCellFormula,
29233
29975
  setCellStyle,
29234
29976
  setCellValue,
29235
29977
  setRangeStyle,
29978
+ setSelectedFormula,
29236
29979
  setSelectedCellFormula,
29237
29980
  setSelectedCellStyle,
29238
29981
  setSelectedCellValue,
@@ -29256,8 +29999,10 @@ function useXlsxViewerImages() {
29256
29999
  const {
29257
30000
  charts,
29258
30001
  clearSelectedChart,
30002
+ clearSelectedChartElement,
29259
30003
  clearSelectedImage,
29260
30004
  getChartById,
30005
+ getChartSeriesFormula,
29261
30006
  getSheetCharts,
29262
30007
  getImageById,
29263
30008
  getSheetImages,
@@ -29269,11 +30014,15 @@ function useXlsxViewerImages() {
29269
30014
  resizeChartBy,
29270
30015
  resizeImageBy,
29271
30016
  selectedChart,
30017
+ selectedChartElement,
30018
+ selectedChartFormula,
29272
30019
  selectedChartId,
29273
30020
  selectedImage,
29274
30021
  selectedImageId,
29275
30022
  selectChart,
30023
+ selectChartElement,
29276
30024
  selectImage,
30025
+ setChartSeriesFormula,
29277
30026
  setChartRect,
29278
30027
  setImageRect,
29279
30028
  updateChart
@@ -29282,8 +30031,10 @@ function useXlsxViewerImages() {
29282
30031
  () => ({
29283
30032
  charts,
29284
30033
  clearSelectedChart,
30034
+ clearSelectedChartElement,
29285
30035
  clearSelectedImage,
29286
30036
  getChartById,
30037
+ getChartSeriesFormula,
29287
30038
  getSheetCharts,
29288
30039
  getImageById,
29289
30040
  getSheetImages,
@@ -29295,11 +30046,15 @@ function useXlsxViewerImages() {
29295
30046
  resizeChartBy,
29296
30047
  resizeImageBy,
29297
30048
  selectedChart,
30049
+ selectedChartElement,
30050
+ selectedChartFormula,
29298
30051
  selectedChartId,
29299
30052
  selectedImage,
29300
30053
  selectedImageId,
29301
30054
  selectChart,
30055
+ selectChartElement,
29302
30056
  selectImage,
30057
+ setChartSeriesFormula,
29303
30058
  setChartRect,
29304
30059
  setImageRect,
29305
30060
  updateChart
@@ -29307,8 +30062,10 @@ function useXlsxViewerImages() {
29307
30062
  [
29308
30063
  charts,
29309
30064
  clearSelectedChart,
30065
+ clearSelectedChartElement,
29310
30066
  clearSelectedImage,
29311
30067
  getChartById,
30068
+ getChartSeriesFormula,
29312
30069
  getSheetCharts,
29313
30070
  getImageById,
29314
30071
  getSheetImages,
@@ -29320,11 +30077,15 @@ function useXlsxViewerImages() {
29320
30077
  resizeChartBy,
29321
30078
  resizeImageBy,
29322
30079
  selectedChart,
30080
+ selectedChartElement,
30081
+ selectedChartFormula,
29323
30082
  selectedChartId,
29324
30083
  selectedImage,
29325
30084
  selectedImageId,
29326
30085
  selectChart,
30086
+ selectChartElement,
29327
30087
  selectImage,
30088
+ setChartSeriesFormula,
29328
30089
  setChartRect,
29329
30090
  setImageRect,
29330
30091
  updateChart
@@ -29338,7 +30099,9 @@ function useXlsxViewerCharts() {
29338
30099
  charts,
29339
30100
  chartsheets,
29340
30101
  clearSelectedChart,
30102
+ clearSelectedChartElement,
29341
30103
  getChartById,
30104
+ getChartSeriesFormula,
29342
30105
  getChartsheetById,
29343
30106
  getSheetCharts,
29344
30107
  isChartsLoading,
@@ -29347,8 +30110,12 @@ function useXlsxViewerCharts() {
29347
30110
  resizeChartBy,
29348
30111
  selectChart,
29349
30112
  selectedChart,
30113
+ selectedChartElement,
30114
+ selectedChartFormula,
29350
30115
  selectedChartId,
30116
+ selectChartElement,
29351
30117
  setActiveTabIndex,
30118
+ setChartSeriesFormula,
29352
30119
  setChartRect,
29353
30120
  tabs,
29354
30121
  updateChart
@@ -29360,7 +30127,9 @@ function useXlsxViewerCharts() {
29360
30127
  charts,
29361
30128
  chartsheets,
29362
30129
  clearSelectedChart,
30130
+ clearSelectedChartElement,
29363
30131
  getChartById,
30132
+ getChartSeriesFormula,
29364
30133
  getChartsheetById,
29365
30134
  getSheetCharts,
29366
30135
  isChartsLoading,
@@ -29369,8 +30138,12 @@ function useXlsxViewerCharts() {
29369
30138
  resizeChartBy,
29370
30139
  selectChart,
29371
30140
  selectedChart,
30141
+ selectedChartElement,
30142
+ selectedChartFormula,
29372
30143
  selectedChartId,
30144
+ selectChartElement,
29373
30145
  setActiveTabIndex,
30146
+ setChartSeriesFormula,
29374
30147
  setChartRect,
29375
30148
  tabs,
29376
30149
  updateChart
@@ -29381,7 +30154,9 @@ function useXlsxViewerCharts() {
29381
30154
  charts,
29382
30155
  chartsheets,
29383
30156
  clearSelectedChart,
30157
+ clearSelectedChartElement,
29384
30158
  getChartById,
30159
+ getChartSeriesFormula,
29385
30160
  getChartsheetById,
29386
30161
  getSheetCharts,
29387
30162
  isChartsLoading,
@@ -29390,8 +30165,12 @@ function useXlsxViewerCharts() {
29390
30165
  resizeChartBy,
29391
30166
  selectChart,
29392
30167
  selectedChart,
30168
+ selectedChartElement,
30169
+ selectedChartFormula,
29393
30170
  selectedChartId,
30171
+ selectChartElement,
29394
30172
  setActiveTabIndex,
30173
+ setChartSeriesFormula,
29395
30174
  setChartRect,
29396
30175
  tabs,
29397
30176
  updateChart