@odoo/o-spreadsheet 19.3.18 → 19.3.20

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.3.18
6
- * @date 2026-08-29T09:16:28.272Z
7
- * @hash 1f4b1ae
5
+ * @version 19.3.20
6
+ * @date 2026-09-10T05:38:03.233Z
7
+ * @hash e488e8d
8
8
  */
9
9
 
10
10
  import { App, Component, blockDom, markRaw, onMounted, onPatched, onWillPatch, onWillStart, onWillUnmount, onWillUpdateProps, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, whenReady, xml } from "@odoo/owl";
@@ -9592,16 +9592,16 @@ const chartShowValuesPlugin = {
9592
9592
  drawLineOrBarOrRadarChartValues(chart, options, ctx);
9593
9593
  break;
9594
9594
  case "bar":
9595
- options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9595
+ options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true }) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9596
9596
  break;
9597
9597
  case "pyramid":
9598
- drawHorizontalBarChartValues(chart, options, ctx);
9598
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true });
9599
9599
  break;
9600
9600
  case "calendar":
9601
9601
  drawBarChartValues(chart, options, ctx);
9602
9602
  break;
9603
9603
  case "funnel":
9604
- drawHorizontalBarChartValues(chart, options, ctx);
9604
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: false });
9605
9605
  break;
9606
9606
  }
9607
9607
  ctx.restore();
@@ -9625,7 +9625,7 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
9625
9625
  const point = dataset.data[i];
9626
9626
  const xPosition = point.x;
9627
9627
  let yPosition = 0;
9628
- if (chart.config.type === "line" || chart.config.type === "radar") yPosition = value < 0 ? point.y + 10 : point.y - 10;
9628
+ if (dataset.type === "line" || dataset.type === "radar") yPosition = value < 0 ? point.y + 10 : point.y - 10;
9629
9629
  else {
9630
9630
  const yZeroLine = yAxisScale.getPixelForValue(0);
9631
9631
  const distanceFromAxisOrigin = Math.abs(yZeroLine - point.y);
@@ -9671,7 +9671,7 @@ function drawBarChartValues(chart, options, ctx) {
9671
9671
  }
9672
9672
  }
9673
9673
  }
9674
- function drawHorizontalBarChartValues(chart, options, ctx) {
9674
+ function drawHorizontalBarChartValues(chart, options, ctx, args) {
9675
9675
  const textsPositions = {};
9676
9676
  for (const dataset of chart._metasets) {
9677
9677
  if (isTrendLineAxis(dataset.xAxisID)) return;
@@ -9686,7 +9686,7 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
9686
9686
  const distanceFromAxisOrigin = Math.abs(point.x - xZeroLine);
9687
9687
  const PADDING = 3;
9688
9688
  let xPosition;
9689
- if (distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9689
+ if (args.offsetFromAxisOrigin && distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9690
9690
  else xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
9691
9691
  if (!textsPositions[yPosition]) textsPositions[yPosition] = [];
9692
9692
  for (const otherPosition of textsPositions[yPosition]) if (Math.abs(otherPosition - xPosition) < textWidth) xPosition = value < 0 ? otherPosition - textWidth - PADDING : otherPosition + textWidth + PADDING;
@@ -18573,7 +18573,7 @@ const RemoveDuplicateTerms = { Errors: {
18573
18573
  ["MoreThanOneRangeSelected"]: _t("Please select only one range of cells"),
18574
18574
  ["EmptySelectedRange"]: _t("Please select a range of cells containing values."),
18575
18575
  ["NoColumnsProvided"]: _t("Please select at latest one column to analyze."),
18576
- ["WillRemoveExistingMerge"]: _t("This operation is not possible due to a merge. Please remove the merges first than try again.")
18576
+ ["WillRemoveExistingMerge"]: _t("Cannot perform this action on merged cells. Unmerge the cells and try again.")
18577
18577
  } };
18578
18578
  const DVTerms = {
18579
18579
  DateIs: {
@@ -25445,9 +25445,10 @@ var Composer = class extends Component {
25445
25445
  compositionActive = false;
25446
25446
  spreadsheetRect = useSpreadsheetRect();
25447
25447
  lastHoveredTokenIndex = void 0;
25448
- debouncedHover = debounce((tokenIndex, hoveredRect) => {
25448
+ debouncedHover = debounce((tokenIndex, composerContent, hoveredRect) => {
25449
25449
  const selection = this.contentHelper.getCurrentSelection();
25450
- if (selection.start !== selection.end) return;
25450
+ const currentContent = this.props.composerStore.currentContent;
25451
+ if (selection.start !== selection.end || currentContent !== composerContent) return;
25451
25452
  const currentHoveredContext = this.props.composerStore.hoveredTokens;
25452
25453
  this.props.composerStore.hoverToken(tokenIndex);
25453
25454
  if (!deepEquals(currentHoveredContext, this.props.composerStore.hoveredTokens)) this.composerState.hoveredRect = hoveredRect;
@@ -25765,7 +25766,8 @@ var Composer = class extends Component {
25765
25766
  onTokenHover(tokenIndex, hoveredRect) {
25766
25767
  if (this.lastHoveredTokenIndex !== tokenIndex) {
25767
25768
  this.lastHoveredTokenIndex = tokenIndex;
25768
- this.debouncedHover(tokenIndex, hoveredRect);
25769
+ const composerContent = this.props.composerStore.currentContent;
25770
+ this.debouncedHover(tokenIndex, composerContent, hoveredRect);
25769
25771
  }
25770
25772
  }
25771
25773
  /**
@@ -26812,7 +26814,7 @@ var AbstractComposerStore = class extends SpreadsheetStore {
26812
26814
  col: range.zone.left,
26813
26815
  row: range.zone.top
26814
26816
  });
26815
- if (spreadZone) return this.getters.getRangeFromZone(sheetId, spreadZone);
26817
+ if (spreadZone) return this.getters.getRangeFromZone(range.sheetId, spreadZone);
26816
26818
  return range;
26817
26819
  }
26818
26820
  updateAutoCompleteProvider() {
@@ -32823,433 +32825,6 @@ var ChartRangeDataSourceComponent = class extends Component {
32823
32825
  }
32824
32826
  };
32825
32827
 
32826
- //#endregion
32827
- //#region src/helpers/figures/chart.ts
32828
- var SpreadsheetChart = class SpreadsheetChart {
32829
- getters;
32830
- sheetId;
32831
- definition;
32832
- chartTypeBuilder;
32833
- dataSourceBuilder;
32834
- dataSource;
32835
- constructor(getters, sheetId, definition, chartTypeBuilder, dataSourceBuilder) {
32836
- this.getters = getters;
32837
- this.sheetId = sheetId;
32838
- this.definition = definition;
32839
- this.chartTypeBuilder = chartTypeBuilder;
32840
- this.dataSourceBuilder = dataSourceBuilder;
32841
- this.dataSource = definition.dataSource;
32842
- }
32843
- static fromStrDefinition(getters, sheetId, definition) {
32844
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
32845
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
32846
- const dataSource = dataSourceBuilder.fromExternalDefinition(definition.dataSource ?? { type: "none" }, sheetId, getters);
32847
- const rangeDefinition = {
32848
- ...chartTypeBuilder.fromStrDefinition(definition, sheetId, getters),
32849
- dataSource
32850
- };
32851
- return new SpreadsheetChart(getters, sheetId, SpreadsheetChart.deleteInvalidKeys(rangeDefinition), chartTypeBuilder, dataSourceBuilder);
32852
- }
32853
- static fromDefinition(getters, sheetId, definition) {
32854
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
32855
- return new SpreadsheetChart(getters, sheetId, definition, chartTypeRegistry.get(definition.type), dataSourceBuilder);
32856
- }
32857
- static validate(validator, definition) {
32858
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
32859
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
32860
- return validator.batchValidations(() => chartTypeBuilder.validateDefinition(validator, definition), () => dataSourceBuilder.validate(definition.dataSource ?? { type: "none" }, validator))(void 0);
32861
- }
32862
- static transformDefinition(chartSheetId, definition, rangeAdapters) {
32863
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
32864
- if (!definition.dataSource) return chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters);
32865
- const newDataSource = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none").transform(definition.dataSource, chartSheetId, rangeAdapters);
32866
- return {
32867
- ...chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters),
32868
- dataSource: newDataSource
32869
- };
32870
- }
32871
- getRangeDefinition() {
32872
- return {
32873
- ...this.definition,
32874
- dataSource: this.dataSource
32875
- };
32876
- }
32877
- getDefinition() {
32878
- return {
32879
- ...this.chartTypeBuilder.toStrDefinition(this.definition, this.sheetId, this.getters),
32880
- dataSource: this.dataSource && this.dataSourceBuilder.getDefinition(this.dataSource, this.sheetId, this.getters)
32881
- };
32882
- }
32883
- updateRanges(rangeAdapters) {
32884
- return {
32885
- ...this.chartTypeBuilder.updateRanges(this.definition, rangeAdapters, this.sheetId),
32886
- dataSource: this.dataSource && this.dataSourceBuilder.adaptRanges(this.dataSource, rangeAdapters)
32887
- };
32888
- }
32889
- duplicateInDuplicatedSheet(sheetIdFrom, sheetIdTo) {
32890
- const newDataSource = this.dataSource && this.dataSourceBuilder.duplicateInDuplicatedSheet(this.dataSource, sheetIdFrom, sheetIdTo, this.getters);
32891
- const definition = {
32892
- ...this.chartTypeBuilder.duplicateInDuplicatedSheet(this.definition, sheetIdFrom, sheetIdTo, this.getters),
32893
- dataSource: newDataSource
32894
- };
32895
- return SpreadsheetChart.fromDefinition(this.getters, sheetIdTo, definition).getDefinition();
32896
- }
32897
- copyInSheetId(sheetIdTo) {
32898
- return {
32899
- ...this.chartTypeBuilder.copyInSheetId(this.definition, this.sheetId, sheetIdTo, this.getters),
32900
- dataSource: this.dataSource
32901
- };
32902
- }
32903
- getContextCreation() {
32904
- const definition = this.getDefinition();
32905
- return {
32906
- ...this.dataSourceBuilder.getContextCreation(definition.dataSource ?? { type: "none" }),
32907
- ...this.chartTypeBuilder.getContextCreation(definition, this.dataSourceBuilder, definition.dataSource)
32908
- };
32909
- }
32910
- getDefinitionForExcel(getters) {
32911
- const definition = this.definition;
32912
- const excelDataSets = this.dataSourceBuilder.toExcelDataSets(this.dataSource, "dataSetStyles" in definition ? definition.dataSetStyles : {}, getters);
32913
- if (excelDataSets === void 0) return;
32914
- return this.chartTypeBuilder.getDefinitionForExcel(getters, definition, excelDataSets);
32915
- }
32916
- getData(getters, chartId) {
32917
- const dataSource = this.dataSource;
32918
- return dataSource ? this.dataSourceBuilder.extractData(dataSource, chartId, getters) : {
32919
- dataSetsValues: [],
32920
- labelValues: []
32921
- };
32922
- }
32923
- getRuntime(getters, chartId) {
32924
- const dataSource = this.dataSource;
32925
- const dataExtractors = dataSource ? {
32926
- extractData: () => this.dataSourceBuilder.extractData(dataSource, chartId, getters),
32927
- extractHierarchicalData: () => this.dataSourceBuilder.extractHierarchicalData(dataSource, chartId, getters)
32928
- } : {
32929
- extractData: () => ({
32930
- dataSetsValues: [],
32931
- labelValues: []
32932
- }),
32933
- extractHierarchicalData: () => ({
32934
- dataSetsValues: [],
32935
- labelValues: []
32936
- })
32937
- };
32938
- return this.chartTypeBuilder.getRuntime(getters, this.definition, dataExtractors, this.sheetId, {
32939
- onClick: (event, items, chartJsChart) => {
32940
- return this.dataSourceBuilder.onDataSetClick?.(this.definition.type, chartId, event, items, chartJsChart, getters);
32941
- },
32942
- onHover: (event, items, chartJsChart) => this.dataSourceBuilder.onDataSetHover?.(this.definition.type, chartId, event, items, chartJsChart)
32943
- });
32944
- }
32945
- static deleteInvalidKeys(definition) {
32946
- definition = { ...definition };
32947
- const keys = new Set(chartTypeRegistry.get(definition.type).allowedDefinitionKeys);
32948
- for (const key of Object.keys(definition)) if (!keys.has(key)) delete definition[key];
32949
- return definition;
32950
- }
32951
- };
32952
-
32953
- //#endregion
32954
- //#region src/helpers/figures/charts/chart_data_sources.ts
32955
- const EMPTY = Object.freeze({ value: null });
32956
- const ONE = Object.freeze({ value: 1 });
32957
- const ChartRangeDataSourceHandler = {
32958
- supportedChartTypes: CHART_TYPES,
32959
- fromExternalDefinition(dataSource, defaultSheetId, getters) {
32960
- const dataSets = createDataSets(getters, defaultSheetId, dataSource);
32961
- const labelRange = createValidRange(getters, defaultSheetId, dataSource.labelRange);
32962
- return {
32963
- ...dataSource,
32964
- dataSets,
32965
- labelRange
32966
- };
32967
- },
32968
- fromContextCreation(context) {
32969
- return {
32970
- type: "range",
32971
- dataSets: [],
32972
- dataSetsHaveTitle: false,
32973
- labelRange: context.auxiliaryRange,
32974
- ...context.dataSource
32975
- };
32976
- },
32977
- fromHierarchicalContextCreation(context) {
32978
- if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
32979
- type: "range",
32980
- dataSets: [],
32981
- dataSetsHaveTitle: false
32982
- };
32983
- let dataSource = {
32984
- type: "range",
32985
- dataSets: [],
32986
- dataSetsHaveTitle: context.dataSource?.dataSetsHaveTitle ?? false,
32987
- labelRange: context.dataSource?.dataSets?.[0]?.dataRange
32988
- };
32989
- if (context.hierarchicalDataSource?.dataSets.length) dataSource = context.hierarchicalDataSource;
32990
- else if (context.auxiliaryRange) dataSource = {
32991
- ...dataSource,
32992
- dataSets: [{
32993
- dataRange: context.auxiliaryRange,
32994
- dataSetId: "0"
32995
- }]
32996
- };
32997
- return dataSource;
32998
- },
32999
- validate: (dataSource, validator) => validator.checkValidations(dataSource, checkDataset, checkLabelRange),
33000
- transform(dataSource, defaultSheetId, { adaptRangeString }) {
33001
- let labelRange;
33002
- if (dataSource.labelRange) {
33003
- const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSource.labelRange);
33004
- if (changeType !== "REMOVE") labelRange = adaptedRange;
33005
- }
33006
- const dataSets = [];
33007
- for (const dataSet of dataSource.dataSets) {
33008
- const newDataSet = { ...dataSet };
33009
- const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSet.dataRange);
33010
- if (changeType !== "REMOVE") {
33011
- newDataSet.dataRange = adaptedRange;
33012
- dataSets.push(newDataSet);
33013
- }
33014
- }
33015
- return {
33016
- ...dataSource,
33017
- dataSets,
33018
- labelRange
33019
- };
33020
- },
33021
- extractData: (dataSource, chartId, getters) => getChartData(getters, dataSource),
33022
- extractHierarchicalData(dataSource, chartId, getters) {
33023
- const dataSets = dataSource.dataSets;
33024
- const labelRange = dataSource.labelRange;
33025
- const labelValues = getChartLabelValues(getters, dataSets, labelRange);
33026
- const dataSetsValues = getHierarchicalDatasetValues(getters, dataSets);
33027
- const data = {
33028
- labelValues,
33029
- dataSetsValues
33030
- };
33031
- if (shouldRemoveFirstLabel(labelValues.length, dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0), dataSource.dataSetsHaveTitle || false)) labelValues.shift();
33032
- return data;
33033
- },
33034
- adaptRanges(dataSource, { applyChange }) {
33035
- const dataSetsWithUndefined = dataSource.dataSets.map((ds) => {
33036
- const { range: adaptedRangeStr, changeType } = applyChange(ds.dataRange);
33037
- if (changeType === "REMOVE") return;
33038
- let labelCell = void 0;
33039
- if (ds.labelCell) {
33040
- const { range: adaptedLabelCellRange, changeType: labelCellChangeType } = applyChange(ds.labelCell);
33041
- if (labelCellChangeType !== "REMOVE") labelCell = adaptedLabelCellRange;
33042
- }
33043
- return {
33044
- ...ds,
33045
- dataRange: adaptedRangeStr,
33046
- labelCell
33047
- };
33048
- }).filter(isDefined);
33049
- let labelRange = dataSource.labelRange;
33050
- if (labelRange) {
33051
- const { range: adaptedLabelRange, changeType } = applyChange(labelRange);
33052
- if (changeType === "REMOVE") labelRange = void 0;
33053
- else labelRange = adaptedLabelRange;
33054
- }
33055
- const dataSets = dataSetsWithUndefined;
33056
- return {
33057
- ...dataSource,
33058
- dataSets,
33059
- labelRange: labelRange?.invalidSheetName || labelRange?.invalidXc ? void 0 : labelRange
33060
- };
33061
- },
33062
- getDefinition(dataSource, defaultSheetId, getters) {
33063
- return {
33064
- labelRange: dataSource.labelRange ? getters.getRangeString(dataSource.labelRange, defaultSheetId) : void 0,
33065
- type: "range",
33066
- dataSets: dataSource.dataSets.map((dataSet) => ({
33067
- dataSetId: dataSet.dataSetId,
33068
- dataRange: getters.getRangeString(dataSet.dataRange, defaultSheetId)
33069
- })),
33070
- dataSetsHaveTitle: dataSource.dataSetsHaveTitle
33071
- };
33072
- },
33073
- /**
33074
- * Duplicate the dataSets. All ranges on sheetIdFrom are adapted to target
33075
- * sheetIdTo.
33076
- */
33077
- duplicateInDuplicatedSheet(dataSource, sheetIdFrom, sheetIdTo, getters) {
33078
- return {
33079
- ...dataSource,
33080
- labelRange: duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, dataSource.labelRange),
33081
- dataSets: dataSource.dataSets.map((ds) => ({
33082
- ...ds,
33083
- dataRange: duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.dataRange)
33084
- }))
33085
- };
33086
- },
33087
- getContextCreation: (dataSource) => ({
33088
- auxiliaryRange: dataSource.labelRange,
33089
- dataSource
33090
- }),
33091
- getHierarchicalContextCreation(dataSource) {
33092
- const leafRange = dataSource.dataSets.at(-1)?.dataRange;
33093
- const dataSetsHaveTitle = dataSource.dataSetsHaveTitle;
33094
- return {
33095
- auxiliaryRange: leafRange,
33096
- hierarchicalDataSource: dataSource,
33097
- dataSource: dataSource.labelRange ? {
33098
- type: "range",
33099
- dataSets: [{
33100
- dataRange: dataSource.labelRange,
33101
- dataSetId: "0"
33102
- }],
33103
- dataSetsHaveTitle
33104
- } : {
33105
- type: "range",
33106
- dataSets: [],
33107
- dataSetsHaveTitle
33108
- }
33109
- };
33110
- },
33111
- toExcelDataSets(dataSource, dataSetStyles, getters) {
33112
- const dataSets = dataSource.dataSets;
33113
- const labelRange = dataSource.labelRange;
33114
- const excelDataSets = dataSets.map((ds) => toExcelDataset(getters, dataSetStyles, ds)).filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
33115
- const datasetLength = dataSets[0] ? getZoneArea(dataSets[0].dataRange.zone) : void 0;
33116
- return {
33117
- dataSets: excelDataSets,
33118
- labelRange: toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel(labelRange ? getZoneArea(labelRange.zone) : 0, datasetLength, dataSource.dataSetsHaveTitle))
33119
- };
33120
- }
33121
- };
33122
- function getChartData(getters, dataSource) {
33123
- const dataSets = dataSource.dataSets;
33124
- const labelRange = dataSource.labelRange;
33125
- const labelValues = getChartLabelValues(getters, dataSets, labelRange);
33126
- const dataSetsValues = getChartDatasetValues(getters, dataSets);
33127
- const data = {
33128
- labelValues,
33129
- dataSetsValues
33130
- };
33131
- const numberOfDataPoints = dataSetsValues.length ? dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0) : 0;
33132
- if (shouldRemoveFirstLabel(labelValues.length, numberOfDataPoints, dataSource.dataSetsHaveTitle || false)) labelValues.shift();
33133
- return data;
33134
- }
33135
- function getChartDatasetValues(getters, dataSets) {
33136
- const datasetValues = [];
33137
- for (const [dsIndex, ds] of Object.entries(dataSets)) {
33138
- let label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`;
33139
- let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
33140
- if (ds.labelCell) {
33141
- const { sheetId, zone } = ds.labelCell;
33142
- const cell = getters.getEvaluatedCell({
33143
- sheetId,
33144
- col: zone.left,
33145
- row: zone.top
33146
- });
33147
- if (cell) label = cell.formattedValue;
33148
- }
33149
- let data = ds.dataRange ? getData(getters, ds) : [];
33150
- if (data.every((cell) => !cell.value || isTextResult(cell)) && data.filter(isTextResult).length > 1) data = data.map((cell) => cell.value && !isErrorResult(cell) ? ONE : EMPTY);
33151
- else if (data.every((cell) => !isNumberResult(cell))) hidden = true;
33152
- datasetValues.push({
33153
- data,
33154
- label,
33155
- hidden,
33156
- dataSetId: ds.dataSetId
33157
- });
33158
- }
33159
- return datasetValues;
33160
- }
33161
- function getChartLabelValues(getters, dataSets, labelRange) {
33162
- if (labelRange) {
33163
- const { left } = labelRange.zone;
33164
- if (!labelRange.invalidXc && !labelRange.invalidSheetName && !getters.isColHidden(labelRange.sheetId, left)) return getters.getVisibleRangeValues(labelRange);
33165
- }
33166
- if (dataSets[0]) {
33167
- const dataLength = getData(getters, dataSets[0]).length;
33168
- return Array.from({ length: dataLength }, () => ({ value: "" }));
33169
- }
33170
- return [];
33171
- }
33172
- /**
33173
- * Get the values for a hierarchical dataset. The values can be defined in a tree-like structure
33174
- * in the sheet, and this function will fill up the blanks.
33175
- *
33176
- * @example the following dataset:
33177
- *
33178
- * 2024 Q1 W1 100
33179
- * W2 200
33180
- *
33181
- * will have the same value as the dataset:
33182
- * 2024 Q1 W1 100
33183
- * 2024 Q1 W2 200
33184
- */
33185
- function getHierarchicalDatasetValues(getters, dataSets) {
33186
- dataSets = dataSets.filter((ds) => !getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left));
33187
- const datasetValues = dataSets.map((ds) => ({
33188
- data: [],
33189
- label: "",
33190
- dataSetId: ds.dataSetId
33191
- }));
33192
- const locale = getters.getLocale();
33193
- const dataSetsData = dataSets.map((ds) => getData(getters, ds)).map((values) => values.map(({ value, format }) => value === null ? EMPTY : { value: formatValue(value, {
33194
- format,
33195
- locale
33196
- }) }));
33197
- if (!dataSetsData.length) return datasetValues;
33198
- const minLength = Math.min(...dataSetsData.map((ds) => ds.length));
33199
- let currentValues = [];
33200
- const leafDatasetIndex = dataSets.length - 1;
33201
- for (let i = 0; i < minLength; i++) for (let dsIndex = 0; dsIndex < dataSetsData.length; dsIndex++) {
33202
- let cell = dataSetsData[dsIndex][i];
33203
- if ((cell === void 0 || cell.value === null) && dsIndex !== leafDatasetIndex) cell = currentValues[dsIndex];
33204
- if (cell?.value !== currentValues[dsIndex]?.value) {
33205
- currentValues = currentValues.slice(0, dsIndex);
33206
- currentValues[dsIndex] = cell;
33207
- }
33208
- datasetValues[dsIndex].data.push(cell ?? EMPTY);
33209
- }
33210
- return datasetValues.filter((ds) => ds.data.some((d) => d.value !== null));
33211
- }
33212
- /**
33213
- * Get the data from a dataSet
33214
- */
33215
- function getData(getters, ds) {
33216
- if (ds.dataRange) {
33217
- const labelCellZone = ds.labelCell ? [ds.labelCell.zone] : [];
33218
- const dataZone = recomputeZones([ds.dataRange.zone], labelCellZone)[0];
33219
- if (dataZone === void 0) return [];
33220
- const dataRange = getters.getRangeFromZone(ds.dataRange.sheetId, dataZone);
33221
- return getters.getVisibleRangeValues(dataRange).map((cell) => cell.value === "" ? EMPTY : cell);
33222
- }
33223
- return [];
33224
- }
33225
- const ChartNeverDataSourceHandler = {
33226
- supportedChartTypes: [],
33227
- fromExternalDefinition: () => ({ type: "none" }),
33228
- fromContextCreation: () => ({ type: "none" }),
33229
- fromHierarchicalContextCreation: () => ({ type: "none" }),
33230
- validate: () => "Success",
33231
- transform: () => ({ type: "none" }),
33232
- extractData: () => ({
33233
- dataSetsValues: [],
33234
- labelValues: []
33235
- }),
33236
- extractHierarchicalData: () => ({
33237
- dataSetsValues: [],
33238
- labelValues: []
33239
- }),
33240
- adaptRanges: (dataSource) => dataSource,
33241
- getDefinition: (dataSource) => dataSource,
33242
- duplicateInDuplicatedSheet: (dataSource) => dataSource,
33243
- getContextCreation: () => ({}),
33244
- getHierarchicalContextCreation: () => ({}),
33245
- toExcelDataSets: () => ({
33246
- dataSets: [],
33247
- labelRange: void 0
33248
- })
33249
- };
33250
- chartDataSourceRegistry.add("range", ChartRangeDataSourceHandler);
33251
- chartDataSourceRegistry.add("none", ChartNeverDataSourceHandler);
33252
-
33253
32828
  //#endregion
33254
32829
  //#region src/types/chart/calendar_chart.ts
33255
32830
  const CALENDAR_CHART_GRANULARITIES = [
@@ -33276,41 +32851,6 @@ var CalendarChartConfigPanel = class extends GenericChartConfigPanel {
33276
32851
  value,
33277
32852
  label: ALL_PERIODS[value]
33278
32853
  }));
33279
- getGroupByOptions() {
33280
- const sheetId = this.env.model.getters.getFigureSheetId(this.env.model.getters.getFigureIdFromChartId(this.props.chartId));
33281
- const definition = SpreadsheetChart.fromStrDefinition(this.env.model.getters, sheetId, this.props.definition).getRangeDefinition();
33282
- const labels = getBarChartData(definition, getChartData(this.env.model.getters, definition.dataSource), this.env.model.getters).labels.filter((l) => isDateTime(l, DEFAULT_LOCALE));
33283
- if (labels.length === 0) return [];
33284
- const dates = labels.map((label) => toJsDate(label, this.env.model.getters.getLocale()));
33285
- const uniqueYears = /* @__PURE__ */ new Set();
33286
- const uniqueMonths = /* @__PURE__ */ new Set();
33287
- const uniqueDays = /* @__PURE__ */ new Set();
33288
- const uniqueHours = /* @__PURE__ */ new Set();
33289
- const uniqueMinutes = /* @__PURE__ */ new Set();
33290
- const uniqueSeconds = /* @__PURE__ */ new Set();
33291
- for (const date of dates) {
33292
- uniqueYears.add(date.getFullYear());
33293
- uniqueMonths.add(date.getMonth());
33294
- uniqueDays.add(date.getDate());
33295
- uniqueHours.add(date.getHours());
33296
- uniqueMinutes.add(date.getMinutes());
33297
- uniqueSeconds.add(date.getSeconds());
33298
- }
33299
- return this.groupByChoices.filter((groupBy) => {
33300
- switch (groupBy.value) {
33301
- case "year": return uniqueYears.size > 1;
33302
- case "quarter_number":
33303
- case "month_number": return uniqueMonths.size > 1;
33304
- case "iso_week_number":
33305
- case "day_of_month":
33306
- case "day_of_week": return uniqueDays.size > 1;
33307
- case "hour_number": return uniqueHours.size > 1;
33308
- case "minute_number": return uniqueMinutes.size > 1;
33309
- case "second_number": return uniqueSeconds.size > 1;
33310
- default: return false;
33311
- }
33312
- });
33313
- }
33314
32854
  getGroupByType(currentAxis) {
33315
32855
  return (currentAxis === "horizontal" ? this.props.definition.horizontalGroupBy : this.props.definition.verticalGroupBy) || "year";
33316
32856
  }
@@ -34516,6 +34056,133 @@ var ChartTypePicker = class extends Component {
34516
34056
  }
34517
34057
  };
34518
34058
 
34059
+ //#endregion
34060
+ //#region src/helpers/figures/chart.ts
34061
+ var SpreadsheetChart = class SpreadsheetChart {
34062
+ getters;
34063
+ sheetId;
34064
+ definition;
34065
+ chartTypeBuilder;
34066
+ dataSourceBuilder;
34067
+ dataSource;
34068
+ constructor(getters, sheetId, definition, chartTypeBuilder, dataSourceBuilder) {
34069
+ this.getters = getters;
34070
+ this.sheetId = sheetId;
34071
+ this.definition = definition;
34072
+ this.chartTypeBuilder = chartTypeBuilder;
34073
+ this.dataSourceBuilder = dataSourceBuilder;
34074
+ this.dataSource = definition.dataSource;
34075
+ }
34076
+ static fromStrDefinition(getters, sheetId, definition) {
34077
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
34078
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
34079
+ const dataSource = dataSourceBuilder.fromExternalDefinition(definition.dataSource ?? { type: "none" }, sheetId, getters);
34080
+ const rangeDefinition = {
34081
+ ...chartTypeBuilder.fromStrDefinition(definition, sheetId, getters),
34082
+ dataSource
34083
+ };
34084
+ return new SpreadsheetChart(getters, sheetId, SpreadsheetChart.deleteInvalidKeys(rangeDefinition), chartTypeBuilder, dataSourceBuilder);
34085
+ }
34086
+ static fromDefinition(getters, sheetId, definition) {
34087
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
34088
+ return new SpreadsheetChart(getters, sheetId, definition, chartTypeRegistry.get(definition.type), dataSourceBuilder);
34089
+ }
34090
+ static validate(validator, definition) {
34091
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
34092
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
34093
+ return validator.batchValidations(() => chartTypeBuilder.validateDefinition(validator, definition), () => dataSourceBuilder.validate(definition.dataSource ?? { type: "none" }, validator))(void 0);
34094
+ }
34095
+ static transformDefinition(chartSheetId, definition, rangeAdapters) {
34096
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
34097
+ if (!definition.dataSource) return chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters);
34098
+ const newDataSource = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none").transform(definition.dataSource, chartSheetId, rangeAdapters);
34099
+ return {
34100
+ ...chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters),
34101
+ dataSource: newDataSource
34102
+ };
34103
+ }
34104
+ getRangeDefinition() {
34105
+ return {
34106
+ ...this.definition,
34107
+ dataSource: this.dataSource
34108
+ };
34109
+ }
34110
+ getDefinition() {
34111
+ return {
34112
+ ...this.chartTypeBuilder.toStrDefinition(this.definition, this.sheetId, this.getters),
34113
+ dataSource: this.dataSource && this.dataSourceBuilder.getDefinition(this.dataSource, this.sheetId, this.getters)
34114
+ };
34115
+ }
34116
+ updateRanges(rangeAdapters) {
34117
+ return {
34118
+ ...this.chartTypeBuilder.updateRanges(this.definition, rangeAdapters, this.sheetId),
34119
+ dataSource: this.dataSource && this.dataSourceBuilder.adaptRanges(this.dataSource, rangeAdapters)
34120
+ };
34121
+ }
34122
+ duplicateInDuplicatedSheet(sheetIdFrom, sheetIdTo) {
34123
+ const newDataSource = this.dataSource && this.dataSourceBuilder.duplicateInDuplicatedSheet(this.dataSource, sheetIdFrom, sheetIdTo, this.getters);
34124
+ const definition = {
34125
+ ...this.chartTypeBuilder.duplicateInDuplicatedSheet(this.definition, sheetIdFrom, sheetIdTo, this.getters),
34126
+ dataSource: newDataSource
34127
+ };
34128
+ return SpreadsheetChart.fromDefinition(this.getters, sheetIdTo, definition).getDefinition();
34129
+ }
34130
+ copyInSheetId(sheetIdTo) {
34131
+ return {
34132
+ ...this.chartTypeBuilder.copyInSheetId(this.definition, this.sheetId, sheetIdTo, this.getters),
34133
+ dataSource: this.dataSource
34134
+ };
34135
+ }
34136
+ getContextCreation() {
34137
+ const definition = this.getDefinition();
34138
+ return {
34139
+ ...this.dataSourceBuilder.getContextCreation(definition.dataSource ?? { type: "none" }),
34140
+ ...this.chartTypeBuilder.getContextCreation(definition, this.dataSourceBuilder, definition.dataSource)
34141
+ };
34142
+ }
34143
+ getDefinitionForExcel(getters) {
34144
+ const definition = this.definition;
34145
+ const excelDataSets = this.dataSourceBuilder.toExcelDataSets(this.dataSource, "dataSetStyles" in definition ? definition.dataSetStyles : {}, getters);
34146
+ if (excelDataSets === void 0) return;
34147
+ return this.chartTypeBuilder.getDefinitionForExcel(getters, definition, excelDataSets);
34148
+ }
34149
+ getData(getters, chartId) {
34150
+ const dataSource = this.dataSource;
34151
+ return dataSource ? this.dataSourceBuilder.extractData(dataSource, chartId, getters) : {
34152
+ dataSetsValues: [],
34153
+ labelValues: []
34154
+ };
34155
+ }
34156
+ getRuntime(getters, chartId) {
34157
+ const dataSource = this.dataSource;
34158
+ const dataExtractors = dataSource ? {
34159
+ extractData: () => this.dataSourceBuilder.extractData(dataSource, chartId, getters),
34160
+ extractHierarchicalData: () => this.dataSourceBuilder.extractHierarchicalData(dataSource, chartId, getters)
34161
+ } : {
34162
+ extractData: () => ({
34163
+ dataSetsValues: [],
34164
+ labelValues: []
34165
+ }),
34166
+ extractHierarchicalData: () => ({
34167
+ dataSetsValues: [],
34168
+ labelValues: []
34169
+ })
34170
+ };
34171
+ return this.chartTypeBuilder.getRuntime(getters, this.definition, dataExtractors, this.sheetId, {
34172
+ onClick: (event, items, chartJsChart) => {
34173
+ return this.dataSourceBuilder.onDataSetClick?.(this.definition.type, chartId, event, items, chartJsChart, getters);
34174
+ },
34175
+ onHover: (event, items, chartJsChart) => this.dataSourceBuilder.onDataSetHover?.(this.definition.type, chartId, event, items, chartJsChart)
34176
+ });
34177
+ }
34178
+ static deleteInvalidKeys(definition) {
34179
+ definition = { ...definition };
34180
+ const keys = new Set(chartTypeRegistry.get(definition.type).allowedDefinitionKeys);
34181
+ for (const key of Object.keys(definition)) if (!keys.has(key)) delete definition[key];
34182
+ return definition;
34183
+ }
34184
+ };
34185
+
34519
34186
  //#endregion
34520
34187
  //#region src/components/side_panel/chart/main_chart_panel/main_chart_panel_store.ts
34521
34188
  var MainChartPanelStore = class extends SpreadsheetStore {
@@ -36504,7 +36171,7 @@ var FindAndReplacePanel = class extends Component {
36504
36171
  }
36505
36172
  get specificRangeMatchesCount() {
36506
36173
  const range = this.searchOptions.specificRange;
36507
- if (!range) return "";
36174
+ if (!range || range.invalidSheetName || range.invalidXc) return "";
36508
36175
  const { sheetId, zone } = range;
36509
36176
  return _t("%(matches)s matches in range %(range)s of %(sheetName)s", {
36510
36177
  matches: this.store.specificRangeMatchesCount,
@@ -40076,7 +39743,13 @@ var PivotSpreadsheetSidePanel = class extends Component {
40076
39743
  }
40077
39744
  onSelectionChanged(ranges) {
40078
39745
  this.state.rangeHasChanged = true;
40079
- this.state.range = ranges[0];
39746
+ if (ranges.length === 0) {
39747
+ this.state.range = void 0;
39748
+ return;
39749
+ }
39750
+ const sheetId = this.env.model.getters.getActiveSheetId();
39751
+ const range = this.env.model.getters.getRangeFromSheetXC(sheetId, ranges[0]);
39752
+ this.state.range = this.env.model.getters.getRangeString(range, "forceSheetReference", { useBoundedReference: true });
40080
39753
  }
40081
39754
  onSelectionConfirmed() {
40082
39755
  if (this.state.range) {
@@ -46127,6 +45800,11 @@ var GridOverlay = class extends Component {
46127
45800
  });
46128
45801
  return icon?.onClick ? icon : void 0;
46129
45802
  }
45803
+ get isFooterVisible() {
45804
+ const { y } = this.env.model.getters.getMainViewportCoordinates();
45805
+ const { height } = this.env.model.getters.getSheetViewDimension();
45806
+ return !this.env.model.getters.isReadonly() && height - y > 46;
45807
+ }
46130
45808
  };
46131
45809
 
46132
45810
  //#endregion
@@ -49735,6 +49413,7 @@ var CarouselPlugin = class extends CorePlugin {
49735
49413
  return "Success";
49736
49414
  case "UPDATE_CAROUSEL":
49737
49415
  if (!this.carousels[cmd.sheetId]?.[cmd.figureId]) return "InvalidFigureId";
49416
+ for (const item of cmd.definition.items) if (item.type === "chart" && !this.getters.getChart(item.chartId)) return "ChartDoesNotExist";
49738
49417
  return "Success";
49739
49418
  }
49740
49419
  return "Success";
@@ -54609,7 +54288,7 @@ var CompilationParametersBuilder = class {
54609
54288
  if (rangeError) return [[rangeError]];
54610
54289
  const sheetId = range.sheetId;
54611
54290
  const zone = range.zone;
54612
- const _zone = intersection(zone, this.getters.getSheetZone(sheetId));
54291
+ const _zone = this.getters.clipRangeToSheet(range)?.zone;
54613
54292
  if (!_zone) return [[]];
54614
54293
  const { top, left, bottom, right } = zone;
54615
54294
  const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
@@ -54913,6 +54592,7 @@ var FormulaDependencyGraph = class {
54913
54592
  }
54914
54593
  getCellsDependingOn(ranges, visited = new RangeSet()) {
54915
54594
  visited = visited.copy();
54595
+ let initialRangesToRemove = visited.copy();
54916
54596
  const queue = Array.from(ranges).reverse();
54917
54597
  while (queue.length > 0) {
54918
54598
  const range = queue.pop();
@@ -54928,8 +54608,9 @@ var FormulaDependencyGraph = class {
54928
54608
  for (const interval of overlappingIntervals) impactedRanges.add(interval.dependents);
54929
54609
  }
54930
54610
  queue.push(...impactedRanges.difference(visited));
54611
+ initialRangesToRemove = initialRangesToRemove.difference(impactedRanges);
54931
54612
  }
54932
- for (const range of ranges) visited.delete(range);
54613
+ for (const range of initialRangesToRemove) visited.delete(range);
54933
54614
  return visited;
54934
54615
  }
54935
54616
  getOrCreateIntervalTree(sheetId, col) {
@@ -55590,10 +55271,10 @@ var Evaluator = class {
55590
55271
  updateDependencies(position) {
55591
55272
  this.formulaDependencies().removeAllDependencies(position);
55592
55273
  const dependencies = this.getDirectDependencies(position);
55593
- this.formulaDependencies().addDependencies(position, dependencies);
55274
+ this.formulaDependencies().addDependencies(position, this.getters.clipRangesToSheet(dependencies));
55594
55275
  }
55595
55276
  addDependencies(position, dependencies) {
55596
- this.formulaDependencies().addDependencies(position, dependencies);
55277
+ this.formulaDependencies().addDependencies(position, this.getters.clipRangesToSheet(dependencies));
55597
55278
  this.computeDependencies(dependencies);
55598
55279
  }
55599
55280
  computeDependencies(dependencies) {
@@ -55655,7 +55336,8 @@ var Evaluator = class {
55655
55336
  const graph = new FormulaDependencyGraph();
55656
55337
  for (const sheetId of this.getters.getSheetIds()) for (const cell of this.getters.getCells(sheetId)) if (cell.isFormula) {
55657
55338
  const cellPosition = this.getters.getCellPosition(cell.id);
55658
- graph.addDependencies(cellPosition, cell.compiledFormula.rangeDependencies);
55339
+ const dependencies = this.getters.clipRangesToSheet(cell.compiledFormula.rangeDependencies);
55340
+ graph.addDependencies(cellPosition, dependencies);
55659
55341
  }
55660
55342
  return graph;
55661
55343
  });
@@ -61420,7 +61102,8 @@ var GeoFeaturePlugin = class extends UIPlugin {
61420
61102
  "getGeoJsonFeatures",
61421
61103
  "geoFeatureNameToId",
61422
61104
  "getGeoChartAvailableRegions",
61423
- "getAvailableChartRegions"
61105
+ "getAvailableChartRegions",
61106
+ "loadUsedGeoJsonFeatures"
61424
61107
  ];
61425
61108
  geoJsonService;
61426
61109
  geoJsonCache = {};
@@ -61503,6 +61186,23 @@ var GeoFeaturePlugin = class extends UIPlugin {
61503
61186
  }
61504
61187
  return this.geoJsonService.geoFeatureNameToId(region, featureName);
61505
61188
  }
61189
+ loadUsedGeoJsonFeatures() {
61190
+ const regions = this.getters.getSheetIds().flatMap((sheetId) => this.getters.getChartIds(sheetId).map((chartId) => {
61191
+ const definition = this.getters.getChartDefinition(chartId);
61192
+ return definition.type === "geo" ? definition.region || this.getters.getGeoChartAvailableRegions()[0]?.id : void 0;
61193
+ })).filter(isDefined);
61194
+ const uniqueRegions = Array.from(new Set(regions));
61195
+ if (uniqueRegions.length && !this.geoJsonService) {
61196
+ console.error("No geoJsonService provided to the model");
61197
+ return Promise.resolve();
61198
+ }
61199
+ for (const region of uniqueRegions) this.getGeoJsonFeatures(region);
61200
+ const promises = uniqueRegions.map((region) => {
61201
+ const cachedGeoJson = this.geoJsonCache[region];
61202
+ return cachedGeoJson instanceof Promise ? cachedGeoJson : Promise.resolve();
61203
+ });
61204
+ return Promise.all(promises).then(() => {});
61205
+ }
61506
61206
  convertToGeoJson(json) {
61507
61207
  if (!json) return null;
61508
61208
  if (json.type === "Topology") {
@@ -64564,7 +64264,7 @@ var InternalViewport = class {
64564
64264
  let height = lastRowEnd - this.offsetCorrectionY;
64565
64265
  if (this.canScrollVertically) {
64566
64266
  height = Math.max(height, this.viewportHeight);
64567
- if (lastRowEnd + 46 > height && !this.getters.isReadonly()) height += 46;
64267
+ if (lastRowEnd + 46 > height && !this.getters.isReadonly() && this.viewportHeight > 46) height += 46;
64568
64268
  }
64569
64269
  return {
64570
64270
  width,
@@ -68802,7 +68502,7 @@ var FigureRendererStore = class extends DisposableStore {
68802
68502
  if (!this.getters.isDashboard()) {
68803
68503
  ctx.strokeStyle = GRAY_400;
68804
68504
  ctx.lineWidth = 1;
68805
- ctx.strokeRect(x, y, figure.width, figure.height);
68505
+ ctx.strokeRect(x + .5, y + .5, figure.width - 1, figure.height - 1);
68806
68506
  }
68807
68507
  }
68808
68508
  }
@@ -69011,12 +68711,11 @@ var SpreadsheetPrintStore = class extends SpreadsheetStore {
69011
68711
  const { width: printWidth, height: printHeight } = this.pageDimensionWithMargins;
69012
68712
  const start = dimension === "COL" ? printZone.left : printZone.top;
69013
68713
  const end = dimension === "COL" ? printZone.right : printZone.bottom;
69014
- const getHeaderSize = dimension === "COL" ? this.getters.getColDimensions : this.getters.getRowDimensions;
69015
68714
  const max = dimension === "COL" ? printWidth : printHeight;
69016
68715
  const breaks = [];
69017
68716
  let current = 0;
69018
68717
  for (let i = start; i <= end; i++) {
69019
- const headerSize = getHeaderSize(sheetId, i).size * zoom;
68718
+ const headerSize = this.getters.getHeaderSize(sheetId, dimension, i) * zoom;
69020
68719
  current += headerSize;
69021
68720
  if (current >= max) {
69022
68721
  breaks.push(i);
@@ -71501,6 +71200,8 @@ var RangeAdapterPlugin = class {
71501
71200
  "extendRange",
71502
71201
  "getRangeString",
71503
71202
  "getRangeFromSheetXC",
71203
+ "clipRangesToSheet",
71204
+ "clipRangeToSheet",
71504
71205
  "createAdaptedRanges",
71505
71206
  "getRangeData",
71506
71207
  "getRangeDataFromXc",
@@ -71539,6 +71240,22 @@ var RangeAdapterPlugin = class {
71539
71240
  addRangeProvider(provider) {
71540
71241
  this.providers.push(provider);
71541
71242
  }
71243
+ clipRangeToSheet(range) {
71244
+ if (range.invalidXc) return range;
71245
+ const sheetZone = this.getters.getSheetZone(range.sheetId);
71246
+ if (isZoneInside(range.zone, sheetZone)) return range;
71247
+ const newZone = intersection(range.zone, sheetZone);
71248
+ if (!newZone) return;
71249
+ return this.getters.getRangeFromZone(range.sheetId, newZone);
71250
+ }
71251
+ clipRangesToSheet(ranges) {
71252
+ const clippedRanges = [];
71253
+ for (const range of ranges) {
71254
+ const clippedRange = this.clipRangeToSheet(range);
71255
+ if (clippedRange) clippedRanges.push(clippedRange);
71256
+ }
71257
+ return clippedRanges;
71258
+ }
71542
71259
  createAdaptedRanges(ranges, offsetX, offsetY, sheetId) {
71543
71260
  return ranges.map((range) => {
71544
71261
  if (!isZoneValid(range.zone)) return range;
@@ -74736,6 +74453,8 @@ var Model = class Model extends EventBus {
74736
74453
  this.range = new RangeAdapterPlugin(this.coreGetters);
74737
74454
  this.coreGetters.getRangeString = this.range.getRangeString.bind(this.range);
74738
74455
  this.coreGetters.getRangeFromSheetXC = this.range.getRangeFromSheetXC.bind(this.range);
74456
+ this.coreGetters.clipRangesToSheet = this.range.clipRangesToSheet.bind(this.range);
74457
+ this.coreGetters.clipRangeToSheet = this.range.clipRangeToSheet.bind(this.range);
74739
74458
  this.coreGetters.createAdaptedRanges = this.range.createAdaptedRanges.bind(this.range);
74740
74459
  this.coreGetters.getRangeData = this.range.getRangeData.bind(this.range);
74741
74460
  this.coreGetters.getRangeDataFromXc = this.range.getRangeDataFromXc.bind(this.range);
@@ -75142,6 +74861,306 @@ function createCommand(type, payload = {}) {
75142
74861
  return command;
75143
74862
  }
75144
74863
 
74864
+ //#endregion
74865
+ //#region src/helpers/figures/charts/chart_data_sources.ts
74866
+ const EMPTY = Object.freeze({ value: null });
74867
+ const ONE = Object.freeze({ value: 1 });
74868
+ const ChartRangeDataSourceHandler = {
74869
+ supportedChartTypes: CHART_TYPES,
74870
+ fromExternalDefinition(dataSource, defaultSheetId, getters) {
74871
+ const dataSets = createDataSets(getters, defaultSheetId, dataSource);
74872
+ const labelRange = createValidRange(getters, defaultSheetId, dataSource.labelRange);
74873
+ return {
74874
+ ...dataSource,
74875
+ dataSets,
74876
+ labelRange
74877
+ };
74878
+ },
74879
+ fromContextCreation(context) {
74880
+ return {
74881
+ type: "range",
74882
+ dataSets: [],
74883
+ dataSetsHaveTitle: false,
74884
+ labelRange: context.auxiliaryRange,
74885
+ ...context.dataSource
74886
+ };
74887
+ },
74888
+ fromHierarchicalContextCreation(context) {
74889
+ if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
74890
+ type: "range",
74891
+ dataSets: [],
74892
+ dataSetsHaveTitle: false
74893
+ };
74894
+ let dataSource = {
74895
+ type: "range",
74896
+ dataSets: [],
74897
+ dataSetsHaveTitle: context.dataSource?.dataSetsHaveTitle ?? false,
74898
+ labelRange: context.dataSource?.dataSets?.[0]?.dataRange
74899
+ };
74900
+ if (context.hierarchicalDataSource?.dataSets.length) dataSource = context.hierarchicalDataSource;
74901
+ else if (context.auxiliaryRange) dataSource = {
74902
+ ...dataSource,
74903
+ dataSets: [{
74904
+ dataRange: context.auxiliaryRange,
74905
+ dataSetId: "0"
74906
+ }]
74907
+ };
74908
+ return dataSource;
74909
+ },
74910
+ validate: (dataSource, validator) => validator.checkValidations(dataSource, checkDataset, checkLabelRange),
74911
+ transform(dataSource, defaultSheetId, { adaptRangeString }) {
74912
+ let labelRange;
74913
+ if (dataSource.labelRange) {
74914
+ const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSource.labelRange);
74915
+ if (changeType !== "REMOVE") labelRange = adaptedRange;
74916
+ }
74917
+ const dataSets = [];
74918
+ for (const dataSet of dataSource.dataSets) {
74919
+ const newDataSet = { ...dataSet };
74920
+ const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSet.dataRange);
74921
+ if (changeType !== "REMOVE") {
74922
+ newDataSet.dataRange = adaptedRange;
74923
+ dataSets.push(newDataSet);
74924
+ }
74925
+ }
74926
+ return {
74927
+ ...dataSource,
74928
+ dataSets,
74929
+ labelRange
74930
+ };
74931
+ },
74932
+ extractData: (dataSource, chartId, getters) => getChartData(getters, dataSource),
74933
+ extractHierarchicalData(dataSource, chartId, getters) {
74934
+ const dataSets = dataSource.dataSets;
74935
+ const labelRange = dataSource.labelRange;
74936
+ const labelValues = getChartLabelValues(getters, dataSets, labelRange);
74937
+ const dataSetsValues = getHierarchicalDatasetValues(getters, dataSets);
74938
+ const data = {
74939
+ labelValues,
74940
+ dataSetsValues
74941
+ };
74942
+ if (shouldRemoveFirstLabel(labelValues.length, dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0), dataSource.dataSetsHaveTitle || false)) labelValues.shift();
74943
+ return data;
74944
+ },
74945
+ adaptRanges(dataSource, { applyChange }) {
74946
+ const dataSetsWithUndefined = dataSource.dataSets.map((ds) => {
74947
+ const { range: adaptedRangeStr, changeType } = applyChange(ds.dataRange);
74948
+ if (changeType === "REMOVE") return;
74949
+ let labelCell = void 0;
74950
+ if (ds.labelCell) {
74951
+ const { range: adaptedLabelCellRange, changeType: labelCellChangeType } = applyChange(ds.labelCell);
74952
+ if (labelCellChangeType !== "REMOVE") labelCell = adaptedLabelCellRange;
74953
+ }
74954
+ return {
74955
+ ...ds,
74956
+ dataRange: adaptedRangeStr,
74957
+ labelCell
74958
+ };
74959
+ }).filter(isDefined);
74960
+ let labelRange = dataSource.labelRange;
74961
+ if (labelRange) {
74962
+ const { range: adaptedLabelRange, changeType } = applyChange(labelRange);
74963
+ if (changeType === "REMOVE") labelRange = void 0;
74964
+ else labelRange = adaptedLabelRange;
74965
+ }
74966
+ const dataSets = dataSetsWithUndefined;
74967
+ return {
74968
+ ...dataSource,
74969
+ dataSets,
74970
+ labelRange: labelRange?.invalidSheetName || labelRange?.invalidXc ? void 0 : labelRange
74971
+ };
74972
+ },
74973
+ getDefinition(dataSource, defaultSheetId, getters) {
74974
+ return {
74975
+ labelRange: dataSource.labelRange ? getters.getRangeString(dataSource.labelRange, defaultSheetId) : void 0,
74976
+ type: "range",
74977
+ dataSets: dataSource.dataSets.map((dataSet) => ({
74978
+ dataSetId: dataSet.dataSetId,
74979
+ dataRange: getters.getRangeString(dataSet.dataRange, defaultSheetId)
74980
+ })),
74981
+ dataSetsHaveTitle: dataSource.dataSetsHaveTitle
74982
+ };
74983
+ },
74984
+ /**
74985
+ * Duplicate the dataSets. All ranges on sheetIdFrom are adapted to target
74986
+ * sheetIdTo.
74987
+ */
74988
+ duplicateInDuplicatedSheet(dataSource, sheetIdFrom, sheetIdTo, getters) {
74989
+ return {
74990
+ ...dataSource,
74991
+ labelRange: duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, dataSource.labelRange),
74992
+ dataSets: dataSource.dataSets.map((ds) => ({
74993
+ ...ds,
74994
+ dataRange: duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.dataRange)
74995
+ }))
74996
+ };
74997
+ },
74998
+ getContextCreation: (dataSource) => ({
74999
+ auxiliaryRange: dataSource.labelRange,
75000
+ dataSource
75001
+ }),
75002
+ getHierarchicalContextCreation(dataSource) {
75003
+ const leafRange = dataSource.dataSets.at(-1)?.dataRange;
75004
+ const dataSetsHaveTitle = dataSource.dataSetsHaveTitle;
75005
+ return {
75006
+ auxiliaryRange: leafRange,
75007
+ hierarchicalDataSource: dataSource,
75008
+ dataSource: dataSource.labelRange ? {
75009
+ type: "range",
75010
+ dataSets: [{
75011
+ dataRange: dataSource.labelRange,
75012
+ dataSetId: "0"
75013
+ }],
75014
+ dataSetsHaveTitle
75015
+ } : {
75016
+ type: "range",
75017
+ dataSets: [],
75018
+ dataSetsHaveTitle
75019
+ }
75020
+ };
75021
+ },
75022
+ toExcelDataSets(dataSource, dataSetStyles, getters) {
75023
+ const dataSets = dataSource.dataSets;
75024
+ const labelRange = dataSource.labelRange;
75025
+ const excelDataSets = dataSets.map((ds) => toExcelDataset(getters, dataSetStyles, ds)).filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
75026
+ const datasetLength = dataSets[0] ? getZoneArea(dataSets[0].dataRange.zone) : void 0;
75027
+ return {
75028
+ dataSets: excelDataSets,
75029
+ labelRange: toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel(labelRange ? getZoneArea(labelRange.zone) : 0, datasetLength, dataSource.dataSetsHaveTitle))
75030
+ };
75031
+ }
75032
+ };
75033
+ function getChartData(getters, dataSource) {
75034
+ const dataSets = dataSource.dataSets;
75035
+ const labelRange = dataSource.labelRange;
75036
+ const labelValues = getChartLabelValues(getters, dataSets, labelRange);
75037
+ const dataSetsValues = getChartDatasetValues(getters, dataSets);
75038
+ const data = {
75039
+ labelValues,
75040
+ dataSetsValues
75041
+ };
75042
+ const numberOfDataPoints = dataSetsValues.length ? dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0) : 0;
75043
+ if (shouldRemoveFirstLabel(labelValues.length, numberOfDataPoints, dataSource.dataSetsHaveTitle || false)) labelValues.shift();
75044
+ return data;
75045
+ }
75046
+ function getChartDatasetValues(getters, dataSets) {
75047
+ const datasetValues = [];
75048
+ for (const [dsIndex, ds] of Object.entries(dataSets)) {
75049
+ let label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`;
75050
+ let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
75051
+ if (ds.labelCell) {
75052
+ const { sheetId, zone } = ds.labelCell;
75053
+ const cell = getters.getEvaluatedCell({
75054
+ sheetId,
75055
+ col: zone.left,
75056
+ row: zone.top
75057
+ });
75058
+ if (cell) label = cell.formattedValue;
75059
+ }
75060
+ let data = ds.dataRange ? getData(getters, ds) : [];
75061
+ if (data.every((cell) => !cell.value || isTextResult(cell)) && data.filter(isTextResult).length > 1) data = data.map((cell) => cell.value && !isErrorResult(cell) ? ONE : EMPTY);
75062
+ else if (data.every((cell) => !isNumberResult(cell))) hidden = true;
75063
+ datasetValues.push({
75064
+ data,
75065
+ label,
75066
+ hidden,
75067
+ dataSetId: ds.dataSetId
75068
+ });
75069
+ }
75070
+ return datasetValues;
75071
+ }
75072
+ function getChartLabelValues(getters, dataSets, labelRange) {
75073
+ if (labelRange) {
75074
+ const { left } = labelRange.zone;
75075
+ if (!labelRange.invalidXc && !labelRange.invalidSheetName && !getters.isColHidden(labelRange.sheetId, left)) return getters.getVisibleRangeValues(labelRange);
75076
+ }
75077
+ if (dataSets[0]) {
75078
+ const dataLength = getData(getters, dataSets[0]).length;
75079
+ return Array.from({ length: dataLength }, () => ({ value: "" }));
75080
+ }
75081
+ return [];
75082
+ }
75083
+ /**
75084
+ * Get the values for a hierarchical dataset. The values can be defined in a tree-like structure
75085
+ * in the sheet, and this function will fill up the blanks.
75086
+ *
75087
+ * @example the following dataset:
75088
+ *
75089
+ * 2024 Q1 W1 100
75090
+ * W2 200
75091
+ *
75092
+ * will have the same value as the dataset:
75093
+ * 2024 Q1 W1 100
75094
+ * 2024 Q1 W2 200
75095
+ */
75096
+ function getHierarchicalDatasetValues(getters, dataSets) {
75097
+ dataSets = dataSets.filter((ds) => !getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left));
75098
+ const datasetValues = dataSets.map((ds) => ({
75099
+ data: [],
75100
+ label: "",
75101
+ dataSetId: ds.dataSetId
75102
+ }));
75103
+ const locale = getters.getLocale();
75104
+ const dataSetsData = dataSets.map((ds) => getData(getters, ds)).map((values) => values.map(({ value, format }) => value === null ? EMPTY : { value: formatValue(value, {
75105
+ format,
75106
+ locale
75107
+ }) }));
75108
+ if (!dataSetsData.length) return datasetValues;
75109
+ const minLength = Math.min(...dataSetsData.map((ds) => ds.length));
75110
+ let currentValues = [];
75111
+ const leafDatasetIndex = dataSets.length - 1;
75112
+ for (let i = 0; i < minLength; i++) for (let dsIndex = 0; dsIndex < dataSetsData.length; dsIndex++) {
75113
+ let cell = dataSetsData[dsIndex][i];
75114
+ if ((cell === void 0 || cell.value === null) && dsIndex !== leafDatasetIndex) cell = currentValues[dsIndex];
75115
+ if (cell?.value !== currentValues[dsIndex]?.value) {
75116
+ currentValues = currentValues.slice(0, dsIndex);
75117
+ currentValues[dsIndex] = cell;
75118
+ }
75119
+ datasetValues[dsIndex].data.push(cell ?? EMPTY);
75120
+ }
75121
+ return datasetValues.filter((ds) => ds.data.some((d) => d.value !== null));
75122
+ }
75123
+ /**
75124
+ * Get the data from a dataSet
75125
+ */
75126
+ function getData(getters, ds) {
75127
+ if (ds.dataRange) {
75128
+ const labelCellZone = ds.labelCell ? [ds.labelCell.zone] : [];
75129
+ const dataZone = recomputeZones([ds.dataRange.zone], labelCellZone)[0];
75130
+ if (dataZone === void 0) return [];
75131
+ const dataRange = getters.getRangeFromZone(ds.dataRange.sheetId, dataZone);
75132
+ return getters.getVisibleRangeValues(dataRange).map((cell) => cell.value === "" ? EMPTY : cell);
75133
+ }
75134
+ return [];
75135
+ }
75136
+ const ChartNeverDataSourceHandler = {
75137
+ supportedChartTypes: [],
75138
+ fromExternalDefinition: () => ({ type: "none" }),
75139
+ fromContextCreation: () => ({ type: "none" }),
75140
+ fromHierarchicalContextCreation: () => ({ type: "none" }),
75141
+ validate: () => "Success",
75142
+ transform: () => ({ type: "none" }),
75143
+ extractData: () => ({
75144
+ dataSetsValues: [],
75145
+ labelValues: []
75146
+ }),
75147
+ extractHierarchicalData: () => ({
75148
+ dataSetsValues: [],
75149
+ labelValues: []
75150
+ }),
75151
+ adaptRanges: (dataSource) => dataSource,
75152
+ getDefinition: (dataSource) => dataSource,
75153
+ duplicateInDuplicatedSheet: (dataSource) => dataSource,
75154
+ getContextCreation: () => ({}),
75155
+ getHierarchicalContextCreation: () => ({}),
75156
+ toExcelDataSets: () => ({
75157
+ dataSets: [],
75158
+ labelRange: void 0
75159
+ })
75160
+ };
75161
+ chartDataSourceRegistry.add("range", ChartRangeDataSourceHandler);
75162
+ chartDataSourceRegistry.add("none", ChartNeverDataSourceHandler);
75163
+
75145
75164
  //#endregion
75146
75165
  //#region src/helpers/figures/charts/calendar_chart.ts
75147
75166
  function checkDateGranularity(definition) {
@@ -84759,6 +84778,6 @@ const chartHelpers = {
84759
84778
  //#endregion
84760
84779
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CompiledFormula, CorePlugin, CoreViewPlugin, DEFAULT_LOCALE, DEFAULT_LOCALES, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, canExecuteInReadonly, categories, chartHelpers, components, constants, convertAstNodes, coreTypes, createAutocompleteArgumentsProvider, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, isCoreCommand, isSheetDependent, iterateAstNodes, links, load, lockedSheetAllowedCommands, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
84761
84780
 
84762
- __info__.version = "19.3.18";
84763
- __info__.date = "2026-08-29T09:16:28.272Z";
84764
- __info__.hash = "1f4b1ae";
84781
+ __info__.version = "19.3.20";
84782
+ __info__.date = "2026-09-10T05:38:03.233Z";
84783
+ __info__.hash = "e488e8d";