@extend-ai/react-xlsx 0.12.3 → 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
@@ -7889,6 +8074,7 @@ function useXlsxViewerController(options) {
7889
8074
  const [activeCell, setActiveCell] = React.useState(null);
7890
8075
  const [selection, setSelection] = React.useState(null);
7891
8076
  const [selectedChartId, setSelectedChartId] = React.useState(null);
8077
+ const [selectedChartElement, setSelectedChartElement] = React.useState(null);
7892
8078
  const [selectedImageId, setSelectedImageId] = React.useState(null);
7893
8079
  const [revision, setRevision] = React.useState(0);
7894
8080
  const selectionAnchorRef = React.useRef(null);
@@ -8161,6 +8347,7 @@ function useXlsxViewerController(options) {
8161
8347
  setActiveCell(null);
8162
8348
  setSelection(null);
8163
8349
  setSelectedChartId(null);
8350
+ setSelectedChartElement(null);
8164
8351
  setSelectedImageId(null);
8165
8352
  selectionAnchorRef.current = null;
8166
8353
  undoStackRef.current = [];
@@ -8189,6 +8376,7 @@ function useXlsxViewerController(options) {
8189
8376
  setActiveCell(null);
8190
8377
  setSelection(null);
8191
8378
  setSelectedChartId(null);
8379
+ setSelectedChartElement(null);
8192
8380
  setSelectedImageId(null);
8193
8381
  selectionAnchorRef.current = null;
8194
8382
  undoStackRef.current = [];
@@ -8340,6 +8528,7 @@ function useXlsxViewerController(options) {
8340
8528
  setActiveCell(null);
8341
8529
  setSelection(null);
8342
8530
  setSelectedChartId(null);
8531
+ setSelectedChartElement(null);
8343
8532
  setSelectedImageId(null);
8344
8533
  selectionAnchorRef.current = null;
8345
8534
  setSortState(null);
@@ -8661,12 +8850,49 @@ function useXlsxViewerController(options) {
8661
8850
  () => selectedChartId ? getChartById(selectedChartId) : null,
8662
8851
  [getChartById, selectedChartId]
8663
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]);
8664
8880
  const selectChart = React.useCallback((id) => {
8665
8881
  setSelectedImageId(null);
8666
8882
  setSelectedChartId(id);
8883
+ setSelectedChartElement(id ? { chartId: id, kind: "chart" } : null);
8667
8884
  }, []);
8668
8885
  const clearSelectedChart = React.useCallback(() => {
8669
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);
8670
8896
  }, []);
8671
8897
  const getSheetImages = React.useCallback((sheetIndex = activeSheetIndex) => {
8672
8898
  const targetSheet = sheets[sheetIndex];
@@ -8713,6 +8939,7 @@ function useXlsxViewerController(options) {
8713
8939
  );
8714
8940
  const selectImage = React.useCallback((id) => {
8715
8941
  setSelectedChartId(null);
8942
+ setSelectedChartElement(null);
8716
8943
  setSelectedImageId(id);
8717
8944
  }, []);
8718
8945
  const clearSelectedImage = React.useCallback(() => {
@@ -8937,10 +9164,32 @@ function useXlsxViewerController(options) {
8937
9164
  () => getCellDisplayValue2(deferredMetadataCell),
8938
9165
  [deferredMetadataCell, getCellDisplayValue2, revision, workerCellSnapshotRevision]
8939
9166
  );
8940
- const selectedFormula = React.useMemo(
9167
+ const selectedCellFormula = React.useMemo(
8941
9168
  () => getCellFormula(deferredMetadataCell),
8942
9169
  [deferredMetadataCell, getCellFormula, revision, workerCellSnapshotRevision]
8943
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;
8944
9193
  const isLoadDeferred = deferredLoadFileSize !== null;
8945
9194
  const canLoadDeferred = !isLoading && isLoadDeferred;
8946
9195
  const canUndo = !readOnly && undoStackRef.current.length > 0;
@@ -9483,8 +9732,32 @@ function useXlsxViewerController(options) {
9483
9732
  setChartsByWorkbookSheetIndex((current) => current.map((sheetCharts) => sheetCharts.map((chart) => chart.id === id ? { ...chart, ...patch } : chart)));
9484
9733
  setRevision((current) => current + 1);
9485
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]);
9486
9758
  const selectCell = React.useCallback((cell, options2) => {
9487
9759
  setSelectedChartId(null);
9760
+ setSelectedChartElement(null);
9488
9761
  setSelectedImageId(null);
9489
9762
  setActiveCell(cell);
9490
9763
  if (options2?.extend && selectionAnchorRef.current) {
@@ -9497,6 +9770,7 @@ function useXlsxViewerController(options) {
9497
9770
  const selectRange = React.useCallback((range) => {
9498
9771
  const normalized = normalizeRange(range);
9499
9772
  setSelectedChartId(null);
9773
+ setSelectedChartElement(null);
9500
9774
  setSelectedImageId(null);
9501
9775
  selectionAnchorRef.current = normalized.start;
9502
9776
  setActiveCell(normalized.end);
@@ -9507,6 +9781,7 @@ function useXlsxViewerController(options) {
9507
9781
  setActiveCell(null);
9508
9782
  setSelection(null);
9509
9783
  setSelectedChartId(null);
9784
+ setSelectedChartElement(null);
9510
9785
  setSelectedImageId(null);
9511
9786
  }, []);
9512
9787
  const clearSelectedCells = React.useCallback(() => {
@@ -9624,6 +9899,16 @@ function useXlsxViewerController(options) {
9624
9899
  }
9625
9900
  setCellFormula(activeCell, formula);
9626
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]);
9627
9912
  const setSelectedCellStyle = React.useCallback((style) => {
9628
9913
  if (!activeCell) {
9629
9914
  return;
@@ -10100,6 +10385,7 @@ function useXlsxViewerController(options) {
10100
10385
  charts,
10101
10386
  chartsheets,
10102
10387
  clearSelectedChart,
10388
+ clearSelectedChartElement,
10103
10389
  clearSelectedCells,
10104
10390
  clearSelectedImage,
10105
10391
  clearSelection,
@@ -10116,6 +10402,7 @@ function useXlsxViewerController(options) {
10116
10402
  fillSelection,
10117
10403
  formControls,
10118
10404
  getChartById,
10405
+ getChartSeriesFormula,
10119
10406
  getChartsheetById,
10120
10407
  getImageById,
10121
10408
  getSheetCharts,
@@ -10156,18 +10443,25 @@ function useXlsxViewerController(options) {
10156
10443
  setCellStyle,
10157
10444
  setCellValue,
10158
10445
  setRangeStyle,
10446
+ setSelectedFormula,
10159
10447
  setZoomScale,
10160
10448
  setChartRect,
10449
+ setChartSeriesFormula,
10161
10450
  setImageRect,
10162
10451
  selectedChart,
10452
+ selectedChartElement,
10453
+ selectedChartFormula,
10163
10454
  selectedChartId,
10455
+ selectedCellFormula,
10164
10456
  selectedFormula,
10457
+ selectedFormulaTarget,
10165
10458
  selectedImage,
10166
10459
  selectedImageId,
10167
10460
  selectedRangeAddress,
10168
10461
  selectedValue,
10169
10462
  selectCell,
10170
10463
  selectChart,
10464
+ selectChartElement,
10171
10465
  selectImage,
10172
10466
  selectRange,
10173
10467
  selection,
@@ -10207,6 +10501,7 @@ function useXlsxViewerController(options) {
10207
10501
  charts,
10208
10502
  chartsheets,
10209
10503
  clearSelectedChart,
10504
+ clearSelectedChartElement,
10210
10505
  clearSelectedCells,
10211
10506
  clearSelectedImage,
10212
10507
  continueDeferredLoad,
@@ -10223,6 +10518,7 @@ function useXlsxViewerController(options) {
10223
10518
  fillSelection,
10224
10519
  formControls,
10225
10520
  getChartById,
10521
+ getChartSeriesFormula,
10226
10522
  getChartsheetById,
10227
10523
  getImageById,
10228
10524
  getSheetCharts,
@@ -10261,18 +10557,25 @@ function useXlsxViewerController(options) {
10261
10557
  setCellStyle,
10262
10558
  setCellValue,
10263
10559
  setRangeStyle,
10560
+ setSelectedFormula,
10264
10561
  setZoomScale,
10265
10562
  setChartRect,
10563
+ setChartSeriesFormula,
10266
10564
  setImageRect,
10267
10565
  selectedChart,
10566
+ selectedChartElement,
10567
+ selectedChartFormula,
10268
10568
  selectedChartId,
10569
+ selectedCellFormula,
10269
10570
  selectedFormula,
10571
+ selectedFormulaTarget,
10270
10572
  selectedImage,
10271
10573
  selectedImageId,
10272
10574
  selectedRangeAddress,
10273
10575
  selectedValue,
10274
10576
  selectCell,
10275
10577
  selectChart,
10578
+ selectChartElement,
10276
10579
  selectImage,
10277
10580
  selectRange,
10278
10581
  selection,
@@ -11060,6 +11363,8 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11060
11363
  chart,
11061
11364
  fontFamily,
11062
11365
  layout,
11366
+ onDoubleClick,
11367
+ onPointerDown,
11063
11368
  overlay,
11064
11369
  palette,
11065
11370
  fallback
@@ -11255,7 +11560,7 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11255
11560
  fontFamily,
11256
11561
  height: "100%",
11257
11562
  overflow: "hidden",
11258
- pointerEvents: "none",
11563
+ pointerEvents: "auto",
11259
11564
  position: "relative",
11260
11565
  width: "100%"
11261
11566
  },
@@ -11276,6 +11581,8 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11276
11581
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
11277
11582
  "svg",
11278
11583
  {
11584
+ onDoubleClick,
11585
+ onPointerDown,
11279
11586
  style: { display: "block", height: "100%", inset: 0, position: "absolute", width: "100%" },
11280
11587
  viewBox: `0 0 ${layout.width} ${layout.height}`,
11281
11588
  children: [
@@ -11287,10 +11594,104 @@ var MemoSurfaceChartComposite = React2.memo(function MemoSurfaceChartComposite2(
11287
11594
  ]
11288
11595
  }
11289
11596
  );
11290
- }, (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);
11291
11598
 
11292
11599
  // src/chart-renderer.tsx
11293
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
+ }
11294
11695
  var WORLD_COUNTRY_FEATURES = (0, import_topojson_client.feature)(
11295
11696
  countries_50m_default,
11296
11697
  countries_50m_default.objects.countries
@@ -12988,10 +13389,17 @@ function renderLegend(chart, layout, palette) {
12988
13389
  const startY = layout.plot.top + 6;
12989
13390
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { children: items.map((item, index) => {
12990
13391
  const y = startY + index * 18;
12991
- 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
+ },
12992
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 }),
12993
13401
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { fill: textColor, fontSize: 10, x: textOffset, y: 0, children: item.label })
12994
- ] }, `legend-${index}`);
13402
+ );
12995
13403
  }) });
12996
13404
  }
12997
13405
  const rowY = legendPos === "top" ? layout.titleHeight + 12 : layout.height - 8;
@@ -12999,10 +13407,17 @@ function renderLegend(chart, layout, palette) {
12999
13407
  let cursorX = Math.max(8, (layout.width - totalWidth) / 2);
13000
13408
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { children: items.map((item, index) => {
13001
13409
  const labelWidth = Math.min(96, item.label.length * 5.4);
13002
- 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
+ },
13003
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 }),
13004
13419
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { fill: textColor, fontSize: 10, x: textOffset, y: 0, children: item.label })
13005
- ] }, `legend-${index}`);
13420
+ );
13006
13421
  cursorX += 24 + labelWidth;
13007
13422
  return node;
13008
13423
  }) });
@@ -13329,7 +13744,7 @@ function projectCartesian3dPoint2(x, y, z, rotXRad, rotYRad, usePerspective, per
13329
13744
  y: y1 * perspective
13330
13745
  };
13331
13746
  }
13332
- function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPointsBySeries, minValue, maxValue, isAreaChart, isStackedSeries) {
13747
+ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPointsBySeries, minValue, maxValue, isAreaChart, isStackedSeries, selectedChartElement) {
13333
13748
  const plot = layout.plot;
13334
13749
  const valueDomain = resolveAxisDomainWithChartOverrides(
13335
13750
  chart.valueAxis,
@@ -13396,6 +13811,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13396
13811
  return {
13397
13812
  bottom,
13398
13813
  bottomBack,
13814
+ categoryIndex,
13399
13815
  defined: point.defined,
13400
13816
  depth: top.depth,
13401
13817
  depthBack: topBack?.depth ?? top.depth,
@@ -13431,6 +13847,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13431
13847
  points: series.map((point) => ({
13432
13848
  bottom: toScreenPoint(point.bottom),
13433
13849
  bottomBack: point.bottomBack ? toScreenPoint(point.bottomBack) : null,
13850
+ categoryIndex: point.categoryIndex,
13434
13851
  defined: point.defined,
13435
13852
  top: toScreenPoint(point.top),
13436
13853
  topBack: point.topBack ? toScreenPoint(point.topBack) : null
@@ -13535,6 +13952,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13535
13952
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13536
13953
  "path",
13537
13954
  {
13955
+ ...chartElementDataProps(seriesIndex),
13538
13956
  d: topFace,
13539
13957
  fill: lightenColor2(fillColor, 0.08),
13540
13958
  fillOpacity: 0.8,
@@ -13545,6 +13963,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13545
13963
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13546
13964
  "path",
13547
13965
  {
13966
+ ...chartElementDataProps(seriesIndex),
13548
13967
  d: bottomFace,
13549
13968
  fill: darkenColor2(fillColor, 0.2),
13550
13969
  fillOpacity: 0.34,
@@ -13572,6 +13991,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13572
13991
  isAreaChart && isStackedSeries && areaBackPoints.length >= 3 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13573
13992
  "path",
13574
13993
  {
13994
+ ...chartElementDataProps(seriesIndex),
13575
13995
  d: buildLinearSvgPath(areaBackPoints, true),
13576
13996
  fill: darkenColor2(fillColor, 0.18),
13577
13997
  fillOpacity: 0.44,
@@ -13583,6 +14003,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13583
14003
  startCap ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13584
14004
  "path",
13585
14005
  {
14006
+ ...chartElementDataProps(seriesIndex),
13586
14007
  d: startCap,
13587
14008
  fill: darkenColor2(fillColor, 0.24),
13588
14009
  fillOpacity: 0.54,
@@ -13593,6 +14014,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13593
14014
  endCap ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13594
14015
  "path",
13595
14016
  {
14017
+ ...chartElementDataProps(seriesIndex),
13596
14018
  d: endCap,
13597
14019
  fill: darkenColor2(fillColor, 0.14),
13598
14020
  fillOpacity: 0.6,
@@ -13603,6 +14025,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13603
14025
  isAreaChart && areaPoints.length >= 3 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13604
14026
  "path",
13605
14027
  {
14028
+ ...chartElementDataProps(seriesIndex),
13606
14029
  d: buildLinearSvgPath(areaPoints, true),
13607
14030
  fill: fillColor,
13608
14031
  fillOpacity: 0.74,
@@ -13626,6 +14049,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13626
14049
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13627
14050
  "path",
13628
14051
  {
14052
+ ...chartElementDataProps(seriesIndex),
13629
14053
  d: buildLinearSvgPath(linePoints),
13630
14054
  fill: "none",
13631
14055
  stroke: strokeColor,
@@ -13640,6 +14064,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13640
14064
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13641
14065
  "path",
13642
14066
  {
14067
+ ...chartElementDataProps(seriesIndex, point.categoryIndex),
13643
14068
  d: markerPath,
13644
14069
  fill: chart.series[seriesIndex]?.markerColor ?? fillColor,
13645
14070
  stroke: chart.series[seriesIndex]?.markerLineColor ?? chart.chartAreaFillColor ?? palette.surface,
@@ -13648,7 +14073,23 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13648
14073
  )
13649
14074
  },
13650
14075
  `line3d-marker-${seriesIndex}-${pointIndex}`
13651
- )) : 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)
13652
14093
  ] }, `line3d-series-${seriesIndex}`);
13653
14094
  }),
13654
14095
  yLabelPoints.map(({ point, tick }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -13677,7 +14118,7 @@ function renderLineOrAreaChart3d(chart, palette, layout, categories, stackedPoin
13677
14118
  ))
13678
14119
  ] });
13679
14120
  }
13680
- function renderBarChart(chart, palette, layout, chartType) {
14121
+ function renderBarChart(chart, palette, layout, chartType, selectedChartElement) {
13681
14122
  if (chart.series.length === 0) {
13682
14123
  return null;
13683
14124
  }
@@ -14058,9 +14499,11 @@ function renderBarChart(chart, palette, layout, chartType) {
14058
14499
  axisNode,
14059
14500
  frameNode,
14060
14501
  depthAxisNode,
14061
- 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)(
14062
14503
  "rect",
14063
14504
  {
14505
+ ...barChartElementDataProps(bar.seriesIndex, bar.categoryIndex),
14506
+ key: bar.key,
14064
14507
  fill: bar.color,
14065
14508
  height: bar.height,
14066
14509
  stroke: isHistogramLike ? "none" : bar.stroke,
@@ -14068,12 +14511,12 @@ function renderBarChart(chart, palette, layout, chartType) {
14068
14511
  width: bar.width,
14069
14512
  x: bar.left,
14070
14513
  y: bar.top
14071
- },
14072
- bar.key
14073
- ))
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)
14074
14517
  ] });
14075
14518
  }
14076
- function renderLineOrAreaChart(chart, palette, layout, chartType) {
14519
+ function renderLineOrAreaChart(chart, palette, layout, chartType, selectedChartElement) {
14077
14520
  if (chart.series.length === 0) {
14078
14521
  return null;
14079
14522
  }
@@ -14184,7 +14627,8 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14184
14627
  minValue,
14185
14628
  maxValue,
14186
14629
  isAreaChart,
14187
- isStackedSeries
14630
+ isStackedSeries,
14631
+ selectedChartElement
14188
14632
  );
14189
14633
  }
14190
14634
  const rawRecord = chart.raw && typeof chart.raw === "object" ? chart.raw : null;
@@ -14273,6 +14717,7 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14273
14717
  isAreaChart ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14274
14718
  "path",
14275
14719
  {
14720
+ ...chartElementDataProps(seriesIndex),
14276
14721
  d: areaPath,
14277
14722
  fill: seriesFillColor,
14278
14723
  fillOpacity: 1,
@@ -14282,6 +14727,7 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14282
14727
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14283
14728
  "path",
14284
14729
  {
14730
+ ...chartElementDataProps(seriesIndex),
14285
14731
  d: linePath,
14286
14732
  fill: "none",
14287
14733
  stroke: chartSeriesStrokeColor(chart, seriesIndex),
@@ -14290,23 +14736,31 @@ function renderLineOrAreaChart(chart, palette, layout, chartType) {
14290
14736
  strokeWidth: Math.max(1.5, series.lineWidthPx ?? 2)
14291
14737
  }
14292
14738
  ),
14293
- 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)(
14294
14740
  "circle",
14295
14741
  {
14742
+ ...chartElementDataProps(seriesIndex, pointIndex),
14743
+ key: `line-marker-${seriesIndex}-${pointIndex}`,
14296
14744
  cx: point.x,
14297
14745
  cy: yScale(point.y),
14298
14746
  fill: series.markerColor ?? chartSeriesColor(chart, seriesIndex),
14299
14747
  r: Math.max(2, (series.markerSize ?? 6) * 0.25),
14300
14748
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? chartSeriesStrokeColor(chart, seriesIndex),
14301
14749
  strokeWidth: 1
14302
- },
14303
- `line-marker-${seriesIndex}-${pointIndex}`
14304
- ))
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)
14305
14759
  ] }, `line-series-${seriesIndex}`);
14306
14760
  })
14307
14761
  ] });
14308
14762
  }
14309
- function renderComboChart(chart, palette, layout) {
14763
+ function renderComboChart(chart, palette, layout, selectedChartElement) {
14310
14764
  const groups = buildComboGroups(chart);
14311
14765
  const columnGroup = groups.find((group) => group.chartType.startsWith("Column"));
14312
14766
  const lineGroup = groups.find((group) => group.chartType.startsWith("Line"));
@@ -14333,6 +14787,10 @@ function renderComboChart(chart, palette, layout) {
14333
14787
  const categoryScale = (0, import_d3_scale.scaleBand)().domain(categories).range([plot.left, plot.left + plot.width]).paddingInner(categoryBandPadding.inner).paddingOuter(categoryBandPadding.outer);
14334
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);
14335
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
+ };
14336
14794
  const primaryValues = columnGroup.series.flatMap((series) => series.values.map((value) => safeNumber2(value)).filter((value) => value != null));
14337
14795
  const secondaryValues = lineGroup.series.flatMap((series) => series.values.map((value) => safeNumber2(value)).filter((value) => value != null));
14338
14796
  if (primaryValues.length === 0 || secondaryValues.length === 0) {
@@ -14392,6 +14850,7 @@ function renderComboChart(chart, palette, layout) {
14392
14850
  }
14393
14851
  ),
14394
14852
  columnGroup.series.flatMap((series, seriesIndex) => categories.map((category, categoryIndex) => {
14853
+ const globalSeriesIndex = resolveGlobalSeriesIndex(series);
14395
14854
  const value = safeNumber2(series.values[categoryIndex]) ?? 0;
14396
14855
  const categoryStart = categoryScale(category) ?? plot.left;
14397
14856
  const barWidth = Math.max(1, histogramColumns ? categoryScale.bandwidth() : seriesScale.bandwidth());
@@ -14399,21 +14858,32 @@ function renderComboChart(chart, palette, layout) {
14399
14858
  const y = primaryScale(Math.max(0, value));
14400
14859
  const zeroY = primaryScale(0);
14401
14860
  const height = Math.max(1, Math.abs(zeroY - primaryScale(value)));
14402
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14403
- "rect",
14404
- {
14405
- fill: series.color ?? series.lineColor ?? chartSeriesColor(primaryChart, seriesIndex),
14406
- height,
14407
- stroke: histogramColumns ? "none" : series.lineColor ?? series.color ?? chartSeriesStrokeColor(primaryChart, seriesIndex),
14408
- strokeWidth: histogramColumns ? 0 : 1,
14409
- 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}`,
14410
14878
  x,
14411
- y: Math.min(y, zeroY)
14412
- },
14413
- `combo-bar-${seriesIndex}-${categoryIndex}`
14414
- );
14879
+ Math.min(y, zeroY),
14880
+ barWidth,
14881
+ height
14882
+ ) : null
14883
+ ] }, `combo-bar-${seriesIndex}-${categoryIndex}`);
14415
14884
  })),
14416
14885
  lineGroup.series.map((series, seriesIndex) => {
14886
+ const globalSeriesIndex = resolveGlobalSeriesIndex(series);
14417
14887
  const points = categories.map((category, categoryIndex) => ({
14418
14888
  x: (categoryScale(category) ?? plot.left) + categoryScale.bandwidth() / 2,
14419
14889
  y: safeNumber2(series.values[categoryIndex])
@@ -14424,6 +14894,7 @@ function renderComboChart(chart, palette, layout) {
14424
14894
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14425
14895
  "path",
14426
14896
  {
14897
+ ...chartElementDataProps(globalSeriesIndex),
14427
14898
  d: path,
14428
14899
  fill: "none",
14429
14900
  stroke: series.lineColor ?? series.color ?? chartSeriesStrokeColor(chart, columnGroup.series.length + seriesIndex),
@@ -14432,22 +14903,30 @@ function renderComboChart(chart, palette, layout) {
14432
14903
  strokeWidth: Math.max(1.5, series.lineWidthPx ?? 2)
14433
14904
  }
14434
14905
  ),
14435
- 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)(
14436
14907
  "path",
14437
14908
  {
14909
+ ...chartElementDataProps(globalSeriesIndex, pointIndex),
14438
14910
  d: markerSymbolPath(normalizeChartMarkerSymbol(series.markerSymbol), Math.max(4, series.markerSize ?? 7)) || markerSymbolPath("circle", 7),
14439
14911
  fill: series.markerColor ?? series.color ?? series.lineColor ?? chartSeriesColor(chart, columnGroup.series.length + seriesIndex),
14912
+ key: `combo-line-marker-${seriesIndex}-${pointIndex}`,
14440
14913
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? "#ffffff",
14441
14914
  strokeWidth: 1,
14442
14915
  transform: `translate(${point.x}, ${secondaryScale(point.y)})`
14443
- },
14444
- `combo-line-marker-${seriesIndex}-${pointIndex}`
14445
- ))
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)
14446
14925
  ] }, `combo-line-${seriesIndex}`);
14447
14926
  })
14448
14927
  ] });
14449
14928
  }
14450
- function renderScatterChart(chart, palette, layout, smooth) {
14929
+ function renderScatterChart(chart, palette, layout, smooth, selectedChartElement) {
14451
14930
  const plot = layout.plot;
14452
14931
  const rawRecord = chart.raw && typeof chart.raw === "object" ? chart.raw : null;
14453
14932
  const normalizedTitle = typeof chart.title === "string" ? chart.title.trim().toLowerCase() : "";
@@ -14633,6 +15112,7 @@ function renderScatterChart(chart, palette, layout, smooth) {
14633
15112
  shouldDrawLine && linePath.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14634
15113
  "path",
14635
15114
  {
15115
+ ...chartElementDataProps(seriesIndex),
14636
15116
  d: linePath,
14637
15117
  fill: "none",
14638
15118
  stroke: series.lineColor ?? chartSeriesStrokeColor(chart, seriesIndex),
@@ -14652,6 +15132,7 @@ function renderScatterChart(chart, palette, layout, smooth) {
14652
15132
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14653
15133
  "path",
14654
15134
  {
15135
+ ...chartElementDataProps(seriesIndex, pointIndex, { selectionMode: "seriesFirst" }),
14655
15136
  d: markerPath,
14656
15137
  fill: markerFill,
14657
15138
  stroke: "none",
@@ -14661,12 +15142,16 @@ function renderScatterChart(chart, palette, layout, smooth) {
14661
15142
  },
14662
15143
  `scatter-point-${seriesIndex}-${pointIndex}`
14663
15144
  );
14664
- })
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)
14665
15150
  ] }, `scatter-series-${seriesIndex}`);
14666
15151
  })
14667
15152
  ] });
14668
15153
  }
14669
- function renderBubbleChart(chart, palette, layout) {
15154
+ function renderBubbleChart(chart, palette, layout, selectedChartElement) {
14670
15155
  const plot = layout.plot;
14671
15156
  const pointsBySeries = chart.series.map((series) => series.values.map((value, index) => {
14672
15157
  const x = safeNumber2(series.categories[index]);
@@ -14786,6 +15271,7 @@ function renderBubbleChart(chart, palette, layout) {
14786
15271
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14787
15272
  "circle",
14788
15273
  {
15274
+ ...chartElementDataProps(seriesIndex, point.index, { selectionMode: "seriesFirst" }),
14789
15275
  cx: xScale(point.x),
14790
15276
  cy: yScale(point.y),
14791
15277
  fill: isBubble3d ? `url(#bubble3d-grad-${chart.id}-${seriesIndex})` : baseColor,
@@ -14795,6 +15281,13 @@ function renderBubbleChart(chart, palette, layout) {
14795
15281
  strokeWidth: isBubble3d ? 1.2 : 1
14796
15282
  }
14797
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,
14798
15291
  isBubble3d ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14799
15292
  "ellipse",
14800
15293
  {
@@ -14822,7 +15315,7 @@ function renderBubbleChart(chart, palette, layout) {
14822
15315
  ] }, `bubble-series-${seriesIndex}`))
14823
15316
  ] });
14824
15317
  }
14825
- function renderRadarChart(chart, palette, layout) {
15318
+ function renderRadarChart(chart, palette, layout, selectedChartElement) {
14826
15319
  if (chart.series.length === 0) {
14827
15320
  return null;
14828
15321
  }
@@ -14901,12 +15394,14 @@ function renderRadarChart(chart, palette, layout) {
14901
15394
  if (rawValue == null) {
14902
15395
  return {
14903
15396
  defined: false,
15397
+ pointIndex: categoryIndex,
14904
15398
  ...radialPoint(categoryIndex, 0)
14905
15399
  };
14906
15400
  }
14907
15401
  const ratio = clamp2((rawValue - minValue) / (safeMax - minValue), 0, 1);
14908
15402
  return {
14909
15403
  defined: true,
15404
+ pointIndex: categoryIndex,
14910
15405
  ...radialPoint(categoryIndex, ratio)
14911
15406
  };
14912
15407
  });
@@ -14925,6 +15420,7 @@ function renderRadarChart(chart, palette, layout) {
14925
15420
  definedPoints.length >= 2 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14926
15421
  "path",
14927
15422
  {
15423
+ ...chartElementDataProps(seriesIndex),
14928
15424
  d: polygon,
14929
15425
  fill: filled && !hasGap && definedPoints.length >= 3 ? color : "none",
14930
15426
  fillOpacity: filled ? 0.26 : 0,
@@ -14932,13 +15428,14 @@ function renderRadarChart(chart, palette, layout) {
14932
15428
  strokeWidth: 1.8
14933
15429
  }
14934
15430
  ) : null,
14935
- showMarkers ? definedPoints.map((point, pointIndex) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15431
+ showMarkers ? definedPoints.map((point) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14936
15432
  "g",
14937
15433
  {
14938
15434
  transform: `translate(${point.x}, ${point.y})`,
14939
15435
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
14940
15436
  "path",
14941
15437
  {
15438
+ ...chartElementDataProps(seriesIndex, point.pointIndex),
14942
15439
  d: markerPath,
14943
15440
  fill: series.markerColor ?? color,
14944
15441
  stroke: series.markerLineColor ?? chart.chartAreaFillColor ?? palette.surface,
@@ -14946,13 +15443,17 @@ function renderRadarChart(chart, palette, layout) {
14946
15443
  }
14947
15444
  )
14948
15445
  },
14949
- `radar-point-${seriesIndex}-${pointIndex}`
14950
- )) : 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)
14951
15452
  ] }, `radar-series-${seriesIndex}`);
14952
15453
  })
14953
15454
  ] });
14954
15455
  }
14955
- function renderPieChart(chart, palette, layout, chartType) {
15456
+ function renderPieChart(chart, palette, layout, chartType, selectedChartElement) {
14956
15457
  const pieSeriesIndex = selectPrimaryPieSeriesIndex(chart);
14957
15458
  const pieSeries = chart.series[pieSeriesIndex];
14958
15459
  const pieData = buildPieEntries(chart, pieSeriesIndex);
@@ -15104,6 +15605,16 @@ function renderPieChart(chart, palette, layout, chartType) {
15104
15605
  const midAngle = (arc.startAngle + arc.endAngle) / 2;
15105
15606
  const explodeX = Math.sin(midAngle) * explosion;
15106
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
+ })) : [];
15107
15618
  const labelRadius = outerRadius + (chartType === "PieExploded" ? 8 : 12);
15108
15619
  const labelX = centerX + Math.sin(midAngle) * labelRadius + explodeX;
15109
15620
  const labelY = centerY - Math.cos(midAngle) * labelRadius * (isPie3d ? tilt : 1) + explodeY;
@@ -15137,14 +15648,16 @@ function renderPieChart(chart, palette, layout, chartType) {
15137
15648
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { transform: `translate(${explodeX}, ${explodeY})`, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15138
15649
  "path",
15139
15650
  {
15651
+ ...chartElementDataProps(pieSeriesIndex, arc.data.index),
15140
15652
  d: arcPath(arc) ?? "",
15141
15653
  fill: arc.data.color,
15142
- stroke: sliceSeparatorColor,
15143
- strokeWidth: sliceSeparatorWidth,
15144
- transform: `translate(${centerX}, ${centerY})${isPie3d ? ` scale(1, ${tilt})` : ""}`,
15145
- 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})` : ""}`
15146
15658
  }
15147
15659
  ) }),
15660
+ isSliceSelected ? renderSelectionPointHandles(`pie-selection-${arc.data.index}`, sliceHandlePoints) : null,
15148
15661
  dataLabelsEnabled && truncatedLabelText.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15149
15662
  "text",
15150
15663
  {
@@ -15172,7 +15685,7 @@ function renderPieChart(chart, palette, layout, chartType) {
15172
15685
  ) : null
15173
15686
  ] });
15174
15687
  }
15175
- function renderBarOfPieChart(chart, palette, layout) {
15688
+ function renderBarOfPieChart(chart, palette, layout, selectedChartElement) {
15176
15689
  const pieSeriesIndex = selectPrimaryPieSeriesIndex(chart);
15177
15690
  const pieSeries = chart.series[pieSeriesIndex];
15178
15691
  const categories = getCategoryLabels(chart);
@@ -15189,10 +15702,11 @@ function renderBarOfPieChart(chart, palette, layout) {
15189
15702
  }
15190
15703
  const secondarySet = new Set(secondaryIndices);
15191
15704
  const secondaryTotal = secondaryIndices.reduce((sum, index) => sum + (values[index] ?? 0), 0);
15192
- 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 }]);
15193
15706
  if (secondaryTotal > 0) {
15194
15707
  primaryData.push({
15195
15708
  color: chartPointColor(chart, secondaryIndices[0] ?? 0, pieSeriesIndex),
15709
+ index: secondaryIndices[0] ?? 0,
15196
15710
  label: "Other",
15197
15711
  value: secondaryTotal
15198
15712
  });
@@ -15207,6 +15721,7 @@ function renderBarOfPieChart(chart, palette, layout) {
15207
15721
  const connectorTargetX = layout.plot.left + layout.plot.width * 0.69;
15208
15722
  const secondaryData = secondaryIndices.map((index) => ({
15209
15723
  color: chartPointColor(chart, index, pieSeriesIndex),
15724
+ index,
15210
15725
  label: categories[index] ?? "",
15211
15726
  value: values[index] ?? 0
15212
15727
  }));
@@ -15222,17 +15737,25 @@ function renderBarOfPieChart(chart, palette, layout) {
15222
15737
  const secondaryTotalSafe = Math.max(1e-6, secondaryTotal);
15223
15738
  let stackCursor = stackedBarTop;
15224
15739
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
15225
- pieArcs.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15226
- "path",
15227
- {
15228
- d: arc(entry) ?? "",
15229
- fill: entry.data.color,
15230
- stroke: chart.chartAreaFillColor ?? palette.surface,
15231
- strokeWidth: 1,
15232
- transform: `translate(${pieCenterX}, ${pieCenterY})`
15233
- },
15234
- `bar-of-pie-main-${index}`
15235
- )),
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
+ }),
15236
15759
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15237
15760
  "line",
15238
15761
  {
@@ -15255,33 +15778,50 @@ function renderBarOfPieChart(chart, palette, layout) {
15255
15778
  y2: layout.plot.top + layout.plot.height - 10
15256
15779
  }
15257
15780
  ),
15258
- ofPieType === "pie" ? secondaryPieArcs.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15259
- "path",
15260
- {
15261
- d: secondaryArc(entry) ?? "",
15262
- fill: entry.data.color,
15263
- stroke: chart.chartAreaFillColor ?? palette.surface,
15264
- strokeWidth: 1,
15265
- transform: `translate(${secondaryCenterX}, ${secondaryCenterY})`
15266
- },
15267
- `bar-of-pie-secondary-pie-${index}`
15268
- )) : 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) => {
15269
15800
  const segmentHeight = index === secondaryData.length - 1 ? Math.max(1, stackedBarTop + stackedBarHeight - stackCursor) : Math.max(1, entry.value / secondaryTotalSafe * stackedBarHeight);
15270
15801
  const y = stackCursor;
15271
15802
  stackCursor += segmentHeight;
15803
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, pieSeriesIndex, entry.index);
15272
15804
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
15273
15805
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15274
15806
  "rect",
15275
15807
  {
15808
+ ...chartElementDataProps(pieSeriesIndex, entry.index),
15276
15809
  fill: entry.color,
15277
15810
  height: segmentHeight,
15278
- stroke: chart.chartAreaFillColor ?? palette.surface,
15279
- strokeWidth: 1,
15811
+ stroke: selected ? "#64748b" : chart.chartAreaFillColor ?? palette.surface,
15812
+ strokeWidth: selected ? 2 : 1,
15280
15813
  width: stackedBarWidth,
15281
15814
  x: stackedBarLeft,
15282
15815
  y
15283
15816
  }
15284
15817
  ),
15818
+ selected ? renderSelectionRectHandles(
15819
+ `bar-of-pie-secondary-bar-selection-${index}`,
15820
+ stackedBarLeft,
15821
+ y,
15822
+ stackedBarWidth,
15823
+ segmentHeight
15824
+ ) : null,
15285
15825
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15286
15826
  "text",
15287
15827
  {
@@ -15297,7 +15837,7 @@ function renderBarOfPieChart(chart, palette, layout) {
15297
15837
  })
15298
15838
  ] });
15299
15839
  }
15300
- function renderSurfaceChart(chart, palette, layout) {
15840
+ function renderSurfaceChart(chart, palette, layout, selectedChartElement) {
15301
15841
  const plot = resolveSurfacePlotRect(chart, layout);
15302
15842
  const categories = getCategoryLabels(chart);
15303
15843
  const rows = chart.series.length;
@@ -15822,11 +16362,51 @@ function renderSurfaceChart(chart, palette, layout) {
15822
16362
  ) : null
15823
16363
  ] });
15824
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
+ }
15825
16405
  function indexByName(series, matcher) {
15826
16406
  const index = series.findIndex((entry) => matcher.test((entry.name ?? "").toLowerCase()));
15827
16407
  return index >= 0 ? index : null;
15828
16408
  }
15829
- function renderStockChart(chart, palette, layout) {
16409
+ function renderStockChart(chart, palette, layout, selectedChartElement) {
15830
16410
  const categories = getCategoryLabels(chart);
15831
16411
  if (categories.length === 0 || chart.series.length < 2) {
15832
16412
  return null;
@@ -15929,7 +16509,13 @@ function renderStockChart(chart, palette, layout) {
15929
16509
  const closeY = yScale(entry.close);
15930
16510
  const highY = yScale(entry.high);
15931
16511
  const lowY = yScale(entry.low);
15932
- 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
+ },
15933
16519
  hasVolume && entry.volume != null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
15934
16520
  "rect",
15935
16521
  {
@@ -15955,12 +16541,13 @@ function renderStockChart(chart, palette, layout) {
15955
16541
  y: Math.min(openY, closeY)
15956
16542
  }
15957
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 }),
15958
- 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
15959
- ] }, `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
+ );
15960
16547
  })
15961
16548
  ] });
15962
16549
  }
15963
- function renderWaterfallChart(chart, palette, layout) {
16550
+ function renderWaterfallChart(chart, palette, layout, selectedChartElement) {
15964
16551
  const stages = buildChartStages(chart);
15965
16552
  if (stages.length === 0) {
15966
16553
  return null;
@@ -16015,6 +16602,7 @@ function renderWaterfallChart(chart, palette, layout) {
16015
16602
  const fill = bar.isSubtotal ? darkenColor2(bar.color, 0.18) : bar.value >= 0 ? bar.color : lightenColor2(bar.color, 0.22);
16016
16603
  const connectorStart = index > 0 ? bars[index - 1] : null;
16017
16604
  const connectorY = connectorStart ? yScale(connectorStart.end) : 0;
16605
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16018
16606
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16019
16607
  connectorStart ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16020
16608
  "line",
@@ -16031,17 +16619,19 @@ function renderWaterfallChart(chart, palette, layout) {
16031
16619
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16032
16620
  "rect",
16033
16621
  {
16622
+ ...chartElementDataProps(0, index),
16034
16623
  fill,
16035
16624
  rx: 2,
16036
16625
  ry: 2,
16037
- stroke: darkenColor2(fill, 0.22),
16038
- strokeWidth: 1,
16626
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.22),
16627
+ strokeWidth: selected ? 2 : 1,
16039
16628
  x: bandLeft,
16040
16629
  y: top,
16041
16630
  width: bandWidth,
16042
16631
  height
16043
16632
  }
16044
16633
  ),
16634
+ selected ? renderSelectionRectHandles(`waterfall-selection-${index}`, bandLeft, top, bandWidth, height) : null,
16045
16635
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16046
16636
  "text",
16047
16637
  {
@@ -16068,7 +16658,7 @@ function renderWaterfallChart(chart, palette, layout) {
16068
16658
  })
16069
16659
  ] });
16070
16660
  }
16071
- function renderFunnelChart(chart, palette, layout) {
16661
+ function renderFunnelChart(chart, palette, layout, selectedChartElement) {
16072
16662
  const stages = buildChartStages(chart).map((stage) => ({ ...stage, value: Math.max(0, stage.value) })).filter((stage) => stage.value > 0);
16073
16663
  if (stages.length === 0) {
16074
16664
  return null;
@@ -16085,21 +16675,24 @@ function renderFunnelChart(chart, palette, layout) {
16085
16675
  const left = centerX - stageWidth * 0.5;
16086
16676
  const fill = stage.isSubtotal ? darkenColor2(stage.color, 0.14) : stage.color;
16087
16677
  const labelFitsInside = stageWidth > 90;
16678
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16088
16679
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16089
16680
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16090
16681
  "rect",
16091
16682
  {
16683
+ ...chartElementDataProps(0, index),
16092
16684
  fill,
16093
16685
  height: stageHeight,
16094
16686
  rx: 0,
16095
16687
  ry: 0,
16096
- stroke: darkenColor2(fill, 0.2),
16097
- strokeWidth: 1,
16688
+ stroke: selected ? "#64748b" : darkenColor2(fill, 0.2),
16689
+ strokeWidth: selected ? 2 : 1,
16098
16690
  width: stageWidth,
16099
16691
  x: left,
16100
16692
  y: topY
16101
16693
  }
16102
16694
  ),
16695
+ selected ? renderSelectionRectHandles(`funnel-selection-${index}`, left, topY, stageWidth, stageHeight) : null,
16103
16696
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16104
16697
  "text",
16105
16698
  {
@@ -16114,7 +16707,7 @@ function renderFunnelChart(chart, palette, layout) {
16114
16707
  ] }, `funnel-stage-${index}`);
16115
16708
  }) });
16116
16709
  }
16117
- function renderSunburstChart(chart, palette, layout) {
16710
+ function renderSunburstChart(chart, palette, layout, selectedChartElement) {
16118
16711
  const hierarchyData = buildHierarchyData(chart);
16119
16712
  if (!hierarchyData) {
16120
16713
  return null;
@@ -16141,16 +16734,19 @@ function renderSunburstChart(chart, palette, layout) {
16141
16734
  const arcSpan = node.x1 - node.x0;
16142
16735
  const canShowLabel = arcSpan * labelRadius > 26;
16143
16736
  const fill = resolveHierarchyNodeColor(chart, node);
16737
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16144
16738
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16145
16739
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16146
16740
  "path",
16147
16741
  {
16742
+ ...chartElementDataProps(0, index),
16148
16743
  d: path,
16149
16744
  fill,
16150
- stroke: palette.surface,
16151
- strokeWidth: 1
16745
+ stroke: selected ? "#64748b" : palette.surface,
16746
+ strokeWidth: selected ? 2 : 1
16152
16747
  }
16153
16748
  ),
16749
+ selected ? renderSelectionPointHandles(`sunburst-selection-${index}`, [{ x: labelX, y: labelY }]) : null,
16154
16750
  canShowLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16155
16751
  "text",
16156
16752
  {
@@ -16166,7 +16762,7 @@ function renderSunburstChart(chart, palette, layout) {
16166
16762
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { fill: chart.chartAreaFillColor ?? palette.surface, r: holeRadius - 2 })
16167
16763
  ] });
16168
16764
  }
16169
- function renderTreemapChart(chart, palette, layout) {
16765
+ function renderTreemapChart(chart, palette, layout, selectedChartElement) {
16170
16766
  const hierarchyData = buildHierarchyData(chart);
16171
16767
  if (!hierarchyData) {
16172
16768
  return null;
@@ -16178,21 +16774,24 @@ function renderTreemapChart(chart, palette, layout) {
16178
16774
  const width = Math.max(0, leaf.x1 - leaf.x0);
16179
16775
  const height = Math.max(0, leaf.y1 - leaf.y0);
16180
16776
  const canShowLabel = width > 48 && height > 22;
16777
+ const selected = isSelectedChartPointOrSeries(selectedChartElement, chart.id, 0, index);
16181
16778
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16182
16779
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16183
16780
  "rect",
16184
16781
  {
16782
+ ...chartElementDataProps(0, index),
16185
16783
  fill,
16186
16784
  rx: 3,
16187
16785
  ry: 3,
16188
- stroke: palette.surface,
16189
- strokeWidth: 1,
16786
+ stroke: selected ? "#64748b" : palette.surface,
16787
+ strokeWidth: selected ? 2 : 1,
16190
16788
  x: leaf.x0,
16191
16789
  y: leaf.y0,
16192
16790
  width,
16193
16791
  height
16194
16792
  }
16195
16793
  ),
16794
+ selected ? renderSelectionRectHandles(`treemap-selection-${index}`, leaf.x0, leaf.y0, width, height) : null,
16196
16795
  canShowLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
16197
16796
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16198
16797
  "text",
@@ -16219,7 +16818,7 @@ function renderTreemapChart(chart, palette, layout) {
16219
16818
  ] }, `treemap-leaf-${index}`);
16220
16819
  }) });
16221
16820
  }
16222
- function renderBoxWhiskerChart(chart, palette, layout) {
16821
+ function renderBoxWhiskerChart(chart, palette, layout, selectedChartElement) {
16223
16822
  const visibleSeries = chart.series.filter((series) => series.hidden !== true);
16224
16823
  if (visibleSeries.length === 0) {
16225
16824
  return null;
@@ -16325,146 +16924,145 @@ function renderBoxWhiskerChart(chart, palette, layout) {
16325
16924
  const meanY = yScale(entry.stats.mean);
16326
16925
  const visiblePoints = entry.visibility.nonoutliers ? entry.stats.visiblePoints : [];
16327
16926
  const outliers = entry.visibility.outliers ? entry.stats.outliers : [];
16328
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
16329
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16330
- "line",
16331
- {
16332
- stroke: entry.lineColor,
16333
- strokeWidth: 1.5,
16334
- x1: x,
16335
- x2: x,
16336
- y1: upperWhiskerY,
16337
- y2: boxTop
16338
- }
16339
- ),
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: [
16340
16998
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16341
16999
  "line",
16342
17000
  {
16343
- stroke: entry.lineColor,
16344
- strokeWidth: 1.5,
16345
- x1: x,
16346
- x2: x,
16347
- y1: boxBottom,
16348
- 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
16349
17007
  }
16350
17008
  ),
16351
17009
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16352
17010
  "line",
16353
17011
  {
16354
- stroke: entry.lineColor,
16355
- strokeWidth: 1.5,
16356
- x1: x - capWidth * 0.5,
16357
- x2: x + capWidth * 0.5,
16358
- y1: upperWhiskerY,
16359
- 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
16360
17018
  }
16361
- ),
16362
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16363
- "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",
16364
17025
  {
16365
- stroke: entry.lineColor,
16366
- strokeWidth: 1.5,
16367
- x1: x - capWidth * 0.5,
16368
- x2: x + capWidth * 0.5,
16369
- y1: lowerWhiskerY,
16370
- 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"
16371
17034
  }
16372
- ),
16373
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16374
- "rect",
17035
+ );
17036
+ }), outliers.map((value, pointIndex) => {
17037
+ const y = yScale(value);
17038
+ return /* @__PURE__ */ (0, import_react.createElement)(
17039
+ "circle",
16375
17040
  {
16376
- fill: lightenColor2(entry.color, 0.35),
16377
- fillOpacity: 0.72,
16378
- 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,
16379
17047
  stroke: entry.lineColor,
16380
- strokeWidth: 1.5,
16381
- width: boxWidth,
16382
- x: x - boxWidth * 0.5,
16383
- y: boxTop
16384
- }
16385
- ),
16386
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16387
- "line",
16388
- {
16389
- stroke: darkenColor2(entry.lineColor, 0.15),
16390
- strokeWidth: 2,
16391
- x1: x - boxWidth * 0.5,
16392
- x2: x + boxWidth * 0.5,
16393
- y1: medianY,
16394
- y2: medianY
17048
+ strokeWidth: 1.2
16395
17049
  }
16396
- ),
16397
- entry.visibility.meanMarker ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
16398
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16399
- "line",
16400
- {
16401
- stroke: darkenColor2(entry.lineColor, 0.18),
16402
- strokeWidth: 1.2,
16403
- x1: x - 4,
16404
- x2: x + 4,
16405
- y1: meanY - 4,
16406
- y2: meanY + 4
16407
- }
16408
- ),
16409
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16410
- "line",
16411
- {
16412
- stroke: darkenColor2(entry.lineColor, 0.18),
16413
- strokeWidth: 1.2,
16414
- x1: x - 4,
16415
- x2: x + 4,
16416
- y1: meanY + 4,
16417
- y2: meanY - 4
16418
- }
16419
- )
16420
- ] }) : null,
16421
- visiblePoints.map((value, pointIndex) => {
16422
- const y = yScale(value);
16423
- const jitter = (pointIndex % 7 - 3) * (boxWidth / 16);
16424
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16425
- "circle",
16426
- {
16427
- cx: x + jitter,
16428
- cy: y,
16429
- fill: entry.color,
16430
- fillOpacity: 0.45,
16431
- r: 2,
16432
- stroke: "none"
16433
- },
16434
- `box-whisker-visible-${index}-${pointIndex}`
16435
- );
16436
- }),
16437
- outliers.map((value, pointIndex) => {
16438
- const y = yScale(value);
16439
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16440
- "circle",
16441
- {
16442
- cx: x,
16443
- cy: y,
16444
- fill: "#ffffff",
16445
- r: 3,
16446
- stroke: entry.lineColor,
16447
- strokeWidth: 1.2
16448
- },
16449
- `box-whisker-outlier-${index}-${pointIndex}`
16450
- );
16451
- }),
16452
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16453
- "text",
16454
- {
16455
- fill: labelColor,
16456
- fontSize: 10,
16457
- textAnchor: "middle",
16458
- x,
16459
- y: layout.plot.top + layout.plot.height + 14,
16460
- children: entry.label
16461
- }
16462
- )
16463
- ] }, `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
+ ));
16464
17062
  })
16465
17063
  ] });
16466
17064
  }
16467
- function renderRegionMapChart(chart, palette, layout) {
17065
+ function renderRegionMapChart(chart, palette, layout, selectedChartElement) {
16468
17066
  const primarySeriesIndex = Math.max(0, chart.series.findIndex((series) => series.hidden !== true));
16469
17067
  const primarySeries = chart.series[primarySeriesIndex] ?? null;
16470
17068
  if (!primarySeries) {
@@ -16544,17 +17142,23 @@ function renderRegionMapChart(chart, palette, layout) {
16544
17142
  const ratio = maxValue <= minValue ? 1 : (entry.value - minValue) / Math.max(1e-6, maxValue - minValue);
16545
17143
  return resolveRegionMapValueColor(chart, primarySeriesIndex, ratio);
16546
17144
  })() : categoricalColorByLabel?.get(entry.colorLabel ?? "") ?? resolveRegionMapDataColor(chart, primarySeriesIndex);
16547
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16548
- "path",
16549
- {
16550
- d,
16551
- fill,
16552
- stroke: darkenColor2(fill, 0.18),
16553
- strokeLinejoin: "round",
16554
- strokeWidth: 0.85
16555
- },
16556
- `region-map-value-${entry.key || index}`
16557
- );
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}`);
16558
17162
  }),
16559
17163
  showRegionLabels ? entries.map((entry, index) => {
16560
17164
  const bounds = path.bounds(entry.feature);
@@ -16611,64 +17215,71 @@ function renderUnsupported(chart, palette, layout, chartType) {
16611
17215
  )
16612
17216
  ] });
16613
17217
  }
16614
- function renderChartPlot(chart, palette, layout, chartType) {
17218
+ function renderChartPlot(chart, palette, layout, chartType, selectedChartElement) {
16615
17219
  if (isComboChart(chart)) {
16616
- return renderComboChart(chart, palette, layout) ?? renderUnsupported(chart, palette, layout, "Combo");
17220
+ return renderComboChart(chart, palette, layout, selectedChartElement) ?? renderUnsupported(chart, palette, layout, "Combo");
16617
17221
  }
16618
17222
  if (chartType === "ColumnClustered" || chartType === "ColumnStacked" || chartType === "ColumnPercentStacked" || chartType === "BarClustered" || chartType === "BarStacked" || chartType === "BarPercentStacked") {
16619
- return renderBarChart(chart, palette, layout, chartType);
17223
+ return renderBarChart(chart, palette, layout, chartType, selectedChartElement);
16620
17224
  }
16621
17225
  if (chartType === "Line" || chartType === "LineStacked" || chartType === "LinePercentStacked" || chartType === "Area" || chartType === "AreaStacked" || chartType === "AreaPercentStacked") {
16622
- return renderLineOrAreaChart(chart, palette, layout, chartType);
17226
+ return renderLineOrAreaChart(chart, palette, layout, chartType, selectedChartElement);
16623
17227
  }
16624
17228
  if (chartType === "Scatter") {
16625
- return renderScatterChart(chart, palette, layout, false);
17229
+ return renderScatterChart(chart, palette, layout, false, selectedChartElement);
16626
17230
  }
16627
17231
  if (chartType === "ScatterLines") {
16628
- return renderScatterChart(chart, palette, layout, false);
17232
+ return renderScatterChart(chart, palette, layout, false, selectedChartElement);
16629
17233
  }
16630
17234
  if (chartType === "ScatterSmooth") {
16631
- return renderScatterChart(chart, palette, layout, true);
17235
+ return renderScatterChart(chart, palette, layout, true, selectedChartElement);
16632
17236
  }
16633
17237
  if (chartType === "Bubble") {
16634
- return renderBubbleChart(chart, palette, layout);
17238
+ return renderBubbleChart(chart, palette, layout, selectedChartElement);
16635
17239
  }
16636
17240
  if (chartType === "Radar") {
16637
- return renderRadarChart(chart, palette, layout);
17241
+ return renderRadarChart(chart, palette, layout, selectedChartElement);
16638
17242
  }
16639
17243
  if (chartType === "Pie" || chartType === "Pie3D" || chartType === "PieExploded" || chartType === "Doughnut") {
16640
- return renderPieChart(chart, palette, layout, chartType);
17244
+ return renderPieChart(chart, palette, layout, chartType, selectedChartElement);
16641
17245
  }
16642
17246
  if (chartType === "BarOfPie") {
16643
- return renderBarOfPieChart(chart, palette, layout);
17247
+ return renderBarOfPieChart(chart, palette, layout, selectedChartElement);
16644
17248
  }
16645
17249
  if (chartType === "Surface") {
16646
- return renderSurfaceChart(chart, palette, layout);
17250
+ return renderSurfaceChart(chart, palette, layout, selectedChartElement);
16647
17251
  }
16648
17252
  if (chartType === "Stock") {
16649
- return renderStockChart(chart, palette, layout);
17253
+ return renderStockChart(chart, palette, layout, selectedChartElement);
16650
17254
  }
16651
17255
  if (chartType === "Waterfall") {
16652
- return renderWaterfallChart(chart, palette, layout);
17256
+ return renderWaterfallChart(chart, palette, layout, selectedChartElement);
16653
17257
  }
16654
17258
  if (chartType === "Funnel") {
16655
- return renderFunnelChart(chart, palette, layout);
17259
+ return renderFunnelChart(chart, palette, layout, selectedChartElement);
16656
17260
  }
16657
17261
  if (chartType === "BoxWhisker") {
16658
- return renderBoxWhiskerChart(chart, palette, layout);
17262
+ return renderBoxWhiskerChart(chart, palette, layout, selectedChartElement);
16659
17263
  }
16660
17264
  if (chartType === "Sunburst") {
16661
- return renderSunburstChart(chart, palette, layout);
17265
+ return renderSunburstChart(chart, palette, layout, selectedChartElement);
16662
17266
  }
16663
17267
  if (chartType === "Treemap") {
16664
- return renderTreemapChart(chart, palette, layout);
17268
+ return renderTreemapChart(chart, palette, layout, selectedChartElement);
16665
17269
  }
16666
17270
  if (chartType === "RegionMap") {
16667
- return renderRegionMapChart(chart, palette, layout);
17271
+ return renderRegionMapChart(chart, palette, layout, selectedChartElement);
16668
17272
  }
16669
17273
  return renderUnsupported(chart, palette, layout, chartType);
16670
17274
  }
16671
- 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
+ }) {
16672
17283
  const renderChartType = normalizeRenderableChartType(chart);
16673
17284
  const legendItems = getLegendItems(chart, renderChartType, palette);
16674
17285
  const layout = buildLayout(chart, rect, legendItems);
@@ -16680,6 +17291,26 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16680
17291
  const normalizedBorderColor = borderColor.trim().toLowerCase();
16681
17292
  const hideBackgroundRect = normalizedBackground === "transparent" && normalizedBorderColor === "transparent";
16682
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]);
16683
17314
  if (renderChartType === "Surface") {
16684
17315
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
16685
17316
  MemoSurfaceChartComposite,
@@ -16687,10 +17318,13 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16687
17318
  background,
16688
17319
  borderColor,
16689
17320
  chart,
16690
- fallback: renderSurfaceChart(chart, palette, layout),
17321
+ fallback: renderSurfaceChart(chart, palette, layout, selectedChartElement),
16691
17322
  fontFamily,
16692
17323
  layout,
17324
+ onDoubleClick: handleDoubleClick,
17325
+ onPointerDown: handlePointerDown,
16693
17326
  overlay: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
17327
+ renderSurfaceHitOverlay(chart, layout, selectedChartElement),
16694
17328
  renderSurfaceAxes(chart, layout),
16695
17329
  renderTitle(chart, layout, palette),
16696
17330
  renderLegend(chart, layout, palette)
@@ -16703,18 +17337,20 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({ chart, palette, rect })
16703
17337
  "svg",
16704
17338
  {
16705
17339
  "aria-label": chart.title ?? chart.name ?? "Chart",
17340
+ onDoubleClick: handleDoubleClick,
17341
+ onPointerDown: handlePointerDown,
16706
17342
  role: "img",
16707
- style: { display: "block", fontFamily, height: "100%", pointerEvents: "none", width: "100%" },
17343
+ style: { display: "block", fontFamily, height: "100%", pointerEvents: "auto", width: "100%" },
16708
17344
  viewBox: `0 0 ${layout.width} ${layout.height}`,
16709
17345
  children: [
16710
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 }),
16711
17347
  renderTitle(chart, layout, palette),
16712
17348
  renderLegend(chart, layout, palette),
16713
- renderChartPlot(chart, palette, layout, renderChartType)
17349
+ renderChartPlot(chart, palette, layout, renderChartType, selectedChartElement)
16714
17350
  ]
16715
17351
  }
16716
17352
  );
16717
- }, (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);
16718
17354
 
16719
17355
  // src/XlsxViewer.tsx
16720
17356
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -16757,6 +17393,13 @@ var LIVE_ZOOM_COMMIT_IDLE_MS = 48;
16757
17393
  var WHEEL_ZOOM_SENSITIVITY = 25e-5;
16758
17394
  var WHEEL_LINE_DELTA_PX = 16;
16759
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
+ };
16760
17403
  var SHEET_SURFACE = "#ffffff";
16761
17404
  var DRAWING_SELECTION_STROKE = "#64748b";
16762
17405
  var DRAWING_SELECTION_HANDLE_FILL = "#ffffff";
@@ -19691,23 +20334,57 @@ function resolveChartFormulaRange(formula, fallbackSheetIndex, sheets, workbook)
19691
20334
  workbookSheetIndex
19692
20335
  };
19693
20336
  }
19694
- 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) {
19695
20354
  if (!chart) {
19696
20355
  return [];
19697
20356
  }
19698
20357
  const highlights = [];
19699
20358
  const seenRanges = /* @__PURE__ */ new Set();
19700
- const references = chart.series.flatMap((series) => [
19701
- series.categoriesRef?.formula,
19702
- typeof series.raw?.name === "string" ? series.raw.name : void 0,
19703
- series.valuesRef?.formula,
19704
- 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
+ }
19705
20382
  ]);
19706
- references.forEach((formula) => {
19707
- if (!formula) {
20383
+ references.forEach((reference) => {
20384
+ if (!reference.formula) {
19708
20385
  return;
19709
20386
  }
19710
- const resolved = resolveChartFormulaRange(formula, chart.workbookSheetIndex, sheets, workbook);
20387
+ const resolved = resolveChartFormulaRange(reference.formula, chart.workbookSheetIndex, sheets, workbook);
19711
20388
  if (!resolved) {
19712
20389
  return;
19713
20390
  }
@@ -19722,7 +20399,7 @@ function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
19722
20399
  return;
19723
20400
  }
19724
20401
  seenRanges.add(key);
19725
- 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];
19726
20403
  highlights.push({
19727
20404
  fillColor: applyAlphaToColor(strokeColor, isDark ? 0.24 : 0.14),
19728
20405
  range: resolved.range,
@@ -19730,6 +20407,28 @@ function collectChartRangeHighlights(chart, sheets, workbook, isDark) {
19730
20407
  workbookSheetIndex: resolved.workbookSheetIndex
19731
20408
  });
19732
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
+ }
19733
20432
  return highlights;
19734
20433
  }
19735
20434
  function clampSparklineValue(value, min, max) {
@@ -21787,11 +22486,13 @@ function XlsxGrid({
21787
22486
  redo,
21788
22487
  revision,
21789
22488
  selectedChart,
22489
+ selectedChartElement,
21790
22490
  selectedChartId,
21791
22491
  selectedImage,
21792
22492
  selectedImageId,
21793
22493
  selectCell,
21794
22494
  selectChart,
22495
+ selectChartElement,
21795
22496
  selectImage,
21796
22497
  selectRange,
21797
22498
  selection,
@@ -23700,8 +24401,8 @@ function XlsxGrid({
23700
24401
  return map;
23701
24402
  }, [activeSheet?.sparklines]);
23702
24403
  const chartRangeHighlights = React4.useMemo(
23703
- () => collectChartRangeHighlights(selectedChart, sheets, workbook, paletteIsDark(palette)),
23704
- [palette, selectedChart, sheets, workbook]
24404
+ () => collectChartRangeHighlights(selectedChart, selectedChartElement, sheets, workbook, paletteIsDark(palette)),
24405
+ [palette, selectedChart, selectedChartElement, sheets, workbook]
23705
24406
  );
23706
24407
  const activeSheetChartHighlights = React4.useMemo(
23707
24408
  () => activeSheet ? chartRangeHighlights.filter((highlight) => highlight.workbookSheetIndex === activeSheet.workbookSheetIndex) : [],
@@ -23716,6 +24417,7 @@ function XlsxGrid({
23716
24417
  getCellStyle,
23717
24418
  palette,
23718
24419
  revision,
24420
+ selectedChartElement,
23719
24421
  selectedChartId,
23720
24422
  viewportRowBatch,
23721
24423
  worksheet,
@@ -23729,6 +24431,7 @@ function XlsxGrid({
23729
24431
  getCellStyle,
23730
24432
  palette,
23731
24433
  revision,
24434
+ selectedChartElement,
23732
24435
  selectedChartId,
23733
24436
  viewportRowBatch,
23734
24437
  worksheet,
@@ -26924,6 +27627,13 @@ function XlsxGrid({
26924
27627
  }
26925
27628
  selectChart(chart.id);
26926
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]);
26927
27637
  if (isLoading) {
26928
27638
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderLoading(loadingComponent, loadingState, palette) });
26929
27639
  }
@@ -26973,7 +27683,17 @@ function XlsxGrid({
26973
27683
  },
26974
27684
  children: charts.length > 0 ? charts.map((chart) => {
26975
27685
  const chartsheetRect = { height: 320, left: 0, top: 0, width: 640 };
26976
- 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);
26977
27697
  }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
26978
27698
  "div",
26979
27699
  {
@@ -27647,7 +28367,6 @@ function XlsxGrid({
27647
28367
  }
27648
28368
  ) : null;
27649
28369
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React4.Fragment, { children: [
27650
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style, children: isChartsLoading ? renderChartLoadingNode(renderChartLoading, chart, rect) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MemoChartSvg, { chart, palette, rect }) }),
27651
28370
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
27652
28371
  "div",
27653
28372
  {
@@ -27655,11 +28374,20 @@ function XlsxGrid({
27655
28374
  onPointerDown: (event) => startChartMove(event, chart, rect),
27656
28375
  style: {
27657
28376
  ...style,
27658
- background: "transparent",
27659
28377
  cursor: canEditChart && selectedChartId === chart.id ? "move" : "cell",
27660
- pointerEvents: "auto",
27661
- zIndex: isFrozenDrawing ? chart.zIndex + 21 : chart.zIndex + 1
27662
- }
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
+ )
27663
28391
  }
27664
28392
  ),
27665
28393
  selectionNode
@@ -27742,7 +28470,7 @@ function XlsxGrid({
27742
28470
  };
27743
28471
  const drawingViewportCacheSignature = `${Math.floor(drawingViewport.left / CANVAS_VIEWPORT_OVERSCAN_PX)}:${Math.floor(drawingViewport.top / CANVAS_VIEWPORT_OVERSCAN_PX)}:${drawingViewport.width}:${drawingViewport.height}`;
27744
28472
  const previousPaneDrawingNodes = paneDrawingNodesCacheRef.current;
27745
- 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;
27746
28474
  const paneDrawingNodes = canReusePaneDrawingNodes ? previousPaneDrawingNodes.value : !showImages ? {
27747
28475
  corner: null,
27748
28476
  left: null,
@@ -27786,6 +28514,7 @@ function XlsxGrid({
27786
28514
  renderChartLoading,
27787
28515
  renderImage,
27788
28516
  renderImageSelection,
28517
+ selectedChartElement,
27789
28518
  selectedChartId,
27790
28519
  selectedImageId,
27791
28520
  selectionStroke,
@@ -29202,12 +29931,16 @@ function useXlsxViewerEditing() {
29202
29931
  removeActiveSheet,
29203
29932
  readOnly,
29204
29933
  redo,
29934
+ selectedCellFormula,
29935
+ selectedChartFormula,
29205
29936
  selectedFormula,
29937
+ selectedFormulaTarget,
29206
29938
  selectedValue,
29207
29939
  setCellFormula,
29208
29940
  setCellStyle,
29209
29941
  setCellValue,
29210
29942
  setRangeStyle,
29943
+ setSelectedFormula,
29211
29944
  setSelectedCellFormula,
29212
29945
  setSelectedCellStyle,
29213
29946
  setSelectedCellValue,
@@ -29233,12 +29966,16 @@ function useXlsxViewerEditing() {
29233
29966
  removeActiveSheet,
29234
29967
  readOnly,
29235
29968
  redo,
29969
+ selectedCellFormula,
29970
+ selectedChartFormula,
29236
29971
  selectedFormula,
29972
+ selectedFormulaTarget,
29237
29973
  selectedValue,
29238
29974
  setCellFormula,
29239
29975
  setCellStyle,
29240
29976
  setCellValue,
29241
29977
  setRangeStyle,
29978
+ setSelectedFormula,
29242
29979
  setSelectedCellFormula,
29243
29980
  setSelectedCellStyle,
29244
29981
  setSelectedCellValue,
@@ -29263,12 +30000,16 @@ function useXlsxViewerEditing() {
29263
30000
  removeActiveSheet,
29264
30001
  readOnly,
29265
30002
  redo,
30003
+ selectedCellFormula,
30004
+ selectedChartFormula,
29266
30005
  selectedFormula,
30006
+ selectedFormulaTarget,
29267
30007
  selectedValue,
29268
30008
  setCellFormula,
29269
30009
  setCellStyle,
29270
30010
  setCellValue,
29271
30011
  setRangeStyle,
30012
+ setSelectedFormula,
29272
30013
  setSelectedCellFormula,
29273
30014
  setSelectedCellStyle,
29274
30015
  setSelectedCellValue,
@@ -29292,8 +30033,10 @@ function useXlsxViewerImages() {
29292
30033
  const {
29293
30034
  charts,
29294
30035
  clearSelectedChart,
30036
+ clearSelectedChartElement,
29295
30037
  clearSelectedImage,
29296
30038
  getChartById,
30039
+ getChartSeriesFormula,
29297
30040
  getSheetCharts,
29298
30041
  getImageById,
29299
30042
  getSheetImages,
@@ -29305,11 +30048,15 @@ function useXlsxViewerImages() {
29305
30048
  resizeChartBy,
29306
30049
  resizeImageBy,
29307
30050
  selectedChart,
30051
+ selectedChartElement,
30052
+ selectedChartFormula,
29308
30053
  selectedChartId,
29309
30054
  selectedImage,
29310
30055
  selectedImageId,
29311
30056
  selectChart,
30057
+ selectChartElement,
29312
30058
  selectImage,
30059
+ setChartSeriesFormula,
29313
30060
  setChartRect,
29314
30061
  setImageRect,
29315
30062
  updateChart
@@ -29318,8 +30065,10 @@ function useXlsxViewerImages() {
29318
30065
  () => ({
29319
30066
  charts,
29320
30067
  clearSelectedChart,
30068
+ clearSelectedChartElement,
29321
30069
  clearSelectedImage,
29322
30070
  getChartById,
30071
+ getChartSeriesFormula,
29323
30072
  getSheetCharts,
29324
30073
  getImageById,
29325
30074
  getSheetImages,
@@ -29331,11 +30080,15 @@ function useXlsxViewerImages() {
29331
30080
  resizeChartBy,
29332
30081
  resizeImageBy,
29333
30082
  selectedChart,
30083
+ selectedChartElement,
30084
+ selectedChartFormula,
29334
30085
  selectedChartId,
29335
30086
  selectedImage,
29336
30087
  selectedImageId,
29337
30088
  selectChart,
30089
+ selectChartElement,
29338
30090
  selectImage,
30091
+ setChartSeriesFormula,
29339
30092
  setChartRect,
29340
30093
  setImageRect,
29341
30094
  updateChart
@@ -29343,8 +30096,10 @@ function useXlsxViewerImages() {
29343
30096
  [
29344
30097
  charts,
29345
30098
  clearSelectedChart,
30099
+ clearSelectedChartElement,
29346
30100
  clearSelectedImage,
29347
30101
  getChartById,
30102
+ getChartSeriesFormula,
29348
30103
  getSheetCharts,
29349
30104
  getImageById,
29350
30105
  getSheetImages,
@@ -29356,11 +30111,15 @@ function useXlsxViewerImages() {
29356
30111
  resizeChartBy,
29357
30112
  resizeImageBy,
29358
30113
  selectedChart,
30114
+ selectedChartElement,
30115
+ selectedChartFormula,
29359
30116
  selectedChartId,
29360
30117
  selectedImage,
29361
30118
  selectedImageId,
29362
30119
  selectChart,
30120
+ selectChartElement,
29363
30121
  selectImage,
30122
+ setChartSeriesFormula,
29364
30123
  setChartRect,
29365
30124
  setImageRect,
29366
30125
  updateChart
@@ -29374,7 +30133,9 @@ function useXlsxViewerCharts() {
29374
30133
  charts,
29375
30134
  chartsheets,
29376
30135
  clearSelectedChart,
30136
+ clearSelectedChartElement,
29377
30137
  getChartById,
30138
+ getChartSeriesFormula,
29378
30139
  getChartsheetById,
29379
30140
  getSheetCharts,
29380
30141
  isChartsLoading,
@@ -29383,8 +30144,12 @@ function useXlsxViewerCharts() {
29383
30144
  resizeChartBy,
29384
30145
  selectChart,
29385
30146
  selectedChart,
30147
+ selectedChartElement,
30148
+ selectedChartFormula,
29386
30149
  selectedChartId,
30150
+ selectChartElement,
29387
30151
  setActiveTabIndex,
30152
+ setChartSeriesFormula,
29388
30153
  setChartRect,
29389
30154
  tabs,
29390
30155
  updateChart
@@ -29396,7 +30161,9 @@ function useXlsxViewerCharts() {
29396
30161
  charts,
29397
30162
  chartsheets,
29398
30163
  clearSelectedChart,
30164
+ clearSelectedChartElement,
29399
30165
  getChartById,
30166
+ getChartSeriesFormula,
29400
30167
  getChartsheetById,
29401
30168
  getSheetCharts,
29402
30169
  isChartsLoading,
@@ -29405,8 +30172,12 @@ function useXlsxViewerCharts() {
29405
30172
  resizeChartBy,
29406
30173
  selectChart,
29407
30174
  selectedChart,
30175
+ selectedChartElement,
30176
+ selectedChartFormula,
29408
30177
  selectedChartId,
30178
+ selectChartElement,
29409
30179
  setActiveTabIndex,
30180
+ setChartSeriesFormula,
29410
30181
  setChartRect,
29411
30182
  tabs,
29412
30183
  updateChart
@@ -29417,7 +30188,9 @@ function useXlsxViewerCharts() {
29417
30188
  charts,
29418
30189
  chartsheets,
29419
30190
  clearSelectedChart,
30191
+ clearSelectedChartElement,
29420
30192
  getChartById,
30193
+ getChartSeriesFormula,
29421
30194
  getChartsheetById,
29422
30195
  getSheetCharts,
29423
30196
  isChartsLoading,
@@ -29426,8 +30199,12 @@ function useXlsxViewerCharts() {
29426
30199
  resizeChartBy,
29427
30200
  selectChart,
29428
30201
  selectedChart,
30202
+ selectedChartElement,
30203
+ selectedChartFormula,
29429
30204
  selectedChartId,
30205
+ selectChartElement,
29430
30206
  setActiveTabIndex,
30207
+ setChartSeriesFormula,
29431
30208
  setChartRect,
29432
30209
  tabs,
29433
30210
  updateChart