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