@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.cjs CHANGED
@@ -72,6 +72,170 @@ var SERIES_COLORS = [
72
72
  "#636363",
73
73
  "#997300"
74
74
  ];
75
+ function quoteSeriesFormulaString(value) {
76
+ return `"${value.replace(/"/g, '""')}"`;
77
+ }
78
+ function unquoteSeriesFormulaString(value) {
79
+ const trimmed = value.trim();
80
+ if (trimmed.length < 2 || !trimmed.startsWith('"') || !trimmed.endsWith('"')) {
81
+ return null;
82
+ }
83
+ return trimmed.slice(1, -1).replace(/""/g, '"');
84
+ }
85
+ function splitTopLevelSeriesArguments(value) {
86
+ const args = [];
87
+ let current = "";
88
+ let doubleQuoted = false;
89
+ let singleQuoted = false;
90
+ let depth = 0;
91
+ for (let index = 0; index < value.length; index += 1) {
92
+ const char = value[index] ?? "";
93
+ const next = value[index + 1] ?? "";
94
+ if (doubleQuoted) {
95
+ current += char;
96
+ if (char === '"' && next === '"') {
97
+ current += next;
98
+ index += 1;
99
+ } else if (char === '"') {
100
+ doubleQuoted = false;
101
+ }
102
+ continue;
103
+ }
104
+ if (singleQuoted) {
105
+ current += char;
106
+ if (char === "'" && next === "'") {
107
+ current += next;
108
+ index += 1;
109
+ } else if (char === "'") {
110
+ singleQuoted = false;
111
+ }
112
+ continue;
113
+ }
114
+ if (char === '"') {
115
+ doubleQuoted = true;
116
+ current += char;
117
+ continue;
118
+ }
119
+ if (char === "'") {
120
+ singleQuoted = true;
121
+ current += char;
122
+ continue;
123
+ }
124
+ if (char === "(") {
125
+ depth += 1;
126
+ current += char;
127
+ continue;
128
+ }
129
+ if (char === ")") {
130
+ depth = Math.max(0, depth - 1);
131
+ current += char;
132
+ continue;
133
+ }
134
+ if (char === "," && depth === 0) {
135
+ args.push(current.trim());
136
+ current = "";
137
+ continue;
138
+ }
139
+ current += char;
140
+ }
141
+ args.push(current.trim());
142
+ return args;
143
+ }
144
+ function readSeriesNameFormula(series) {
145
+ const raw = series.raw && typeof series.raw === "object" ? series.raw : null;
146
+ return typeof raw?.name === "string" && raw.name.length > 0 ? raw.name : null;
147
+ }
148
+ function buildChartSeriesFormula(chart, seriesIndex) {
149
+ const series = chart?.series[seriesIndex];
150
+ if (!chart || !series) {
151
+ return "";
152
+ }
153
+ const nameFormula = readSeriesNameFormula(series);
154
+ const nameArgument = nameFormula ?? quoteSeriesFormulaString(series.name ?? `Series ${seriesIndex + 1}`);
155
+ const categoryArgument = series.categoriesRef?.formula ?? "";
156
+ const valueArgument = series.valuesRef?.formula ?? "";
157
+ const orderArgument = String(seriesIndex + 1);
158
+ const bubbleArgument = series.bubbleSizeRef?.formula;
159
+ return [
160
+ `=SERIES(${nameArgument}`,
161
+ categoryArgument,
162
+ valueArgument,
163
+ orderArgument,
164
+ ...chart.chartType === "Bubble" || bubbleArgument ? [bubbleArgument ?? ""] : []
165
+ ].join(",") + ")";
166
+ }
167
+ function parseChartSeriesFormula(formula, chart) {
168
+ const trimmed = formula.trim();
169
+ const withoutEquals = trimmed.startsWith("=") ? trimmed.slice(1).trim() : trimmed;
170
+ const match = /^SERIES\s*\(([\s\S]*)\)$/i.exec(withoutEquals);
171
+ if (!match) {
172
+ return null;
173
+ }
174
+ const args = splitTopLevelSeriesArguments(match[1]);
175
+ const isBubble = chart?.chartType === "Bubble";
176
+ if (args.length < 4 || args.length > 5 || isBubble && args.length !== 5) {
177
+ return null;
178
+ }
179
+ const [nameArg = "", categoryFormula = "", valueFormula = "", orderArg = "", bubbleSizeFormula] = args;
180
+ if (!categoryFormula || !valueFormula) {
181
+ return null;
182
+ }
183
+ const parsedOrder = Number(orderArg);
184
+ if (!Number.isFinite(parsedOrder)) {
185
+ return null;
186
+ }
187
+ const nameLiteral = unquoteSeriesFormulaString(nameArg);
188
+ return {
189
+ bubbleSizeFormula: bubbleSizeFormula && bubbleSizeFormula.length > 0 ? bubbleSizeFormula : void 0,
190
+ categoryFormula,
191
+ nameFormula: nameLiteral == null && nameArg.length > 0 ? nameArg : void 0,
192
+ nameLiteral: nameLiteral ?? void 0,
193
+ order: parsedOrder,
194
+ valueFormula
195
+ };
196
+ }
197
+ function applyChartSeriesFormula(chart, seriesIndex, formula, workbook) {
198
+ const parsed = parseChartSeriesFormula(formula, chart);
199
+ const currentSeries = chart.series[seriesIndex];
200
+ if (!parsed || !currentSeries) {
201
+ return null;
202
+ }
203
+ const categoriesRef = {
204
+ ...currentSeries.categoriesRef ?? {},
205
+ formula: parsed.categoryFormula
206
+ };
207
+ const valuesRef = {
208
+ ...currentSeries.valuesRef ?? {},
209
+ formula: parsed.valueFormula
210
+ };
211
+ const bubbleSizeRef = chart.chartType === "Bubble" || parsed.bubbleSizeFormula ? {
212
+ ...currentSeries.bubbleSizeRef ?? {},
213
+ formula: parsed.bubbleSizeFormula
214
+ } : currentSeries.bubbleSizeRef ?? null;
215
+ const raw = {
216
+ ...currentSeries.raw ?? {}
217
+ };
218
+ if (parsed.nameFormula) {
219
+ raw.name = parsed.nameFormula;
220
+ } else {
221
+ delete raw.name;
222
+ }
223
+ const nextSeries = {
224
+ ...currentSeries,
225
+ bubbleSizeRef,
226
+ bubbleSizes: workbook && bubbleSizeRef?.formula ? resolveReferenceValues(workbook, chart.workbookSheetIndex, bubbleSizeRef, "value").map((value) => typeof value === "number" && Number.isFinite(value) ? value : null) : currentSeries.bubbleSizes,
227
+ categories: workbook ? resolveReferenceValues(workbook, chart.workbookSheetIndex, categoriesRef, "category") : currentSeries.categories,
228
+ categoriesRef,
229
+ name: parsed.nameLiteral ?? (parsed.nameFormula && workbook ? resolveSeriesName(workbook, chart.workbookSheetIndex, parsed.nameFormula) : parsed.nameFormula ?? currentSeries.name),
230
+ raw,
231
+ values: workbook ? resolveReferenceValues(workbook, chart.workbookSheetIndex, valuesRef, "value").map((value) => typeof value === "number" && Number.isFinite(value) ? value : null) : currentSeries.values,
232
+ valuesRef
233
+ };
234
+ return {
235
+ ...chart,
236
+ series: chart.series.map((series, index) => index === seriesIndex ? nextSeries : series)
237
+ };
238
+ }
75
239
  function normalizeWorksheetVisibility(value) {
76
240
  return value === "hidden" || value === "veryHidden" ? value : "visible";
77
241
  }
@@ -1638,6 +1802,9 @@ function getLocalChildren(parent, localName) {
1638
1802
  (node) => node.nodeType === Node.ELEMENT_NODE && node.localName === localName
1639
1803
  );
1640
1804
  }
1805
+ function removeLocalChildren(parent, localName) {
1806
+ getLocalChildren(parent, localName).forEach((node) => node.parentNode?.removeChild(node));
1807
+ }
1641
1808
  function getLocalDescendants(parent, localName) {
1642
1809
  return Array.from(parent.getElementsByTagName("*")).filter(
1643
1810
  (node) => node.localName === localName
@@ -3096,34 +3263,52 @@ function setChartTitle(chartNode, value) {
3096
3263
  }
3097
3264
  function setRefFormula(parent, refNodeName, formula) {
3098
3265
  if (!formula) {
3266
+ removeLocalChildren(parent, refNodeName);
3099
3267
  return;
3100
3268
  }
3101
3269
  const refNode = ensureChild(parent, refNodeName);
3102
3270
  setLeafValue(refNode, "f", formula);
3103
3271
  }
3104
- function updateSeriesNodes(chartTypeNode, chart) {
3272
+ function setSeriesText(seriesNode, series) {
3273
+ const raw = series.raw && typeof series.raw === "object" ? series.raw : null;
3274
+ const nameFormula = typeof raw?.name === "string" && raw.name.length > 0 ? raw.name : void 0;
3275
+ if (!nameFormula && series.name === void 0) {
3276
+ return;
3277
+ }
3278
+ const tx = ensureChild(seriesNode, "tx");
3279
+ removeLocalChildren(tx, "strRef");
3280
+ removeLocalChildren(tx, "v");
3281
+ if (nameFormula) {
3282
+ const strRef = ensureChild(tx, "strRef");
3283
+ setLeafValue(strRef, "f", nameFormula);
3284
+ return;
3285
+ }
3286
+ setLeafValue(tx, "v", series.name ?? "");
3287
+ }
3288
+ function updateSeriesNodes(plotAreaNode, chart) {
3105
3289
  if (!chart.series) {
3106
3290
  return;
3107
3291
  }
3108
- const seriesNodes = getLocalDescendants(chartTypeNode, "ser");
3292
+ const seriesNodes = getLocalDescendants(plotAreaNode, "ser");
3109
3293
  chart.series.forEach((series, index) => {
3110
3294
  const seriesNode = seriesNodes[index];
3111
3295
  if (!seriesNode) {
3112
3296
  return;
3113
3297
  }
3114
- if (series.name !== void 0) {
3115
- const tx = ensureChild(seriesNode, "tx");
3116
- const strRef = ensureChild(tx, "strRef");
3117
- setLeafValue(strRef, "f", series.name);
3118
- }
3298
+ setSeriesText(seriesNode, series);
3119
3299
  if (series.categoriesRef?.formula) {
3120
- const target = chart.chartType === "Scatter" || chart.chartType === "ScatterLines" || chart.chartType === "ScatterSmooth" ? ensureChild(seriesNode, "xVal") : ensureChild(seriesNode, "cat");
3121
- setRefFormula(target, "strRef", series.categoriesRef.formula);
3300
+ 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"));
3301
+ const categoryRefName = target.localName === "xVal" || getFirstLocalChild(target, "numRef") ? "numRef" : "strRef";
3302
+ setRefFormula(target, categoryRefName, series.categoriesRef.formula);
3122
3303
  }
3123
3304
  if (series.valuesRef?.formula) {
3124
- const target = chart.chartType === "Scatter" || chart.chartType === "ScatterLines" || chart.chartType === "ScatterSmooth" ? ensureChild(seriesNode, "yVal") : ensureChild(seriesNode, "val");
3305
+ 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"));
3125
3306
  setRefFormula(target, "numRef", series.valuesRef.formula);
3126
3307
  }
3308
+ if (series.bubbleSizeRef) {
3309
+ const target = getFirstLocalChild(seriesNode, "bubbleSize") ?? ensureChild(seriesNode, "bubbleSize");
3310
+ setRefFormula(target, "numRef", series.bubbleSizeRef.formula);
3311
+ }
3127
3312
  if (series.invertIfNegative !== void 0) {
3128
3313
  setBooleanValue(seriesNode, "invertIfNegative", series.invertIfNegative);
3129
3314
  }
@@ -3272,7 +3457,7 @@ function updateWorkbookChartDefinition(imageAssets, chartAssets, chartId, patch)
3272
3457
  if (patch.dataLabels) {
3273
3458
  updateDataLabels(chartTypeNode, patch.dataLabels);
3274
3459
  }
3275
- updateSeriesNodes(chartTypeNode, patch);
3460
+ updateSeriesNodes(plotAreaNode, patch);
3276
3461
  updateAxisNode(
3277
3462
  getLocalChildren(plotAreaNode, "catAx")[0] ?? getLocalChildren(plotAreaNode, "dateAx")[0] ?? getLocalChildren(plotAreaNode, "serAx")[0] ?? null,
3278
3463
  patch.categoryAxis
@@ -3508,6 +3693,85 @@ function sheetColumnWidthToPixels(width, columnCharacterWidthPx = DEFAULT_COLUMN
3508
3693
  const pixels = width < 1 ? Math.floor(width * (digitWidth + 5) + 0.5) : Math.floor((256 * width + Math.floor(128 / digitWidth)) / 256 * digitWidth);
3509
3694
  return Math.max(MIN_COL_WIDTH_PX, pixels);
3510
3695
  }
3696
+ function resolveWorksheetDefaultColumnWidthPixels(worksheet, columnCharacterWidthPx = DEFAULT_COLUMN_CHARACTER_WIDTH_PX, fallbackPx = sheetColumnWidthToPixels(8.43, columnCharacterWidthPx)) {
3697
+ const width = typeof worksheet.defaultColumnWidth === "number" ? worksheet.defaultColumnWidth : Number.NaN;
3698
+ return Number.isFinite(width) && width > 0 ? sheetColumnWidthToPixels(width, columnCharacterWidthPx) : fallbackPx;
3699
+ }
3700
+ function resolveWorksheetDefaultRowHeightPixels(worksheet, fallbackPx = Math.max(MIN_ROW_HEIGHT_PX, Math.round(15 * 1.33))) {
3701
+ const height = typeof worksheet.defaultRowHeight === "number" ? worksheet.defaultRowHeight : Number.NaN;
3702
+ return Number.isFinite(height) && height > 0 ? Math.max(MIN_ROW_HEIGHT_PX, Math.round(height * 1.33)) : fallbackPx;
3703
+ }
3704
+ function resolveWorksheetHiddenRows(worksheet, maxRow) {
3705
+ if (!Number.isFinite(maxRow) || maxRow < 0 || typeof worksheet.isRowHidden !== "function") {
3706
+ return [];
3707
+ }
3708
+ const hiddenRows = [];
3709
+ for (let row = 0; row <= maxRow; row += 1) {
3710
+ if (worksheet.isRowHidden(row)) {
3711
+ hiddenRows.push(row);
3712
+ }
3713
+ }
3714
+ return hiddenRows;
3715
+ }
3716
+ function resolveWorksheetHiddenCols(worksheet, maxCol) {
3717
+ if (!Number.isFinite(maxCol) || maxCol < 0 || typeof worksheet.isColumnHidden !== "function") {
3718
+ return [];
3719
+ }
3720
+ const hiddenCols = [];
3721
+ for (let col = 0; col <= maxCol; col += 1) {
3722
+ if (worksheet.isColumnHidden(col)) {
3723
+ hiddenCols.push(col);
3724
+ }
3725
+ }
3726
+ return hiddenCols;
3727
+ }
3728
+ function resolveWorksheetMergeMetadata(worksheet) {
3729
+ const mergeMetadata = {
3730
+ hasHorizontalMerges: false,
3731
+ hasVerticalMerges: false,
3732
+ maxHorizontalMergeEndCol: -1,
3733
+ maxVerticalMergeEndRow: -1
3734
+ };
3735
+ const mergedRegions = Array.isArray(worksheet.mergedRegions) ? worksheet.mergedRegions : [];
3736
+ for (const rawRegion of mergedRegions) {
3737
+ let range = null;
3738
+ if (typeof rawRegion === "string") {
3739
+ range = parseA1RangeReference(rawRegion);
3740
+ } else if (rawRegion && typeof rawRegion === "object") {
3741
+ const region = rawRegion;
3742
+ const startRow = typeof region.startRow === "number" ? region.startRow : Number.NaN;
3743
+ const startCol = typeof region.startCol === "number" ? region.startCol : Number.NaN;
3744
+ const endRow = typeof region.endRow === "number" ? region.endRow : Number.NaN;
3745
+ const endCol = typeof region.endCol === "number" ? region.endCol : Number.NaN;
3746
+ if ([startRow, startCol, endRow, endCol].every((value) => Number.isFinite(value) && value >= 0)) {
3747
+ range = {
3748
+ end: {
3749
+ col: Math.max(startCol, endCol),
3750
+ row: Math.max(startRow, endRow)
3751
+ },
3752
+ start: {
3753
+ col: Math.min(startCol, endCol),
3754
+ row: Math.min(startRow, endRow)
3755
+ }
3756
+ };
3757
+ } else if (typeof region.range === "string") {
3758
+ range = parseA1RangeReference(region.range);
3759
+ }
3760
+ }
3761
+ if (!range) {
3762
+ continue;
3763
+ }
3764
+ if (range.end.col > range.start.col) {
3765
+ mergeMetadata.hasHorizontalMerges = true;
3766
+ mergeMetadata.maxHorizontalMergeEndCol = Math.max(mergeMetadata.maxHorizontalMergeEndCol, range.end.col);
3767
+ }
3768
+ if (range.end.row > range.start.row) {
3769
+ mergeMetadata.hasVerticalMerges = true;
3770
+ mergeMetadata.maxVerticalMergeEndRow = Math.max(mergeMetadata.maxVerticalMergeEndRow, range.end.row);
3771
+ }
3772
+ }
3773
+ return mergeMetadata;
3774
+ }
3511
3775
  function buildThemePalette(theme) {
3512
3776
  const themeOrder = ["lt1", "dk1", "lt2", "dk2", "accent1", "accent2", "accent3", "accent4", "accent5", "accent6", "hlink", "folHlink"];
3513
3777
  const colorsByIndex = {};
@@ -4239,67 +4503,6 @@ function parseWorkbookStyles(archive) {
4239
4503
  tableStyleByName
4240
4504
  };
4241
4505
  }
4242
- function parseWorkbookTableMetadata(archive, workbookSheets) {
4243
- return workbookSheets.map((sheet) => {
4244
- const sheetRelationships = parseRelationships(archive, relsPathForDocument(sheet.path), sheet.path);
4245
- const sheetXml = readArchiveText2(archive, sheet.path);
4246
- if (!sheetXml) {
4247
- return [];
4248
- }
4249
- const sheetDocument = parseXml2(sheetXml);
4250
- if (!sheetDocument) {
4251
- return [];
4252
- }
4253
- return getLocalElements(sheetDocument, "tablePart").flatMap((tablePartNode) => {
4254
- const relationshipId = getRelationshipId(tablePartNode);
4255
- if (!relationshipId) {
4256
- return [];
4257
- }
4258
- const relationship = sheetRelationships.get(relationshipId);
4259
- if (!relationship) {
4260
- return [];
4261
- }
4262
- const tableXml = readArchiveText2(archive, relationship.target);
4263
- if (!tableXml) {
4264
- return [];
4265
- }
4266
- const tableDocument = parseXml2(tableXml);
4267
- const tableNode = tableDocument?.documentElement;
4268
- if (!tableNode || tableNode.localName !== "table") {
4269
- return [];
4270
- }
4271
- return [{
4272
- displayName: tableNode.getAttribute("displayName") ?? void 0,
4273
- headerRowCount: parseWorkbookTableCount(tableNode.getAttribute("headerRowCount"), 1),
4274
- headerRowCellStyle: tableNode.getAttribute("headerRowCellStyle") ?? void 0,
4275
- name: tableNode.getAttribute("name") ?? void 0,
4276
- reference: tableNode.getAttribute("ref") ?? void 0,
4277
- totalsRowCount: parseWorkbookTableCount(tableNode.getAttribute("totalsRowCount"), 0),
4278
- totalsRowShown: parseWorkbookTableBoolean(tableNode.getAttribute("totalsRowShown"), false)
4279
- }];
4280
- });
4281
- });
4282
- }
4283
- function parseWorkbookTableCount(value, fallback) {
4284
- if (value === null) {
4285
- return fallback;
4286
- }
4287
- const parsed = Number.parseInt(value, 10);
4288
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
4289
- }
4290
- function parseWorkbookTableBoolean(value, fallback) {
4291
- if (value === null) {
4292
- return fallback;
4293
- }
4294
- const normalized = value.trim().toLowerCase();
4295
- if (normalized === "0" || normalized === "false" || normalized === "") {
4296
- return false;
4297
- }
4298
- if (normalized === "1" || normalized === "true") {
4299
- return true;
4300
- }
4301
- return fallback;
4302
- }
4303
4506
  function parseSqrefRanges(sqref) {
4304
4507
  if (!sqref) {
4305
4508
  return [];
@@ -4571,12 +4774,6 @@ function parseSheetState(archive, path, options) {
4571
4774
  const colWidthOverridesPx = {};
4572
4775
  const rowStyleIds = {};
4573
4776
  const colStyleIds = {};
4574
- const hiddenRows = /* @__PURE__ */ new Set();
4575
- const hiddenCols = /* @__PURE__ */ new Set();
4576
- let hasHorizontalMerges = false;
4577
- let hasVerticalMerges = false;
4578
- let maxHorizontalMergeEndCol = -1;
4579
- let maxVerticalMergeEndRow = -1;
4580
4777
  let minContentCol = Number.POSITIVE_INFINITY;
4581
4778
  let minContentRow = Number.POSITIVE_INFINITY;
4582
4779
  let maxContentCol = -1;
@@ -4617,16 +4814,12 @@ function parseSheetState(archive, path, options) {
4617
4814
  const rowIndex = Number(rowNode.getAttribute("r") ?? 0) - 1;
4618
4815
  const height = Number(rowNode.getAttribute("ht") ?? Number.NaN);
4619
4816
  const styleId = Number(rowNode.getAttribute("s") ?? Number.NaN);
4620
- const isHidden = (rowNode.getAttribute("hidden") ?? "0") === "1";
4621
4817
  if (rowIndex >= 0 && Number.isFinite(height)) {
4622
4818
  rowHeightOverridesPx[rowIndex] = Math.max(MIN_ROW_HEIGHT_PX, Math.round(height * 1.33));
4623
4819
  }
4624
4820
  if (rowIndex >= 0 && Number.isFinite(styleId)) {
4625
4821
  rowStyleIds[rowIndex] = styleId;
4626
4822
  }
4627
- if (rowIndex >= 0 && isHidden) {
4628
- hiddenRows.add(rowIndex);
4629
- }
4630
4823
  getChildElements(rowNode, "c").forEach((cellNode) => {
4631
4824
  const cellRef = cellNode.getAttribute("r");
4632
4825
  if (isMeaningfulCellNode(cellNode)) {
@@ -4641,28 +4834,12 @@ function parseSheetState(archive, path, options) {
4641
4834
  }
4642
4835
  });
4643
4836
  });
4644
- getLocalElements(document2, "mergeCell").forEach((mergeNode) => {
4645
- const reference = mergeNode.getAttribute("ref");
4646
- const range = reference ? parseA1RangeReference(reference) : null;
4647
- if (!range) {
4648
- return;
4649
- }
4650
- if (range.end.col > range.start.col) {
4651
- hasHorizontalMerges = true;
4652
- maxHorizontalMergeEndCol = Math.max(maxHorizontalMergeEndCol, range.end.col);
4653
- }
4654
- if (range.end.row > range.start.row) {
4655
- hasVerticalMerges = true;
4656
- maxVerticalMergeEndRow = Math.max(maxVerticalMergeEndRow, range.end.row);
4657
- }
4658
- });
4659
- const maxMetadataCol = Math.max(maxContentCol, maxHorizontalMergeEndCol, 0) + 256;
4837
+ const maxMetadataCol = Math.max(maxContentCol, 0) + 256;
4660
4838
  getLocalElements(document2, "col").forEach((colNode) => {
4661
4839
  const min = Number(colNode.getAttribute("min") ?? 0) - 1;
4662
4840
  const max = Number(colNode.getAttribute("max") ?? 0) - 1;
4663
4841
  const width = Number(colNode.getAttribute("width") ?? Number.NaN);
4664
4842
  const styleId = Number(colNode.getAttribute("style") ?? Number.NaN);
4665
- const isHidden = (colNode.getAttribute("hidden") ?? "0") === "1";
4666
4843
  if (!Number.isFinite(width)) {
4667
4844
  if (!Number.isFinite(styleId)) {
4668
4845
  return;
@@ -4677,9 +4854,6 @@ function parseSheetState(archive, path, options) {
4677
4854
  if (Number.isFinite(styleId)) {
4678
4855
  colStyleIds[col] = styleId;
4679
4856
  }
4680
- if (isHidden) {
4681
- hiddenCols.add(col);
4682
- }
4683
4857
  }
4684
4858
  }
4685
4859
  });
@@ -4691,16 +4865,16 @@ function parseSheetState(archive, path, options) {
4691
4865
  conditionalFormatRules,
4692
4866
  defaultColWidthPx: sheetColumnWidthToPixels(defaultColWidth, columnWidthCharacterWidthPx),
4693
4867
  defaultRowHeightPx: Math.max(MIN_ROW_HEIGHT_PX, Math.round(defaultRowHeight * 1.33)),
4694
- hasHorizontalMerges,
4695
- hasVerticalMerges,
4696
- maxHorizontalMergeEndCol,
4697
- maxVerticalMergeEndRow,
4868
+ hasHorizontalMerges: false,
4869
+ hasVerticalMerges: false,
4870
+ maxHorizontalMergeEndCol: -1,
4871
+ maxVerticalMergeEndRow: -1,
4698
4872
  maxContentCol,
4699
4873
  maxContentRow,
4700
4874
  minContentCol: Number.isFinite(minContentCol) ? minContentCol : -1,
4701
4875
  minContentRow: Number.isFinite(minContentRow) ? minContentRow : -1,
4702
- hiddenCols: [...hiddenCols].sort((left, right) => left - right),
4703
- hiddenRows: [...hiddenRows].sort((left, right) => left - right),
4876
+ hiddenCols: [],
4877
+ hiddenRows: [],
4704
4878
  rowHeightOverridesPx,
4705
4879
  rowStyleIds,
4706
4880
  showGridLines: (sheetViewNode?.getAttribute("showGridLines") ?? "1") !== "0",
@@ -5870,7 +6044,6 @@ function parseWorkbookStructureAssetsFromArchive(archive, options) {
5870
6044
  const theme = parseWorkbookTheme(archive);
5871
6045
  const themePalette = buildThemePalette(theme);
5872
6046
  const { defaultFont, namedCellStyleByName, styleById, tableStyleByName } = parseWorkbookStyles(archive);
5873
- const tableMetadataByWorkbookSheetIndex = parseWorkbookTableMetadata(archive, workbookSheets);
5874
6047
  return {
5875
6048
  contentTypes,
5876
6049
  namedCellStyleByName,
@@ -5880,7 +6053,7 @@ function parseWorkbookStructureAssetsFromArchive(archive, options) {
5880
6053
  themePalette
5881
6054
  })),
5882
6055
  styleById,
5883
- tableMetadataByWorkbookSheetIndex,
6056
+ tableMetadataByWorkbookSheetIndex: workbookSheets.map(() => []),
5884
6057
  tableStyleByName,
5885
6058
  theme,
5886
6059
  themePalette,
@@ -6777,16 +6950,20 @@ function resolveDisplayFileName(src, fileName) {
6777
6950
  }
6778
6951
  function resolveSheetDisplayUsedRange(usedRange, sheetState) {
6779
6952
  const [minRow, minCol, maxRow, maxCol] = usedRange;
6780
- const maxMeaningfulRow = Math.max(sheetState?.maxContentRow ?? -1, sheetState?.maxVerticalMergeEndRow ?? -1);
6781
- const maxMeaningfulCol = Math.max(sheetState?.maxContentCol ?? -1, sheetState?.maxHorizontalMergeEndCol ?? -1);
6953
+ const maxContentRow = sheetState?.maxContentRow ?? -1;
6954
+ const maxContentCol = sheetState?.maxContentCol ?? -1;
6955
+ const maxVerticalMergeEndRow = sheetState?.maxVerticalMergeEndRow ?? -1;
6956
+ const maxHorizontalMergeEndCol = sheetState?.maxHorizontalMergeEndCol ?? -1;
6957
+ const maxMeaningfulRow = Math.max(maxContentRow, maxVerticalMergeEndRow);
6958
+ const maxMeaningfulCol = Math.max(maxContentCol, maxHorizontalMergeEndCol);
6782
6959
  if (maxMeaningfulRow < 0 && maxMeaningfulCol < 0) {
6783
6960
  return usedRange;
6784
6961
  }
6785
6962
  return [
6786
6963
  sheetState?.minContentRow !== void 0 && sheetState.minContentRow >= 0 ? Math.min(minRow, sheetState.minContentRow) : minRow,
6787
6964
  sheetState?.minContentCol !== void 0 && sheetState.minContentCol >= 0 ? Math.min(minCol, sheetState.minContentCol) : minCol,
6788
- maxMeaningfulRow >= 0 ? Math.min(maxRow, maxMeaningfulRow) : maxRow,
6789
- maxMeaningfulCol >= 0 ? Math.min(maxCol, maxMeaningfulCol) : maxCol
6965
+ maxMeaningfulRow >= 0 ? maxContentRow >= 0 ? Math.min(maxRow, maxMeaningfulRow) : Math.max(maxRow, maxMeaningfulRow) : maxRow,
6966
+ maxMeaningfulCol >= 0 ? maxContentCol >= 0 ? Math.min(maxCol, maxMeaningfulCol) : Math.max(maxCol, maxMeaningfulCol) : maxCol
6790
6967
  ];
6791
6968
  }
6792
6969
  function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette, styleById, namedCellStyleByName, tableStyleByName, showHiddenSheets = false) {
@@ -6794,6 +6971,20 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6794
6971
  for (let index = 0; index < workbook.sheetCount; index += 1) {
6795
6972
  const worksheet = workbook.getSheet(index);
6796
6973
  const sheetState = sheetStatesByWorkbookSheetIndex?.[index] ?? null;
6974
+ const mergeMetadata = resolveWorksheetMergeMetadata(worksheet);
6975
+ const effectiveSheetState = {
6976
+ ...sheetState,
6977
+ ...mergeMetadata
6978
+ };
6979
+ const defaultColWidthPx = resolveWorksheetDefaultColumnWidthPixels(
6980
+ worksheet,
6981
+ sheetState?.columnWidthCharacterWidthPx,
6982
+ sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH
6983
+ );
6984
+ const defaultRowHeightPx = resolveWorksheetDefaultRowHeightPixels(
6985
+ worksheet,
6986
+ sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT
6987
+ );
6797
6988
  const visibility = normalizeWorksheetVisibility2(worksheet.visibility);
6798
6989
  if (!showHiddenSheets && visibility !== "visible") {
6799
6990
  continue;
@@ -6803,14 +6994,14 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6803
6994
  if (width !== void 0 && width !== null) {
6804
6995
  return resolveSheetColumnWidthPixels(width, sheetState?.columnWidthCharacterWidthPx);
6805
6996
  }
6806
- return sheetState?.colWidthOverridesPx?.[col] ?? sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH;
6997
+ return sheetState?.colWidthOverridesPx?.[col] ?? defaultColWidthPx;
6807
6998
  };
6808
6999
  const resolveRowHeightPx = (row) => {
6809
7000
  const height = worksheet.getRowHeight(row);
6810
7001
  if (height !== void 0 && height !== null) {
6811
7002
  return Math.max(Math.round(height * 1.33), MIN_ROW_HEIGHT_PX2);
6812
7003
  }
6813
- return sheetState?.rowHeightOverridesPx?.[row] ?? sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT;
7004
+ return sheetState?.rowHeightOverridesPx?.[row] ?? defaultRowHeightPx;
6814
7005
  };
6815
7006
  const usedRange = worksheet.usedRange();
6816
7007
  if (!usedRange) {
@@ -6821,15 +7012,15 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6821
7012
  colStyleIds: sheetState?.colStyleIds ?? {},
6822
7013
  conditionalFormatRules: sheetState?.conditionalFormatRules ?? [],
6823
7014
  dataValidations: parseWorksheetDataValidations(worksheet),
6824
- defaultColWidthPx: sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH,
6825
- defaultRowHeightPx: sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT,
7015
+ defaultColWidthPx,
7016
+ defaultRowHeightPx,
6826
7017
  freezePanes: parseWorksheetFreezePanes(worksheet),
6827
- hasHorizontalMerges: sheetState?.hasHorizontalMerges ?? false,
6828
- hasVerticalMerges: sheetState?.hasVerticalMerges ?? false,
6829
- maxHorizontalMergeEndCol: sheetState?.maxHorizontalMergeEndCol ?? -1,
6830
- maxVerticalMergeEndRow: sheetState?.maxVerticalMergeEndRow ?? -1,
6831
- hiddenCols: sheetState?.hiddenCols ?? [],
6832
- hiddenRows: sheetState?.hiddenRows ?? [],
7018
+ hasHorizontalMerges: mergeMetadata.hasHorizontalMerges,
7019
+ hasVerticalMerges: mergeMetadata.hasVerticalMerges,
7020
+ maxHorizontalMergeEndCol: mergeMetadata.maxHorizontalMergeEndCol,
7021
+ maxVerticalMergeEndRow: mergeMetadata.maxVerticalMergeEndRow,
7022
+ hiddenCols: [],
7023
+ hiddenRows: [],
6833
7024
  minUsedCol: -1,
6834
7025
  minUsedRow: -1,
6835
7026
  maxUsedCol: -1,
@@ -6855,7 +7046,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6855
7046
  });
6856
7047
  continue;
6857
7048
  }
6858
- const [minRow, minCol, maxRow, maxCol] = resolveSheetDisplayUsedRange(usedRange, sheetState);
7049
+ const [minRow, minCol, maxRow, maxCol] = resolveSheetDisplayUsedRange(usedRange, effectiveSheetState);
6859
7050
  let visibleRowsCache = null;
6860
7051
  let visibleColsCache = null;
6861
7052
  let rowHeightsCache = null;
@@ -6907,15 +7098,15 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
6907
7098
  colStyleIds: sheetState?.colStyleIds ?? {},
6908
7099
  conditionalFormatRules: sheetState?.conditionalFormatRules ?? [],
6909
7100
  dataValidations: parseWorksheetDataValidations(worksheet),
6910
- defaultColWidthPx: sheetState?.defaultColWidthPx ?? DEFAULT_COL_WIDTH,
6911
- defaultRowHeightPx: sheetState?.defaultRowHeightPx ?? DEFAULT_ROW_HEIGHT,
7101
+ defaultColWidthPx,
7102
+ defaultRowHeightPx,
6912
7103
  freezePanes: parseWorksheetFreezePanes(worksheet),
6913
- hasHorizontalMerges: sheetState?.hasHorizontalMerges ?? false,
6914
- hasVerticalMerges: sheetState?.hasVerticalMerges ?? false,
6915
- maxHorizontalMergeEndCol: sheetState?.maxHorizontalMergeEndCol ?? -1,
6916
- maxVerticalMergeEndRow: sheetState?.maxVerticalMergeEndRow ?? -1,
6917
- hiddenCols: sheetState?.hiddenCols ?? [],
6918
- hiddenRows: sheetState?.hiddenRows ?? [],
7104
+ hasHorizontalMerges: mergeMetadata.hasHorizontalMerges,
7105
+ hasVerticalMerges: mergeMetadata.hasVerticalMerges,
7106
+ maxHorizontalMergeEndCol: mergeMetadata.maxHorizontalMergeEndCol,
7107
+ maxVerticalMergeEndRow: mergeMetadata.maxVerticalMergeEndRow,
7108
+ hiddenCols: resolveWorksheetHiddenCols(worksheet, maxCol),
7109
+ hiddenRows: resolveWorksheetHiddenRows(worksheet, maxRow),
6919
7110
  minUsedCol: minCol,
6920
7111
  minUsedRow: minRow,
6921
7112
  maxUsedCol: maxCol,
@@ -7074,17 +7265,14 @@ function rangeContainsCell(range, cell) {
7074
7265
  const normalized = normalizeRange(range);
7075
7266
  return cell.row >= normalized.start.row && cell.row <= normalized.end.row && cell.col >= normalized.start.col && cell.col <= normalized.end.col;
7076
7267
  }
7077
- function mapWorksheetTables(worksheet, metadataForSheet) {
7268
+ function mapWorksheetTables(worksheet) {
7078
7269
  const rawTables = worksheet?.tables ?? [];
7079
7270
  return rawTables.flatMap((table, index) => {
7080
7271
  const rawColumns = Array.isArray(table.columns) ? table.columns : [];
7081
7272
  const rawName = typeof table.name === "string" ? table.name : `Table${index + 1}`;
7082
7273
  const rawDisplayName = typeof table.displayName === "string" ? table.displayName : typeof table.name === "string" ? table.name : `Table ${index + 1}`;
7083
- const metadata = metadataForSheet?.find(
7084
- (entry) => entry.name && entry.name === rawName || entry.displayName && entry.displayName === rawDisplayName || entry.reference && entry.reference === table.reference
7085
- );
7086
7274
  const rawReference = typeof table.reference === "string" ? table.reference : "";
7087
- const reference = metadata?.reference ?? rawReference;
7275
+ const reference = rawReference;
7088
7276
  const parsedRange = parseA1RangeReference2(reference);
7089
7277
  if (!parsedRange) {
7090
7278
  return [];
@@ -7097,14 +7285,14 @@ function mapWorksheetTables(worksheet, metadataForSheet) {
7097
7285
  })),
7098
7286
  displayName: rawDisplayName,
7099
7287
  end: parsedRange.end,
7100
- headerRowCount: metadata?.headerRowCount ?? resolveWorkbookTableCount(table.headerRowCount, 1),
7101
- headerRowCellStyle: metadata?.headerRowCellStyle,
7288
+ headerRowCount: resolveWorkbookTableCount(table.headerRowCount, 1),
7289
+ headerRowCellStyle: typeof table.headerRowCellStyle === "string" ? table.headerRowCellStyle : void 0,
7102
7290
  name: rawName,
7103
7291
  reference,
7104
7292
  start: parsedRange.start,
7105
7293
  styleInfo: table.styleInfo,
7106
- totalsRowCount: metadata?.totalsRowCount ?? resolveWorkbookTableCount(table.totalsRowCount, 0),
7107
- totalsRowShown: metadata?.totalsRowShown ?? resolveWorkbookTableBoolean(table.totalsRowShown)
7294
+ totalsRowCount: resolveWorkbookTableCount(table.totalsRowCount, 0),
7295
+ totalsRowShown: resolveWorkbookTableBoolean(table.totalsRowShown)
7108
7296
  }];
7109
7297
  });
7110
7298
  }
@@ -7886,6 +8074,7 @@ function useXlsxViewerController(options) {
7886
8074
  const [activeCell, setActiveCell] = React.useState(null);
7887
8075
  const [selection, setSelection] = React.useState(null);
7888
8076
  const [selectedChartId, setSelectedChartId] = React.useState(null);
8077
+ const [selectedChartElement, setSelectedChartElement] = React.useState(null);
7889
8078
  const [selectedImageId, setSelectedImageId] = React.useState(null);
7890
8079
  const [revision, setRevision] = React.useState(0);
7891
8080
  const selectionAnchorRef = React.useRef(null);
@@ -8158,6 +8347,7 @@ function useXlsxViewerController(options) {
8158
8347
  setActiveCell(null);
8159
8348
  setSelection(null);
8160
8349
  setSelectedChartId(null);
8350
+ setSelectedChartElement(null);
8161
8351
  setSelectedImageId(null);
8162
8352
  selectionAnchorRef.current = null;
8163
8353
  undoStackRef.current = [];
@@ -8186,6 +8376,7 @@ function useXlsxViewerController(options) {
8186
8376
  setActiveCell(null);
8187
8377
  setSelection(null);
8188
8378
  setSelectedChartId(null);
8379
+ setSelectedChartElement(null);
8189
8380
  setSelectedImageId(null);
8190
8381
  selectionAnchorRef.current = null;
8191
8382
  undoStackRef.current = [];
@@ -8337,6 +8528,7 @@ function useXlsxViewerController(options) {
8337
8528
  setActiveCell(null);
8338
8529
  setSelection(null);
8339
8530
  setSelectedChartId(null);
8531
+ setSelectedChartElement(null);
8340
8532
  setSelectedImageId(null);
8341
8533
  selectionAnchorRef.current = null;
8342
8534
  setSortState(null);
@@ -8579,10 +8771,9 @@ function useXlsxViewerController(options) {
8579
8771
  }
8580
8772
  return workbook.getSheet(activeSheet.workbookSheetIndex);
8581
8773
  }, [activeSheet, workbook]);
8582
- const activeTableMetadata = imageAssetsRef.current?.tableMetadataByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? null;
8583
8774
  const tables = React.useMemo(
8584
- () => isWorkerBacked ? workerTablesByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? [] : mapWorksheetTables(getActiveWorksheet(), activeTableMetadata),
8585
- [activeSheet?.workbookSheetIndex, activeTableMetadata, getActiveWorksheet, isWorkerBacked, revision, workerTablesByWorkbookSheetIndex]
8775
+ () => isWorkerBacked ? workerTablesByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? [] : mapWorksheetTables(getActiveWorksheet()),
8776
+ [activeSheet?.workbookSheetIndex, getActiveWorksheet, isWorkerBacked, revision, workerTablesByWorkbookSheetIndex]
8586
8777
  );
8587
8778
  const getCellSnapshotAsync = React.useCallback((workbookSheetIndex, row, col) => {
8588
8779
  if (!isWorkerBacked) {
@@ -8659,12 +8850,49 @@ function useXlsxViewerController(options) {
8659
8850
  () => selectedChartId ? getChartById(selectedChartId) : null,
8660
8851
  [getChartById, selectedChartId]
8661
8852
  );
8853
+ React.useEffect(() => {
8854
+ if (!selectedChartId) {
8855
+ if (selectedChartElement) {
8856
+ setSelectedChartElement(null);
8857
+ }
8858
+ return;
8859
+ }
8860
+ if (!selectedChart) {
8861
+ setSelectedChartId(null);
8862
+ setSelectedChartElement(null);
8863
+ return;
8864
+ }
8865
+ if (!selectedChartElement) {
8866
+ setSelectedChartElement({ chartId: selectedChartId, kind: "chart" });
8867
+ return;
8868
+ }
8869
+ if (selectedChartElement.chartId !== selectedChartId) {
8870
+ setSelectedChartElement({ chartId: selectedChartId, kind: "chart" });
8871
+ return;
8872
+ }
8873
+ if (selectedChartElement.kind !== "chart") {
8874
+ const selectedSeries = selectedChart.series[selectedChartElement.seriesIndex];
8875
+ if (!selectedSeries || selectedSeries.id !== selectedChartElement.seriesId) {
8876
+ setSelectedChartElement({ chartId: selectedChartId, kind: "chart" });
8877
+ }
8878
+ }
8879
+ }, [selectedChart, selectedChartElement, selectedChartId]);
8662
8880
  const selectChart = React.useCallback((id) => {
8663
8881
  setSelectedImageId(null);
8664
8882
  setSelectedChartId(id);
8883
+ setSelectedChartElement(id ? { chartId: id, kind: "chart" } : null);
8665
8884
  }, []);
8666
8885
  const clearSelectedChart = React.useCallback(() => {
8667
8886
  setSelectedChartId(null);
8887
+ setSelectedChartElement(null);
8888
+ }, []);
8889
+ const clearSelectedChartElement = React.useCallback(() => {
8890
+ setSelectedChartElement(selectedChartId ? { chartId: selectedChartId, kind: "chart" } : null);
8891
+ }, [selectedChartId]);
8892
+ const selectChartElement = React.useCallback((selection2) => {
8893
+ setSelectedImageId(null);
8894
+ setSelectedChartId(selection2?.chartId ?? null);
8895
+ setSelectedChartElement(selection2);
8668
8896
  }, []);
8669
8897
  const getSheetImages = React.useCallback((sheetIndex = activeSheetIndex) => {
8670
8898
  const targetSheet = sheets[sheetIndex];
@@ -8711,6 +8939,7 @@ function useXlsxViewerController(options) {
8711
8939
  );
8712
8940
  const selectImage = React.useCallback((id) => {
8713
8941
  setSelectedChartId(null);
8942
+ setSelectedChartElement(null);
8714
8943
  setSelectedImageId(id);
8715
8944
  }, []);
8716
8945
  const clearSelectedImage = React.useCallback(() => {
@@ -8935,10 +9164,32 @@ function useXlsxViewerController(options) {
8935
9164
  () => getCellDisplayValue2(deferredMetadataCell),
8936
9165
  [deferredMetadataCell, getCellDisplayValue2, revision, workerCellSnapshotRevision]
8937
9166
  );
8938
- const selectedFormula = React.useMemo(
9167
+ const selectedCellFormula = React.useMemo(
8939
9168
  () => getCellFormula(deferredMetadataCell),
8940
9169
  [deferredMetadataCell, getCellFormula, revision, workerCellSnapshotRevision]
8941
9170
  );
9171
+ const getChartSeriesFormula = React.useCallback((chartId, seriesIndex) => buildChartSeriesFormula(getChartById(chartId), seriesIndex), [getChartById]);
9172
+ const selectedChartFormula = React.useMemo(() => {
9173
+ if (!selectedChartElement || selectedChartElement.kind === "chart" || selectedChartElement.seriesIndex < 0) {
9174
+ return null;
9175
+ }
9176
+ return getChartSeriesFormula(selectedChartElement.chartId, selectedChartElement.seriesIndex);
9177
+ }, [getChartSeriesFormula, selectedChartElement]);
9178
+ const selectedFormulaTarget = React.useMemo(() => {
9179
+ if (selectedChartFormula && selectedChartElement && selectedChartElement.kind !== "chart") {
9180
+ return {
9181
+ chartId: selectedChartElement.chartId,
9182
+ kind: "chartSeries",
9183
+ seriesId: selectedChartElement.seriesId,
9184
+ seriesIndex: selectedChartElement.seriesIndex
9185
+ };
9186
+ }
9187
+ return {
9188
+ cell: deferredMetadataCell,
9189
+ kind: "cell"
9190
+ };
9191
+ }, [deferredMetadataCell, selectedChartElement, selectedChartFormula]);
9192
+ const selectedFormula = selectedChartFormula ?? selectedCellFormula;
8942
9193
  const isLoadDeferred = deferredLoadFileSize !== null;
8943
9194
  const canLoadDeferred = !isLoading && isLoadDeferred;
8944
9195
  const canUndo = !readOnly && undoStackRef.current.length > 0;
@@ -9481,8 +9732,32 @@ function useXlsxViewerController(options) {
9481
9732
  setChartsByWorkbookSheetIndex((current) => current.map((sheetCharts) => sheetCharts.map((chart) => chart.id === id ? { ...chart, ...patch } : chart)));
9482
9733
  setRevision((current) => current + 1);
9483
9734
  }, [ensureChartAssetsHydrated, getChartById, readOnly, recordHistoryBeforeMutation, sheets, workbook]);
9735
+ const setChartSeriesFormula = React.useCallback((chartId, seriesIndex, formula) => {
9736
+ if (readOnly) {
9737
+ return false;
9738
+ }
9739
+ const chart = getChartById(chartId);
9740
+ if (!chart || chart.editable === false) {
9741
+ return false;
9742
+ }
9743
+ const nextChart = applyChartSeriesFormula(chart, seriesIndex, formula, workbook);
9744
+ if (!nextChart) {
9745
+ return false;
9746
+ }
9747
+ updateChart(chartId, { series: nextChart.series });
9748
+ const selectedSeries = nextChart.series[seriesIndex];
9749
+ if (selectedSeries) {
9750
+ setSelectedChartElement((current) => current && current.chartId === chartId && current.kind !== "chart" ? {
9751
+ ...current,
9752
+ seriesId: selectedSeries.id,
9753
+ seriesIndex
9754
+ } : current);
9755
+ }
9756
+ return true;
9757
+ }, [getChartById, readOnly, updateChart, workbook]);
9484
9758
  const selectCell = React.useCallback((cell, options2) => {
9485
9759
  setSelectedChartId(null);
9760
+ setSelectedChartElement(null);
9486
9761
  setSelectedImageId(null);
9487
9762
  setActiveCell(cell);
9488
9763
  if (options2?.extend && selectionAnchorRef.current) {
@@ -9495,6 +9770,7 @@ function useXlsxViewerController(options) {
9495
9770
  const selectRange = React.useCallback((range) => {
9496
9771
  const normalized = normalizeRange(range);
9497
9772
  setSelectedChartId(null);
9773
+ setSelectedChartElement(null);
9498
9774
  setSelectedImageId(null);
9499
9775
  selectionAnchorRef.current = normalized.start;
9500
9776
  setActiveCell(normalized.end);
@@ -9505,6 +9781,7 @@ function useXlsxViewerController(options) {
9505
9781
  setActiveCell(null);
9506
9782
  setSelection(null);
9507
9783
  setSelectedChartId(null);
9784
+ setSelectedChartElement(null);
9508
9785
  setSelectedImageId(null);
9509
9786
  }, []);
9510
9787
  const clearSelectedCells = React.useCallback(() => {
@@ -9622,6 +9899,16 @@ function useXlsxViewerController(options) {
9622
9899
  }
9623
9900
  setCellFormula(activeCell, formula);
9624
9901
  }, [activeCell, setCellFormula]);
9902
+ const setSelectedFormula = React.useCallback((formula) => {
9903
+ if (selectedFormulaTarget?.kind === "chartSeries") {
9904
+ return setChartSeriesFormula(selectedFormulaTarget.chartId, selectedFormulaTarget.seriesIndex, formula);
9905
+ }
9906
+ if (!activeCell) {
9907
+ return false;
9908
+ }
9909
+ setCellFormula(activeCell, formula);
9910
+ return true;
9911
+ }, [activeCell, selectedFormulaTarget, setCellFormula, setChartSeriesFormula]);
9625
9912
  const setSelectedCellStyle = React.useCallback((style) => {
9626
9913
  if (!activeCell) {
9627
9914
  return;
@@ -10098,6 +10385,7 @@ function useXlsxViewerController(options) {
10098
10385
  charts,
10099
10386
  chartsheets,
10100
10387
  clearSelectedChart,
10388
+ clearSelectedChartElement,
10101
10389
  clearSelectedCells,
10102
10390
  clearSelectedImage,
10103
10391
  clearSelection,
@@ -10114,6 +10402,7 @@ function useXlsxViewerController(options) {
10114
10402
  fillSelection,
10115
10403
  formControls,
10116
10404
  getChartById,
10405
+ getChartSeriesFormula,
10117
10406
  getChartsheetById,
10118
10407
  getImageById,
10119
10408
  getSheetCharts,
@@ -10154,18 +10443,25 @@ function useXlsxViewerController(options) {
10154
10443
  setCellStyle,
10155
10444
  setCellValue,
10156
10445
  setRangeStyle,
10446
+ setSelectedFormula,
10157
10447
  setZoomScale,
10158
10448
  setChartRect,
10449
+ setChartSeriesFormula,
10159
10450
  setImageRect,
10160
10451
  selectedChart,
10452
+ selectedChartElement,
10453
+ selectedChartFormula,
10161
10454
  selectedChartId,
10455
+ selectedCellFormula,
10162
10456
  selectedFormula,
10457
+ selectedFormulaTarget,
10163
10458
  selectedImage,
10164
10459
  selectedImageId,
10165
10460
  selectedRangeAddress,
10166
10461
  selectedValue,
10167
10462
  selectCell,
10168
10463
  selectChart,
10464
+ selectChartElement,
10169
10465
  selectImage,
10170
10466
  selectRange,
10171
10467
  selection,
@@ -10205,6 +10501,7 @@ function useXlsxViewerController(options) {
10205
10501
  charts,
10206
10502
  chartsheets,
10207
10503
  clearSelectedChart,
10504
+ clearSelectedChartElement,
10208
10505
  clearSelectedCells,
10209
10506
  clearSelectedImage,
10210
10507
  continueDeferredLoad,
@@ -10221,6 +10518,7 @@ function useXlsxViewerController(options) {
10221
10518
  fillSelection,
10222
10519
  formControls,
10223
10520
  getChartById,
10521
+ getChartSeriesFormula,
10224
10522
  getChartsheetById,
10225
10523
  getImageById,
10226
10524
  getSheetCharts,
@@ -10259,18 +10557,25 @@ function useXlsxViewerController(options) {
10259
10557
  setCellStyle,
10260
10558
  setCellValue,
10261
10559
  setRangeStyle,
10560
+ setSelectedFormula,
10262
10561
  setZoomScale,
10263
10562
  setChartRect,
10563
+ setChartSeriesFormula,
10264
10564
  setImageRect,
10265
10565
  selectedChart,
10566
+ selectedChartElement,
10567
+ selectedChartFormula,
10266
10568
  selectedChartId,
10569
+ selectedCellFormula,
10267
10570
  selectedFormula,
10571
+ selectedFormulaTarget,
10268
10572
  selectedImage,
10269
10573
  selectedImageId,
10270
10574
  selectedRangeAddress,
10271
10575
  selectedValue,
10272
10576
  selectCell,
10273
10577
  selectChart,
10578
+ selectChartElement,
10274
10579
  selectImage,
10275
10580
  selectRange,
10276
10581
  selection,
@@ -11058,6 +11363,8 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11058
11363
  chart,
11059
11364
  fontFamily,
11060
11365
  layout,
11366
+ onDoubleClick,
11367
+ onPointerDown,
11061
11368
  overlay,
11062
11369
  palette,
11063
11370
  fallback
@@ -11253,7 +11560,7 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11253
11560
  fontFamily,
11254
11561
  height: "100%",
11255
11562
  overflow: "hidden",
11256
- pointerEvents: "none",
11563
+ pointerEvents: "auto",
11257
11564
  position: "relative",
11258
11565
  width: "100%"
11259
11566
  },
@@ -11274,6 +11581,8 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11274
11581
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
11275
11582
  "svg",
11276
11583
  {
11584
+ onDoubleClick,
11585
+ onPointerDown,
11277
11586
  style: { display: "block", height: "100%", inset: 0, position: "absolute", width: "100%" },
11278
11587
  viewBox: `0 0 ${layout.width} ${layout.height}`,
11279
11588
  children: [
@@ -11285,10 +11594,104 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11285
11594
  ]
11286
11595
  }
11287
11596
  );
11288
- }, (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);
11597
+ }, (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);
11289
11598
 
11290
11599
  // src/chart-renderer.tsx
11291
11600
  var import_jsx_runtime2 = require("react/jsx-runtime");
11601
+ var import_react = require("react");
11602
+ function chartElementDataProps(seriesIndex, pointIndex, options) {
11603
+ return {
11604
+ "data-xlsx-chart-point-index": typeof pointIndex === "number" ? String(pointIndex) : void 0,
11605
+ "data-xlsx-chart-selection-mode": options?.selectionMode,
11606
+ "data-xlsx-chart-series-index": String(seriesIndex),
11607
+ style: {
11608
+ cursor: "pointer",
11609
+ pointerEvents: "all"
11610
+ }
11611
+ };
11612
+ }
11613
+ function barChartElementDataProps(seriesIndex, pointIndex) {
11614
+ return chartElementDataProps(seriesIndex, pointIndex, { selectionMode: "seriesFirst" });
11615
+ }
11616
+ function resolveChartElementTarget(target) {
11617
+ if (!(target instanceof Element)) {
11618
+ return null;
11619
+ }
11620
+ return target.closest("[data-xlsx-chart-series-index]");
11621
+ }
11622
+ function resolveChartSelectionFromTarget(chart, target, selectedChartElement) {
11623
+ const element = resolveChartElementTarget(target);
11624
+ if (!element) {
11625
+ return selectedChartElement?.chartId === chart.id ? { chartId: chart.id, kind: "chart" } : { chartId: chart.id, kind: "chart" };
11626
+ }
11627
+ const seriesIndex = Number(element.dataset.xlsxChartSeriesIndex);
11628
+ if (!Number.isInteger(seriesIndex) || seriesIndex < 0 || seriesIndex >= chart.series.length) {
11629
+ return null;
11630
+ }
11631
+ const series = chart.series[seriesIndex];
11632
+ if (!series) {
11633
+ return null;
11634
+ }
11635
+ const rawPointIndex = element.dataset.xlsxChartPointIndex;
11636
+ const rawElementKind = element.dataset.xlsxChartElementKind;
11637
+ const selectionMode = element.dataset.xlsxChartSelectionMode;
11638
+ const pointIndex = rawPointIndex == null || rawPointIndex === "" ? null : Number(rawPointIndex);
11639
+ const hasPoint = pointIndex != null && Number.isInteger(pointIndex) && pointIndex >= 0;
11640
+ const sameSelectedSeries = selectedChartElement?.chartId === chart.id && selectedChartElement.kind !== "chart" && selectedChartElement.seriesIndex === seriesIndex;
11641
+ if (hasPoint && (selectionMode !== "seriesFirst" || sameSelectedSeries)) {
11642
+ return {
11643
+ chartId: chart.id,
11644
+ kind: "point",
11645
+ pointIndex,
11646
+ seriesId: series.id,
11647
+ seriesIndex
11648
+ };
11649
+ }
11650
+ return {
11651
+ chartId: chart.id,
11652
+ kind: rawElementKind === "legendEntry" ? "legendEntry" : "series",
11653
+ seriesId: series.id,
11654
+ seriesIndex
11655
+ };
11656
+ }
11657
+ function isSelectedChartSeries(selectedChartElement, chartId, seriesIndex) {
11658
+ return selectedChartElement?.chartId === chartId && selectedChartElement.kind !== "chart" && selectedChartElement.seriesIndex === seriesIndex;
11659
+ }
11660
+ function isSelectedChartPoint(selectedChartElement, chartId, seriesIndex, pointIndex) {
11661
+ return selectedChartElement?.chartId === chartId && selectedChartElement.kind === "point" && selectedChartElement.seriesIndex === seriesIndex && selectedChartElement.pointIndex === pointIndex;
11662
+ }
11663
+ function isSelectedChartPointOrSeries(selectedChartElement, chartId, seriesIndex, pointIndex) {
11664
+ return isSelectedChartPoint(selectedChartElement, chartId, seriesIndex, pointIndex) || isSelectedChartSeries(selectedChartElement, chartId, seriesIndex) && selectedChartElement?.kind !== "point";
11665
+ }
11666
+ function renderSelectionRectHandles(key, left, top, width, height, color = "#64748b") {
11667
+ return renderSelectionPointHandles(
11668
+ key,
11669
+ [
11670
+ { x: left, y: top },
11671
+ { x: left + width, y: top },
11672
+ { x: left, y: top + height },
11673
+ { x: left + width, y: top + height }
11674
+ ],
11675
+ color
11676
+ );
11677
+ }
11678
+ function renderSelectionPointHandles(key, points, color = "#64748b") {
11679
+ const radius = 3;
11680
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { pointerEvents: "none", children: points.map((point, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
11681
+ "circle",
11682
+ {
11683
+ cx: point.x,
11684
+ cy: point.y,
11685
+ fill: "#ffffff",
11686
+ r: radius,
11687
+ stroke: color,
11688
+ strokeWidth: 1.1,
11689
+ style: { filter: "drop-shadow(0 1px 2px rgba(15, 23, 42, 0.18))" },
11690
+ vectorEffect: "non-scaling-stroke"
11691
+ },
11692
+ `${key}-handle-${index}`
11693
+ )) }, key);
11694
+ }
11292
11695
  var WORLD_COUNTRY_FEATURES = (0, import_topojson_client.feature)(
11293
11696
  countries_50m_default,
11294
11697
  countries_50m_default.objects.countries
@@ -12986,10 +13389,17 @@ function renderLegend(chart, layout, palette) {
12986
13389
  const startY = layout.plot.top + 6;
12987
13390
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { children: items.map((item, index) => {
12988
13391
  const y = startY + index * 18;
12989
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { transform: `translate(${x}, ${y})`, children: [
13392
+ return /* @__PURE__ */ (0, import_react.createElement)(
13393
+ "g",
13394
+ {
13395
+ ...index < chart.series.length ? chartElementDataProps(index) : {},
13396
+ "data-xlsx-chart-element-kind": index < chart.series.length ? "legendEntry" : void 0,
13397
+ key: `legend-${index}`,
13398
+ transform: `translate(${x}, ${y})`
13399
+ },
12990
13400
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { fill: item.color, height: swatchSize, rx: 1.2, ry: 1.2, width: swatchSize, x: 0, y: -7 }),
12991
13401
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { fill: textColor, fontSize: 10, x: textOffset, y: 0, children: item.label })
12992
- ] }, `legend-${index}`);
13402
+ );
12993
13403
  }) });
12994
13404
  }
12995
13405
  const rowY = legendPos === "top" ? layout.titleHeight + 12 : layout.height - 8;
@@ -12997,10 +13407,17 @@ function renderLegend(chart, layout, palette) {
12997
13407
  let cursorX = Math.max(8, (layout.width - totalWidth) / 2);
12998
13408
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { children: items.map((item, index) => {
12999
13409
  const labelWidth = Math.min(96, item.label.length * 5.4);
13000
- const node = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { transform: `translate(${cursorX}, ${rowY})`, children: [
13410
+ const node = /* @__PURE__ */ (0, import_react.createElement)(
13411
+ "g",
13412
+ {
13413
+ ...index < chart.series.length ? chartElementDataProps(index) : {},
13414
+ "data-xlsx-chart-element-kind": index < chart.series.length ? "legendEntry" : void 0,
13415
+ key: `legend-${index}`,
13416
+ transform: `translate(${cursorX}, ${rowY})`
13417
+ },
13001
13418
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { fill: item.color, height: swatchSize, rx: 1.2, ry: 1.2, width: swatchSize, x: 0, y: -7 }),
13002
13419
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { fill: textColor, fontSize: 10, x: textOffset, y: 0, children: item.label })
13003
- ] }, `legend-${index}`);
13420
+ );
13004
13421
  cursorX += 24 + labelWidth;
13005
13422
  return node;
13006
13423
  }) });
@@ -13327,7 +13744,7 @@ function projectCartesian3dPoint2(x, y, z, rotXRad, rotYRad, usePerspective, per
13327
13744
  y: y1 * perspective
13328
13745
  };
13329
13746
  }
13330
- function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPointsBySeries, minValue, maxValue, isAreaChart, isStackedSeries) {
13747
+ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPointsBySeries, minValue, maxValue, isAreaChart, isStackedSeries, selectedChartElement) {
13331
13748
  const plot = layout.plot;
13332
13749
  const valueDomain = resolveAxisDomainWithChartOverrides(
13333
13750
  chart.valueAxis,
@@ -13394,6 +13811,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13394
13811
  return {
13395
13812
  bottom,
13396
13813
  bottomBack,
13814
+ categoryIndex,
13397
13815
  defined: point.defined,
13398
13816
  depth: top.depth,
13399
13817
  depthBack: topBack?.depth ?? top.depth,
@@ -13429,6 +13847,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13429
13847
  points: series.map((point) => ({
13430
13848
  bottom: toScreenPoint(point.bottom),
13431
13849
  bottomBack: point.bottomBack ? toScreenPoint(point.bottomBack) : null,
13850
+ categoryIndex: point.categoryIndex,
13432
13851
  defined: point.defined,
13433
13852
  top: toScreenPoint(point.top),
13434
13853
  topBack: point.topBack ? toScreenPoint(point.topBack) : null
@@ -13533,6 +13952,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13533
13952
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13534
13953
  "path",
13535
13954
  {
13955
+ ...chartElementDataProps(seriesIndex),
13536
13956
  d: topFace,
13537
13957
  fill: lightenColor2(fillColor, 0.08),
13538
13958
  fillOpacity: 0.8,
@@ -13543,6 +13963,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13543
13963
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13544
13964
  "path",
13545
13965
  {
13966
+ ...chartElementDataProps(seriesIndex),
13546
13967
  d: bottomFace,
13547
13968
  fill: darkenColor2(fillColor, 0.2),
13548
13969
  fillOpacity: 0.34,
@@ -13570,6 +13991,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13570
13991
  isAreaChart && isStackedSeries && areaBackPoints.length >= 3 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13571
13992
  "path",
13572
13993
  {
13994
+ ...chartElementDataProps(seriesIndex),
13573
13995
  d: buildLinearSvgPath(areaBackPoints, true),
13574
13996
  fill: darkenColor2(fillColor, 0.18),
13575
13997
  fillOpacity: 0.44,
@@ -13581,6 +14003,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13581
14003
  startCap ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13582
14004
  "path",
13583
14005
  {
14006
+ ...chartElementDataProps(seriesIndex),
13584
14007
  d: startCap,
13585
14008
  fill: darkenColor2(fillColor, 0.24),
13586
14009
  fillOpacity: 0.54,
@@ -13591,6 +14014,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13591
14014
  endCap ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13592
14015
  "path",
13593
14016
  {
14017
+ ...chartElementDataProps(seriesIndex),
13594
14018
  d: endCap,
13595
14019
  fill: darkenColor2(fillColor, 0.14),
13596
14020
  fillOpacity: 0.6,
@@ -13601,6 +14025,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13601
14025
  isAreaChart && areaPoints.length >= 3 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13602
14026
  "path",
13603
14027
  {
14028
+ ...chartElementDataProps(seriesIndex),
13604
14029
  d: buildLinearSvgPath(areaPoints, true),
13605
14030
  fill: fillColor,
13606
14031
  fillOpacity: 0.74,
@@ -13624,6 +14049,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13624
14049
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13625
14050
  "path",
13626
14051
  {
14052
+ ...chartElementDataProps(seriesIndex),
13627
14053
  d: buildLinearSvgPath(linePoints),
13628
14054
  fill: "none",
13629
14055
  stroke: strokeColor,
@@ -13638,6 +14064,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13638
14064
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13639
14065
  "path",
13640
14066
  {
14067
+ ...chartElementDataProps(seriesIndex, point.categoryIndex),
13641
14068
  d: markerPath,
13642
14069
  fill: chart.series[seriesIndex]?.markerColor ?? fillColor,
13643
14070
  stroke: chart.series[seriesIndex]?.markerLineColor ?? chart.chartAreaFillColor ?? palette.surface,
@@ -13646,7 +14073,23 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13646
14073
  )
13647
14074
  },
13648
14075
  `line3d-marker-${seriesIndex}-${pointIndex}`
13649
- )) : null
14076
+ )) : null,
14077
+ definedPoints.map((point) => /* @__PURE__ */ (0, import_react.createElement)(
14078
+ "circle",
14079
+ {
14080
+ ...chartElementDataProps(seriesIndex, point.categoryIndex),
14081
+ cx: point.top.x,
14082
+ cy: point.top.y,
14083
+ fill: "transparent",
14084
+ key: `line3d-hit-${seriesIndex}-${point.categoryIndex}`,
14085
+ r: 7,
14086
+ stroke: "none"
14087
+ }
14088
+ )),
14089
+ definedPoints.map((point) => isSelectedChartPointOrSeries(selectedChartElement, chart.id, seriesIndex, point.categoryIndex) ? renderSelectionPointHandles(
14090
+ `line3d-selection-${seriesIndex}-${point.categoryIndex}`,
14091
+ [{ x: point.top.x, y: point.top.y }]
14092
+ ) : null)
13650
14093
  ] }, `line3d-series-${seriesIndex}`);
13651
14094
  }),
13652
14095
  yLabelPoints.map(({ point, tick }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -13675,7 +14118,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13675
14118
  ))
13676
14119
  ] });
13677
14120
  }
13678
- function renderBarChart(chart, palette, layout, chartType) {
14121
+ function renderBarChart(chart, palette, layout, chartType, selectedChartElement) {
13679
14122
  if (chart.series.length === 0) {
13680
14123
  return null;
13681
14124
  }
@@ -14056,9 +14499,11 @@ function renderBarChart(chart, palette, layout, chartType) {
14056
14499
  axisNode,
14057
14500
  frameNode,
14058
14501
  depthAxisNode,
14059
- chart.is3d ? sortedBars.map((bar) => renderExtrudedRect(bar)) : renderedBars.map((bar) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14502
+ chart.is3d ? sortedBars.map((bar) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { ...barChartElementDataProps(bar.seriesIndex, bar.categoryIndex), children: renderExtrudedRect(bar) }, `bar-hit-${bar.key}`)) : renderedBars.map((bar) => /* @__PURE__ */ (0, import_react.createElement)(
14060
14503
  "rect",
14061
14504
  {
14505
+ ...barChartElementDataProps(bar.seriesIndex, bar.categoryIndex),
14506
+ key: bar.key,
14062
14507
  fill: bar.color,
14063
14508
  height: bar.height,
14064
14509
  stroke: isHistogramLike ? "none" : bar.stroke,
@@ -14066,12 +14511,12 @@ function renderBarChart(chart, palette, layout, chartType) {
14066
14511
  width: bar.width,
14067
14512
  x: bar.left,
14068
14513
  y: bar.top
14069
- },
14070
- bar.key
14071
- ))
14514
+ }
14515
+ )),
14516
+ 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)
14072
14517
  ] });
14073
14518
  }
14074
- function renderLineOrAreaChart(chart, palette, layout, chartType) {
14519
+ function renderLineOrAreaChart(chart, palette, layout, chartType, selectedChartElement) {
14075
14520
  if (chart.series.length === 0) {
14076
14521
  return null;
14077
14522
  }
@@ -14182,7 +14627,8 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14182
14627
  minValue,
14183
14628
  maxValue,
14184
14629
  isAreaChart,
14185
- isStackedSeries
14630
+ isStackedSeries,
14631
+ selectedChartElement
14186
14632
  );
14187
14633
  }
14188
14634
  const rawRecord = chart.raw && typeof chart.raw === "object" ? chart.raw : null;
@@ -14271,6 +14717,7 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14271
14717
  isAreaChart ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14272
14718
  "path",
14273
14719
  {
14720
+ ...chartElementDataProps(seriesIndex),
14274
14721
  d: areaPath,
14275
14722
  fill: seriesFillColor,
14276
14723
  fillOpacity: 1,
@@ -14280,6 +14727,7 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14280
14727
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14281
14728
  "path",
14282
14729
  {
14730
+ ...chartElementDataProps(seriesIndex),
14283
14731
  d: linePath,
14284
14732
  fill: "none",
14285
14733
  stroke: chartSeriesStrokeColor(chart, seriesIndex),
@@ -14288,23 +14736,31 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14288
14736
  strokeWidth: Math.max(1.5, series.lineWidthPx ?? 2)
14289
14737
  }
14290
14738
  ),
14291
- points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14739
+ points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ (0, import_react.createElement)(
14292
14740
  "circle",
14293
14741
  {
14742
+ ...chartElementDataProps(seriesIndex, pointIndex),
14743
+ key: `line-marker-${seriesIndex}-${pointIndex}`,
14294
14744
  cx: point.x,
14295
14745
  cy: yScale(point.y),
14296
14746
  fill: series.markerColor ?? chartSeriesColor(chart, seriesIndex),
14297
14747
  r: Math.max(2, (series.markerSize ?? 6) * 0.25),
14298
14748
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? chartSeriesStrokeColor(chart, seriesIndex),
14299
14749
  strokeWidth: 1
14300
- },
14301
- `line-marker-${seriesIndex}-${pointIndex}`
14302
- ))
14750
+ }
14751
+ )),
14752
+ 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(
14753
+ `line-selection-${seriesIndex}-${pointIndex}`,
14754
+ point.x - 4,
14755
+ yScale(point.y) - 4,
14756
+ 8,
14757
+ 8
14758
+ ) : null)
14303
14759
  ] }, `line-series-${seriesIndex}`);
14304
14760
  })
14305
14761
  ] });
14306
14762
  }
14307
- function renderComboChart(chart, palette, layout) {
14763
+ function renderComboChart(chart, palette, layout, selectedChartElement) {
14308
14764
  const groups = buildComboGroups(chart);
14309
14765
  const columnGroup = groups.find((group) => group.chartType.startsWith("Column"));
14310
14766
  const lineGroup = groups.find((group) => group.chartType.startsWith("Line"));
@@ -14331,6 +14787,10 @@ function renderComboChart(chart, palette, layout) {
14331
14787
  const categoryScale = (0, import_d3_scale.scaleBand)().domain(categories).range([plot.left, plot.left + plot.width]).paddingInner(categoryBandPadding.inner).paddingOuter(categoryBandPadding.outer);
14332
14788
  const seriesScale = (0, import_d3_scale.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);
14333
14789
  const categoryPositions = categories.map((category) => (categoryScale(category) ?? plot.left) + categoryScale.bandwidth() / 2);
14790
+ const resolveGlobalSeriesIndex = (series) => {
14791
+ const index = chart.series.findIndex((candidate) => candidate.id === series.id);
14792
+ return index >= 0 ? index : 0;
14793
+ };
14334
14794
  const primaryValues = columnGroup.series.flatMap((series) => series.values.map((value) => safeNumber2(value)).filter((value) => value != null));
14335
14795
  const secondaryValues = lineGroup.series.flatMap((series) => series.values.map((value) => safeNumber2(value)).filter((value) => value != null));
14336
14796
  if (primaryValues.length === 0 || secondaryValues.length === 0) {
@@ -14390,6 +14850,7 @@ function renderComboChart(chart, palette, layout) {
14390
14850
  }
14391
14851
  ),
14392
14852
  columnGroup.series.flatMap((series, seriesIndex) => categories.map((category, categoryIndex) => {
14853
+ const globalSeriesIndex = resolveGlobalSeriesIndex(series);
14393
14854
  const value = safeNumber2(series.values[categoryIndex]) ?? 0;
14394
14855
  const categoryStart = categoryScale(category) ?? plot.left;
14395
14856
  const barWidth = Math.max(1, histogramColumns ? categoryScale.bandwidth() : seriesScale.bandwidth());
@@ -14397,21 +14858,32 @@ function renderComboChart(chart, palette, layout) {
14397
14858
  const y = primaryScale(Math.max(0, value));
14398
14859
  const zeroY = primaryScale(0);
14399
14860
  const height = Math.max(1, Math.abs(zeroY - primaryScale(value)));
14400
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14401
- "rect",
14402
- {
14403
- fill: series.color ?? series.lineColor ?? chartSeriesColor(primaryChart, seriesIndex),
14404
- height,
14405
- stroke: histogramColumns ? "none" : series.lineColor ?? series.color ?? chartSeriesStrokeColor(primaryChart, seriesIndex),
14406
- strokeWidth: histogramColumns ? 0 : 1,
14407
- width: barWidth,
14861
+ const selected = isSelectedChartPoint(selectedChartElement, chart.id, globalSeriesIndex, categoryIndex) || isSelectedChartSeries(selectedChartElement, chart.id, globalSeriesIndex) && selectedChartElement?.kind !== "point";
14862
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(React3.Fragment, { children: [
14863
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14864
+ "rect",
14865
+ {
14866
+ ...barChartElementDataProps(globalSeriesIndex, categoryIndex),
14867
+ fill: series.color ?? series.lineColor ?? chartSeriesColor(primaryChart, seriesIndex),
14868
+ height,
14869
+ stroke: selected ? "#64748b" : histogramColumns ? "none" : series.lineColor ?? series.color ?? chartSeriesStrokeColor(primaryChart, seriesIndex),
14870
+ strokeWidth: selected ? 2 : histogramColumns ? 0 : 1,
14871
+ width: barWidth,
14872
+ x,
14873
+ y: Math.min(y, zeroY)
14874
+ }
14875
+ ),
14876
+ selected ? renderSelectionRectHandles(
14877
+ `combo-bar-selection-${globalSeriesIndex}-${categoryIndex}`,
14408
14878
  x,
14409
- y: Math.min(y, zeroY)
14410
- },
14411
- `combo-bar-${seriesIndex}-${categoryIndex}`
14412
- );
14879
+ Math.min(y, zeroY),
14880
+ barWidth,
14881
+ height
14882
+ ) : null
14883
+ ] }, `combo-bar-${seriesIndex}-${categoryIndex}`);
14413
14884
  })),
14414
14885
  lineGroup.series.map((series, seriesIndex) => {
14886
+ const globalSeriesIndex = resolveGlobalSeriesIndex(series);
14415
14887
  const points = categories.map((category, categoryIndex) => ({
14416
14888
  x: (categoryScale(category) ?? plot.left) + categoryScale.bandwidth() / 2,
14417
14889
  y: safeNumber2(series.values[categoryIndex])
@@ -14422,6 +14894,7 @@ function renderComboChart(chart, palette, layout) {
14422
14894
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14423
14895
  "path",
14424
14896
  {
14897
+ ...chartElementDataProps(globalSeriesIndex),
14425
14898
  d: path,
14426
14899
  fill: "none",
14427
14900
  stroke: series.lineColor ?? series.color ?? chartSeriesStrokeColor(chart, columnGroup.series.length + seriesIndex),
@@ -14430,22 +14903,30 @@ function renderComboChart(chart, palette, layout) {
14430
14903
  strokeWidth: Math.max(1.5, series.lineWidthPx ?? 2)
14431
14904
  }
14432
14905
  ),
14433
- points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14906
+ points.map((point, pointIndex) => point.y == null ? null : /* @__PURE__ */ (0, import_react.createElement)(
14434
14907
  "path",
14435
14908
  {
14909
+ ...chartElementDataProps(globalSeriesIndex, pointIndex),
14436
14910
  d: markerSymbolPath(normalizeChartMarkerSymbol(series.markerSymbol), Math.max(4, series.markerSize ?? 7)) || markerSymbolPath("circle", 7),
14437
14911
  fill: series.markerColor ?? series.color ?? series.lineColor ?? chartSeriesColor(chart, columnGroup.series.length + seriesIndex),
14912
+ key: `combo-line-marker-${seriesIndex}-${pointIndex}`,
14438
14913
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? "#ffffff",
14439
14914
  strokeWidth: 1,
14440
14915
  transform: `translate(${point.x}, ${secondaryScale(point.y)})`
14441
- },
14442
- `combo-line-marker-${seriesIndex}-${pointIndex}`
14443
- ))
14916
+ }
14917
+ )),
14918
+ points.map((point, pointIndex) => point.y != null && isSelectedChartPointOrSeries(selectedChartElement, chart.id, globalSeriesIndex, pointIndex) ? renderSelectionRectHandles(
14919
+ `combo-line-selection-${globalSeriesIndex}-${pointIndex}`,
14920
+ point.x - 4,
14921
+ secondaryScale(point.y) - 4,
14922
+ 8,
14923
+ 8
14924
+ ) : null)
14444
14925
  ] }, `combo-line-${seriesIndex}`);
14445
14926
  })
14446
14927
  ] });
14447
14928
  }
14448
- function renderScatterChart(chart, palette, layout, smooth) {
14929
+ function renderScatterChart(chart, palette, layout, smooth, selectedChartElement) {
14449
14930
  const plot = layout.plot;
14450
14931
  const rawRecord = chart.raw && typeof chart.raw === "object" ? chart.raw : null;
14451
14932
  const normalizedTitle = typeof chart.title === "string" ? chart.title.trim().toLowerCase() : "";
@@ -14631,6 +15112,7 @@ function renderScatterChart(chart, palette, layout, smooth) {
14631
15112
  shouldDrawLine && linePath.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14632
15113
  "path",
14633
15114
  {
15115
+ ...chartElementDataProps(seriesIndex),
14634
15116
  d: linePath,
14635
15117
  fill: "none",
14636
15118
  stroke: series.lineColor ?? chartSeriesStrokeColor(chart, seriesIndex),
@@ -14650,6 +15132,7 @@ function renderScatterChart(chart, palette, layout, smooth) {
14650
15132
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14651
15133
  "path",
14652
15134
  {
15135
+ ...chartElementDataProps(seriesIndex, pointIndex, { selectionMode: "seriesFirst" }),
14653
15136
  d: markerPath,
14654
15137
  fill: markerFill,
14655
15138
  stroke: "none",
@@ -14659,12 +15142,16 @@ function renderScatterChart(chart, palette, layout, smooth) {
14659
15142
  },
14660
15143
  `scatter-point-${seriesIndex}-${pointIndex}`
14661
15144
  );
14662
- })
15145
+ }),
15146
+ seriesPoints.points.map((point, pointIndex) => isSelectedChartPoint(selectedChartElement, chart.id, seriesIndex, pointIndex) || isSelectedChartSeries(selectedChartElement, chart.id, seriesIndex) && selectedChartElement?.kind !== "point" ? renderSelectionPointHandles(
15147
+ `scatter-selection-${seriesIndex}-${pointIndex}`,
15148
+ [{ x: xScale(point.x), y: yScale(point.y) }]
15149
+ ) : null)
14663
15150
  ] }, `scatter-series-${seriesIndex}`);
14664
15151
  })
14665
15152
  ] });
14666
15153
  }
14667
- function renderBubbleChart(chart, palette, layout) {
15154
+ function renderBubbleChart(chart, palette, layout, selectedChartElement) {
14668
15155
  const plot = layout.plot;
14669
15156
  const pointsBySeries = chart.series.map((series) => series.values.map((value, index) => {
14670
15157
  const x = safeNumber2(series.categories[index]);
@@ -14784,6 +15271,7 @@ function renderBubbleChart(chart, palette, layout) {
14784
15271
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14785
15272
  "circle",
14786
15273
  {
15274
+ ...chartElementDataProps(seriesIndex, point.index, { selectionMode: "seriesFirst" }),
14787
15275
  cx: xScale(point.x),
14788
15276
  cy: yScale(point.y),
14789
15277
  fill: isBubble3d ? `url(#bubble3d-grad-${chart.id}-${seriesIndex})` : baseColor,
@@ -14793,6 +15281,13 @@ function renderBubbleChart(chart, palette, layout) {
14793
15281
  strokeWidth: isBubble3d ? 1.2 : 1
14794
15282
  }
14795
15283
  ),
15284
+ isSelectedChartPoint(selectedChartElement, chart.id, seriesIndex, point.index) || isSelectedChartSeries(selectedChartElement, chart.id, seriesIndex) && selectedChartElement?.kind !== "point" ? renderSelectionRectHandles(
15285
+ `bubble-selection-${seriesIndex}-${point.index}`,
15286
+ xScale(point.x) - radius,
15287
+ yScale(point.y) - radius,
15288
+ radius * 2,
15289
+ radius * 2
15290
+ ) : null,
14796
15291
  isBubble3d ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14797
15292
  "ellipse",
14798
15293
  {
@@ -14820,7 +15315,7 @@ function renderBubbleChart(chart, palette, layout) {
14820
15315
  ] }, `bubble-series-${seriesIndex}`))
14821
15316
  ] });
14822
15317
  }
14823
- function renderRadarChart(chart, palette, layout) {
15318
+ function renderRadarChart(chart, palette, layout, selectedChartElement) {
14824
15319
  if (chart.series.length === 0) {
14825
15320
  return null;
14826
15321
  }
@@ -14899,12 +15394,14 @@ function renderRadarChart(chart, palette, layout) {
14899
15394
  if (rawValue == null) {
14900
15395
  return {
14901
15396
  defined: false,
15397
+ pointIndex: categoryIndex,
14902
15398
  ...radialPoint(categoryIndex, 0)
14903
15399
  };
14904
15400
  }
14905
15401
  const ratio = clamp2((rawValue - minValue) / (safeMax - minValue), 0, 1);
14906
15402
  return {
14907
15403
  defined: true,
15404
+ pointIndex: categoryIndex,
14908
15405
  ...radialPoint(categoryIndex, ratio)
14909
15406
  };
14910
15407
  });
@@ -14923,6 +15420,7 @@ function renderRadarChart(chart, palette, layout) {
14923
15420
  definedPoints.length >= 2 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14924
15421
  "path",
14925
15422
  {
15423
+ ...chartElementDataProps(seriesIndex),
14926
15424
  d: polygon,
14927
15425
  fill: filled && !hasGap && definedPoints.length >= 3 ? color : "none",
14928
15426
  fillOpacity: filled ? 0.26 : 0,
@@ -14930,13 +15428,14 @@ function renderRadarChart(chart, palette, layout) {
14930
15428
  strokeWidth: 1.8
14931
15429
  }
14932
15430
  ) : null,
14933
- showMarkers ? definedPoints.map((point, pointIndex) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15431
+ showMarkers ? definedPoints.map((point) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14934
15432
  "g",
14935
15433
  {
14936
15434
  transform: `translate(${point.x}, ${point.y})`,
14937
15435
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14938
15436
  "path",
14939
15437
  {
15438
+ ...chartElementDataProps(seriesIndex, point.pointIndex),
14940
15439
  d: markerPath,
14941
15440
  fill: series.markerColor ?? color,
14942
15441
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? palette.surface,
@@ -14944,13 +15443,17 @@ function renderRadarChart(chart, palette, layout) {
14944
15443
  }
14945
15444
  )
14946
15445
  },
14947
- `radar-point-${seriesIndex}-${pointIndex}`
14948
- )) : null
15446
+ `radar-point-${seriesIndex}-${point.pointIndex}`
15447
+ )) : null,
15448
+ definedPoints.map((point) => isSelectedChartPoint(selectedChartElement, chart.id, seriesIndex, point.pointIndex) || isSelectedChartSeries(selectedChartElement, chart.id, seriesIndex) && selectedChartElement?.kind !== "point" ? renderSelectionPointHandles(
15449
+ `radar-selection-${seriesIndex}-${point.pointIndex}`,
15450
+ [{ x: point.x, y: point.y }]
15451
+ ) : null)
14949
15452
  ] }, `radar-series-${seriesIndex}`);
14950
15453
  })
14951
15454
  ] });
14952
15455
  }
14953
- function renderPieChart(chart, palette, layout, chartType) {
15456
+ function renderPieChart(chart, palette, layout, chartType, selectedChartElement) {
14954
15457
  const pieSeriesIndex = selectPrimaryPieSeriesIndex(chart);
14955
15458
  const pieSeries = chart.series[pieSeriesIndex];
14956
15459
  const pieData = buildPieEntries(chart, pieSeriesIndex);
@@ -15102,6 +15605,16 @@ function renderPieChart(chart, palette, layout, chartType) {
15102
15605
  const midAngle = (arc.startAngle + arc.endAngle) / 2;
15103
15606
  const explodeX = Math.sin(midAngle) * explosion;
15104
15607
  const explodeY = -Math.cos(midAngle) * explosion * (isPie3d ? tilt : 1);
15608
+ const isSliceSelected = isSelectedChartPoint(selectedChartElement, chart.id, pieSeriesIndex, arc.data.index) || isSelectedChartSeries(selectedChartElement, chart.id, pieSeriesIndex) && selectedChartElement?.kind !== "point";
15609
+ const sliceHandlePoints = isSliceSelected ? [
15610
+ pieEllipsePoint(centerX, centerY, outerRadius, isPie3d ? tilt : 1, arc.startAngle),
15611
+ pieEllipsePoint(centerX, centerY, outerRadius, isPie3d ? tilt : 1, midAngle),
15612
+ pieEllipsePoint(centerX, centerY, outerRadius, isPie3d ? tilt : 1, arc.endAngle),
15613
+ innerRadius > 0 ? pieEllipsePoint(centerX, centerY, innerRadius, isPie3d ? tilt : 1, midAngle) : { x: centerX, y: centerY }
15614
+ ].map((point) => ({
15615
+ x: point.x + explodeX,
15616
+ y: point.y + explodeY
15617
+ })) : [];
15105
15618
  const labelRadius = outerRadius + (chartType === "PieExploded" ? 8 : 12);
15106
15619
  const labelX = centerX + Math.sin(midAngle) * labelRadius + explodeX;
15107
15620
  const labelY = centerY - Math.cos(midAngle) * labelRadius * (isPie3d ? tilt : 1) + explodeY;
@@ -15135,14 +15648,16 @@ function renderPieChart(chart, palette, layout, chartType) {
15135
15648
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { transform: `translate(${explodeX}, ${explodeY})`, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15136
15649
  "path",
15137
15650
  {
15651
+ ...chartElementDataProps(pieSeriesIndex, arc.data.index),
15138
15652
  d: arcPath(arc) ?? "",
15139
15653
  fill: arc.data.color,
15140
- stroke: sliceSeparatorColor,
15141
- strokeWidth: sliceSeparatorWidth,
15142
- transform: `translate(${centerX}, ${centerY})${isPie3d ? ` scale(1, ${tilt})` : ""}`,
15143
- filter: isPie3d ? `url(#${shadowId})` : void 0
15654
+ filter: isPie3d ? `url(#${shadowId})` : void 0,
15655
+ stroke: isSliceSelected ? "#64748b" : sliceSeparatorColor,
15656
+ strokeWidth: isSliceSelected ? Math.max(2, sliceSeparatorWidth) : sliceSeparatorWidth,
15657
+ transform: `translate(${centerX}, ${centerY})${isPie3d ? ` scale(1, ${tilt})` : ""}`
15144
15658
  }
15145
15659
  ) }),
15660
+ isSliceSelected ? renderSelectionPointHandles(`pie-selection-${arc.data.index}`, sliceHandlePoints) : null,
15146
15661
  dataLabelsEnabled && truncatedLabelText.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15147
15662
  "text",
15148
15663
  {
@@ -15170,7 +15685,7 @@ function renderPieChart(chart, palette, layout, chartType) {
15170
15685
  ) : null
15171
15686
  ] });
15172
15687
  }
15173
- function renderBarOfPieChart(chart, palette, layout) {
15688
+ function renderBarOfPieChart(chart, palette, layout, selectedChartElement) {
15174
15689
  const pieSeriesIndex = selectPrimaryPieSeriesIndex(chart);
15175
15690
  const pieSeries = chart.series[pieSeriesIndex];
15176
15691
  const categories = getCategoryLabels(chart);
@@ -15187,10 +15702,11 @@ function renderBarOfPieChart(chart, palette, layout) {
15187
15702
  }
15188
15703
  const secondarySet = new Set(secondaryIndices);
15189
15704
  const secondaryTotal = secondaryIndices.reduce((sum, index) => sum + (values[index] ?? 0), 0);
15190
- const primaryData = values.flatMap((value, index) => secondarySet.has(index) ? [] : [{ color: chartPointColor(chart, index, pieSeriesIndex), label: categories[index], value }]);
15705
+ const primaryData = values.flatMap((value, index) => secondarySet.has(index) ? [] : [{ color: chartPointColor(chart, index, pieSeriesIndex), index, label: categories[index], value }]);
15191
15706
  if (secondaryTotal > 0) {
15192
15707
  primaryData.push({
15193
15708
  color: chartPointColor(chart, secondaryIndices[0] ?? 0, pieSeriesIndex),
15709
+ index: secondaryIndices[0] ?? 0,
15194
15710
  label: "Other",
15195
15711
  value: secondaryTotal
15196
15712
  });
@@ -15205,6 +15721,7 @@ function renderBarOfPieChart(chart, palette, layout) {
15205
15721
  const connectorTargetX = layout.plot.left + layout.plot.width * 0.69;
15206
15722
  const secondaryData = secondaryIndices.map((index) => ({
15207
15723
  color: chartPointColor(chart, index, pieSeriesIndex),
15724
+ index,
15208
15725
  label: categories[index] ?? "",
15209
15726
  value: values[index] ?? 0
15210
15727
  }));
@@ -15220,17 +15737,25 @@ function renderBarOfPieChart(chart, palette, layout) {
15220
15737
  const secondaryTotalSafe = Math.max(1e-6, secondaryTotal);
15221
15738
  let stackCursor = stackedBarTop;
15222
15739
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
15223
- pieArcs.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15224
- "path",
15225
- {
15226
- d: arc(entry) ?? "",
15227
- fill: entry.data.color,
15228
- stroke: chart.chartAreaFillColor ?? palette.surface,
15229
- strokeWidth: 1,
15230
- transform: `translate(${pieCenterX}, ${pieCenterY})`
15231
- },
15232
- `bar-of-pie-main-${index}`
15233
- )),
15740
+ pieArcs.map((entry, index) => {
15741
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, pieSeriesIndex, entry.data.index);
15742
+ const midAngle = (entry.startAngle + entry.endAngle) / 2;
15743
+ const dot = pieEllipsePoint(pieCenterX, pieCenterY, pieRadius * 0.62, 1, midAngle);
15744
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(React3.Fragment, { children: [
15745
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15746
+ "path",
15747
+ {
15748
+ ...chartElementDataProps(pieSeriesIndex, entry.data.index),
15749
+ d: arc(entry) ?? "",
15750
+ fill: entry.data.color,
15751
+ stroke: selected ? "#64748b" : chart.chartAreaFillColor ?? palette.surface,
15752
+ strokeWidth: selected ? 2 : 1,
15753
+ transform: `translate(${pieCenterX}, ${pieCenterY})`
15754
+ }
15755
+ ),
15756
+ selected ? renderSelectionPointHandles(`bar-of-pie-main-selection-${index}`, [dot]) : null
15757
+ ] }, `bar-of-pie-main-${index}`);
15758
+ }),
15234
15759
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15235
15760
  "line",
15236
15761
  {
@@ -15253,33 +15778,50 @@ function renderBarOfPieChart(chart, palette, layout) {
15253
15778
  y2: layout.plot.top + layout.plot.height - 10
15254
15779
  }
15255
15780
  ),
15256
- ofPieType === "pie" ? secondaryPieArcs.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15257
- "path",
15258
- {
15259
- d: secondaryArc(entry) ?? "",
15260
- fill: entry.data.color,
15261
- stroke: chart.chartAreaFillColor ?? palette.surface,
15262
- strokeWidth: 1,
15263
- transform: `translate(${secondaryCenterX}, ${secondaryCenterY})`
15264
- },
15265
- `bar-of-pie-secondary-pie-${index}`
15266
- )) : secondaryData.map((entry, index) => {
15781
+ ofPieType === "pie" ? secondaryPieArcs.map((entry, index) => {
15782
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, pieSeriesIndex, entry.data.index);
15783
+ const midAngle = (entry.startAngle + entry.endAngle) / 2;
15784
+ const dot = pieEllipsePoint(secondaryCenterX, secondaryCenterY, secondaryRadius * 0.62, 1, midAngle);
15785
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(React3.Fragment, { children: [
15786
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15787
+ "path",
15788
+ {
15789
+ ...chartElementDataProps(pieSeriesIndex, entry.data.index),
15790
+ d: secondaryArc(entry) ?? "",
15791
+ fill: entry.data.color,
15792
+ stroke: selected ? "#64748b" : chart.chartAreaFillColor ?? palette.surface,
15793
+ strokeWidth: selected ? 2 : 1,
15794
+ transform: `translate(${secondaryCenterX}, ${secondaryCenterY})`
15795
+ }
15796
+ ),
15797
+ selected ? renderSelectionPointHandles(`bar-of-pie-secondary-pie-selection-${index}`, [dot]) : null
15798
+ ] }, `bar-of-pie-secondary-pie-${index}`);
15799
+ }) : secondaryData.map((entry, index) => {
15267
15800
  const segmentHeight = index === secondaryData.length - 1 ? Math.max(1, stackedBarTop + stackedBarHeight - stackCursor) : Math.max(1, entry.value / secondaryTotalSafe * stackedBarHeight);
15268
15801
  const y = stackCursor;
15269
15802
  stackCursor += segmentHeight;
15803
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, pieSeriesIndex, entry.index);
15270
15804
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
15271
15805
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15272
15806
  "rect",
15273
15807
  {
15808
+ ...chartElementDataProps(pieSeriesIndex, entry.index),
15274
15809
  fill: entry.color,
15275
15810
  height: segmentHeight,
15276
- stroke: chart.chartAreaFillColor ?? palette.surface,
15277
- strokeWidth: 1,
15811
+ stroke: selected ? "#64748b" : chart.chartAreaFillColor ?? palette.surface,
15812
+ strokeWidth: selected ? 2 : 1,
15278
15813
  width: stackedBarWidth,
15279
15814
  x: stackedBarLeft,
15280
15815
  y
15281
15816
  }
15282
15817
  ),
15818
+ selected ? renderSelectionRectHandles(
15819
+ `bar-of-pie-secondary-bar-selection-${index}`,
15820
+ stackedBarLeft,
15821
+ y,
15822
+ stackedBarWidth,
15823
+ segmentHeight
15824
+ ) : null,
15283
15825
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15284
15826
  "text",
15285
15827
  {
@@ -15295,7 +15837,7 @@ function renderBarOfPieChart(chart, palette, layout) {
15295
15837
  })
15296
15838
  ] });
15297
15839
  }
15298
- function renderSurfaceChart(chart, palette, layout) {
15840
+ function renderSurfaceChart(chart, palette, layout, selectedChartElement) {
15299
15841
  const plot = resolveSurfacePlotRect(chart, layout);
15300
15842
  const categories = getCategoryLabels(chart);
15301
15843
  const rows = chart.series.length;
@@ -15820,11 +16362,51 @@ function renderSurfaceChart(chart, palette, layout) {
15820
16362
  ) : null
15821
16363
  ] });
15822
16364
  }
16365
+ function renderSurfaceHitOverlay(chart, layout, selectedChartElement) {
16366
+ const plot = resolveSurfacePlotRect(chart, layout);
16367
+ const categories = getCategoryLabels(chart);
16368
+ const rows = chart.series.length;
16369
+ const cols = Math.max(
16370
+ categories.length,
16371
+ chart.series.reduce((max, series) => Math.max(max, series.values.length), 0)
16372
+ );
16373
+ if (rows === 0 || cols === 0) {
16374
+ return null;
16375
+ }
16376
+ const cellWidth = plot.width / cols;
16377
+ const cellHeight = plot.height / rows;
16378
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { children: chart.series.flatMap((_, seriesIndex) => Array.from({ length: cols }, (_2, pointIndex) => {
16379
+ const left = plot.left + pointIndex * cellWidth;
16380
+ const top = plot.top + seriesIndex * cellHeight;
16381
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, seriesIndex, pointIndex);
16382
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(React3.Fragment, { children: [
16383
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16384
+ "rect",
16385
+ {
16386
+ ...chartElementDataProps(seriesIndex, pointIndex),
16387
+ fill: "transparent",
16388
+ height: cellHeight,
16389
+ stroke: "none",
16390
+ width: cellWidth,
16391
+ x: left,
16392
+ y: top
16393
+ }
16394
+ ),
16395
+ selected ? renderSelectionRectHandles(
16396
+ `surface-selection-${seriesIndex}-${pointIndex}`,
16397
+ left,
16398
+ top,
16399
+ cellWidth,
16400
+ cellHeight
16401
+ ) : null
16402
+ ] }, `surface-hit-${seriesIndex}-${pointIndex}`);
16403
+ })) });
16404
+ }
15823
16405
  function indexByName(series, matcher) {
15824
16406
  const index = series.findIndex((entry) => matcher.test((entry.name ?? "").toLowerCase()));
15825
16407
  return index >= 0 ? index : null;
15826
16408
  }
15827
- function renderStockChart(chart, palette, layout) {
16409
+ function renderStockChart(chart, palette, layout, selectedChartElement) {
15828
16410
  const categories = getCategoryLabels(chart);
15829
16411
  if (categories.length === 0 || chart.series.length < 2) {
15830
16412
  return null;
@@ -15927,7 +16509,13 @@ function renderStockChart(chart, palette, layout) {
15927
16509
  const closeY = yScale(entry.close);
15928
16510
  const highY = yScale(entry.high);
15929
16511
  const lowY = yScale(entry.low);
15930
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16512
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, closeIndex, index);
16513
+ return /* @__PURE__ */ (0, import_react.createElement)(
16514
+ "g",
16515
+ {
16516
+ ...chartElementDataProps(closeIndex, index),
16517
+ key: `stock-point-${index}`
16518
+ },
15931
16519
  hasVolume && entry.volume != null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15932
16520
  "rect",
15933
16521
  {
@@ -15953,12 +16541,13 @@ function renderStockChart(chart, palette, layout) {
15953
16541
  y: Math.min(openY, closeY)
15954
16542
  }
15955
16543
  ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { stroke, strokeWidth: 1.6, x1: bodyLeft, x2: bodyLeft + candleWidth, y1: closeY, y2: closeY }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { stroke: closeTickColor, strokeWidth: 1.8, x1: x, x2: x + 7, y1: closeY, y2: closeY }),
15956
- entry.open != null && openY != null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { stroke: openTickColor, strokeWidth: 1.8, x1: x - 7, x2: x, y1: openY, y2: openY }) : null
15957
- ] }, `stock-point-${index}`);
16544
+ entry.open != null && openY != null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { stroke: openTickColor, strokeWidth: 1.8, x1: x - 7, x2: x, y1: openY, y2: openY }) : null,
16545
+ selected ? renderSelectionPointHandles(`stock-selection-${index}`, [{ x, y: closeY }]) : null
16546
+ );
15958
16547
  })
15959
16548
  ] });
15960
16549
  }
15961
- function renderWaterfallChart(chart, palette, layout) {
16550
+ function renderWaterfallChart(chart, palette, layout, selectedChartElement) {
15962
16551
  const stages = buildChartStages(chart);
15963
16552
  if (stages.length === 0) {
15964
16553
  return null;
@@ -16013,6 +16602,7 @@ function renderWaterfallChart(chart, palette, layout) {
16013
16602
  const fill = bar.isSubtotal ? darkenColor2(bar.color, 0.18) : bar.value >= 0 ? bar.color : lightenColor2(bar.color, 0.22);
16014
16603
  const connectorStart = index > 0 ? bars[index - 1] : null;
16015
16604
  const connectorY = connectorStart ? yScale(connectorStart.end) : 0;
16605
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16016
16606
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16017
16607
  connectorStart ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16018
16608
  "line",
@@ -16029,17 +16619,19 @@ function renderWaterfallChart(chart, palette, layout) {
16029
16619
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16030
16620
  "rect",
16031
16621
  {
16622
+ ...chartElementDataProps(0, index),
16032
16623
  fill,
16033
16624
  rx: 2,
16034
16625
  ry: 2,
16035
- stroke: darkenColor2(fill, 0.22),
16036
- strokeWidth: 1,
16626
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.22),
16627
+ strokeWidth: selected ? 2 : 1,
16037
16628
  x: bandLeft,
16038
16629
  y: top,
16039
16630
  width: bandWidth,
16040
16631
  height
16041
16632
  }
16042
16633
  ),
16634
+ selected ? renderSelectionRectHandles(`waterfall-selection-${index}`, bandLeft, top, bandWidth, height) : null,
16043
16635
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16044
16636
  "text",
16045
16637
  {
@@ -16066,7 +16658,7 @@ function renderWaterfallChart(chart, palette, layout) {
16066
16658
  })
16067
16659
  ] });
16068
16660
  }
16069
- function renderFunnelChart(chart, palette, layout) {
16661
+ function renderFunnelChart(chart, palette, layout, selectedChartElement) {
16070
16662
  const stages = buildChartStages(chart).map((stage) => ({ ...stage, value: Math.max(0, stage.value) })).filter((stage) => stage.value > 0);
16071
16663
  if (stages.length === 0) {
16072
16664
  return null;
@@ -16083,21 +16675,24 @@ function renderFunnelChart(chart, palette, layout) {
16083
16675
  const left = centerX - stageWidth * 0.5;
16084
16676
  const fill = stage.isSubtotal ? darkenColor2(stage.color, 0.14) : stage.color;
16085
16677
  const labelFitsInside = stageWidth > 90;
16678
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16086
16679
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16087
16680
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16088
16681
  "rect",
16089
16682
  {
16683
+ ...chartElementDataProps(0, index),
16090
16684
  fill,
16091
16685
  height: stageHeight,
16092
16686
  rx: 0,
16093
16687
  ry: 0,
16094
- stroke: darkenColor2(fill, 0.2),
16095
- strokeWidth: 1,
16688
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.2),
16689
+ strokeWidth: selected ? 2 : 1,
16096
16690
  width: stageWidth,
16097
16691
  x: left,
16098
16692
  y: topY
16099
16693
  }
16100
16694
  ),
16695
+ selected ? renderSelectionRectHandles(`funnel-selection-${index}`, left, topY, stageWidth, stageHeight) : null,
16101
16696
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16102
16697
  "text",
16103
16698
  {
@@ -16112,7 +16707,7 @@ function renderFunnelChart(chart, palette, layout) {
16112
16707
  ] }, `funnel-stage-${index}`);
16113
16708
  }) });
16114
16709
  }
16115
- function renderSunburstChart(chart, palette, layout) {
16710
+ function renderSunburstChart(chart, palette, layout, selectedChartElement) {
16116
16711
  const hierarchyData = buildHierarchyData(chart);
16117
16712
  if (!hierarchyData) {
16118
16713
  return null;
@@ -16139,16 +16734,19 @@ function renderSunburstChart(chart, palette, layout) {
16139
16734
  const arcSpan = node.x1 - node.x0;
16140
16735
  const canShowLabel = arcSpan * labelRadius > 26;
16141
16736
  const fill = resolveHierarchyNodeColor(chart, node);
16737
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16142
16738
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16143
16739
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16144
16740
  "path",
16145
16741
  {
16742
+ ...chartElementDataProps(0, index),
16146
16743
  d: path,
16147
16744
  fill,
16148
- stroke: palette.surface,
16149
- strokeWidth: 1
16745
+ stroke: selected ? "#64748b" : palette.surface,
16746
+ strokeWidth: selected ? 2 : 1
16150
16747
  }
16151
16748
  ),
16749
+ selected ? renderSelectionPointHandles(`sunburst-selection-${index}`, [{ x: labelX, y: labelY }]) : null,
16152
16750
  canShowLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16153
16751
  "text",
16154
16752
  {
@@ -16164,7 +16762,7 @@ function renderSunburstChart(chart, palette, layout) {
16164
16762
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { fill: chart.chartAreaFillColor ?? palette.surface, r: holeRadius - 2 })
16165
16763
  ] });
16166
16764
  }
16167
- function renderTreemapChart(chart, palette, layout) {
16765
+ function renderTreemapChart(chart, palette, layout, selectedChartElement) {
16168
16766
  const hierarchyData = buildHierarchyData(chart);
16169
16767
  if (!hierarchyData) {
16170
16768
  return null;
@@ -16176,21 +16774,24 @@ function renderTreemapChart(chart, palette, layout) {
16176
16774
  const width = Math.max(0, leaf.x1 - leaf.x0);
16177
16775
  const height = Math.max(0, leaf.y1 - leaf.y0);
16178
16776
  const canShowLabel = width > 48 && height > 22;
16777
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16179
16778
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16180
16779
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16181
16780
  "rect",
16182
16781
  {
16782
+ ...chartElementDataProps(0, index),
16183
16783
  fill,
16184
16784
  rx: 3,
16185
16785
  ry: 3,
16186
- stroke: palette.surface,
16187
- strokeWidth: 1,
16786
+ stroke: selected ? "#64748b" : palette.surface,
16787
+ strokeWidth: selected ? 2 : 1,
16188
16788
  x: leaf.x0,
16189
16789
  y: leaf.y0,
16190
16790
  width,
16191
16791
  height
16192
16792
  }
16193
16793
  ),
16794
+ selected ? renderSelectionRectHandles(`treemap-selection-${index}`, leaf.x0, leaf.y0, width, height) : null,
16194
16795
  canShowLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
16195
16796
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16196
16797
  "text",
@@ -16217,7 +16818,7 @@ function renderTreemapChart(chart, palette, layout) {
16217
16818
  ] }, `treemap-leaf-${index}`);
16218
16819
  }) });
16219
16820
  }
16220
- function renderBoxWhiskerChart(chart, palette, layout) {
16821
+ function renderBoxWhiskerChart(chart, palette, layout, selectedChartElement) {
16221
16822
  const visibleSeries = chart.series.filter((series) => series.hidden !== true);
16222
16823
  if (visibleSeries.length === 0) {
16223
16824
  return null;
@@ -16323,146 +16924,145 @@ function renderBoxWhiskerChart(chart, palette, layout) {
16323
16924
  const meanY = yScale(entry.stats.mean);
16324
16925
  const visiblePoints = entry.visibility.nonoutliers ? entry.stats.visiblePoints : [];
16325
16926
  const outliers = entry.visibility.outliers ? entry.stats.outliers : [];
16326
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16327
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16328
- "line",
16329
- {
16330
- stroke: entry.lineColor,
16331
- strokeWidth: 1.5,
16332
- x1: x,
16333
- x2: x,
16334
- y1: upperWhiskerY,
16335
- y2: boxTop
16336
- }
16337
- ),
16927
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, index, index);
16928
+ return /* @__PURE__ */ (0, import_react.createElement)("g", { ...chartElementDataProps(index), key: `box-whisker-series-${index}` }, /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16929
+ "line",
16930
+ {
16931
+ stroke: entry.lineColor,
16932
+ strokeWidth: 1.5,
16933
+ x1: x,
16934
+ x2: x,
16935
+ y1: upperWhiskerY,
16936
+ y2: boxTop
16937
+ }
16938
+ ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16939
+ "line",
16940
+ {
16941
+ stroke: entry.lineColor,
16942
+ strokeWidth: 1.5,
16943
+ x1: x,
16944
+ x2: x,
16945
+ y1: boxBottom,
16946
+ y2: lowerWhiskerY
16947
+ }
16948
+ ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16949
+ "line",
16950
+ {
16951
+ stroke: entry.lineColor,
16952
+ strokeWidth: 1.5,
16953
+ x1: x - capWidth * 0.5,
16954
+ x2: x + capWidth * 0.5,
16955
+ y1: upperWhiskerY,
16956
+ y2: upperWhiskerY
16957
+ }
16958
+ ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16959
+ "line",
16960
+ {
16961
+ stroke: entry.lineColor,
16962
+ strokeWidth: 1.5,
16963
+ x1: x - capWidth * 0.5,
16964
+ x2: x + capWidth * 0.5,
16965
+ y1: lowerWhiskerY,
16966
+ y2: lowerWhiskerY
16967
+ }
16968
+ ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16969
+ "rect",
16970
+ {
16971
+ ...chartElementDataProps(index, index),
16972
+ fill: lightenColor2(entry.color, 0.35),
16973
+ fillOpacity: 0.72,
16974
+ height: Math.max(1, boxBottom - boxTop),
16975
+ stroke: selected ? "#64748b" : entry.lineColor,
16976
+ strokeWidth: selected ? 2 : 1.5,
16977
+ width: boxWidth,
16978
+ x: x - boxWidth * 0.5,
16979
+ y: boxTop
16980
+ }
16981
+ ), selected ? renderSelectionRectHandles(
16982
+ `box-whisker-selection-${index}`,
16983
+ x - boxWidth * 0.5,
16984
+ boxTop,
16985
+ boxWidth,
16986
+ Math.max(1, boxBottom - boxTop)
16987
+ ) : null, /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16988
+ "line",
16989
+ {
16990
+ stroke: darkenColor2(entry.lineColor, 0.15),
16991
+ strokeWidth: 2,
16992
+ x1: x - boxWidth * 0.5,
16993
+ x2: x + boxWidth * 0.5,
16994
+ y1: medianY,
16995
+ y2: medianY
16996
+ }
16997
+ ), entry.visibility.meanMarker ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
16338
16998
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16339
16999
  "line",
16340
17000
  {
16341
- stroke: entry.lineColor,
16342
- strokeWidth: 1.5,
16343
- x1: x,
16344
- x2: x,
16345
- y1: boxBottom,
16346
- y2: lowerWhiskerY
17001
+ stroke: darkenColor2(entry.lineColor, 0.18),
17002
+ strokeWidth: 1.2,
17003
+ x1: x - 4,
17004
+ x2: x + 4,
17005
+ y1: meanY - 4,
17006
+ y2: meanY + 4
16347
17007
  }
16348
17008
  ),
16349
17009
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16350
17010
  "line",
16351
17011
  {
16352
- stroke: entry.lineColor,
16353
- strokeWidth: 1.5,
16354
- x1: x - capWidth * 0.5,
16355
- x2: x + capWidth * 0.5,
16356
- y1: upperWhiskerY,
16357
- y2: upperWhiskerY
17012
+ stroke: darkenColor2(entry.lineColor, 0.18),
17013
+ strokeWidth: 1.2,
17014
+ x1: x - 4,
17015
+ x2: x + 4,
17016
+ y1: meanY + 4,
17017
+ y2: meanY - 4
16358
17018
  }
16359
- ),
16360
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16361
- "line",
17019
+ )
17020
+ ] }) : null, visiblePoints.map((value, pointIndex) => {
17021
+ const y = yScale(value);
17022
+ const jitter = (pointIndex % 7 - 3) * (boxWidth / 16);
17023
+ return /* @__PURE__ */ (0, import_react.createElement)(
17024
+ "circle",
16362
17025
  {
16363
- stroke: entry.lineColor,
16364
- strokeWidth: 1.5,
16365
- x1: x - capWidth * 0.5,
16366
- x2: x + capWidth * 0.5,
16367
- y1: lowerWhiskerY,
16368
- y2: lowerWhiskerY
17026
+ ...chartElementDataProps(index, pointIndex),
17027
+ key: `box-whisker-visible-${index}-${pointIndex}`,
17028
+ cx: x + jitter,
17029
+ cy: y,
17030
+ fill: entry.color,
17031
+ fillOpacity: 0.45,
17032
+ r: 2,
17033
+ stroke: "none"
16369
17034
  }
16370
- ),
16371
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16372
- "rect",
17035
+ );
17036
+ }), outliers.map((value, pointIndex) => {
17037
+ const y = yScale(value);
17038
+ return /* @__PURE__ */ (0, import_react.createElement)(
17039
+ "circle",
16373
17040
  {
16374
- fill: lightenColor2(entry.color, 0.35),
16375
- fillOpacity: 0.72,
16376
- height: Math.max(1, boxBottom - boxTop),
17041
+ ...chartElementDataProps(index, pointIndex),
17042
+ key: `box-whisker-outlier-${index}-${pointIndex}`,
17043
+ cx: x,
17044
+ cy: y,
17045
+ fill: "#ffffff",
17046
+ r: 3,
16377
17047
  stroke: entry.lineColor,
16378
- strokeWidth: 1.5,
16379
- width: boxWidth,
16380
- x: x - boxWidth * 0.5,
16381
- y: boxTop
16382
- }
16383
- ),
16384
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16385
- "line",
16386
- {
16387
- stroke: darkenColor2(entry.lineColor, 0.15),
16388
- strokeWidth: 2,
16389
- x1: x - boxWidth * 0.5,
16390
- x2: x + boxWidth * 0.5,
16391
- y1: medianY,
16392
- y2: medianY
16393
- }
16394
- ),
16395
- entry.visibility.meanMarker ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
16396
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16397
- "line",
16398
- {
16399
- stroke: darkenColor2(entry.lineColor, 0.18),
16400
- strokeWidth: 1.2,
16401
- x1: x - 4,
16402
- x2: x + 4,
16403
- y1: meanY - 4,
16404
- y2: meanY + 4
16405
- }
16406
- ),
16407
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16408
- "line",
16409
- {
16410
- stroke: darkenColor2(entry.lineColor, 0.18),
16411
- strokeWidth: 1.2,
16412
- x1: x - 4,
16413
- x2: x + 4,
16414
- y1: meanY + 4,
16415
- y2: meanY - 4
16416
- }
16417
- )
16418
- ] }) : null,
16419
- visiblePoints.map((value, pointIndex) => {
16420
- const y = yScale(value);
16421
- const jitter = (pointIndex % 7 - 3) * (boxWidth / 16);
16422
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16423
- "circle",
16424
- {
16425
- cx: x + jitter,
16426
- cy: y,
16427
- fill: entry.color,
16428
- fillOpacity: 0.45,
16429
- r: 2,
16430
- stroke: "none"
16431
- },
16432
- `box-whisker-visible-${index}-${pointIndex}`
16433
- );
16434
- }),
16435
- outliers.map((value, pointIndex) => {
16436
- const y = yScale(value);
16437
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16438
- "circle",
16439
- {
16440
- cx: x,
16441
- cy: y,
16442
- fill: "#ffffff",
16443
- r: 3,
16444
- stroke: entry.lineColor,
16445
- strokeWidth: 1.2
16446
- },
16447
- `box-whisker-outlier-${index}-${pointIndex}`
16448
- );
16449
- }),
16450
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16451
- "text",
16452
- {
16453
- fill: labelColor,
16454
- fontSize: 10,
16455
- textAnchor: "middle",
16456
- x,
16457
- y: layout.plot.top + layout.plot.height + 14,
16458
- children: entry.label
17048
+ strokeWidth: 1.2
16459
17049
  }
16460
- )
16461
- ] }, `box-whisker-series-${index}`);
17050
+ );
17051
+ }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
17052
+ "text",
17053
+ {
17054
+ fill: labelColor,
17055
+ fontSize: 10,
17056
+ textAnchor: "middle",
17057
+ x,
17058
+ y: layout.plot.top + layout.plot.height + 14,
17059
+ children: entry.label
17060
+ }
17061
+ ));
16462
17062
  })
16463
17063
  ] });
16464
17064
  }
16465
- function renderRegionMapChart(chart, palette, layout) {
17065
+ function renderRegionMapChart(chart, palette, layout, selectedChartElement) {
16466
17066
  const primarySeriesIndex = Math.max(0, chart.series.findIndex((series) => series.hidden !== true));
16467
17067
  const primarySeries = chart.series[primarySeriesIndex] ?? null;
16468
17068
  if (!primarySeries) {
@@ -16542,17 +17142,23 @@ function renderRegionMapChart(chart, palette, layout) {
16542
17142
  const ratio = maxValue <= minValue ? 1 : (entry.value - minValue) / Math.max(1e-6, maxValue - minValue);
16543
17143
  return resolveRegionMapValueColor(chart, primarySeriesIndex, ratio);
16544
17144
  })() : categoricalColorByLabel?.get(entry.colorLabel ?? "") ?? resolveRegionMapDataColor(chart, primarySeriesIndex);
16545
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16546
- "path",
16547
- {
16548
- d,
16549
- fill,
16550
- stroke: darkenColor2(fill, 0.18),
16551
- strokeLinejoin: "round",
16552
- strokeWidth: 0.85
16553
- },
16554
- `region-map-value-${entry.key || index}`
16555
- );
17145
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, primarySeriesIndex, index);
17146
+ const centroid = path.centroid(entry.feature);
17147
+ const canShowSelectionDot = Number.isFinite(centroid[0]) && Number.isFinite(centroid[1]);
17148
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(React3.Fragment, { children: [
17149
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
17150
+ "path",
17151
+ {
17152
+ ...chartElementDataProps(primarySeriesIndex, index),
17153
+ d,
17154
+ fill,
17155
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.18),
17156
+ strokeLinejoin: "round",
17157
+ strokeWidth: selected ? 1.8 : 0.85
17158
+ }
17159
+ ),
17160
+ selected && canShowSelectionDot ? renderSelectionPointHandles(`region-map-selection-${index}`, [{ x: centroid[0], y: centroid[1] }]) : null
17161
+ ] }, `region-map-value-${entry.key || index}`);
16556
17162
  }),
16557
17163
  showRegionLabels ? entries.map((entry, index) => {
16558
17164
  const bounds = path.bounds(entry.feature);
@@ -16609,64 +17215,71 @@ function renderUnsupported(chart, palette, layout, chartType) {
16609
17215
  )
16610
17216
  ] });
16611
17217
  }
16612
- function renderChartPlot(chart, palette, layout, chartType) {
17218
+ function renderChartPlot(chart, palette, layout, chartType, selectedChartElement) {
16613
17219
  if (isComboChart(chart)) {
16614
- return renderComboChart(chart, palette, layout) ?? renderUnsupported(chart, palette, layout, "Combo");
17220
+ return renderComboChart(chart, palette, layout, selectedChartElement) ?? renderUnsupported(chart, palette, layout, "Combo");
16615
17221
  }
16616
17222
  if (chartType === "ColumnClustered" || chartType === "ColumnStacked" || chartType === "ColumnPercentStacked" || chartType === "BarClustered" || chartType === "BarStacked" || chartType === "BarPercentStacked") {
16617
- return renderBarChart(chart, palette, layout, chartType);
17223
+ return renderBarChart(chart, palette, layout, chartType, selectedChartElement);
16618
17224
  }
16619
17225
  if (chartType === "Line" || chartType === "LineStacked" || chartType === "LinePercentStacked" || chartType === "Area" || chartType === "AreaStacked" || chartType === "AreaPercentStacked") {
16620
- return renderLineOrAreaChart(chart, palette, layout, chartType);
17226
+ return renderLineOrAreaChart(chart, palette, layout, chartType, selectedChartElement);
16621
17227
  }
16622
17228
  if (chartType === "Scatter") {
16623
- return renderScatterChart(chart, palette, layout, false);
17229
+ return renderScatterChart(chart, palette, layout, false, selectedChartElement);
16624
17230
  }
16625
17231
  if (chartType === "ScatterLines") {
16626
- return renderScatterChart(chart, palette, layout, false);
17232
+ return renderScatterChart(chart, palette, layout, false, selectedChartElement);
16627
17233
  }
16628
17234
  if (chartType === "ScatterSmooth") {
16629
- return renderScatterChart(chart, palette, layout, true);
17235
+ return renderScatterChart(chart, palette, layout, true, selectedChartElement);
16630
17236
  }
16631
17237
  if (chartType === "Bubble") {
16632
- return renderBubbleChart(chart, palette, layout);
17238
+ return renderBubbleChart(chart, palette, layout, selectedChartElement);
16633
17239
  }
16634
17240
  if (chartType === "Radar") {
16635
- return renderRadarChart(chart, palette, layout);
17241
+ return renderRadarChart(chart, palette, layout, selectedChartElement);
16636
17242
  }
16637
17243
  if (chartType === "Pie" || chartType === "Pie3D" || chartType === "PieExploded" || chartType === "Doughnut") {
16638
- return renderPieChart(chart, palette, layout, chartType);
17244
+ return renderPieChart(chart, palette, layout, chartType, selectedChartElement);
16639
17245
  }
16640
17246
  if (chartType === "BarOfPie") {
16641
- return renderBarOfPieChart(chart, palette, layout);
17247
+ return renderBarOfPieChart(chart, palette, layout, selectedChartElement);
16642
17248
  }
16643
17249
  if (chartType === "Surface") {
16644
- return renderSurfaceChart(chart, palette, layout);
17250
+ return renderSurfaceChart(chart, palette, layout, selectedChartElement);
16645
17251
  }
16646
17252
  if (chartType === "Stock") {
16647
- return renderStockChart(chart, palette, layout);
17253
+ return renderStockChart(chart, palette, layout, selectedChartElement);
16648
17254
  }
16649
17255
  if (chartType === "Waterfall") {
16650
- return renderWaterfallChart(chart, palette, layout);
17256
+ return renderWaterfallChart(chart, palette, layout, selectedChartElement);
16651
17257
  }
16652
17258
  if (chartType === "Funnel") {
16653
- return renderFunnelChart(chart, palette, layout);
17259
+ return renderFunnelChart(chart, palette, layout, selectedChartElement);
16654
17260
  }
16655
17261
  if (chartType === "BoxWhisker") {
16656
- return renderBoxWhiskerChart(chart, palette, layout);
17262
+ return renderBoxWhiskerChart(chart, palette, layout, selectedChartElement);
16657
17263
  }
16658
17264
  if (chartType === "Sunburst") {
16659
- return renderSunburstChart(chart, palette, layout);
17265
+ return renderSunburstChart(chart, palette, layout, selectedChartElement);
16660
17266
  }
16661
17267
  if (chartType === "Treemap") {
16662
- return renderTreemapChart(chart, palette, layout);
17268
+ return renderTreemapChart(chart, palette, layout, selectedChartElement);
16663
17269
  }
16664
17270
  if (chartType === "RegionMap") {
16665
- return renderRegionMapChart(chart, palette, layout);
17271
+ return renderRegionMapChart(chart, palette, layout, selectedChartElement);
16666
17272
  }
16667
17273
  return renderUnsupported(chart, palette, layout, chartType);
16668
17274
  }
16669
- var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect }) {
17275
+ var MemoChartSvg = React3.memo(function MemoChartSvg2({
17276
+ chart,
17277
+ onChartElementDoubleClick,
17278
+ onChartElementPointerDown,
17279
+ palette,
17280
+ rect,
17281
+ selectedChartElement
17282
+ }) {
16670
17283
  const renderChartType = normalizeRenderableChartType(chart);
16671
17284
  const legendItems = getLegendItems(chart, renderChartType, palette);
16672
17285
  const layout = buildLayout(chart, rect, legendItems);
@@ -16678,6 +17291,26 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16678
17291
  const normalizedBorderColor = borderColor.trim().toLowerCase();
16679
17292
  const hideBackgroundRect = normalizedBackground === "transparent" && normalizedBorderColor === "transparent";
16680
17293
  const fontFamily = buildChartFontFamily(chart.fontFamily);
17294
+ const handlePointerDown = React3.useCallback((event) => {
17295
+ const selection = resolveChartSelectionFromTarget(chart, event.target, selectedChartElement);
17296
+ if (!selection) {
17297
+ return;
17298
+ }
17299
+ if (resolveChartElementTarget(event.target)) {
17300
+ event.stopPropagation();
17301
+ }
17302
+ onChartElementPointerDown?.(selection, event);
17303
+ }, [chart, onChartElementPointerDown, selectedChartElement]);
17304
+ const handleDoubleClick = React3.useCallback((event) => {
17305
+ const selection = resolveChartSelectionFromTarget(chart, event.target, selectedChartElement);
17306
+ if (!selection) {
17307
+ return;
17308
+ }
17309
+ if (resolveChartElementTarget(event.target)) {
17310
+ event.stopPropagation();
17311
+ }
17312
+ onChartElementDoubleClick?.(selection, event);
17313
+ }, [chart, onChartElementDoubleClick, selectedChartElement]);
16681
17314
  if (renderChartType === "Surface") {
16682
17315
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16683
17316
  MemoSurfaceChartComposite,
@@ -16685,10 +17318,13 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16685
17318
  background,
16686
17319
  borderColor,
16687
17320
  chart,
16688
- fallback: renderSurfaceChart(chart, palette, layout),
17321
+ fallback: renderSurfaceChart(chart, palette, layout, selectedChartElement),
16689
17322
  fontFamily,
16690
17323
  layout,
17324
+ onDoubleClick: handleDoubleClick,
17325
+ onPointerDown: handlePointerDown,
16691
17326
  overlay: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
17327
+ renderSurfaceHitOverlay(chart, layout, selectedChartElement),
16692
17328
  renderSurfaceAxes(chart, layout),
16693
17329
  renderTitle(chart, layout, palette),
16694
17330
  renderLegend(chart, layout, palette)
@@ -16701,18 +17337,20 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16701
17337
  "svg",
16702
17338
  {
16703
17339
  "aria-label": chart.title ?? chart.name ?? "Chart",
17340
+ onDoubleClick: handleDoubleClick,
17341
+ onPointerDown: handlePointerDown,
16704
17342
  role: "img",
16705
- style: { display: "block", fontFamily, height: "100%", pointerEvents: "none", width: "100%" },
17343
+ style: { display: "block", fontFamily, height: "100%", pointerEvents: "auto", width: "100%" },
16706
17344
  viewBox: `0 0 ${layout.width} ${layout.height}`,
16707
17345
  children: [
16708
17346
  hideBackgroundRect ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { fill: background, height: layout.height, stroke: borderColor, strokeWidth: 1, width: layout.width, x: 0, y: 0 }),
16709
17347
  renderTitle(chart, layout, palette),
16710
17348
  renderLegend(chart, layout, palette),
16711
- renderChartPlot(chart, palette, layout, renderChartType)
17349
+ renderChartPlot(chart, palette, layout, renderChartType, selectedChartElement)
16712
17350
  ]
16713
17351
  }
16714
17352
  );
16715
- }, (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);
17353
+ }, (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);
16716
17354
 
16717
17355
  // src/XlsxViewer.tsx
16718
17356
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -16755,6 +17393,13 @@ var LIVE_ZOOM_COMMIT_IDLE_MS = 48;
16755
17393
  var WHEEL_ZOOM_SENSITIVITY = 25e-5;
16756
17394
  var WHEEL_LINE_DELTA_PX = 16;
16757
17395
  var CHART_SOURCE_HIGHLIGHT_COLORS = ["#2563eb", "#dc2626", "#7c3aed", "#059669", "#ea580c", "#db2777"];
17396
+ var CHART_SOURCE_HIGHLIGHT_COLOR_BY_ROLE = {
17397
+ bubble: CHART_SOURCE_HIGHLIGHT_COLORS[3] ?? "#059669",
17398
+ category: CHART_SOURCE_HIGHLIGHT_COLORS[2] ?? "#7c3aed",
17399
+ name: CHART_SOURCE_HIGHLIGHT_COLORS[0] ?? "#2563eb",
17400
+ point: CHART_SOURCE_HIGHLIGHT_COLORS[5] ?? "#db2777",
17401
+ value: CHART_SOURCE_HIGHLIGHT_COLORS[4] ?? "#ea580c"
17402
+ };
16758
17403
  var SHEET_SURFACE = "#ffffff";
16759
17404
  var DRAWING_SELECTION_STROKE = "#64748b";
16760
17405
  var DRAWING_SELECTION_HANDLE_FILL = "#ffffff";
@@ -19689,23 +20334,57 @@ function resolveChartFormulaRange(formula, fallbackSheetIndex, sheets, workbook)
19689
20334
  workbookSheetIndex
19690
20335
  };
19691
20336
  }
19692
- function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
20337
+ function resolveRangePointCell(range, pointIndex) {
20338
+ const normalized = normalizeRange2(range);
20339
+ const rowCount = normalized.end.row - normalized.start.row + 1;
20340
+ const colCount = normalized.end.col - normalized.start.col + 1;
20341
+ const cellCount = rowCount * colCount;
20342
+ if (pointIndex < 0 || pointIndex >= cellCount) {
20343
+ return null;
20344
+ }
20345
+ const rowOffset = Math.floor(pointIndex / colCount);
20346
+ const colOffset = pointIndex % colCount;
20347
+ const cell = {
20348
+ col: normalized.start.col + colOffset,
20349
+ row: normalized.start.row + rowOffset
20350
+ };
20351
+ return { start: cell, end: cell };
20352
+ }
20353
+ function collectChartRangeHighlights(chart, selectedElement, sheets, workbook, isDark) {
19693
20354
  if (!chart) {
19694
20355
  return [];
19695
20356
  }
19696
20357
  const highlights = [];
19697
20358
  const seenRanges = /* @__PURE__ */ new Set();
19698
- const references = chart.series.flatMap((series) => [
19699
- series.categoriesRef?.formula,
19700
- typeof series.raw?.name === "string" ? series.raw.name : void 0,
19701
- series.valuesRef?.formula,
19702
- series.bubbleSizeRef?.formula
20359
+ const selectedSeriesIndex = selectedElement?.chartId === chart.id && selectedElement.kind !== "chart" ? selectedElement.seriesIndex : null;
20360
+ const seriesEntries = chart.series.map((series, seriesIndex) => ({ series, seriesIndex })).filter(({ series, seriesIndex }) => series.hidden !== true && (selectedSeriesIndex == null || seriesIndex === selectedSeriesIndex));
20361
+ const references = seriesEntries.flatMap(({ series, seriesIndex }) => [
20362
+ {
20363
+ formula: typeof series.raw?.name === "string" ? series.raw.name : void 0,
20364
+ role: "name",
20365
+ seriesIndex
20366
+ },
20367
+ {
20368
+ formula: series.categoriesRef?.formula,
20369
+ role: "category",
20370
+ seriesIndex
20371
+ },
20372
+ {
20373
+ formula: series.valuesRef?.formula,
20374
+ role: "value",
20375
+ seriesIndex
20376
+ },
20377
+ {
20378
+ formula: series.bubbleSizeRef?.formula,
20379
+ role: "bubble",
20380
+ seriesIndex
20381
+ }
19703
20382
  ]);
19704
- references.forEach((formula) => {
19705
- if (!formula) {
20383
+ references.forEach((reference) => {
20384
+ if (!reference.formula) {
19706
20385
  return;
19707
20386
  }
19708
- const resolved = resolveChartFormulaRange(formula, chart.workbookSheetIndex, sheets, workbook);
20387
+ const resolved = resolveChartFormulaRange(reference.formula, chart.workbookSheetIndex, sheets, workbook);
19709
20388
  if (!resolved) {
19710
20389
  return;
19711
20390
  }
@@ -19720,7 +20399,7 @@ function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
19720
20399
  return;
19721
20400
  }
19722
20401
  seenRanges.add(key);
19723
- const strokeColor = CHART_SOURCE_HIGHLIGHT_COLORS[highlights.length % CHART_SOURCE_HIGHLIGHT_COLORS.length] ?? "#2563eb";
20402
+ const strokeColor = CHART_SOURCE_HIGHLIGHT_COLOR_BY_ROLE[reference.role];
19724
20403
  highlights.push({
19725
20404
  fillColor: applyAlphaToColor(strokeColor, isDark ? 0.24 : 0.14),
19726
20405
  range: resolved.range,
@@ -19728,6 +20407,28 @@ function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
19728
20407
  workbookSheetIndex: resolved.workbookSheetIndex
19729
20408
  });
19730
20409
  });
20410
+ if (selectedElement?.chartId === chart.id && selectedElement.kind === "point") {
20411
+ references.forEach((reference) => {
20412
+ if (!reference.formula || reference.role === "name") {
20413
+ return;
20414
+ }
20415
+ const resolved = resolveChartFormulaRange(reference.formula, chart.workbookSheetIndex, sheets, workbook);
20416
+ if (!resolved) {
20417
+ return;
20418
+ }
20419
+ const range = resolveRangePointCell(resolved.range, selectedElement.pointIndex);
20420
+ if (!range) {
20421
+ return;
20422
+ }
20423
+ const strokeColor = CHART_SOURCE_HIGHLIGHT_COLOR_BY_ROLE.point;
20424
+ highlights.push({
20425
+ fillColor: applyAlphaToColor(strokeColor, isDark ? 0.34 : 0.22),
20426
+ range,
20427
+ strokeColor,
20428
+ workbookSheetIndex: resolved.workbookSheetIndex
20429
+ });
20430
+ });
20431
+ }
19731
20432
  return highlights;
19732
20433
  }
19733
20434
  function clampSparklineValue(value, min, max) {
@@ -21785,11 +22486,13 @@ function XlsxGrid({
21785
22486
  redo,
21786
22487
  revision,
21787
22488
  selectedChart,
22489
+ selectedChartElement,
21788
22490
  selectedChartId,
21789
22491
  selectedImage,
21790
22492
  selectedImageId,
21791
22493
  selectCell,
21792
22494
  selectChart,
22495
+ selectChartElement,
21793
22496
  selectImage,
21794
22497
  selectRange,
21795
22498
  selection,
@@ -23698,8 +24401,8 @@ function XlsxGrid({
23698
24401
  return map;
23699
24402
  }, [activeSheet?.sparklines]);
23700
24403
  const chartRangeHighlights = React4.useMemo(
23701
- () => collectChartRangeHighlights(selectedChart, sheets, workbook, paletteIsDark(palette)),
23702
- [palette, selectedChart, sheets, workbook]
24404
+ () => collectChartRangeHighlights(selectedChart, selectedChartElement, sheets, workbook, paletteIsDark(palette)),
24405
+ [palette, selectedChart, selectedChartElement, sheets, workbook]
23703
24406
  );
23704
24407
  const activeSheetChartHighlights = React4.useMemo(
23705
24408
  () => activeSheet ? chartRangeHighlights.filter((highlight) => highlight.workbookSheetIndex === activeSheet.workbookSheetIndex) : [],
@@ -23714,6 +24417,7 @@ function XlsxGrid({
23714
24417
  getCellStyle,
23715
24418
  palette,
23716
24419
  revision,
24420
+ selectedChartElement,
23717
24421
  selectedChartId,
23718
24422
  viewportRowBatch,
23719
24423
  worksheet,
@@ -23727,6 +24431,7 @@ function XlsxGrid({
23727
24431
  getCellStyle,
23728
24432
  palette,
23729
24433
  revision,
24434
+ selectedChartElement,
23730
24435
  selectedChartId,
23731
24436
  viewportRowBatch,
23732
24437
  worksheet,
@@ -26922,6 +27627,13 @@ function XlsxGrid({
26922
27627
  }
26923
27628
  selectChart(chart.id);
26924
27629
  }, [selectChart]);
27630
+ const handleChartElementPointerDown = React4.useCallback((selection2) => {
27631
+ skipNextChartClickRef.current = selection2.chartId;
27632
+ selectChartElement(selection2);
27633
+ }, [selectChartElement]);
27634
+ const handleChartElementDoubleClick = React4.useCallback((selection2) => {
27635
+ selectChartElement(selection2);
27636
+ }, [selectChartElement]);
26925
27637
  if (isLoading) {
26926
27638
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderLoading(loadingComponent, loadingState, palette) });
26927
27639
  }
@@ -26971,7 +27683,17 @@ function XlsxGrid({
26971
27683
  },
26972
27684
  children: charts.length > 0 ? charts.map((chart) => {
26973
27685
  const chartsheetRect = { height: 320, left: 0, top: 0, width: 640 };
26974
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { minHeight: 320, position: "relative" }, children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, chartsheetRect) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MemoChartSvg, { chart, palette, rect: chartsheetRect }) }, chart.id);
27686
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { minHeight: 320, position: "relative" }, children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, chartsheetRect) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
27687
+ MemoChartSvg,
27688
+ {
27689
+ chart,
27690
+ onChartElementDoubleClick: handleChartElementDoubleClick,
27691
+ onChartElementPointerDown: handleChartElementPointerDown,
27692
+ palette,
27693
+ rect: chartsheetRect,
27694
+ selectedChartElement
27695
+ }
27696
+ ) }, chart.id);
26975
27697
  }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
26976
27698
  "div",
26977
27699
  {
@@ -27645,7 +28367,6 @@ function XlsxGrid({
27645
28367
  }
27646
28368
  ) : null;
27647
28369
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React4.Fragment, { children: [
27648
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style, children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, rect) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MemoChartSvg, { chart, palette, rect }) }),
27649
28370
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
27650
28371
  "div",
27651
28372
  {
@@ -27653,11 +28374,20 @@ function XlsxGrid({
27653
28374
  onPointerDown: (event) => startChartMove(event, chart, rect),
27654
28375
  style: {
27655
28376
  ...style,
27656
- background: "transparent",
27657
28377
  cursor: canEditChart && selectedChartId === chart.id ? "move" : "cell",
27658
- pointerEvents: "auto",
27659
- zIndex: isFrozenDrawing ? chart.zIndex + 21 : chart.zIndex + 1
27660
- }
28378
+ pointerEvents: "auto"
28379
+ },
28380
+ children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, rect) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
28381
+ MemoChartSvg,
28382
+ {
28383
+ chart,
28384
+ onChartElementDoubleClick: handleChartElementDoubleClick,
28385
+ onChartElementPointerDown: handleChartElementPointerDown,
28386
+ palette,
28387
+ rect,
28388
+ selectedChartElement
28389
+ }
28390
+ )
27661
28391
  }
27662
28392
  ),
27663
28393
  selectionNode
@@ -27740,7 +28470,7 @@ function XlsxGrid({
27740
28470
  };
27741
28471
  const drawingViewportCacheSignature = `${Math.floor(drawingViewport.left / CANVAS_VIEWPORT_OVERSCAN_PX)}:${Math.floor(drawingViewport.top / CANVAS_VIEWPORT_OVERSCAN_PX)}:${drawingViewport.width}:${drawingViewport.height}`;
27742
28472
  const previousPaneDrawingNodes = paneDrawingNodesCacheRef.current;
27743
- 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;
28473
+ 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;
27744
28474
  const paneDrawingNodes = canReusePaneDrawingNodes ? previousPaneDrawingNodes.value : !showImages ? {
27745
28475
  corner: null,
27746
28476
  left: null,
@@ -27784,6 +28514,7 @@ function XlsxGrid({
27784
28514
  renderChartLoading,
27785
28515
  renderImage,
27786
28516
  renderImageSelection,
28517
+ selectedChartElement,
27787
28518
  selectedChartId,
27788
28519
  selectedImageId,
27789
28520
  selectionStroke,
@@ -29200,12 +29931,16 @@ function useXlsxViewerEditing() {
29200
29931
  removeActiveSheet,
29201
29932
  readOnly,
29202
29933
  redo,
29934
+ selectedCellFormula,
29935
+ selectedChartFormula,
29203
29936
  selectedFormula,
29937
+ selectedFormulaTarget,
29204
29938
  selectedValue,
29205
29939
  setCellFormula,
29206
29940
  setCellStyle,
29207
29941
  setCellValue,
29208
29942
  setRangeStyle,
29943
+ setSelectedFormula,
29209
29944
  setSelectedCellFormula,
29210
29945
  setSelectedCellStyle,
29211
29946
  setSelectedCellValue,
@@ -29231,12 +29966,16 @@ function useXlsxViewerEditing() {
29231
29966
  removeActiveSheet,
29232
29967
  readOnly,
29233
29968
  redo,
29969
+ selectedCellFormula,
29970
+ selectedChartFormula,
29234
29971
  selectedFormula,
29972
+ selectedFormulaTarget,
29235
29973
  selectedValue,
29236
29974
  setCellFormula,
29237
29975
  setCellStyle,
29238
29976
  setCellValue,
29239
29977
  setRangeStyle,
29978
+ setSelectedFormula,
29240
29979
  setSelectedCellFormula,
29241
29980
  setSelectedCellStyle,
29242
29981
  setSelectedCellValue,
@@ -29261,12 +30000,16 @@ function useXlsxViewerEditing() {
29261
30000
  removeActiveSheet,
29262
30001
  readOnly,
29263
30002
  redo,
30003
+ selectedCellFormula,
30004
+ selectedChartFormula,
29264
30005
  selectedFormula,
30006
+ selectedFormulaTarget,
29265
30007
  selectedValue,
29266
30008
  setCellFormula,
29267
30009
  setCellStyle,
29268
30010
  setCellValue,
29269
30011
  setRangeStyle,
30012
+ setSelectedFormula,
29270
30013
  setSelectedCellFormula,
29271
30014
  setSelectedCellStyle,
29272
30015
  setSelectedCellValue,
@@ -29290,8 +30033,10 @@ function useXlsxViewerImages() {
29290
30033
  const {
29291
30034
  charts,
29292
30035
  clearSelectedChart,
30036
+ clearSelectedChartElement,
29293
30037
  clearSelectedImage,
29294
30038
  getChartById,
30039
+ getChartSeriesFormula,
29295
30040
  getSheetCharts,
29296
30041
  getImageById,
29297
30042
  getSheetImages,
@@ -29303,11 +30048,15 @@ function useXlsxViewerImages() {
29303
30048
  resizeChartBy,
29304
30049
  resizeImageBy,
29305
30050
  selectedChart,
30051
+ selectedChartElement,
30052
+ selectedChartFormula,
29306
30053
  selectedChartId,
29307
30054
  selectedImage,
29308
30055
  selectedImageId,
29309
30056
  selectChart,
30057
+ selectChartElement,
29310
30058
  selectImage,
30059
+ setChartSeriesFormula,
29311
30060
  setChartRect,
29312
30061
  setImageRect,
29313
30062
  updateChart
@@ -29316,8 +30065,10 @@ function useXlsxViewerImages() {
29316
30065
  () => ({
29317
30066
  charts,
29318
30067
  clearSelectedChart,
30068
+ clearSelectedChartElement,
29319
30069
  clearSelectedImage,
29320
30070
  getChartById,
30071
+ getChartSeriesFormula,
29321
30072
  getSheetCharts,
29322
30073
  getImageById,
29323
30074
  getSheetImages,
@@ -29329,11 +30080,15 @@ function useXlsxViewerImages() {
29329
30080
  resizeChartBy,
29330
30081
  resizeImageBy,
29331
30082
  selectedChart,
30083
+ selectedChartElement,
30084
+ selectedChartFormula,
29332
30085
  selectedChartId,
29333
30086
  selectedImage,
29334
30087
  selectedImageId,
29335
30088
  selectChart,
30089
+ selectChartElement,
29336
30090
  selectImage,
30091
+ setChartSeriesFormula,
29337
30092
  setChartRect,
29338
30093
  setImageRect,
29339
30094
  updateChart
@@ -29341,8 +30096,10 @@ function useXlsxViewerImages() {
29341
30096
  [
29342
30097
  charts,
29343
30098
  clearSelectedChart,
30099
+ clearSelectedChartElement,
29344
30100
  clearSelectedImage,
29345
30101
  getChartById,
30102
+ getChartSeriesFormula,
29346
30103
  getSheetCharts,
29347
30104
  getImageById,
29348
30105
  getSheetImages,
@@ -29354,11 +30111,15 @@ function useXlsxViewerImages() {
29354
30111
  resizeChartBy,
29355
30112
  resizeImageBy,
29356
30113
  selectedChart,
30114
+ selectedChartElement,
30115
+ selectedChartFormula,
29357
30116
  selectedChartId,
29358
30117
  selectedImage,
29359
30118
  selectedImageId,
29360
30119
  selectChart,
30120
+ selectChartElement,
29361
30121
  selectImage,
30122
+ setChartSeriesFormula,
29362
30123
  setChartRect,
29363
30124
  setImageRect,
29364
30125
  updateChart
@@ -29372,7 +30133,9 @@ function useXlsxViewerCharts() {
29372
30133
  charts,
29373
30134
  chartsheets,
29374
30135
  clearSelectedChart,
30136
+ clearSelectedChartElement,
29375
30137
  getChartById,
30138
+ getChartSeriesFormula,
29376
30139
  getChartsheetById,
29377
30140
  getSheetCharts,
29378
30141
  isChartsLoading,
@@ -29381,8 +30144,12 @@ function useXlsxViewerCharts() {
29381
30144
  resizeChartBy,
29382
30145
  selectChart,
29383
30146
  selectedChart,
30147
+ selectedChartElement,
30148
+ selectedChartFormula,
29384
30149
  selectedChartId,
30150
+ selectChartElement,
29385
30151
  setActiveTabIndex,
30152
+ setChartSeriesFormula,
29386
30153
  setChartRect,
29387
30154
  tabs,
29388
30155
  updateChart
@@ -29394,7 +30161,9 @@ function useXlsxViewerCharts() {
29394
30161
  charts,
29395
30162
  chartsheets,
29396
30163
  clearSelectedChart,
30164
+ clearSelectedChartElement,
29397
30165
  getChartById,
30166
+ getChartSeriesFormula,
29398
30167
  getChartsheetById,
29399
30168
  getSheetCharts,
29400
30169
  isChartsLoading,
@@ -29403,8 +30172,12 @@ function useXlsxViewerCharts() {
29403
30172
  resizeChartBy,
29404
30173
  selectChart,
29405
30174
  selectedChart,
30175
+ selectedChartElement,
30176
+ selectedChartFormula,
29406
30177
  selectedChartId,
30178
+ selectChartElement,
29407
30179
  setActiveTabIndex,
30180
+ setChartSeriesFormula,
29408
30181
  setChartRect,
29409
30182
  tabs,
29410
30183
  updateChart
@@ -29415,7 +30188,9 @@ function useXlsxViewerCharts() {
29415
30188
  charts,
29416
30189
  chartsheets,
29417
30190
  clearSelectedChart,
30191
+ clearSelectedChartElement,
29418
30192
  getChartById,
30193
+ getChartSeriesFormula,
29419
30194
  getChartsheetById,
29420
30195
  getSheetCharts,
29421
30196
  isChartsLoading,
@@ -29424,8 +30199,12 @@ function useXlsxViewerCharts() {
29424
30199
  resizeChartBy,
29425
30200
  selectChart,
29426
30201
  selectedChart,
30202
+ selectedChartElement,
30203
+ selectedChartFormula,
29427
30204
  selectedChartId,
30205
+ selectChartElement,
29428
30206
  setActiveTabIndex,
30207
+ setChartSeriesFormula,
29429
30208
  setChartRect,
29430
30209
  tabs,
29431
30210
  updateChart