@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
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -9593,16 +9593,16 @@ const chartShowValuesPlugin = {
9593
9593
  drawLineOrBarOrRadarChartValues(chart, options, ctx);
9594
9594
  break;
9595
9595
  case "bar":
9596
- options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9596
+ options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true }) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9597
9597
  break;
9598
9598
  case "pyramid":
9599
- drawHorizontalBarChartValues(chart, options, ctx);
9599
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true });
9600
9600
  break;
9601
9601
  case "calendar":
9602
9602
  drawBarChartValues(chart, options, ctx);
9603
9603
  break;
9604
9604
  case "funnel":
9605
- drawHorizontalBarChartValues(chart, options, ctx);
9605
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: false });
9606
9606
  break;
9607
9607
  }
9608
9608
  ctx.restore();
@@ -9626,7 +9626,7 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
9626
9626
  const point = dataset.data[i];
9627
9627
  const xPosition = point.x;
9628
9628
  let yPosition = 0;
9629
- if (chart.config.type === "line" || chart.config.type === "radar") yPosition = value < 0 ? point.y + 10 : point.y - 10;
9629
+ if (dataset.type === "line" || dataset.type === "radar") yPosition = value < 0 ? point.y + 10 : point.y - 10;
9630
9630
  else {
9631
9631
  const yZeroLine = yAxisScale.getPixelForValue(0);
9632
9632
  const distanceFromAxisOrigin = Math.abs(yZeroLine - point.y);
@@ -9672,7 +9672,7 @@ function drawBarChartValues(chart, options, ctx) {
9672
9672
  }
9673
9673
  }
9674
9674
  }
9675
- function drawHorizontalBarChartValues(chart, options, ctx) {
9675
+ function drawHorizontalBarChartValues(chart, options, ctx, args) {
9676
9676
  const textsPositions = {};
9677
9677
  for (const dataset of chart._metasets) {
9678
9678
  if (isTrendLineAxis(dataset.xAxisID)) return;
@@ -9687,7 +9687,7 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
9687
9687
  const distanceFromAxisOrigin = Math.abs(point.x - xZeroLine);
9688
9688
  const PADDING = 3;
9689
9689
  let xPosition;
9690
- if (distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9690
+ if (args.offsetFromAxisOrigin && distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9691
9691
  else xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
9692
9692
  if (!textsPositions[yPosition]) textsPositions[yPosition] = [];
9693
9693
  for (const otherPosition of textsPositions[yPosition]) if (Math.abs(otherPosition - xPosition) < textWidth) xPosition = value < 0 ? otherPosition - textWidth - PADDING : otherPosition + textWidth + PADDING;
@@ -18574,7 +18574,7 @@ const RemoveDuplicateTerms = { Errors: {
18574
18574
  ["MoreThanOneRangeSelected"]: _t("Please select only one range of cells"),
18575
18575
  ["EmptySelectedRange"]: _t("Please select a range of cells containing values."),
18576
18576
  ["NoColumnsProvided"]: _t("Please select at latest one column to analyze."),
18577
- ["WillRemoveExistingMerge"]: _t("This operation is not possible due to a merge. Please remove the merges first than try again.")
18577
+ ["WillRemoveExistingMerge"]: _t("Cannot perform this action on merged cells. Unmerge the cells and try again.")
18578
18578
  } };
18579
18579
  const DVTerms = {
18580
18580
  DateIs: {
@@ -25446,9 +25446,10 @@ var Composer = class extends _odoo_owl.Component {
25446
25446
  compositionActive = false;
25447
25447
  spreadsheetRect = useSpreadsheetRect();
25448
25448
  lastHoveredTokenIndex = void 0;
25449
- debouncedHover = debounce((tokenIndex, hoveredRect) => {
25449
+ debouncedHover = debounce((tokenIndex, composerContent, hoveredRect) => {
25450
25450
  const selection = this.contentHelper.getCurrentSelection();
25451
- if (selection.start !== selection.end) return;
25451
+ const currentContent = this.props.composerStore.currentContent;
25452
+ if (selection.start !== selection.end || currentContent !== composerContent) return;
25452
25453
  const currentHoveredContext = this.props.composerStore.hoveredTokens;
25453
25454
  this.props.composerStore.hoverToken(tokenIndex);
25454
25455
  if (!deepEquals(currentHoveredContext, this.props.composerStore.hoveredTokens)) this.composerState.hoveredRect = hoveredRect;
@@ -25766,7 +25767,8 @@ var Composer = class extends _odoo_owl.Component {
25766
25767
  onTokenHover(tokenIndex, hoveredRect) {
25767
25768
  if (this.lastHoveredTokenIndex !== tokenIndex) {
25768
25769
  this.lastHoveredTokenIndex = tokenIndex;
25769
- this.debouncedHover(tokenIndex, hoveredRect);
25770
+ const composerContent = this.props.composerStore.currentContent;
25771
+ this.debouncedHover(tokenIndex, composerContent, hoveredRect);
25770
25772
  }
25771
25773
  }
25772
25774
  /**
@@ -26813,7 +26815,7 @@ var AbstractComposerStore = class extends SpreadsheetStore {
26813
26815
  col: range.zone.left,
26814
26816
  row: range.zone.top
26815
26817
  });
26816
- if (spreadZone) return this.getters.getRangeFromZone(sheetId, spreadZone);
26818
+ if (spreadZone) return this.getters.getRangeFromZone(range.sheetId, spreadZone);
26817
26819
  return range;
26818
26820
  }
26819
26821
  updateAutoCompleteProvider() {
@@ -32824,433 +32826,6 @@ var ChartRangeDataSourceComponent = class extends _odoo_owl.Component {
32824
32826
  }
32825
32827
  };
32826
32828
 
32827
- //#endregion
32828
- //#region src/helpers/figures/chart.ts
32829
- var SpreadsheetChart = class SpreadsheetChart {
32830
- getters;
32831
- sheetId;
32832
- definition;
32833
- chartTypeBuilder;
32834
- dataSourceBuilder;
32835
- dataSource;
32836
- constructor(getters, sheetId, definition, chartTypeBuilder, dataSourceBuilder) {
32837
- this.getters = getters;
32838
- this.sheetId = sheetId;
32839
- this.definition = definition;
32840
- this.chartTypeBuilder = chartTypeBuilder;
32841
- this.dataSourceBuilder = dataSourceBuilder;
32842
- this.dataSource = definition.dataSource;
32843
- }
32844
- static fromStrDefinition(getters, sheetId, definition) {
32845
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
32846
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
32847
- const dataSource = dataSourceBuilder.fromExternalDefinition(definition.dataSource ?? { type: "none" }, sheetId, getters);
32848
- const rangeDefinition = {
32849
- ...chartTypeBuilder.fromStrDefinition(definition, sheetId, getters),
32850
- dataSource
32851
- };
32852
- return new SpreadsheetChart(getters, sheetId, SpreadsheetChart.deleteInvalidKeys(rangeDefinition), chartTypeBuilder, dataSourceBuilder);
32853
- }
32854
- static fromDefinition(getters, sheetId, definition) {
32855
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
32856
- return new SpreadsheetChart(getters, sheetId, definition, chartTypeRegistry.get(definition.type), dataSourceBuilder);
32857
- }
32858
- static validate(validator, definition) {
32859
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
32860
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
32861
- return validator.batchValidations(() => chartTypeBuilder.validateDefinition(validator, definition), () => dataSourceBuilder.validate(definition.dataSource ?? { type: "none" }, validator))(void 0);
32862
- }
32863
- static transformDefinition(chartSheetId, definition, rangeAdapters) {
32864
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
32865
- if (!definition.dataSource) return chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters);
32866
- const newDataSource = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none").transform(definition.dataSource, chartSheetId, rangeAdapters);
32867
- return {
32868
- ...chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters),
32869
- dataSource: newDataSource
32870
- };
32871
- }
32872
- getRangeDefinition() {
32873
- return {
32874
- ...this.definition,
32875
- dataSource: this.dataSource
32876
- };
32877
- }
32878
- getDefinition() {
32879
- return {
32880
- ...this.chartTypeBuilder.toStrDefinition(this.definition, this.sheetId, this.getters),
32881
- dataSource: this.dataSource && this.dataSourceBuilder.getDefinition(this.dataSource, this.sheetId, this.getters)
32882
- };
32883
- }
32884
- updateRanges(rangeAdapters) {
32885
- return {
32886
- ...this.chartTypeBuilder.updateRanges(this.definition, rangeAdapters, this.sheetId),
32887
- dataSource: this.dataSource && this.dataSourceBuilder.adaptRanges(this.dataSource, rangeAdapters)
32888
- };
32889
- }
32890
- duplicateInDuplicatedSheet(sheetIdFrom, sheetIdTo) {
32891
- const newDataSource = this.dataSource && this.dataSourceBuilder.duplicateInDuplicatedSheet(this.dataSource, sheetIdFrom, sheetIdTo, this.getters);
32892
- const definition = {
32893
- ...this.chartTypeBuilder.duplicateInDuplicatedSheet(this.definition, sheetIdFrom, sheetIdTo, this.getters),
32894
- dataSource: newDataSource
32895
- };
32896
- return SpreadsheetChart.fromDefinition(this.getters, sheetIdTo, definition).getDefinition();
32897
- }
32898
- copyInSheetId(sheetIdTo) {
32899
- return {
32900
- ...this.chartTypeBuilder.copyInSheetId(this.definition, this.sheetId, sheetIdTo, this.getters),
32901
- dataSource: this.dataSource
32902
- };
32903
- }
32904
- getContextCreation() {
32905
- const definition = this.getDefinition();
32906
- return {
32907
- ...this.dataSourceBuilder.getContextCreation(definition.dataSource ?? { type: "none" }),
32908
- ...this.chartTypeBuilder.getContextCreation(definition, this.dataSourceBuilder, definition.dataSource)
32909
- };
32910
- }
32911
- getDefinitionForExcel(getters) {
32912
- const definition = this.definition;
32913
- const excelDataSets = this.dataSourceBuilder.toExcelDataSets(this.dataSource, "dataSetStyles" in definition ? definition.dataSetStyles : {}, getters);
32914
- if (excelDataSets === void 0) return;
32915
- return this.chartTypeBuilder.getDefinitionForExcel(getters, definition, excelDataSets);
32916
- }
32917
- getData(getters, chartId) {
32918
- const dataSource = this.dataSource;
32919
- return dataSource ? this.dataSourceBuilder.extractData(dataSource, chartId, getters) : {
32920
- dataSetsValues: [],
32921
- labelValues: []
32922
- };
32923
- }
32924
- getRuntime(getters, chartId) {
32925
- const dataSource = this.dataSource;
32926
- const dataExtractors = dataSource ? {
32927
- extractData: () => this.dataSourceBuilder.extractData(dataSource, chartId, getters),
32928
- extractHierarchicalData: () => this.dataSourceBuilder.extractHierarchicalData(dataSource, chartId, getters)
32929
- } : {
32930
- extractData: () => ({
32931
- dataSetsValues: [],
32932
- labelValues: []
32933
- }),
32934
- extractHierarchicalData: () => ({
32935
- dataSetsValues: [],
32936
- labelValues: []
32937
- })
32938
- };
32939
- return this.chartTypeBuilder.getRuntime(getters, this.definition, dataExtractors, this.sheetId, {
32940
- onClick: (event, items, chartJsChart) => {
32941
- return this.dataSourceBuilder.onDataSetClick?.(this.definition.type, chartId, event, items, chartJsChart, getters);
32942
- },
32943
- onHover: (event, items, chartJsChart) => this.dataSourceBuilder.onDataSetHover?.(this.definition.type, chartId, event, items, chartJsChart)
32944
- });
32945
- }
32946
- static deleteInvalidKeys(definition) {
32947
- definition = { ...definition };
32948
- const keys = new Set(chartTypeRegistry.get(definition.type).allowedDefinitionKeys);
32949
- for (const key of Object.keys(definition)) if (!keys.has(key)) delete definition[key];
32950
- return definition;
32951
- }
32952
- };
32953
-
32954
- //#endregion
32955
- //#region src/helpers/figures/charts/chart_data_sources.ts
32956
- const EMPTY = Object.freeze({ value: null });
32957
- const ONE = Object.freeze({ value: 1 });
32958
- const ChartRangeDataSourceHandler = {
32959
- supportedChartTypes: CHART_TYPES,
32960
- fromExternalDefinition(dataSource, defaultSheetId, getters) {
32961
- const dataSets = createDataSets(getters, defaultSheetId, dataSource);
32962
- const labelRange = createValidRange(getters, defaultSheetId, dataSource.labelRange);
32963
- return {
32964
- ...dataSource,
32965
- dataSets,
32966
- labelRange
32967
- };
32968
- },
32969
- fromContextCreation(context) {
32970
- return {
32971
- type: "range",
32972
- dataSets: [],
32973
- dataSetsHaveTitle: false,
32974
- labelRange: context.auxiliaryRange,
32975
- ...context.dataSource
32976
- };
32977
- },
32978
- fromHierarchicalContextCreation(context) {
32979
- if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
32980
- type: "range",
32981
- dataSets: [],
32982
- dataSetsHaveTitle: false
32983
- };
32984
- let dataSource = {
32985
- type: "range",
32986
- dataSets: [],
32987
- dataSetsHaveTitle: context.dataSource?.dataSetsHaveTitle ?? false,
32988
- labelRange: context.dataSource?.dataSets?.[0]?.dataRange
32989
- };
32990
- if (context.hierarchicalDataSource?.dataSets.length) dataSource = context.hierarchicalDataSource;
32991
- else if (context.auxiliaryRange) dataSource = {
32992
- ...dataSource,
32993
- dataSets: [{
32994
- dataRange: context.auxiliaryRange,
32995
- dataSetId: "0"
32996
- }]
32997
- };
32998
- return dataSource;
32999
- },
33000
- validate: (dataSource, validator) => validator.checkValidations(dataSource, checkDataset, checkLabelRange),
33001
- transform(dataSource, defaultSheetId, { adaptRangeString }) {
33002
- let labelRange;
33003
- if (dataSource.labelRange) {
33004
- const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSource.labelRange);
33005
- if (changeType !== "REMOVE") labelRange = adaptedRange;
33006
- }
33007
- const dataSets = [];
33008
- for (const dataSet of dataSource.dataSets) {
33009
- const newDataSet = { ...dataSet };
33010
- const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSet.dataRange);
33011
- if (changeType !== "REMOVE") {
33012
- newDataSet.dataRange = adaptedRange;
33013
- dataSets.push(newDataSet);
33014
- }
33015
- }
33016
- return {
33017
- ...dataSource,
33018
- dataSets,
33019
- labelRange
33020
- };
33021
- },
33022
- extractData: (dataSource, chartId, getters) => getChartData(getters, dataSource),
33023
- extractHierarchicalData(dataSource, chartId, getters) {
33024
- const dataSets = dataSource.dataSets;
33025
- const labelRange = dataSource.labelRange;
33026
- const labelValues = getChartLabelValues(getters, dataSets, labelRange);
33027
- const dataSetsValues = getHierarchicalDatasetValues(getters, dataSets);
33028
- const data = {
33029
- labelValues,
33030
- dataSetsValues
33031
- };
33032
- if (shouldRemoveFirstLabel(labelValues.length, dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0), dataSource.dataSetsHaveTitle || false)) labelValues.shift();
33033
- return data;
33034
- },
33035
- adaptRanges(dataSource, { applyChange }) {
33036
- const dataSetsWithUndefined = dataSource.dataSets.map((ds) => {
33037
- const { range: adaptedRangeStr, changeType } = applyChange(ds.dataRange);
33038
- if (changeType === "REMOVE") return;
33039
- let labelCell = void 0;
33040
- if (ds.labelCell) {
33041
- const { range: adaptedLabelCellRange, changeType: labelCellChangeType } = applyChange(ds.labelCell);
33042
- if (labelCellChangeType !== "REMOVE") labelCell = adaptedLabelCellRange;
33043
- }
33044
- return {
33045
- ...ds,
33046
- dataRange: adaptedRangeStr,
33047
- labelCell
33048
- };
33049
- }).filter(isDefined);
33050
- let labelRange = dataSource.labelRange;
33051
- if (labelRange) {
33052
- const { range: adaptedLabelRange, changeType } = applyChange(labelRange);
33053
- if (changeType === "REMOVE") labelRange = void 0;
33054
- else labelRange = adaptedLabelRange;
33055
- }
33056
- const dataSets = dataSetsWithUndefined;
33057
- return {
33058
- ...dataSource,
33059
- dataSets,
33060
- labelRange: labelRange?.invalidSheetName || labelRange?.invalidXc ? void 0 : labelRange
33061
- };
33062
- },
33063
- getDefinition(dataSource, defaultSheetId, getters) {
33064
- return {
33065
- labelRange: dataSource.labelRange ? getters.getRangeString(dataSource.labelRange, defaultSheetId) : void 0,
33066
- type: "range",
33067
- dataSets: dataSource.dataSets.map((dataSet) => ({
33068
- dataSetId: dataSet.dataSetId,
33069
- dataRange: getters.getRangeString(dataSet.dataRange, defaultSheetId)
33070
- })),
33071
- dataSetsHaveTitle: dataSource.dataSetsHaveTitle
33072
- };
33073
- },
33074
- /**
33075
- * Duplicate the dataSets. All ranges on sheetIdFrom are adapted to target
33076
- * sheetIdTo.
33077
- */
33078
- duplicateInDuplicatedSheet(dataSource, sheetIdFrom, sheetIdTo, getters) {
33079
- return {
33080
- ...dataSource,
33081
- labelRange: duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, dataSource.labelRange),
33082
- dataSets: dataSource.dataSets.map((ds) => ({
33083
- ...ds,
33084
- dataRange: duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.dataRange)
33085
- }))
33086
- };
33087
- },
33088
- getContextCreation: (dataSource) => ({
33089
- auxiliaryRange: dataSource.labelRange,
33090
- dataSource
33091
- }),
33092
- getHierarchicalContextCreation(dataSource) {
33093
- const leafRange = dataSource.dataSets.at(-1)?.dataRange;
33094
- const dataSetsHaveTitle = dataSource.dataSetsHaveTitle;
33095
- return {
33096
- auxiliaryRange: leafRange,
33097
- hierarchicalDataSource: dataSource,
33098
- dataSource: dataSource.labelRange ? {
33099
- type: "range",
33100
- dataSets: [{
33101
- dataRange: dataSource.labelRange,
33102
- dataSetId: "0"
33103
- }],
33104
- dataSetsHaveTitle
33105
- } : {
33106
- type: "range",
33107
- dataSets: [],
33108
- dataSetsHaveTitle
33109
- }
33110
- };
33111
- },
33112
- toExcelDataSets(dataSource, dataSetStyles, getters) {
33113
- const dataSets = dataSource.dataSets;
33114
- const labelRange = dataSource.labelRange;
33115
- const excelDataSets = dataSets.map((ds) => toExcelDataset(getters, dataSetStyles, ds)).filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
33116
- const datasetLength = dataSets[0] ? getZoneArea(dataSets[0].dataRange.zone) : void 0;
33117
- return {
33118
- dataSets: excelDataSets,
33119
- labelRange: toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel(labelRange ? getZoneArea(labelRange.zone) : 0, datasetLength, dataSource.dataSetsHaveTitle))
33120
- };
33121
- }
33122
- };
33123
- function getChartData(getters, dataSource) {
33124
- const dataSets = dataSource.dataSets;
33125
- const labelRange = dataSource.labelRange;
33126
- const labelValues = getChartLabelValues(getters, dataSets, labelRange);
33127
- const dataSetsValues = getChartDatasetValues(getters, dataSets);
33128
- const data = {
33129
- labelValues,
33130
- dataSetsValues
33131
- };
33132
- const numberOfDataPoints = dataSetsValues.length ? dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0) : 0;
33133
- if (shouldRemoveFirstLabel(labelValues.length, numberOfDataPoints, dataSource.dataSetsHaveTitle || false)) labelValues.shift();
33134
- return data;
33135
- }
33136
- function getChartDatasetValues(getters, dataSets) {
33137
- const datasetValues = [];
33138
- for (const [dsIndex, ds] of Object.entries(dataSets)) {
33139
- let label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`;
33140
- let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
33141
- if (ds.labelCell) {
33142
- const { sheetId, zone } = ds.labelCell;
33143
- const cell = getters.getEvaluatedCell({
33144
- sheetId,
33145
- col: zone.left,
33146
- row: zone.top
33147
- });
33148
- if (cell) label = cell.formattedValue;
33149
- }
33150
- let data = ds.dataRange ? getData(getters, ds) : [];
33151
- if (data.every((cell) => !cell.value || isTextResult(cell)) && data.filter(isTextResult).length > 1) data = data.map((cell) => cell.value && !isErrorResult(cell) ? ONE : EMPTY);
33152
- else if (data.every((cell) => !isNumberResult(cell))) hidden = true;
33153
- datasetValues.push({
33154
- data,
33155
- label,
33156
- hidden,
33157
- dataSetId: ds.dataSetId
33158
- });
33159
- }
33160
- return datasetValues;
33161
- }
33162
- function getChartLabelValues(getters, dataSets, labelRange) {
33163
- if (labelRange) {
33164
- const { left } = labelRange.zone;
33165
- if (!labelRange.invalidXc && !labelRange.invalidSheetName && !getters.isColHidden(labelRange.sheetId, left)) return getters.getVisibleRangeValues(labelRange);
33166
- }
33167
- if (dataSets[0]) {
33168
- const dataLength = getData(getters, dataSets[0]).length;
33169
- return Array.from({ length: dataLength }, () => ({ value: "" }));
33170
- }
33171
- return [];
33172
- }
33173
- /**
33174
- * Get the values for a hierarchical dataset. The values can be defined in a tree-like structure
33175
- * in the sheet, and this function will fill up the blanks.
33176
- *
33177
- * @example the following dataset:
33178
- *
33179
- * 2024 Q1 W1 100
33180
- * W2 200
33181
- *
33182
- * will have the same value as the dataset:
33183
- * 2024 Q1 W1 100
33184
- * 2024 Q1 W2 200
33185
- */
33186
- function getHierarchicalDatasetValues(getters, dataSets) {
33187
- dataSets = dataSets.filter((ds) => !getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left));
33188
- const datasetValues = dataSets.map((ds) => ({
33189
- data: [],
33190
- label: "",
33191
- dataSetId: ds.dataSetId
33192
- }));
33193
- const locale = getters.getLocale();
33194
- const dataSetsData = dataSets.map((ds) => getData(getters, ds)).map((values) => values.map(({ value, format }) => value === null ? EMPTY : { value: formatValue(value, {
33195
- format,
33196
- locale
33197
- }) }));
33198
- if (!dataSetsData.length) return datasetValues;
33199
- const minLength = Math.min(...dataSetsData.map((ds) => ds.length));
33200
- let currentValues = [];
33201
- const leafDatasetIndex = dataSets.length - 1;
33202
- for (let i = 0; i < minLength; i++) for (let dsIndex = 0; dsIndex < dataSetsData.length; dsIndex++) {
33203
- let cell = dataSetsData[dsIndex][i];
33204
- if ((cell === void 0 || cell.value === null) && dsIndex !== leafDatasetIndex) cell = currentValues[dsIndex];
33205
- if (cell?.value !== currentValues[dsIndex]?.value) {
33206
- currentValues = currentValues.slice(0, dsIndex);
33207
- currentValues[dsIndex] = cell;
33208
- }
33209
- datasetValues[dsIndex].data.push(cell ?? EMPTY);
33210
- }
33211
- return datasetValues.filter((ds) => ds.data.some((d) => d.value !== null));
33212
- }
33213
- /**
33214
- * Get the data from a dataSet
33215
- */
33216
- function getData(getters, ds) {
33217
- if (ds.dataRange) {
33218
- const labelCellZone = ds.labelCell ? [ds.labelCell.zone] : [];
33219
- const dataZone = recomputeZones([ds.dataRange.zone], labelCellZone)[0];
33220
- if (dataZone === void 0) return [];
33221
- const dataRange = getters.getRangeFromZone(ds.dataRange.sheetId, dataZone);
33222
- return getters.getVisibleRangeValues(dataRange).map((cell) => cell.value === "" ? EMPTY : cell);
33223
- }
33224
- return [];
33225
- }
33226
- const ChartNeverDataSourceHandler = {
33227
- supportedChartTypes: [],
33228
- fromExternalDefinition: () => ({ type: "none" }),
33229
- fromContextCreation: () => ({ type: "none" }),
33230
- fromHierarchicalContextCreation: () => ({ type: "none" }),
33231
- validate: () => "Success",
33232
- transform: () => ({ type: "none" }),
33233
- extractData: () => ({
33234
- dataSetsValues: [],
33235
- labelValues: []
33236
- }),
33237
- extractHierarchicalData: () => ({
33238
- dataSetsValues: [],
33239
- labelValues: []
33240
- }),
33241
- adaptRanges: (dataSource) => dataSource,
33242
- getDefinition: (dataSource) => dataSource,
33243
- duplicateInDuplicatedSheet: (dataSource) => dataSource,
33244
- getContextCreation: () => ({}),
33245
- getHierarchicalContextCreation: () => ({}),
33246
- toExcelDataSets: () => ({
33247
- dataSets: [],
33248
- labelRange: void 0
33249
- })
33250
- };
33251
- chartDataSourceRegistry.add("range", ChartRangeDataSourceHandler);
33252
- chartDataSourceRegistry.add("none", ChartNeverDataSourceHandler);
33253
-
33254
32829
  //#endregion
33255
32830
  //#region src/types/chart/calendar_chart.ts
33256
32831
  const CALENDAR_CHART_GRANULARITIES = [
@@ -33277,41 +32852,6 @@ var CalendarChartConfigPanel = class extends GenericChartConfigPanel {
33277
32852
  value,
33278
32853
  label: ALL_PERIODS[value]
33279
32854
  }));
33280
- getGroupByOptions() {
33281
- const sheetId = this.env.model.getters.getFigureSheetId(this.env.model.getters.getFigureIdFromChartId(this.props.chartId));
33282
- const definition = SpreadsheetChart.fromStrDefinition(this.env.model.getters, sheetId, this.props.definition).getRangeDefinition();
33283
- const labels = getBarChartData(definition, getChartData(this.env.model.getters, definition.dataSource), this.env.model.getters).labels.filter((l) => isDateTime(l, DEFAULT_LOCALE));
33284
- if (labels.length === 0) return [];
33285
- const dates = labels.map((label) => toJsDate(label, this.env.model.getters.getLocale()));
33286
- const uniqueYears = /* @__PURE__ */ new Set();
33287
- const uniqueMonths = /* @__PURE__ */ new Set();
33288
- const uniqueDays = /* @__PURE__ */ new Set();
33289
- const uniqueHours = /* @__PURE__ */ new Set();
33290
- const uniqueMinutes = /* @__PURE__ */ new Set();
33291
- const uniqueSeconds = /* @__PURE__ */ new Set();
33292
- for (const date of dates) {
33293
- uniqueYears.add(date.getFullYear());
33294
- uniqueMonths.add(date.getMonth());
33295
- uniqueDays.add(date.getDate());
33296
- uniqueHours.add(date.getHours());
33297
- uniqueMinutes.add(date.getMinutes());
33298
- uniqueSeconds.add(date.getSeconds());
33299
- }
33300
- return this.groupByChoices.filter((groupBy) => {
33301
- switch (groupBy.value) {
33302
- case "year": return uniqueYears.size > 1;
33303
- case "quarter_number":
33304
- case "month_number": return uniqueMonths.size > 1;
33305
- case "iso_week_number":
33306
- case "day_of_month":
33307
- case "day_of_week": return uniqueDays.size > 1;
33308
- case "hour_number": return uniqueHours.size > 1;
33309
- case "minute_number": return uniqueMinutes.size > 1;
33310
- case "second_number": return uniqueSeconds.size > 1;
33311
- default: return false;
33312
- }
33313
- });
33314
- }
33315
32855
  getGroupByType(currentAxis) {
33316
32856
  return (currentAxis === "horizontal" ? this.props.definition.horizontalGroupBy : this.props.definition.verticalGroupBy) || "year";
33317
32857
  }
@@ -34517,6 +34057,133 @@ var ChartTypePicker = class extends _odoo_owl.Component {
34517
34057
  }
34518
34058
  };
34519
34059
 
34060
+ //#endregion
34061
+ //#region src/helpers/figures/chart.ts
34062
+ var SpreadsheetChart = class SpreadsheetChart {
34063
+ getters;
34064
+ sheetId;
34065
+ definition;
34066
+ chartTypeBuilder;
34067
+ dataSourceBuilder;
34068
+ dataSource;
34069
+ constructor(getters, sheetId, definition, chartTypeBuilder, dataSourceBuilder) {
34070
+ this.getters = getters;
34071
+ this.sheetId = sheetId;
34072
+ this.definition = definition;
34073
+ this.chartTypeBuilder = chartTypeBuilder;
34074
+ this.dataSourceBuilder = dataSourceBuilder;
34075
+ this.dataSource = definition.dataSource;
34076
+ }
34077
+ static fromStrDefinition(getters, sheetId, definition) {
34078
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
34079
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
34080
+ const dataSource = dataSourceBuilder.fromExternalDefinition(definition.dataSource ?? { type: "none" }, sheetId, getters);
34081
+ const rangeDefinition = {
34082
+ ...chartTypeBuilder.fromStrDefinition(definition, sheetId, getters),
34083
+ dataSource
34084
+ };
34085
+ return new SpreadsheetChart(getters, sheetId, SpreadsheetChart.deleteInvalidKeys(rangeDefinition), chartTypeBuilder, dataSourceBuilder);
34086
+ }
34087
+ static fromDefinition(getters, sheetId, definition) {
34088
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
34089
+ return new SpreadsheetChart(getters, sheetId, definition, chartTypeRegistry.get(definition.type), dataSourceBuilder);
34090
+ }
34091
+ static validate(validator, definition) {
34092
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
34093
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
34094
+ return validator.batchValidations(() => chartTypeBuilder.validateDefinition(validator, definition), () => dataSourceBuilder.validate(definition.dataSource ?? { type: "none" }, validator))(void 0);
34095
+ }
34096
+ static transformDefinition(chartSheetId, definition, rangeAdapters) {
34097
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
34098
+ if (!definition.dataSource) return chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters);
34099
+ const newDataSource = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none").transform(definition.dataSource, chartSheetId, rangeAdapters);
34100
+ return {
34101
+ ...chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters),
34102
+ dataSource: newDataSource
34103
+ };
34104
+ }
34105
+ getRangeDefinition() {
34106
+ return {
34107
+ ...this.definition,
34108
+ dataSource: this.dataSource
34109
+ };
34110
+ }
34111
+ getDefinition() {
34112
+ return {
34113
+ ...this.chartTypeBuilder.toStrDefinition(this.definition, this.sheetId, this.getters),
34114
+ dataSource: this.dataSource && this.dataSourceBuilder.getDefinition(this.dataSource, this.sheetId, this.getters)
34115
+ };
34116
+ }
34117
+ updateRanges(rangeAdapters) {
34118
+ return {
34119
+ ...this.chartTypeBuilder.updateRanges(this.definition, rangeAdapters, this.sheetId),
34120
+ dataSource: this.dataSource && this.dataSourceBuilder.adaptRanges(this.dataSource, rangeAdapters)
34121
+ };
34122
+ }
34123
+ duplicateInDuplicatedSheet(sheetIdFrom, sheetIdTo) {
34124
+ const newDataSource = this.dataSource && this.dataSourceBuilder.duplicateInDuplicatedSheet(this.dataSource, sheetIdFrom, sheetIdTo, this.getters);
34125
+ const definition = {
34126
+ ...this.chartTypeBuilder.duplicateInDuplicatedSheet(this.definition, sheetIdFrom, sheetIdTo, this.getters),
34127
+ dataSource: newDataSource
34128
+ };
34129
+ return SpreadsheetChart.fromDefinition(this.getters, sheetIdTo, definition).getDefinition();
34130
+ }
34131
+ copyInSheetId(sheetIdTo) {
34132
+ return {
34133
+ ...this.chartTypeBuilder.copyInSheetId(this.definition, this.sheetId, sheetIdTo, this.getters),
34134
+ dataSource: this.dataSource
34135
+ };
34136
+ }
34137
+ getContextCreation() {
34138
+ const definition = this.getDefinition();
34139
+ return {
34140
+ ...this.dataSourceBuilder.getContextCreation(definition.dataSource ?? { type: "none" }),
34141
+ ...this.chartTypeBuilder.getContextCreation(definition, this.dataSourceBuilder, definition.dataSource)
34142
+ };
34143
+ }
34144
+ getDefinitionForExcel(getters) {
34145
+ const definition = this.definition;
34146
+ const excelDataSets = this.dataSourceBuilder.toExcelDataSets(this.dataSource, "dataSetStyles" in definition ? definition.dataSetStyles : {}, getters);
34147
+ if (excelDataSets === void 0) return;
34148
+ return this.chartTypeBuilder.getDefinitionForExcel(getters, definition, excelDataSets);
34149
+ }
34150
+ getData(getters, chartId) {
34151
+ const dataSource = this.dataSource;
34152
+ return dataSource ? this.dataSourceBuilder.extractData(dataSource, chartId, getters) : {
34153
+ dataSetsValues: [],
34154
+ labelValues: []
34155
+ };
34156
+ }
34157
+ getRuntime(getters, chartId) {
34158
+ const dataSource = this.dataSource;
34159
+ const dataExtractors = dataSource ? {
34160
+ extractData: () => this.dataSourceBuilder.extractData(dataSource, chartId, getters),
34161
+ extractHierarchicalData: () => this.dataSourceBuilder.extractHierarchicalData(dataSource, chartId, getters)
34162
+ } : {
34163
+ extractData: () => ({
34164
+ dataSetsValues: [],
34165
+ labelValues: []
34166
+ }),
34167
+ extractHierarchicalData: () => ({
34168
+ dataSetsValues: [],
34169
+ labelValues: []
34170
+ })
34171
+ };
34172
+ return this.chartTypeBuilder.getRuntime(getters, this.definition, dataExtractors, this.sheetId, {
34173
+ onClick: (event, items, chartJsChart) => {
34174
+ return this.dataSourceBuilder.onDataSetClick?.(this.definition.type, chartId, event, items, chartJsChart, getters);
34175
+ },
34176
+ onHover: (event, items, chartJsChart) => this.dataSourceBuilder.onDataSetHover?.(this.definition.type, chartId, event, items, chartJsChart)
34177
+ });
34178
+ }
34179
+ static deleteInvalidKeys(definition) {
34180
+ definition = { ...definition };
34181
+ const keys = new Set(chartTypeRegistry.get(definition.type).allowedDefinitionKeys);
34182
+ for (const key of Object.keys(definition)) if (!keys.has(key)) delete definition[key];
34183
+ return definition;
34184
+ }
34185
+ };
34186
+
34520
34187
  //#endregion
34521
34188
  //#region src/components/side_panel/chart/main_chart_panel/main_chart_panel_store.ts
34522
34189
  var MainChartPanelStore = class extends SpreadsheetStore {
@@ -36505,7 +36172,7 @@ var FindAndReplacePanel = class extends _odoo_owl.Component {
36505
36172
  }
36506
36173
  get specificRangeMatchesCount() {
36507
36174
  const range = this.searchOptions.specificRange;
36508
- if (!range) return "";
36175
+ if (!range || range.invalidSheetName || range.invalidXc) return "";
36509
36176
  const { sheetId, zone } = range;
36510
36177
  return _t("%(matches)s matches in range %(range)s of %(sheetName)s", {
36511
36178
  matches: this.store.specificRangeMatchesCount,
@@ -40077,7 +39744,13 @@ var PivotSpreadsheetSidePanel = class extends _odoo_owl.Component {
40077
39744
  }
40078
39745
  onSelectionChanged(ranges) {
40079
39746
  this.state.rangeHasChanged = true;
40080
- this.state.range = ranges[0];
39747
+ if (ranges.length === 0) {
39748
+ this.state.range = void 0;
39749
+ return;
39750
+ }
39751
+ const sheetId = this.env.model.getters.getActiveSheetId();
39752
+ const range = this.env.model.getters.getRangeFromSheetXC(sheetId, ranges[0]);
39753
+ this.state.range = this.env.model.getters.getRangeString(range, "forceSheetReference", { useBoundedReference: true });
40081
39754
  }
40082
39755
  onSelectionConfirmed() {
40083
39756
  if (this.state.range) {
@@ -46128,6 +45801,11 @@ var GridOverlay = class extends _odoo_owl.Component {
46128
45801
  });
46129
45802
  return icon?.onClick ? icon : void 0;
46130
45803
  }
45804
+ get isFooterVisible() {
45805
+ const { y } = this.env.model.getters.getMainViewportCoordinates();
45806
+ const { height } = this.env.model.getters.getSheetViewDimension();
45807
+ return !this.env.model.getters.isReadonly() && height - y > 46;
45808
+ }
46131
45809
  };
46132
45810
 
46133
45811
  //#endregion
@@ -49736,6 +49414,7 @@ var CarouselPlugin = class extends CorePlugin {
49736
49414
  return "Success";
49737
49415
  case "UPDATE_CAROUSEL":
49738
49416
  if (!this.carousels[cmd.sheetId]?.[cmd.figureId]) return "InvalidFigureId";
49417
+ for (const item of cmd.definition.items) if (item.type === "chart" && !this.getters.getChart(item.chartId)) return "ChartDoesNotExist";
49739
49418
  return "Success";
49740
49419
  }
49741
49420
  return "Success";
@@ -54610,7 +54289,7 @@ var CompilationParametersBuilder = class {
54610
54289
  if (rangeError) return [[rangeError]];
54611
54290
  const sheetId = range.sheetId;
54612
54291
  const zone = range.zone;
54613
- const _zone = intersection(zone, this.getters.getSheetZone(sheetId));
54292
+ const _zone = this.getters.clipRangeToSheet(range)?.zone;
54614
54293
  if (!_zone) return [[]];
54615
54294
  const { top, left, bottom, right } = zone;
54616
54295
  const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
@@ -54914,6 +54593,7 @@ var FormulaDependencyGraph = class {
54914
54593
  }
54915
54594
  getCellsDependingOn(ranges, visited = new RangeSet()) {
54916
54595
  visited = visited.copy();
54596
+ let initialRangesToRemove = visited.copy();
54917
54597
  const queue = Array.from(ranges).reverse();
54918
54598
  while (queue.length > 0) {
54919
54599
  const range = queue.pop();
@@ -54929,8 +54609,9 @@ var FormulaDependencyGraph = class {
54929
54609
  for (const interval of overlappingIntervals) impactedRanges.add(interval.dependents);
54930
54610
  }
54931
54611
  queue.push(...impactedRanges.difference(visited));
54612
+ initialRangesToRemove = initialRangesToRemove.difference(impactedRanges);
54932
54613
  }
54933
- for (const range of ranges) visited.delete(range);
54614
+ for (const range of initialRangesToRemove) visited.delete(range);
54934
54615
  return visited;
54935
54616
  }
54936
54617
  getOrCreateIntervalTree(sheetId, col) {
@@ -55775,10 +55456,10 @@ var Evaluator = class {
55775
55456
  updateDependencies(position) {
55776
55457
  this.formulaDependencies().removeAllDependencies(position);
55777
55458
  const dependencies = this.getDirectDependencies(position);
55778
- this.formulaDependencies().addDependencies(position, dependencies);
55459
+ this.formulaDependencies().addDependencies(position, this.getters.clipRangesToSheet(dependencies));
55779
55460
  }
55780
55461
  addDependencies(position, dependencies) {
55781
- this.formulaDependencies().addDependencies(position, dependencies);
55462
+ this.formulaDependencies().addDependencies(position, this.getters.clipRangesToSheet(dependencies));
55782
55463
  this.computeDependencies(dependencies);
55783
55464
  }
55784
55465
  computeDependencies(dependencies) {
@@ -55840,7 +55521,8 @@ var Evaluator = class {
55840
55521
  const graph = new FormulaDependencyGraph();
55841
55522
  for (const sheetId of this.getters.getSheetIds()) for (const cell of this.getters.getCells(sheetId)) if (cell.isFormula) {
55842
55523
  const cellPosition = this.getters.getCellPosition(cell.id);
55843
- graph.addDependencies(cellPosition, cell.compiledFormula.rangeDependencies);
55524
+ const dependencies = this.getters.clipRangesToSheet(cell.compiledFormula.rangeDependencies);
55525
+ graph.addDependencies(cellPosition, dependencies);
55844
55526
  }
55845
55527
  return graph;
55846
55528
  });
@@ -61605,7 +61287,8 @@ var GeoFeaturePlugin = class extends UIPlugin {
61605
61287
  "getGeoJsonFeatures",
61606
61288
  "geoFeatureNameToId",
61607
61289
  "getGeoChartAvailableRegions",
61608
- "getAvailableChartRegions"
61290
+ "getAvailableChartRegions",
61291
+ "loadUsedGeoJsonFeatures"
61609
61292
  ];
61610
61293
  geoJsonService;
61611
61294
  geoJsonCache = {};
@@ -61688,6 +61371,23 @@ var GeoFeaturePlugin = class extends UIPlugin {
61688
61371
  }
61689
61372
  return this.geoJsonService.geoFeatureNameToId(region, featureName);
61690
61373
  }
61374
+ loadUsedGeoJsonFeatures() {
61375
+ const regions = this.getters.getSheetIds().flatMap((sheetId) => this.getters.getChartIds(sheetId).map((chartId) => {
61376
+ const definition = this.getters.getChartDefinition(chartId);
61377
+ return definition.type === "geo" ? definition.region || this.getters.getGeoChartAvailableRegions()[0]?.id : void 0;
61378
+ })).filter(isDefined);
61379
+ const uniqueRegions = Array.from(new Set(regions));
61380
+ if (uniqueRegions.length && !this.geoJsonService) {
61381
+ console.error("No geoJsonService provided to the model");
61382
+ return Promise.resolve();
61383
+ }
61384
+ for (const region of uniqueRegions) this.getGeoJsonFeatures(region);
61385
+ const promises = uniqueRegions.map((region) => {
61386
+ const cachedGeoJson = this.geoJsonCache[region];
61387
+ return cachedGeoJson instanceof Promise ? cachedGeoJson : Promise.resolve();
61388
+ });
61389
+ return Promise.all(promises).then(() => {});
61390
+ }
61691
61391
  convertToGeoJson(json) {
61692
61392
  if (!json) return null;
61693
61393
  if (json.type === "Topology") {
@@ -64749,7 +64449,7 @@ var InternalViewport = class {
64749
64449
  let height = lastRowEnd - this.offsetCorrectionY;
64750
64450
  if (this.canScrollVertically) {
64751
64451
  height = Math.max(height, this.viewportHeight);
64752
- if (lastRowEnd + 46 > height && !this.getters.isReadonly()) height += 46;
64452
+ if (lastRowEnd + 46 > height && !this.getters.isReadonly() && this.viewportHeight > 46) height += 46;
64753
64453
  }
64754
64454
  return {
64755
64455
  width,
@@ -68987,7 +68687,7 @@ var FigureRendererStore = class extends DisposableStore {
68987
68687
  if (!this.getters.isDashboard()) {
68988
68688
  ctx.strokeStyle = GRAY_400;
68989
68689
  ctx.lineWidth = 1;
68990
- ctx.strokeRect(x, y, figure.width, figure.height);
68690
+ ctx.strokeRect(x + .5, y + .5, figure.width - 1, figure.height - 1);
68991
68691
  }
68992
68692
  }
68993
68693
  }
@@ -69196,12 +68896,11 @@ var SpreadsheetPrintStore = class extends SpreadsheetStore {
69196
68896
  const { width: printWidth, height: printHeight } = this.pageDimensionWithMargins;
69197
68897
  const start = dimension === "COL" ? printZone.left : printZone.top;
69198
68898
  const end = dimension === "COL" ? printZone.right : printZone.bottom;
69199
- const getHeaderSize = dimension === "COL" ? this.getters.getColDimensions : this.getters.getRowDimensions;
69200
68899
  const max = dimension === "COL" ? printWidth : printHeight;
69201
68900
  const breaks = [];
69202
68901
  let current = 0;
69203
68902
  for (let i = start; i <= end; i++) {
69204
- const headerSize = getHeaderSize(sheetId, i).size * zoom;
68903
+ const headerSize = this.getters.getHeaderSize(sheetId, dimension, i) * zoom;
69205
68904
  current += headerSize;
69206
68905
  if (current >= max) {
69207
68906
  breaks.push(i);
@@ -71686,6 +71385,8 @@ var RangeAdapterPlugin = class {
71686
71385
  "extendRange",
71687
71386
  "getRangeString",
71688
71387
  "getRangeFromSheetXC",
71388
+ "clipRangesToSheet",
71389
+ "clipRangeToSheet",
71689
71390
  "createAdaptedRanges",
71690
71391
  "getRangeData",
71691
71392
  "getRangeDataFromXc",
@@ -71724,6 +71425,22 @@ var RangeAdapterPlugin = class {
71724
71425
  addRangeProvider(provider) {
71725
71426
  this.providers.push(provider);
71726
71427
  }
71428
+ clipRangeToSheet(range) {
71429
+ if (range.invalidXc) return range;
71430
+ const sheetZone = this.getters.getSheetZone(range.sheetId);
71431
+ if (isZoneInside(range.zone, sheetZone)) return range;
71432
+ const newZone = intersection(range.zone, sheetZone);
71433
+ if (!newZone) return;
71434
+ return this.getters.getRangeFromZone(range.sheetId, newZone);
71435
+ }
71436
+ clipRangesToSheet(ranges) {
71437
+ const clippedRanges = [];
71438
+ for (const range of ranges) {
71439
+ const clippedRange = this.clipRangeToSheet(range);
71440
+ if (clippedRange) clippedRanges.push(clippedRange);
71441
+ }
71442
+ return clippedRanges;
71443
+ }
71727
71444
  createAdaptedRanges(ranges, offsetX, offsetY, sheetId) {
71728
71445
  return ranges.map((range) => {
71729
71446
  if (!isZoneValid(range.zone)) return range;
@@ -74921,6 +74638,8 @@ var Model = class Model extends EventBus {
74921
74638
  this.range = new RangeAdapterPlugin(this.coreGetters);
74922
74639
  this.coreGetters.getRangeString = this.range.getRangeString.bind(this.range);
74923
74640
  this.coreGetters.getRangeFromSheetXC = this.range.getRangeFromSheetXC.bind(this.range);
74641
+ this.coreGetters.clipRangesToSheet = this.range.clipRangesToSheet.bind(this.range);
74642
+ this.coreGetters.clipRangeToSheet = this.range.clipRangeToSheet.bind(this.range);
74924
74643
  this.coreGetters.createAdaptedRanges = this.range.createAdaptedRanges.bind(this.range);
74925
74644
  this.coreGetters.getRangeData = this.range.getRangeData.bind(this.range);
74926
74645
  this.coreGetters.getRangeDataFromXc = this.range.getRangeDataFromXc.bind(this.range);
@@ -75327,6 +75046,306 @@ function createCommand(type, payload = {}) {
75327
75046
  return command;
75328
75047
  }
75329
75048
 
75049
+ //#endregion
75050
+ //#region src/helpers/figures/charts/chart_data_sources.ts
75051
+ const EMPTY = Object.freeze({ value: null });
75052
+ const ONE = Object.freeze({ value: 1 });
75053
+ const ChartRangeDataSourceHandler = {
75054
+ supportedChartTypes: CHART_TYPES,
75055
+ fromExternalDefinition(dataSource, defaultSheetId, getters) {
75056
+ const dataSets = createDataSets(getters, defaultSheetId, dataSource);
75057
+ const labelRange = createValidRange(getters, defaultSheetId, dataSource.labelRange);
75058
+ return {
75059
+ ...dataSource,
75060
+ dataSets,
75061
+ labelRange
75062
+ };
75063
+ },
75064
+ fromContextCreation(context) {
75065
+ return {
75066
+ type: "range",
75067
+ dataSets: [],
75068
+ dataSetsHaveTitle: false,
75069
+ labelRange: context.auxiliaryRange,
75070
+ ...context.dataSource
75071
+ };
75072
+ },
75073
+ fromHierarchicalContextCreation(context) {
75074
+ if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
75075
+ type: "range",
75076
+ dataSets: [],
75077
+ dataSetsHaveTitle: false
75078
+ };
75079
+ let dataSource = {
75080
+ type: "range",
75081
+ dataSets: [],
75082
+ dataSetsHaveTitle: context.dataSource?.dataSetsHaveTitle ?? false,
75083
+ labelRange: context.dataSource?.dataSets?.[0]?.dataRange
75084
+ };
75085
+ if (context.hierarchicalDataSource?.dataSets.length) dataSource = context.hierarchicalDataSource;
75086
+ else if (context.auxiliaryRange) dataSource = {
75087
+ ...dataSource,
75088
+ dataSets: [{
75089
+ dataRange: context.auxiliaryRange,
75090
+ dataSetId: "0"
75091
+ }]
75092
+ };
75093
+ return dataSource;
75094
+ },
75095
+ validate: (dataSource, validator) => validator.checkValidations(dataSource, checkDataset, checkLabelRange),
75096
+ transform(dataSource, defaultSheetId, { adaptRangeString }) {
75097
+ let labelRange;
75098
+ if (dataSource.labelRange) {
75099
+ const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSource.labelRange);
75100
+ if (changeType !== "REMOVE") labelRange = adaptedRange;
75101
+ }
75102
+ const dataSets = [];
75103
+ for (const dataSet of dataSource.dataSets) {
75104
+ const newDataSet = { ...dataSet };
75105
+ const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSet.dataRange);
75106
+ if (changeType !== "REMOVE") {
75107
+ newDataSet.dataRange = adaptedRange;
75108
+ dataSets.push(newDataSet);
75109
+ }
75110
+ }
75111
+ return {
75112
+ ...dataSource,
75113
+ dataSets,
75114
+ labelRange
75115
+ };
75116
+ },
75117
+ extractData: (dataSource, chartId, getters) => getChartData(getters, dataSource),
75118
+ extractHierarchicalData(dataSource, chartId, getters) {
75119
+ const dataSets = dataSource.dataSets;
75120
+ const labelRange = dataSource.labelRange;
75121
+ const labelValues = getChartLabelValues(getters, dataSets, labelRange);
75122
+ const dataSetsValues = getHierarchicalDatasetValues(getters, dataSets);
75123
+ const data = {
75124
+ labelValues,
75125
+ dataSetsValues
75126
+ };
75127
+ if (shouldRemoveFirstLabel(labelValues.length, dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0), dataSource.dataSetsHaveTitle || false)) labelValues.shift();
75128
+ return data;
75129
+ },
75130
+ adaptRanges(dataSource, { applyChange }) {
75131
+ const dataSetsWithUndefined = dataSource.dataSets.map((ds) => {
75132
+ const { range: adaptedRangeStr, changeType } = applyChange(ds.dataRange);
75133
+ if (changeType === "REMOVE") return;
75134
+ let labelCell = void 0;
75135
+ if (ds.labelCell) {
75136
+ const { range: adaptedLabelCellRange, changeType: labelCellChangeType } = applyChange(ds.labelCell);
75137
+ if (labelCellChangeType !== "REMOVE") labelCell = adaptedLabelCellRange;
75138
+ }
75139
+ return {
75140
+ ...ds,
75141
+ dataRange: adaptedRangeStr,
75142
+ labelCell
75143
+ };
75144
+ }).filter(isDefined);
75145
+ let labelRange = dataSource.labelRange;
75146
+ if (labelRange) {
75147
+ const { range: adaptedLabelRange, changeType } = applyChange(labelRange);
75148
+ if (changeType === "REMOVE") labelRange = void 0;
75149
+ else labelRange = adaptedLabelRange;
75150
+ }
75151
+ const dataSets = dataSetsWithUndefined;
75152
+ return {
75153
+ ...dataSource,
75154
+ dataSets,
75155
+ labelRange: labelRange?.invalidSheetName || labelRange?.invalidXc ? void 0 : labelRange
75156
+ };
75157
+ },
75158
+ getDefinition(dataSource, defaultSheetId, getters) {
75159
+ return {
75160
+ labelRange: dataSource.labelRange ? getters.getRangeString(dataSource.labelRange, defaultSheetId) : void 0,
75161
+ type: "range",
75162
+ dataSets: dataSource.dataSets.map((dataSet) => ({
75163
+ dataSetId: dataSet.dataSetId,
75164
+ dataRange: getters.getRangeString(dataSet.dataRange, defaultSheetId)
75165
+ })),
75166
+ dataSetsHaveTitle: dataSource.dataSetsHaveTitle
75167
+ };
75168
+ },
75169
+ /**
75170
+ * Duplicate the dataSets. All ranges on sheetIdFrom are adapted to target
75171
+ * sheetIdTo.
75172
+ */
75173
+ duplicateInDuplicatedSheet(dataSource, sheetIdFrom, sheetIdTo, getters) {
75174
+ return {
75175
+ ...dataSource,
75176
+ labelRange: duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, dataSource.labelRange),
75177
+ dataSets: dataSource.dataSets.map((ds) => ({
75178
+ ...ds,
75179
+ dataRange: duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.dataRange)
75180
+ }))
75181
+ };
75182
+ },
75183
+ getContextCreation: (dataSource) => ({
75184
+ auxiliaryRange: dataSource.labelRange,
75185
+ dataSource
75186
+ }),
75187
+ getHierarchicalContextCreation(dataSource) {
75188
+ const leafRange = dataSource.dataSets.at(-1)?.dataRange;
75189
+ const dataSetsHaveTitle = dataSource.dataSetsHaveTitle;
75190
+ return {
75191
+ auxiliaryRange: leafRange,
75192
+ hierarchicalDataSource: dataSource,
75193
+ dataSource: dataSource.labelRange ? {
75194
+ type: "range",
75195
+ dataSets: [{
75196
+ dataRange: dataSource.labelRange,
75197
+ dataSetId: "0"
75198
+ }],
75199
+ dataSetsHaveTitle
75200
+ } : {
75201
+ type: "range",
75202
+ dataSets: [],
75203
+ dataSetsHaveTitle
75204
+ }
75205
+ };
75206
+ },
75207
+ toExcelDataSets(dataSource, dataSetStyles, getters) {
75208
+ const dataSets = dataSource.dataSets;
75209
+ const labelRange = dataSource.labelRange;
75210
+ const excelDataSets = dataSets.map((ds) => toExcelDataset(getters, dataSetStyles, ds)).filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
75211
+ const datasetLength = dataSets[0] ? getZoneArea(dataSets[0].dataRange.zone) : void 0;
75212
+ return {
75213
+ dataSets: excelDataSets,
75214
+ labelRange: toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel(labelRange ? getZoneArea(labelRange.zone) : 0, datasetLength, dataSource.dataSetsHaveTitle))
75215
+ };
75216
+ }
75217
+ };
75218
+ function getChartData(getters, dataSource) {
75219
+ const dataSets = dataSource.dataSets;
75220
+ const labelRange = dataSource.labelRange;
75221
+ const labelValues = getChartLabelValues(getters, dataSets, labelRange);
75222
+ const dataSetsValues = getChartDatasetValues(getters, dataSets);
75223
+ const data = {
75224
+ labelValues,
75225
+ dataSetsValues
75226
+ };
75227
+ const numberOfDataPoints = dataSetsValues.length ? dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0) : 0;
75228
+ if (shouldRemoveFirstLabel(labelValues.length, numberOfDataPoints, dataSource.dataSetsHaveTitle || false)) labelValues.shift();
75229
+ return data;
75230
+ }
75231
+ function getChartDatasetValues(getters, dataSets) {
75232
+ const datasetValues = [];
75233
+ for (const [dsIndex, ds] of Object.entries(dataSets)) {
75234
+ let label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`;
75235
+ let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
75236
+ if (ds.labelCell) {
75237
+ const { sheetId, zone } = ds.labelCell;
75238
+ const cell = getters.getEvaluatedCell({
75239
+ sheetId,
75240
+ col: zone.left,
75241
+ row: zone.top
75242
+ });
75243
+ if (cell) label = cell.formattedValue;
75244
+ }
75245
+ let data = ds.dataRange ? getData(getters, ds) : [];
75246
+ if (data.every((cell) => !cell.value || isTextResult(cell)) && data.filter(isTextResult).length > 1) data = data.map((cell) => cell.value && !isErrorResult(cell) ? ONE : EMPTY);
75247
+ else if (data.every((cell) => !isNumberResult(cell))) hidden = true;
75248
+ datasetValues.push({
75249
+ data,
75250
+ label,
75251
+ hidden,
75252
+ dataSetId: ds.dataSetId
75253
+ });
75254
+ }
75255
+ return datasetValues;
75256
+ }
75257
+ function getChartLabelValues(getters, dataSets, labelRange) {
75258
+ if (labelRange) {
75259
+ const { left } = labelRange.zone;
75260
+ if (!labelRange.invalidXc && !labelRange.invalidSheetName && !getters.isColHidden(labelRange.sheetId, left)) return getters.getVisibleRangeValues(labelRange);
75261
+ }
75262
+ if (dataSets[0]) {
75263
+ const dataLength = getData(getters, dataSets[0]).length;
75264
+ return Array.from({ length: dataLength }, () => ({ value: "" }));
75265
+ }
75266
+ return [];
75267
+ }
75268
+ /**
75269
+ * Get the values for a hierarchical dataset. The values can be defined in a tree-like structure
75270
+ * in the sheet, and this function will fill up the blanks.
75271
+ *
75272
+ * @example the following dataset:
75273
+ *
75274
+ * 2024 Q1 W1 100
75275
+ * W2 200
75276
+ *
75277
+ * will have the same value as the dataset:
75278
+ * 2024 Q1 W1 100
75279
+ * 2024 Q1 W2 200
75280
+ */
75281
+ function getHierarchicalDatasetValues(getters, dataSets) {
75282
+ dataSets = dataSets.filter((ds) => !getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left));
75283
+ const datasetValues = dataSets.map((ds) => ({
75284
+ data: [],
75285
+ label: "",
75286
+ dataSetId: ds.dataSetId
75287
+ }));
75288
+ const locale = getters.getLocale();
75289
+ const dataSetsData = dataSets.map((ds) => getData(getters, ds)).map((values) => values.map(({ value, format }) => value === null ? EMPTY : { value: formatValue(value, {
75290
+ format,
75291
+ locale
75292
+ }) }));
75293
+ if (!dataSetsData.length) return datasetValues;
75294
+ const minLength = Math.min(...dataSetsData.map((ds) => ds.length));
75295
+ let currentValues = [];
75296
+ const leafDatasetIndex = dataSets.length - 1;
75297
+ for (let i = 0; i < minLength; i++) for (let dsIndex = 0; dsIndex < dataSetsData.length; dsIndex++) {
75298
+ let cell = dataSetsData[dsIndex][i];
75299
+ if ((cell === void 0 || cell.value === null) && dsIndex !== leafDatasetIndex) cell = currentValues[dsIndex];
75300
+ if (cell?.value !== currentValues[dsIndex]?.value) {
75301
+ currentValues = currentValues.slice(0, dsIndex);
75302
+ currentValues[dsIndex] = cell;
75303
+ }
75304
+ datasetValues[dsIndex].data.push(cell ?? EMPTY);
75305
+ }
75306
+ return datasetValues.filter((ds) => ds.data.some((d) => d.value !== null));
75307
+ }
75308
+ /**
75309
+ * Get the data from a dataSet
75310
+ */
75311
+ function getData(getters, ds) {
75312
+ if (ds.dataRange) {
75313
+ const labelCellZone = ds.labelCell ? [ds.labelCell.zone] : [];
75314
+ const dataZone = recomputeZones([ds.dataRange.zone], labelCellZone)[0];
75315
+ if (dataZone === void 0) return [];
75316
+ const dataRange = getters.getRangeFromZone(ds.dataRange.sheetId, dataZone);
75317
+ return getters.getVisibleRangeValues(dataRange).map((cell) => cell.value === "" ? EMPTY : cell);
75318
+ }
75319
+ return [];
75320
+ }
75321
+ const ChartNeverDataSourceHandler = {
75322
+ supportedChartTypes: [],
75323
+ fromExternalDefinition: () => ({ type: "none" }),
75324
+ fromContextCreation: () => ({ type: "none" }),
75325
+ fromHierarchicalContextCreation: () => ({ type: "none" }),
75326
+ validate: () => "Success",
75327
+ transform: () => ({ type: "none" }),
75328
+ extractData: () => ({
75329
+ dataSetsValues: [],
75330
+ labelValues: []
75331
+ }),
75332
+ extractHierarchicalData: () => ({
75333
+ dataSetsValues: [],
75334
+ labelValues: []
75335
+ }),
75336
+ adaptRanges: (dataSource) => dataSource,
75337
+ getDefinition: (dataSource) => dataSource,
75338
+ duplicateInDuplicatedSheet: (dataSource) => dataSource,
75339
+ getContextCreation: () => ({}),
75340
+ getHierarchicalContextCreation: () => ({}),
75341
+ toExcelDataSets: () => ({
75342
+ dataSets: [],
75343
+ labelRange: void 0
75344
+ })
75345
+ };
75346
+ chartDataSourceRegistry.add("range", ChartRangeDataSourceHandler);
75347
+ chartDataSourceRegistry.add("none", ChartNeverDataSourceHandler);
75348
+
75330
75349
  //#endregion
75331
75350
  //#region src/helpers/figures/charts/calendar_chart.ts
75332
75351
  function checkDateGranularity(definition) {
@@ -85002,6 +85021,6 @@ exports.stores = stores;
85002
85021
  exports.tokenColors = tokenColors;
85003
85022
  exports.tokenize = tokenize;
85004
85023
 
85005
- __info__.version = "19.3.18";
85006
- __info__.date = "2026-08-29T09:16:28.272Z";
85007
- __info__.hash = "1f4b1ae";
85024
+ __info__.version = "19.3.20";
85025
+ __info__.date = "2026-09-10T05:38:03.233Z";
85026
+ __info__.hash = "e488e8d";