@odoo/o-spreadsheet 19.4.11 → 19.4.12

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.4.11
6
- * @date 2026-09-04T07:50:39.272Z
7
- * @hash 7660254
5
+ * @version 19.4.12
6
+ * @date 2026-09-10T05:38:01.898Z
7
+ * @hash cdb63b4
8
8
  */
9
9
 
10
10
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -7853,7 +7853,8 @@ const invalidateChartEvaluationCommands = /* @__PURE__ */ new Set([
7853
7853
  "UPDATE_TABLE",
7854
7854
  "UPDATE_FILTER",
7855
7855
  "UNDO",
7856
- "REDO"
7856
+ "REDO",
7857
+ "UPDATE_COLOR_SCHEME"
7857
7858
  ]);
7858
7859
  const invalidateDependenciesCommands = /* @__PURE__ */ new Set(["MOVE_RANGES"]);
7859
7860
  const invalidateCFEvaluationCommands = /* @__PURE__ */ new Set([
@@ -10249,7 +10250,7 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
10249
10250
  const point = dataset.data[i];
10250
10251
  const xPosition = point.x;
10251
10252
  let yPosition = 0;
10252
- if (chart.config.type === "line" || chart.config.type === "radar") yPosition = value < 0 ? point.y + 10 : point.y - 10;
10253
+ if (dataset.type === "line" || dataset.type === "radar") yPosition = value < 0 ? point.y + 10 : point.y - 10;
10253
10254
  else if (chart.config.type === "bubble") yPosition = point.y;
10254
10255
  else {
10255
10256
  const yZeroLine = yAxisScale.getPixelForValue(0);
@@ -15852,7 +15853,7 @@ const RemoveDuplicateTerms = { Errors: {
15852
15853
  ["MoreThanOneRangeSelected"]: _t("Please select only one range of cells"),
15853
15854
  ["EmptySelectedRange"]: _t("Please select a range of cells containing values."),
15854
15855
  ["NoColumnsProvided"]: _t("Please select at latest one column to analyze."),
15855
- ["WillRemoveExistingMerge"]: _t("This operation is not possible due to a merge. Please remove the merges first than try again.")
15856
+ ["WillRemoveExistingMerge"]: _t("Cannot perform this action on merged cells. Unmerge the cells and try again.")
15856
15857
  } };
15857
15858
  const DVTerms = {
15858
15859
  DateIs: {
@@ -30184,433 +30185,6 @@ var ChartRangeDataSourceComponent = class extends Component {
30184
30185
  }
30185
30186
  };
30186
30187
 
30187
- //#endregion
30188
- //#region src/helpers/figures/chart.ts
30189
- var SpreadsheetChart = class SpreadsheetChart {
30190
- getters;
30191
- sheetId;
30192
- definition;
30193
- chartTypeBuilder;
30194
- dataSourceBuilder;
30195
- dataSource;
30196
- constructor(getters, sheetId, definition, chartTypeBuilder, dataSourceBuilder) {
30197
- this.getters = getters;
30198
- this.sheetId = sheetId;
30199
- this.definition = definition;
30200
- this.chartTypeBuilder = chartTypeBuilder;
30201
- this.dataSourceBuilder = dataSourceBuilder;
30202
- this.dataSource = definition.dataSource;
30203
- }
30204
- static fromStrDefinition(getters, sheetId, definition) {
30205
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
30206
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
30207
- const dataSource = dataSourceBuilder.fromExternalDefinition(definition.dataSource ?? { type: "none" }, sheetId, getters);
30208
- const rangeDefinition = {
30209
- ...chartTypeBuilder.fromStrDefinition(definition, sheetId, getters),
30210
- dataSource
30211
- };
30212
- return new SpreadsheetChart(getters, sheetId, SpreadsheetChart.deleteInvalidKeys(rangeDefinition), chartTypeBuilder, dataSourceBuilder);
30213
- }
30214
- static fromDefinition(getters, sheetId, definition) {
30215
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
30216
- return new SpreadsheetChart(getters, sheetId, definition, chartTypeRegistry.get(definition.type), dataSourceBuilder);
30217
- }
30218
- static validate(validator, definition) {
30219
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
30220
- const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
30221
- return validator.batchValidations(() => chartTypeBuilder.validateDefinition(validator, definition), () => dataSourceBuilder.validate(definition.dataSource ?? { type: "none" }, validator))(void 0);
30222
- }
30223
- static transformDefinition(chartSheetId, definition, rangeAdapters) {
30224
- const chartTypeBuilder = chartTypeRegistry.get(definition.type);
30225
- if (!definition.dataSource) return chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters);
30226
- const newDataSource = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none").transform(definition.dataSource, chartSheetId, rangeAdapters);
30227
- return {
30228
- ...chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters),
30229
- dataSource: newDataSource
30230
- };
30231
- }
30232
- getRangeDefinition() {
30233
- return {
30234
- ...this.definition,
30235
- dataSource: this.dataSource
30236
- };
30237
- }
30238
- getDefinition() {
30239
- return {
30240
- ...this.chartTypeBuilder.toStrDefinition(this.definition, this.sheetId, this.getters),
30241
- dataSource: this.dataSource && this.dataSourceBuilder.getDefinition(this.dataSource, this.sheetId, this.getters)
30242
- };
30243
- }
30244
- updateRanges(rangeAdapters) {
30245
- return {
30246
- ...this.chartTypeBuilder.updateRanges(this.definition, rangeAdapters, this.sheetId),
30247
- dataSource: this.dataSource && this.dataSourceBuilder.adaptRanges(this.dataSource, rangeAdapters)
30248
- };
30249
- }
30250
- duplicateInDuplicatedSheet(sheetIdFrom, sheetIdTo) {
30251
- const newDataSource = this.dataSource && this.dataSourceBuilder.duplicateInDuplicatedSheet(this.dataSource, sheetIdFrom, sheetIdTo, this.getters);
30252
- const definition = {
30253
- ...this.chartTypeBuilder.duplicateInDuplicatedSheet(this.definition, sheetIdFrom, sheetIdTo, this.getters),
30254
- dataSource: newDataSource
30255
- };
30256
- return SpreadsheetChart.fromDefinition(this.getters, sheetIdTo, definition).getDefinition();
30257
- }
30258
- copyInSheetId(sheetIdTo) {
30259
- return {
30260
- ...this.chartTypeBuilder.copyInSheetId(this.definition, this.sheetId, sheetIdTo, this.getters),
30261
- dataSource: this.dataSource
30262
- };
30263
- }
30264
- getContextCreation() {
30265
- const definition = this.getDefinition();
30266
- return {
30267
- ...this.dataSourceBuilder.getContextCreation(definition.dataSource ?? { type: "none" }),
30268
- ...this.chartTypeBuilder.getContextCreation(definition, this.dataSourceBuilder, definition.dataSource)
30269
- };
30270
- }
30271
- getDefinitionForExcel(getters) {
30272
- const definition = this.definition;
30273
- const excelDataSets = this.dataSourceBuilder.toExcelDataSets(this.dataSource, "dataSetStyles" in definition ? definition.dataSetStyles : {}, getters);
30274
- if (excelDataSets === void 0) return;
30275
- return this.chartTypeBuilder.getDefinitionForExcel(getters, definition, excelDataSets);
30276
- }
30277
- getData(getters, chartId) {
30278
- const dataSource = this.dataSource;
30279
- return dataSource ? this.dataSourceBuilder.extractData(dataSource, chartId, getters) : {
30280
- dataSetsValues: [],
30281
- labelValues: []
30282
- };
30283
- }
30284
- getRuntime(getters, chartId) {
30285
- const dataSource = this.dataSource;
30286
- const dataExtractors = dataSource ? {
30287
- extractData: () => this.dataSourceBuilder.extractData(dataSource, chartId, getters),
30288
- extractHierarchicalData: () => this.dataSourceBuilder.extractHierarchicalData(dataSource, chartId, getters)
30289
- } : {
30290
- extractData: () => ({
30291
- dataSetsValues: [],
30292
- labelValues: []
30293
- }),
30294
- extractHierarchicalData: () => ({
30295
- dataSetsValues: [],
30296
- labelValues: []
30297
- })
30298
- };
30299
- return this.chartTypeBuilder.getRuntime(getters, this.definition, dataExtractors, this.sheetId, {
30300
- onClick: (event, items, chartJsChart) => {
30301
- return this.dataSourceBuilder.onDataSetClick?.(this.definition.type, chartId, event, items, chartJsChart, getters);
30302
- },
30303
- onHover: (event, items, chartJsChart) => this.dataSourceBuilder.onDataSetHover?.(this.definition.type, chartId, event, items, chartJsChart)
30304
- });
30305
- }
30306
- static deleteInvalidKeys(definition) {
30307
- definition = { ...definition };
30308
- const keys = new Set(chartTypeRegistry.get(definition.type).allowedDefinitionKeys);
30309
- for (const key of Object.keys(definition)) if (!keys.has(key)) delete definition[key];
30310
- return definition;
30311
- }
30312
- };
30313
-
30314
- //#endregion
30315
- //#region src/helpers/figures/charts/chart_data_sources.ts
30316
- const EMPTY = Object.freeze({ value: null });
30317
- const ONE = Object.freeze({ value: 1 });
30318
- const ChartRangeDataSourceHandler = {
30319
- supportedChartTypes: CHART_TYPES,
30320
- fromExternalDefinition(dataSource, defaultSheetId, getters) {
30321
- const dataSets = createDataSets(getters, defaultSheetId, dataSource);
30322
- const labelRange = createValidRange(getters, defaultSheetId, dataSource.labelRange);
30323
- return {
30324
- ...dataSource,
30325
- dataSets,
30326
- labelRange
30327
- };
30328
- },
30329
- fromContextCreation(context) {
30330
- return {
30331
- type: "range",
30332
- dataSets: [],
30333
- dataSetsHaveTitle: false,
30334
- labelRange: context.auxiliaryRange,
30335
- ...context.dataSource
30336
- };
30337
- },
30338
- fromHierarchicalContextCreation(context) {
30339
- if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
30340
- type: "range",
30341
- dataSets: [],
30342
- dataSetsHaveTitle: false
30343
- };
30344
- let dataSource = {
30345
- type: "range",
30346
- dataSets: [],
30347
- dataSetsHaveTitle: context.dataSource?.dataSetsHaveTitle ?? false,
30348
- labelRange: context.dataSource?.dataSets?.[0]?.dataRange
30349
- };
30350
- if (context.hierarchicalDataSource?.dataSets.length) dataSource = context.hierarchicalDataSource;
30351
- else if (context.auxiliaryRange) dataSource = {
30352
- ...dataSource,
30353
- dataSets: [{
30354
- dataRange: context.auxiliaryRange,
30355
- dataSetId: "0"
30356
- }]
30357
- };
30358
- return dataSource;
30359
- },
30360
- validate: (dataSource, validator) => validator.checkValidations(dataSource, checkDataset, checkLabelRange),
30361
- transform(dataSource, defaultSheetId, { adaptRangeString }) {
30362
- let labelRange;
30363
- if (dataSource.labelRange) {
30364
- const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSource.labelRange);
30365
- if (changeType !== "REMOVE") labelRange = adaptedRange;
30366
- }
30367
- const dataSets = [];
30368
- for (const dataSet of dataSource.dataSets) {
30369
- const newDataSet = { ...dataSet };
30370
- const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSet.dataRange);
30371
- if (changeType !== "REMOVE") {
30372
- newDataSet.dataRange = adaptedRange;
30373
- dataSets.push(newDataSet);
30374
- }
30375
- }
30376
- return {
30377
- ...dataSource,
30378
- dataSets,
30379
- labelRange
30380
- };
30381
- },
30382
- extractData: (dataSource, chartId, getters) => getChartData(getters, dataSource),
30383
- extractHierarchicalData(dataSource, chartId, getters) {
30384
- const dataSets = dataSource.dataSets;
30385
- const labelRange = dataSource.labelRange;
30386
- const labelValues = getChartLabelValues(getters, dataSets, labelRange);
30387
- const dataSetsValues = getHierarchicalDatasetValues(getters, dataSets);
30388
- const data = {
30389
- labelValues,
30390
- dataSetsValues
30391
- };
30392
- if (shouldRemoveFirstLabel(labelValues.length, dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0), dataSource.dataSetsHaveTitle || false)) labelValues.shift();
30393
- return data;
30394
- },
30395
- adaptRanges(dataSource, { applyChange }) {
30396
- const dataSetsWithUndefined = dataSource.dataSets.map((ds) => {
30397
- const { range: adaptedRangeStr, changeType } = applyChange(ds.dataRange);
30398
- if (changeType === "REMOVE") return;
30399
- let labelCell = void 0;
30400
- if (ds.labelCell) {
30401
- const { range: adaptedLabelCellRange, changeType: labelCellChangeType } = applyChange(ds.labelCell);
30402
- if (labelCellChangeType !== "REMOVE") labelCell = adaptedLabelCellRange;
30403
- }
30404
- return {
30405
- ...ds,
30406
- dataRange: adaptedRangeStr,
30407
- labelCell
30408
- };
30409
- }).filter(isDefined);
30410
- let labelRange = dataSource.labelRange;
30411
- if (labelRange) {
30412
- const { range: adaptedLabelRange, changeType } = applyChange(labelRange);
30413
- if (changeType === "REMOVE") labelRange = void 0;
30414
- else labelRange = adaptedLabelRange;
30415
- }
30416
- const dataSets = dataSetsWithUndefined;
30417
- return {
30418
- ...dataSource,
30419
- dataSets,
30420
- labelRange: labelRange?.invalidSheetName || labelRange?.invalidXc ? void 0 : labelRange
30421
- };
30422
- },
30423
- getDefinition(dataSource, defaultSheetId, getters) {
30424
- return {
30425
- labelRange: dataSource.labelRange ? getters.getRangeString(dataSource.labelRange, defaultSheetId) : void 0,
30426
- type: "range",
30427
- dataSets: dataSource.dataSets.map((dataSet) => ({
30428
- dataSetId: dataSet.dataSetId,
30429
- dataRange: getters.getRangeString(dataSet.dataRange, defaultSheetId)
30430
- })),
30431
- dataSetsHaveTitle: dataSource.dataSetsHaveTitle
30432
- };
30433
- },
30434
- /**
30435
- * Duplicate the dataSets. All ranges on sheetIdFrom are adapted to target
30436
- * sheetIdTo.
30437
- */
30438
- duplicateInDuplicatedSheet(dataSource, sheetIdFrom, sheetIdTo, getters) {
30439
- return {
30440
- ...dataSource,
30441
- labelRange: duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, dataSource.labelRange),
30442
- dataSets: dataSource.dataSets.map((ds) => ({
30443
- ...ds,
30444
- dataRange: duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.dataRange)
30445
- }))
30446
- };
30447
- },
30448
- getContextCreation: (dataSource) => ({
30449
- auxiliaryRange: dataSource.labelRange,
30450
- dataSource
30451
- }),
30452
- getHierarchicalContextCreation(dataSource) {
30453
- const leafRange = dataSource.dataSets.at(-1)?.dataRange;
30454
- const dataSetsHaveTitle = dataSource.dataSetsHaveTitle;
30455
- return {
30456
- auxiliaryRange: leafRange,
30457
- hierarchicalDataSource: dataSource,
30458
- dataSource: dataSource.labelRange ? {
30459
- type: "range",
30460
- dataSets: [{
30461
- dataRange: dataSource.labelRange,
30462
- dataSetId: "0"
30463
- }],
30464
- dataSetsHaveTitle
30465
- } : {
30466
- type: "range",
30467
- dataSets: [],
30468
- dataSetsHaveTitle
30469
- }
30470
- };
30471
- },
30472
- toExcelDataSets(dataSource, dataSetStyles, getters) {
30473
- const dataSets = dataSource.dataSets;
30474
- const labelRange = dataSource.labelRange;
30475
- const excelDataSets = dataSets.map((ds) => toExcelDataset(getters, dataSetStyles, ds)).filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
30476
- const datasetLength = dataSets[0] ? getZoneArea(dataSets[0].dataRange.zone) : void 0;
30477
- return {
30478
- dataSets: excelDataSets,
30479
- labelRange: toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel(labelRange ? getZoneArea(labelRange.zone) : 0, datasetLength, dataSource.dataSetsHaveTitle))
30480
- };
30481
- }
30482
- };
30483
- function getChartData(getters, dataSource) {
30484
- const dataSets = dataSource.dataSets;
30485
- const labelRange = dataSource.labelRange;
30486
- const labelValues = getChartLabelValues(getters, dataSets, labelRange);
30487
- const dataSetsValues = getChartDatasetValues(getters, dataSets);
30488
- const data = {
30489
- labelValues,
30490
- dataSetsValues
30491
- };
30492
- const numberOfDataPoints = dataSetsValues.length ? dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0) : 0;
30493
- if (shouldRemoveFirstLabel(labelValues.length, numberOfDataPoints, dataSource.dataSetsHaveTitle || false)) labelValues.shift();
30494
- return data;
30495
- }
30496
- function getChartDatasetValues(getters, dataSets) {
30497
- const datasetValues = [];
30498
- for (const [dsIndex, ds] of Object.entries(dataSets)) {
30499
- let label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`;
30500
- let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
30501
- if (ds.labelCell) {
30502
- const { sheetId, zone } = ds.labelCell;
30503
- const cell = getters.getEvaluatedCell({
30504
- sheetId,
30505
- col: zone.left,
30506
- row: zone.top
30507
- });
30508
- if (cell) label = cell.formattedValue;
30509
- }
30510
- let data = ds.dataRange ? getData(getters, ds) : [];
30511
- if (data.every((cell) => !cell.value || isTextResult(cell)) && data.filter(isTextResult).length > 1) data = data.map((cell) => cell.value && !isErrorResult(cell) ? ONE : EMPTY);
30512
- else if (data.every((cell) => !isNumberResult(cell))) hidden = true;
30513
- datasetValues.push({
30514
- data,
30515
- label,
30516
- hidden,
30517
- dataSetId: ds.dataSetId
30518
- });
30519
- }
30520
- return datasetValues;
30521
- }
30522
- function getChartLabelValues(getters, dataSets, labelRange) {
30523
- if (labelRange) {
30524
- const { left } = labelRange.zone;
30525
- if (!labelRange.invalidXc && !labelRange.invalidSheetName && !getters.isColHidden(labelRange.sheetId, left)) return getters.getVisibleRangeValues(labelRange);
30526
- }
30527
- if (dataSets[0]) {
30528
- const dataLength = getData(getters, dataSets[0]).length;
30529
- return Array.from({ length: dataLength }, () => ({ value: "" }));
30530
- }
30531
- return [];
30532
- }
30533
- /**
30534
- * Get the values for a hierarchical dataset. The values can be defined in a tree-like structure
30535
- * in the sheet, and this function will fill up the blanks.
30536
- *
30537
- * @example the following dataset:
30538
- *
30539
- * 2024 Q1 W1 100
30540
- * W2 200
30541
- *
30542
- * will have the same value as the dataset:
30543
- * 2024 Q1 W1 100
30544
- * 2024 Q1 W2 200
30545
- */
30546
- function getHierarchicalDatasetValues(getters, dataSets) {
30547
- dataSets = dataSets.filter((ds) => !getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left));
30548
- const datasetValues = dataSets.map((ds) => ({
30549
- data: [],
30550
- label: "",
30551
- dataSetId: ds.dataSetId
30552
- }));
30553
- const locale = getters.getLocale();
30554
- const dataSetsData = dataSets.map((ds) => getData(getters, ds)).map((values) => values.map(({ value, format }) => value === null ? EMPTY : { value: formatValue(value, {
30555
- format,
30556
- locale
30557
- }) }));
30558
- if (!dataSetsData.length) return datasetValues;
30559
- const minLength = Math.min(...dataSetsData.map((ds) => ds.length));
30560
- let currentValues = [];
30561
- const leafDatasetIndex = dataSets.length - 1;
30562
- for (let i = 0; i < minLength; i++) for (let dsIndex = 0; dsIndex < dataSetsData.length; dsIndex++) {
30563
- let cell = dataSetsData[dsIndex][i];
30564
- if ((cell === void 0 || cell.value === null) && dsIndex !== leafDatasetIndex) cell = currentValues[dsIndex];
30565
- if (cell?.value !== currentValues[dsIndex]?.value) {
30566
- currentValues = currentValues.slice(0, dsIndex);
30567
- currentValues[dsIndex] = cell;
30568
- }
30569
- datasetValues[dsIndex].data.push(cell ?? EMPTY);
30570
- }
30571
- return datasetValues.filter((ds) => ds.data.some((d) => d.value !== null));
30572
- }
30573
- /**
30574
- * Get the data from a dataSet
30575
- */
30576
- function getData(getters, ds) {
30577
- if (ds.dataRange) {
30578
- const labelCellZone = ds.labelCell ? [ds.labelCell.zone] : [];
30579
- const dataZone = recomputeZones([ds.dataRange.zone], labelCellZone)[0];
30580
- if (dataZone === void 0) return [];
30581
- const dataRange = getters.getRangeFromZone(ds.dataRange.sheetId, dataZone);
30582
- return getters.getVisibleRangeValues(dataRange).map((cell) => cell.value === "" ? EMPTY : cell);
30583
- }
30584
- return [];
30585
- }
30586
- const ChartNeverDataSourceHandler = {
30587
- supportedChartTypes: [],
30588
- fromExternalDefinition: () => ({ type: "none" }),
30589
- fromContextCreation: () => ({ type: "none" }),
30590
- fromHierarchicalContextCreation: () => ({ type: "none" }),
30591
- validate: () => "Success",
30592
- transform: () => ({ type: "none" }),
30593
- extractData: () => ({
30594
- dataSetsValues: [],
30595
- labelValues: []
30596
- }),
30597
- extractHierarchicalData: () => ({
30598
- dataSetsValues: [],
30599
- labelValues: []
30600
- }),
30601
- adaptRanges: (dataSource) => dataSource,
30602
- getDefinition: (dataSource) => dataSource,
30603
- duplicateInDuplicatedSheet: (dataSource) => dataSource,
30604
- getContextCreation: () => ({}),
30605
- getHierarchicalContextCreation: () => ({}),
30606
- toExcelDataSets: () => ({
30607
- dataSets: [],
30608
- labelRange: void 0
30609
- })
30610
- };
30611
- chartDataSourceRegistry.add("range", ChartRangeDataSourceHandler);
30612
- chartDataSourceRegistry.add("none", ChartNeverDataSourceHandler);
30613
-
30614
30188
  //#endregion
30615
30189
  //#region src/types/chart/calendar_chart.ts
30616
30190
  const CALENDAR_CHART_GRANULARITIES = [
@@ -30637,41 +30211,6 @@ var CalendarChartConfigPanel = class extends GenericChartConfigPanel {
30637
30211
  value,
30638
30212
  label: ALL_PERIODS[value]
30639
30213
  }));
30640
- getGroupByOptions() {
30641
- const sheetId = this.env.model.getters.getFigureSheetId(this.env.model.getters.getFigureIdFromChartId(this.props.chartId));
30642
- const definition = SpreadsheetChart.fromStrDefinition(this.env.model.getters, sheetId, this.props.definition).getRangeDefinition();
30643
- const labels = getBarChartData(definition, getChartData(this.env.model.getters, definition.dataSource), this.env.model.getters).labels.filter((l) => isDateTime(l, DEFAULT_LOCALE));
30644
- if (labels.length === 0) return [];
30645
- const dates = labels.map((label) => toJsDate(label, this.env.model.getters.getLocale()));
30646
- const uniqueYears = /* @__PURE__ */ new Set();
30647
- const uniqueMonths = /* @__PURE__ */ new Set();
30648
- const uniqueDays = /* @__PURE__ */ new Set();
30649
- const uniqueHours = /* @__PURE__ */ new Set();
30650
- const uniqueMinutes = /* @__PURE__ */ new Set();
30651
- const uniqueSeconds = /* @__PURE__ */ new Set();
30652
- for (const date of dates) {
30653
- uniqueYears.add(date.getFullYear());
30654
- uniqueMonths.add(date.getMonth());
30655
- uniqueDays.add(date.getDate());
30656
- uniqueHours.add(date.getHours());
30657
- uniqueMinutes.add(date.getMinutes());
30658
- uniqueSeconds.add(date.getSeconds());
30659
- }
30660
- return this.groupByChoices.filter((groupBy) => {
30661
- switch (groupBy.value) {
30662
- case "year": return uniqueYears.size > 1;
30663
- case "quarter_number":
30664
- case "month_number": return uniqueMonths.size > 1;
30665
- case "iso_week_number":
30666
- case "day_of_month":
30667
- case "day_of_week": return uniqueDays.size > 1;
30668
- case "hour_number": return uniqueHours.size > 1;
30669
- case "minute_number": return uniqueMinutes.size > 1;
30670
- case "second_number": return uniqueSeconds.size > 1;
30671
- default: return false;
30672
- }
30673
- });
30674
- }
30675
30214
  getGroupByType(currentAxis) {
30676
30215
  return (currentAxis === "horizontal" ? this.props.definition.horizontalGroupBy : this.props.definition.verticalGroupBy) || "year";
30677
30216
  }
@@ -31244,7 +30783,7 @@ var SpeechBubble = class extends Component {
31244
30783
  spreadsheetRect = useSpreadsheetRect();
31245
30784
  bubbleRef = (0, _odoo_owl.signal)(null);
31246
30785
  setup() {
31247
- (0, _odoo_owl.useEffect)(() => {
30786
+ useLayoutEffect(() => {
31248
30787
  const el = this.bubbleRef();
31249
30788
  if (!el) return;
31250
30789
  const anchorRect = this.props.anchorRect;
@@ -32658,7 +32197,7 @@ var AbstractComposerStore = class extends SpreadsheetStore {
32658
32197
  col: range.zone.left,
32659
32198
  row: range.zone.top
32660
32199
  });
32661
- if (spreadZone) return this.getters.getRangeFromZone(sheetId, spreadZone);
32200
+ if (spreadZone) return this.getters.getRangeFromZone(range.sheetId, spreadZone);
32662
32201
  return range;
32663
32202
  }
32664
32203
  updateAutoCompleteProvider() {
@@ -33871,6 +33410,133 @@ var ChartTypePicker = class extends Component {
33871
33410
  }
33872
33411
  };
33873
33412
 
33413
+ //#endregion
33414
+ //#region src/helpers/figures/chart.ts
33415
+ var SpreadsheetChart = class SpreadsheetChart {
33416
+ getters;
33417
+ sheetId;
33418
+ definition;
33419
+ chartTypeBuilder;
33420
+ dataSourceBuilder;
33421
+ dataSource;
33422
+ constructor(getters, sheetId, definition, chartTypeBuilder, dataSourceBuilder) {
33423
+ this.getters = getters;
33424
+ this.sheetId = sheetId;
33425
+ this.definition = definition;
33426
+ this.chartTypeBuilder = chartTypeBuilder;
33427
+ this.dataSourceBuilder = dataSourceBuilder;
33428
+ this.dataSource = definition.dataSource;
33429
+ }
33430
+ static fromStrDefinition(getters, sheetId, definition) {
33431
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
33432
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
33433
+ const dataSource = dataSourceBuilder.fromExternalDefinition(definition.dataSource ?? { type: "none" }, sheetId, getters);
33434
+ const rangeDefinition = {
33435
+ ...chartTypeBuilder.fromStrDefinition(definition, sheetId, getters),
33436
+ dataSource
33437
+ };
33438
+ return new SpreadsheetChart(getters, sheetId, SpreadsheetChart.deleteInvalidKeys(rangeDefinition), chartTypeBuilder, dataSourceBuilder);
33439
+ }
33440
+ static fromDefinition(getters, sheetId, definition) {
33441
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
33442
+ return new SpreadsheetChart(getters, sheetId, definition, chartTypeRegistry.get(definition.type), dataSourceBuilder);
33443
+ }
33444
+ static validate(validator, definition) {
33445
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
33446
+ const dataSourceBuilder = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none");
33447
+ return validator.batchValidations(() => chartTypeBuilder.validateDefinition(validator, definition), () => dataSourceBuilder.validate(definition.dataSource ?? { type: "none" }, validator))(void 0);
33448
+ }
33449
+ static transformDefinition(chartSheetId, definition, rangeAdapters) {
33450
+ const chartTypeBuilder = chartTypeRegistry.get(definition.type);
33451
+ if (!definition.dataSource) return chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters);
33452
+ const newDataSource = chartDataSourceRegistry.get(definition.dataSource?.type ?? "none").transform(definition.dataSource, chartSheetId, rangeAdapters);
33453
+ return {
33454
+ ...chartTypeBuilder.transformDefinition(definition, chartSheetId, rangeAdapters),
33455
+ dataSource: newDataSource
33456
+ };
33457
+ }
33458
+ getRangeDefinition() {
33459
+ return {
33460
+ ...this.definition,
33461
+ dataSource: this.dataSource
33462
+ };
33463
+ }
33464
+ getDefinition() {
33465
+ return {
33466
+ ...this.chartTypeBuilder.toStrDefinition(this.definition, this.sheetId, this.getters),
33467
+ dataSource: this.dataSource && this.dataSourceBuilder.getDefinition(this.dataSource, this.sheetId, this.getters)
33468
+ };
33469
+ }
33470
+ updateRanges(rangeAdapters) {
33471
+ return {
33472
+ ...this.chartTypeBuilder.updateRanges(this.definition, rangeAdapters, this.sheetId),
33473
+ dataSource: this.dataSource && this.dataSourceBuilder.adaptRanges(this.dataSource, rangeAdapters)
33474
+ };
33475
+ }
33476
+ duplicateInDuplicatedSheet(sheetIdFrom, sheetIdTo) {
33477
+ const newDataSource = this.dataSource && this.dataSourceBuilder.duplicateInDuplicatedSheet(this.dataSource, sheetIdFrom, sheetIdTo, this.getters);
33478
+ const definition = {
33479
+ ...this.chartTypeBuilder.duplicateInDuplicatedSheet(this.definition, sheetIdFrom, sheetIdTo, this.getters),
33480
+ dataSource: newDataSource
33481
+ };
33482
+ return SpreadsheetChart.fromDefinition(this.getters, sheetIdTo, definition).getDefinition();
33483
+ }
33484
+ copyInSheetId(sheetIdTo) {
33485
+ return {
33486
+ ...this.chartTypeBuilder.copyInSheetId(this.definition, this.sheetId, sheetIdTo, this.getters),
33487
+ dataSource: this.dataSource
33488
+ };
33489
+ }
33490
+ getContextCreation() {
33491
+ const definition = this.getDefinition();
33492
+ return {
33493
+ ...this.dataSourceBuilder.getContextCreation(definition.dataSource ?? { type: "none" }),
33494
+ ...this.chartTypeBuilder.getContextCreation(definition, this.dataSourceBuilder, definition.dataSource)
33495
+ };
33496
+ }
33497
+ getDefinitionForExcel(getters) {
33498
+ const definition = this.definition;
33499
+ const excelDataSets = this.dataSourceBuilder.toExcelDataSets(this.dataSource, "dataSetStyles" in definition ? definition.dataSetStyles : {}, getters);
33500
+ if (excelDataSets === void 0) return;
33501
+ return this.chartTypeBuilder.getDefinitionForExcel(getters, definition, excelDataSets);
33502
+ }
33503
+ getData(getters, chartId) {
33504
+ const dataSource = this.dataSource;
33505
+ return dataSource ? this.dataSourceBuilder.extractData(dataSource, chartId, getters) : {
33506
+ dataSetsValues: [],
33507
+ labelValues: []
33508
+ };
33509
+ }
33510
+ getRuntime(getters, chartId) {
33511
+ const dataSource = this.dataSource;
33512
+ const dataExtractors = dataSource ? {
33513
+ extractData: () => this.dataSourceBuilder.extractData(dataSource, chartId, getters),
33514
+ extractHierarchicalData: () => this.dataSourceBuilder.extractHierarchicalData(dataSource, chartId, getters)
33515
+ } : {
33516
+ extractData: () => ({
33517
+ dataSetsValues: [],
33518
+ labelValues: []
33519
+ }),
33520
+ extractHierarchicalData: () => ({
33521
+ dataSetsValues: [],
33522
+ labelValues: []
33523
+ })
33524
+ };
33525
+ return this.chartTypeBuilder.getRuntime(getters, this.definition, dataExtractors, this.sheetId, {
33526
+ onClick: (event, items, chartJsChart) => {
33527
+ return this.dataSourceBuilder.onDataSetClick?.(this.definition.type, chartId, event, items, chartJsChart, getters);
33528
+ },
33529
+ onHover: (event, items, chartJsChart) => this.dataSourceBuilder.onDataSetHover?.(this.definition.type, chartId, event, items, chartJsChart)
33530
+ });
33531
+ }
33532
+ static deleteInvalidKeys(definition) {
33533
+ definition = { ...definition };
33534
+ const keys = new Set(chartTypeRegistry.get(definition.type).allowedDefinitionKeys);
33535
+ for (const key of Object.keys(definition)) if (!keys.has(key)) delete definition[key];
33536
+ return definition;
33537
+ }
33538
+ };
33539
+
33874
33540
  //#endregion
33875
33541
  //#region src/components/side_panel/chart/main_chart_panel/main_chart_panel_store.ts
33876
33542
  var MainChartPanelStore = class extends SpreadsheetStore {
@@ -37092,7 +36758,7 @@ var FindAndReplacePanel = class extends Component {
37092
36758
  }
37093
36759
  get specificRangeMatchesCount() {
37094
36760
  const range = this.searchOptions.specificRange;
37095
- if (!range) return "";
36761
+ if (!range || range.invalidSheetName || range.invalidXc) return "";
37096
36762
  const { specificRangeMatchesCount: count, specificRangeHiddenMatchesCount: hidden, searchOptions } = this.store;
37097
36763
  const { sheetId, zone } = range;
37098
36764
  let label = count === 1 ? _t("1 match in range %(range)s of '%(sheetName)s'", {
@@ -47480,6 +47146,11 @@ var GridOverlay = class extends Component {
47480
47146
  });
47481
47147
  return icon?.onClick ? icon : void 0;
47482
47148
  }
47149
+ get isFooterVisible() {
47150
+ const { y } = this.env.model.getters.getMainViewportCoordinates();
47151
+ const { height } = this.env.model.getters.getSheetViewDimension();
47152
+ return !this.env.model.getters.isReadonly() && height - y > 46;
47153
+ }
47483
47154
  };
47484
47155
 
47485
47156
  //#endregion
@@ -56274,7 +55945,7 @@ var CompilationParametersBuilder = class {
56274
55945
  if (rangeError) return [[rangeError]];
56275
55946
  const sheetId = range.sheetId;
56276
55947
  const zone = range.zone;
56277
- const _zone = intersection(zone, this.getters.getSheetZone(sheetId));
55948
+ const _zone = this.getters.clipRangeToSheet(range)?.zone;
56278
55949
  if (!_zone) return [[]];
56279
55950
  const { top, left, bottom, right } = zone;
56280
55951
  const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
@@ -57448,10 +57119,10 @@ var Evaluator = class {
57448
57119
  updateDependencies(position) {
57449
57120
  this.formulaDependencies().removeAllDependencies(position);
57450
57121
  const dependencies = this.getDirectDependencies(position);
57451
- this.formulaDependencies().addDependencies(position, dependencies);
57122
+ this.formulaDependencies().addDependencies(position, this.getters.clipRangesToSheet(dependencies));
57452
57123
  }
57453
57124
  addDependencies(position, dependencies) {
57454
- this.formulaDependencies().addDependencies(position, dependencies);
57125
+ this.formulaDependencies().addDependencies(position, this.getters.clipRangesToSheet(dependencies));
57455
57126
  this.computeDependencies(dependencies);
57456
57127
  }
57457
57128
  computeDependencies(dependencies) {
@@ -57524,7 +57195,8 @@ var Evaluator = class {
57524
57195
  const graph = new FormulaDependencyGraph();
57525
57196
  for (const sheetId of this.getters.getSheetIds()) for (const cell of this.getters.getCells(sheetId)) if (cell.isFormula) {
57526
57197
  const cellPosition = this.getters.getCellPosition(cell.id);
57527
- graph.addDependencies(cellPosition, cell.compiledFormula.rangeDependencies);
57198
+ const dependencies = this.getters.clipRangesToSheet(cell.compiledFormula.rangeDependencies);
57199
+ graph.addDependencies(cellPosition, dependencies);
57528
57200
  }
57529
57201
  return graph;
57530
57202
  });
@@ -63505,7 +63177,8 @@ var GeoFeaturePlugin = class extends UIPlugin {
63505
63177
  "getGeoJsonFeatures",
63506
63178
  "geoFeatureNameToId",
63507
63179
  "getGeoChartAvailableRegions",
63508
- "getAvailableChartRegions"
63180
+ "getAvailableChartRegions",
63181
+ "loadUsedGeoJsonFeatures"
63509
63182
  ];
63510
63183
  geoJsonService;
63511
63184
  geoJsonCache = {};
@@ -63588,6 +63261,23 @@ var GeoFeaturePlugin = class extends UIPlugin {
63588
63261
  }
63589
63262
  return this.geoJsonService.geoFeatureNameToId(region, featureName);
63590
63263
  }
63264
+ loadUsedGeoJsonFeatures() {
63265
+ const regions = this.getters.getSheetIds().flatMap((sheetId) => this.getters.getChartIds(sheetId).map((chartId) => {
63266
+ const definition = this.getters.getChartDefinition(chartId);
63267
+ return definition.type === "geo" ? definition.region || this.getters.getGeoChartAvailableRegions()[0]?.id : void 0;
63268
+ })).filter(isDefined);
63269
+ const uniqueRegions = Array.from(new Set(regions));
63270
+ if (uniqueRegions.length && !this.geoJsonService) {
63271
+ console.error("No geoJsonService provided to the model");
63272
+ return Promise.resolve();
63273
+ }
63274
+ for (const region of uniqueRegions) this.getGeoJsonFeatures(region);
63275
+ const promises = uniqueRegions.map((region) => {
63276
+ const cachedGeoJson = this.geoJsonCache[region];
63277
+ return cachedGeoJson instanceof Promise ? cachedGeoJson : Promise.resolve();
63278
+ });
63279
+ return Promise.all(promises).then(() => {});
63280
+ }
63591
63281
  convertToGeoJson(json) {
63592
63282
  if (!json) return null;
63593
63283
  if (json.type === "Topology") {
@@ -66672,7 +66362,7 @@ var InternalViewport = class {
66672
66362
  let height = lastRowEnd - this.offsetCorrectionY;
66673
66363
  if (this.canScrollVertically) {
66674
66364
  height = Math.max(height, this.viewportHeight);
66675
- if (lastRowEnd + 46 > height && !this.getters.isReadonly()) height += 46;
66365
+ if (lastRowEnd + 46 > height && !this.getters.isReadonly() && this.viewportHeight > 46) height += 46;
66676
66366
  }
66677
66367
  return {
66678
66368
  width,
@@ -70665,12 +70355,11 @@ var SpreadsheetPrintStore = class extends SpreadsheetStore {
70665
70355
  const { width: printWidth, height: printHeight } = this.pageDimensionWithMargins;
70666
70356
  const start = dimension === "COL" ? printZone.left : printZone.top;
70667
70357
  const end = dimension === "COL" ? printZone.right : printZone.bottom;
70668
- const getHeaderSize = dimension === "COL" ? this.getters.getColDimensions : this.getters.getRowDimensions;
70669
70358
  const max = dimension === "COL" ? printWidth : printHeight;
70670
70359
  const breaks = [];
70671
70360
  let current = 0;
70672
70361
  for (let i = start; i <= end; i++) {
70673
- const headerSize = getHeaderSize(sheetId, i).size * zoom;
70362
+ const headerSize = this.getters.isHeaderHidden(sheetId, dimension, i) ? 0 : this.getters.getHeaderSize(sheetId, dimension, i) * zoom;
70674
70363
  current += headerSize;
70675
70364
  if (current >= max) {
70676
70365
  breaks.push(i);
@@ -72121,7 +71810,10 @@ var Spreadsheet = class extends Component {
72121
71810
  sidePanel;
72122
71811
  spreadsheetRef = (0, _odoo_owl.signal)(null);
72123
71812
  spreadsheetRect = useSpreadsheetRect();
72124
- state = (0, _odoo_owl.proxy)({ printModeEnabled: false });
71813
+ state = (0, _odoo_owl.proxy)({
71814
+ printModeEnabled: false,
71815
+ colorThemeBeforePrint: "light"
71816
+ });
72125
71817
  _focusGrid;
72126
71818
  isViewportTooSmall = false;
72127
71819
  notificationStore;
@@ -72133,7 +71825,7 @@ var Spreadsheet = class extends Component {
72133
71825
  const properties = {};
72134
71826
  properties["--os-scrollbar-width"] = `${this.env.model.getters.getScrollBarWidth()}px`;
72135
71827
  properties["--os-dark-mode-filter"] = DARK_MODE_FILTER_STRING;
72136
- properties["color-scheme"] = this.props.model.getters.isDarkMode() ? "dark" : "light";
71828
+ properties["color-scheme"] = this.colorScheme;
72137
71829
  if (this.state.printModeEnabled) properties["display"] = `block`;
72138
71830
  else {
72139
71831
  if (this.env.model.getters.isDashboard()) properties["grid-template-rows"] = `auto`;
@@ -72173,7 +71865,7 @@ var Spreadsheet = class extends Component {
72173
71865
  askConfirmation: (text, confirm, cancel) => this.notificationStore.askConfirmation(text, confirm, cancel),
72174
71866
  raiseError: (text, cb) => this.notificationStore.raiseError(text, cb),
72175
71867
  isMobile: isMobileOS,
72176
- printSpreadsheet: () => this.state.printModeEnabled = true
71868
+ printSpreadsheet: this.enterPrintMode.bind(this)
72177
71869
  });
72178
71870
  this.notificationStore.updateNotificationCallbacks({ ...this.props });
72179
71871
  useLayoutEffect(() => {
@@ -72190,7 +71882,7 @@ var Spreadsheet = class extends Component {
72190
71882
  useExternalListener(document.body, "wheel", () => {});
72191
71883
  useExternalListener(window, "keydown", async (event) => {
72192
71884
  if (keyboardEventToShortcutString(event) === "Ctrl+P") {
72193
- this.state.printModeEnabled = true;
71885
+ this.enterPrintMode();
72194
71886
  event.stopPropagation();
72195
71887
  event.preventDefault();
72196
71888
  }
@@ -72303,9 +71995,21 @@ var Spreadsheet = class extends Component {
72303
71995
  getSpreadSheetClasses() {
72304
71996
  return [this.env.isSmall ? "o-spreadsheet-mobile" : "", this.props.model.getters.isDarkMode() ? "dark" : ""].join(" ");
72305
71997
  }
71998
+ enterPrintMode() {
71999
+ if (this.state.printModeEnabled) return;
72000
+ this.state.colorThemeBeforePrint = this.props.model.getters.isDarkMode() ? "dark" : "light";
72001
+ this.env.model.dispatch("UPDATE_COLOR_SCHEME", { colorScheme: "light" });
72002
+ this.state.printModeEnabled = true;
72003
+ }
72306
72004
  exitPrintMode() {
72005
+ if (!this.state.printModeEnabled) return;
72006
+ this.env.model.dispatch("UPDATE_COLOR_SCHEME", { colorScheme: this.state.colorThemeBeforePrint });
72307
72007
  this.state.printModeEnabled = false;
72308
72008
  }
72009
+ get colorScheme() {
72010
+ if (this.state.printModeEnabled) return this.state.colorThemeBeforePrint;
72011
+ return this.props.model.getters.isDarkMode() ? "dark" : "light";
72012
+ }
72309
72013
  };
72310
72014
 
72311
72015
  //#endregion
@@ -73180,6 +72884,8 @@ var RangeAdapterPlugin = class {
73180
72884
  "extendRange",
73181
72885
  "getRangeString",
73182
72886
  "getRangeFromSheetXC",
72887
+ "clipRangesToSheet",
72888
+ "clipRangeToSheet",
73183
72889
  "createAdaptedRanges",
73184
72890
  "getRangeData",
73185
72891
  "getRangeDataFromXc",
@@ -73218,6 +72924,22 @@ var RangeAdapterPlugin = class {
73218
72924
  addRangeProvider(provider) {
73219
72925
  this.providers.push(provider);
73220
72926
  }
72927
+ clipRangeToSheet(range) {
72928
+ if (range.invalidXc) return range;
72929
+ const sheetZone = this.getters.getSheetZone(range.sheetId);
72930
+ if (isZoneInside(range.zone, sheetZone)) return range;
72931
+ const newZone = intersection(range.zone, sheetZone);
72932
+ if (!newZone) return;
72933
+ return this.getters.getRangeFromZone(range.sheetId, newZone);
72934
+ }
72935
+ clipRangesToSheet(ranges) {
72936
+ const clippedRanges = [];
72937
+ for (const range of ranges) {
72938
+ const clippedRange = this.clipRangeToSheet(range);
72939
+ if (clippedRange) clippedRanges.push(clippedRange);
72940
+ }
72941
+ return clippedRanges;
72942
+ }
73221
72943
  createAdaptedRanges(ranges, offsetX, offsetY, sheetId) {
73222
72944
  return ranges.map((range) => {
73223
72945
  if (!isZoneValid(range.zone)) return range;
@@ -76451,6 +76173,8 @@ var Model = class Model extends EventBus {
76451
76173
  this.range = new RangeAdapterPlugin(this.coreGetters);
76452
76174
  this.coreGetters.getRangeString = this.range.getRangeString.bind(this.range);
76453
76175
  this.coreGetters.getRangeFromSheetXC = this.range.getRangeFromSheetXC.bind(this.range);
76176
+ this.coreGetters.clipRangesToSheet = this.range.clipRangesToSheet.bind(this.range);
76177
+ this.coreGetters.clipRangeToSheet = this.range.clipRangeToSheet.bind(this.range);
76454
76178
  this.coreGetters.createAdaptedRanges = this.range.createAdaptedRanges.bind(this.range);
76455
76179
  this.coreGetters.getRangeData = this.range.getRangeData.bind(this.range);
76456
76180
  this.coreGetters.getRangeDataFromXc = this.range.getRangeDataFromXc.bind(this.range);
@@ -78413,6 +78137,306 @@ const LinkEditorPopoverBuilder = { onOpen: (position, getters) => {
78413
78137
  //#region src/components/popover/popover_builders.ts
78414
78138
  cellPopoverRegistry.add("ErrorToolTip", ErrorToolTipPopoverBuilder).add("LinkCell", LinkCellPopoverBuilder).add("LinkEditor", LinkEditorPopoverBuilder).add("FilterMenu", FilterMenuPopoverBuilder);
78415
78139
 
78140
+ //#endregion
78141
+ //#region src/helpers/figures/charts/chart_data_sources.ts
78142
+ const EMPTY = Object.freeze({ value: null });
78143
+ const ONE = Object.freeze({ value: 1 });
78144
+ const ChartRangeDataSourceHandler = {
78145
+ supportedChartTypes: CHART_TYPES,
78146
+ fromExternalDefinition(dataSource, defaultSheetId, getters) {
78147
+ const dataSets = createDataSets(getters, defaultSheetId, dataSource);
78148
+ const labelRange = createValidRange(getters, defaultSheetId, dataSource.labelRange);
78149
+ return {
78150
+ ...dataSource,
78151
+ dataSets,
78152
+ labelRange
78153
+ };
78154
+ },
78155
+ fromContextCreation(context) {
78156
+ return {
78157
+ type: "range",
78158
+ dataSets: [],
78159
+ dataSetsHaveTitle: false,
78160
+ labelRange: context.auxiliaryRange,
78161
+ ...context.dataSource
78162
+ };
78163
+ },
78164
+ fromHierarchicalContextCreation(context) {
78165
+ if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
78166
+ type: "range",
78167
+ dataSets: [],
78168
+ dataSetsHaveTitle: false
78169
+ };
78170
+ let dataSource = {
78171
+ type: "range",
78172
+ dataSets: [],
78173
+ dataSetsHaveTitle: context.dataSource?.dataSetsHaveTitle ?? false,
78174
+ labelRange: context.dataSource?.dataSets?.[0]?.dataRange
78175
+ };
78176
+ if (context.hierarchicalDataSource?.dataSets.length) dataSource = context.hierarchicalDataSource;
78177
+ else if (context.auxiliaryRange) dataSource = {
78178
+ ...dataSource,
78179
+ dataSets: [{
78180
+ dataRange: context.auxiliaryRange,
78181
+ dataSetId: "0"
78182
+ }]
78183
+ };
78184
+ return dataSource;
78185
+ },
78186
+ validate: (dataSource, validator) => validator.checkValidations(dataSource, checkDataset, checkLabelRange),
78187
+ transform(dataSource, defaultSheetId, { adaptRangeString }) {
78188
+ let labelRange;
78189
+ if (dataSource.labelRange) {
78190
+ const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSource.labelRange);
78191
+ if (changeType !== "REMOVE") labelRange = adaptedRange;
78192
+ }
78193
+ const dataSets = [];
78194
+ for (const dataSet of dataSource.dataSets) {
78195
+ const newDataSet = { ...dataSet };
78196
+ const { changeType, range: adaptedRange } = adaptRangeString(defaultSheetId, dataSet.dataRange);
78197
+ if (changeType !== "REMOVE") {
78198
+ newDataSet.dataRange = adaptedRange;
78199
+ dataSets.push(newDataSet);
78200
+ }
78201
+ }
78202
+ return {
78203
+ ...dataSource,
78204
+ dataSets,
78205
+ labelRange
78206
+ };
78207
+ },
78208
+ extractData: (dataSource, chartId, getters) => getChartData(getters, dataSource),
78209
+ extractHierarchicalData(dataSource, chartId, getters) {
78210
+ const dataSets = dataSource.dataSets;
78211
+ const labelRange = dataSource.labelRange;
78212
+ const labelValues = getChartLabelValues(getters, dataSets, labelRange);
78213
+ const dataSetsValues = getHierarchicalDatasetValues(getters, dataSets);
78214
+ const data = {
78215
+ labelValues,
78216
+ dataSetsValues
78217
+ };
78218
+ if (shouldRemoveFirstLabel(labelValues.length, dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0), dataSource.dataSetsHaveTitle || false)) labelValues.shift();
78219
+ return data;
78220
+ },
78221
+ adaptRanges(dataSource, { applyChange }) {
78222
+ const dataSetsWithUndefined = dataSource.dataSets.map((ds) => {
78223
+ const { range: adaptedRangeStr, changeType } = applyChange(ds.dataRange);
78224
+ if (changeType === "REMOVE") return;
78225
+ let labelCell = void 0;
78226
+ if (ds.labelCell) {
78227
+ const { range: adaptedLabelCellRange, changeType: labelCellChangeType } = applyChange(ds.labelCell);
78228
+ if (labelCellChangeType !== "REMOVE") labelCell = adaptedLabelCellRange;
78229
+ }
78230
+ return {
78231
+ ...ds,
78232
+ dataRange: adaptedRangeStr,
78233
+ labelCell
78234
+ };
78235
+ }).filter(isDefined);
78236
+ let labelRange = dataSource.labelRange;
78237
+ if (labelRange) {
78238
+ const { range: adaptedLabelRange, changeType } = applyChange(labelRange);
78239
+ if (changeType === "REMOVE") labelRange = void 0;
78240
+ else labelRange = adaptedLabelRange;
78241
+ }
78242
+ const dataSets = dataSetsWithUndefined;
78243
+ return {
78244
+ ...dataSource,
78245
+ dataSets,
78246
+ labelRange: labelRange?.invalidSheetName || labelRange?.invalidXc ? void 0 : labelRange
78247
+ };
78248
+ },
78249
+ getDefinition(dataSource, defaultSheetId, getters) {
78250
+ return {
78251
+ labelRange: dataSource.labelRange ? getters.getRangeString(dataSource.labelRange, defaultSheetId) : void 0,
78252
+ type: "range",
78253
+ dataSets: dataSource.dataSets.map((dataSet) => ({
78254
+ dataSetId: dataSet.dataSetId,
78255
+ dataRange: getters.getRangeString(dataSet.dataRange, defaultSheetId)
78256
+ })),
78257
+ dataSetsHaveTitle: dataSource.dataSetsHaveTitle
78258
+ };
78259
+ },
78260
+ /**
78261
+ * Duplicate the dataSets. All ranges on sheetIdFrom are adapted to target
78262
+ * sheetIdTo.
78263
+ */
78264
+ duplicateInDuplicatedSheet(dataSource, sheetIdFrom, sheetIdTo, getters) {
78265
+ return {
78266
+ ...dataSource,
78267
+ labelRange: duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, dataSource.labelRange),
78268
+ dataSets: dataSource.dataSets.map((ds) => ({
78269
+ ...ds,
78270
+ dataRange: duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.dataRange)
78271
+ }))
78272
+ };
78273
+ },
78274
+ getContextCreation: (dataSource) => ({
78275
+ auxiliaryRange: dataSource.labelRange,
78276
+ dataSource
78277
+ }),
78278
+ getHierarchicalContextCreation(dataSource) {
78279
+ const leafRange = dataSource.dataSets.at(-1)?.dataRange;
78280
+ const dataSetsHaveTitle = dataSource.dataSetsHaveTitle;
78281
+ return {
78282
+ auxiliaryRange: leafRange,
78283
+ hierarchicalDataSource: dataSource,
78284
+ dataSource: dataSource.labelRange ? {
78285
+ type: "range",
78286
+ dataSets: [{
78287
+ dataRange: dataSource.labelRange,
78288
+ dataSetId: "0"
78289
+ }],
78290
+ dataSetsHaveTitle
78291
+ } : {
78292
+ type: "range",
78293
+ dataSets: [],
78294
+ dataSetsHaveTitle
78295
+ }
78296
+ };
78297
+ },
78298
+ toExcelDataSets(dataSource, dataSetStyles, getters) {
78299
+ const dataSets = dataSource.dataSets;
78300
+ const labelRange = dataSource.labelRange;
78301
+ const excelDataSets = dataSets.map((ds) => toExcelDataset(getters, dataSetStyles, ds)).filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
78302
+ const datasetLength = dataSets[0] ? getZoneArea(dataSets[0].dataRange.zone) : void 0;
78303
+ return {
78304
+ dataSets: excelDataSets,
78305
+ labelRange: toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel(labelRange ? getZoneArea(labelRange.zone) : 0, datasetLength, dataSource.dataSetsHaveTitle))
78306
+ };
78307
+ }
78308
+ };
78309
+ function getChartData(getters, dataSource) {
78310
+ const dataSets = dataSource.dataSets;
78311
+ const labelRange = dataSource.labelRange;
78312
+ const labelValues = getChartLabelValues(getters, dataSets, labelRange);
78313
+ const dataSetsValues = getChartDatasetValues(getters, dataSets);
78314
+ const data = {
78315
+ labelValues,
78316
+ dataSetsValues
78317
+ };
78318
+ const numberOfDataPoints = dataSetsValues.length ? dataSetsValues[0]?.data.length + (dataSetsValues[0]?.label !== void 0 ? 1 : 0) : 0;
78319
+ if (shouldRemoveFirstLabel(labelValues.length, numberOfDataPoints, dataSource.dataSetsHaveTitle || false)) labelValues.shift();
78320
+ return data;
78321
+ }
78322
+ function getChartDatasetValues(getters, dataSets) {
78323
+ const datasetValues = [];
78324
+ for (const [dsIndex, ds] of Object.entries(dataSets)) {
78325
+ let label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`;
78326
+ let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
78327
+ if (ds.labelCell) {
78328
+ const { sheetId, zone } = ds.labelCell;
78329
+ const cell = getters.getEvaluatedCell({
78330
+ sheetId,
78331
+ col: zone.left,
78332
+ row: zone.top
78333
+ });
78334
+ if (cell) label = cell.formattedValue;
78335
+ }
78336
+ let data = ds.dataRange ? getData(getters, ds) : [];
78337
+ if (data.every((cell) => !cell.value || isTextResult(cell)) && data.filter(isTextResult).length > 1) data = data.map((cell) => cell.value && !isErrorResult(cell) ? ONE : EMPTY);
78338
+ else if (data.every((cell) => !isNumberResult(cell))) hidden = true;
78339
+ datasetValues.push({
78340
+ data,
78341
+ label,
78342
+ hidden,
78343
+ dataSetId: ds.dataSetId
78344
+ });
78345
+ }
78346
+ return datasetValues;
78347
+ }
78348
+ function getChartLabelValues(getters, dataSets, labelRange) {
78349
+ if (labelRange) {
78350
+ const { left } = labelRange.zone;
78351
+ if (!labelRange.invalidXc && !labelRange.invalidSheetName && !getters.isColHidden(labelRange.sheetId, left)) return getters.getVisibleRangeValues(labelRange);
78352
+ }
78353
+ if (dataSets[0]) {
78354
+ const dataLength = getData(getters, dataSets[0]).length;
78355
+ return Array.from({ length: dataLength }, () => ({ value: "" }));
78356
+ }
78357
+ return [];
78358
+ }
78359
+ /**
78360
+ * Get the values for a hierarchical dataset. The values can be defined in a tree-like structure
78361
+ * in the sheet, and this function will fill up the blanks.
78362
+ *
78363
+ * @example the following dataset:
78364
+ *
78365
+ * 2024 Q1 W1 100
78366
+ * W2 200
78367
+ *
78368
+ * will have the same value as the dataset:
78369
+ * 2024 Q1 W1 100
78370
+ * 2024 Q1 W2 200
78371
+ */
78372
+ function getHierarchicalDatasetValues(getters, dataSets) {
78373
+ dataSets = dataSets.filter((ds) => !getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left));
78374
+ const datasetValues = dataSets.map((ds) => ({
78375
+ data: [],
78376
+ label: "",
78377
+ dataSetId: ds.dataSetId
78378
+ }));
78379
+ const locale = getters.getLocale();
78380
+ const dataSetsData = dataSets.map((ds) => getData(getters, ds)).map((values) => values.map(({ value, format }) => value === null ? EMPTY : { value: formatValue(value, {
78381
+ format,
78382
+ locale
78383
+ }) }));
78384
+ if (!dataSetsData.length) return datasetValues;
78385
+ const minLength = Math.min(...dataSetsData.map((ds) => ds.length));
78386
+ let currentValues = [];
78387
+ const leafDatasetIndex = dataSets.length - 1;
78388
+ for (let i = 0; i < minLength; i++) for (let dsIndex = 0; dsIndex < dataSetsData.length; dsIndex++) {
78389
+ let cell = dataSetsData[dsIndex][i];
78390
+ if ((cell === void 0 || cell.value === null) && dsIndex !== leafDatasetIndex) cell = currentValues[dsIndex];
78391
+ if (cell?.value !== currentValues[dsIndex]?.value) {
78392
+ currentValues = currentValues.slice(0, dsIndex);
78393
+ currentValues[dsIndex] = cell;
78394
+ }
78395
+ datasetValues[dsIndex].data.push(cell ?? EMPTY);
78396
+ }
78397
+ return datasetValues.filter((ds) => ds.data.some((d) => d.value !== null));
78398
+ }
78399
+ /**
78400
+ * Get the data from a dataSet
78401
+ */
78402
+ function getData(getters, ds) {
78403
+ if (ds.dataRange) {
78404
+ const labelCellZone = ds.labelCell ? [ds.labelCell.zone] : [];
78405
+ const dataZone = recomputeZones([ds.dataRange.zone], labelCellZone)[0];
78406
+ if (dataZone === void 0) return [];
78407
+ const dataRange = getters.getRangeFromZone(ds.dataRange.sheetId, dataZone);
78408
+ return getters.getVisibleRangeValues(dataRange).map((cell) => cell.value === "" ? EMPTY : cell);
78409
+ }
78410
+ return [];
78411
+ }
78412
+ const ChartNeverDataSourceHandler = {
78413
+ supportedChartTypes: [],
78414
+ fromExternalDefinition: () => ({ type: "none" }),
78415
+ fromContextCreation: () => ({ type: "none" }),
78416
+ fromHierarchicalContextCreation: () => ({ type: "none" }),
78417
+ validate: () => "Success",
78418
+ transform: () => ({ type: "none" }),
78419
+ extractData: () => ({
78420
+ dataSetsValues: [],
78421
+ labelValues: []
78422
+ }),
78423
+ extractHierarchicalData: () => ({
78424
+ dataSetsValues: [],
78425
+ labelValues: []
78426
+ }),
78427
+ adaptRanges: (dataSource) => dataSource,
78428
+ getDefinition: (dataSource) => dataSource,
78429
+ duplicateInDuplicatedSheet: (dataSource) => dataSource,
78430
+ getContextCreation: () => ({}),
78431
+ getHierarchicalContextCreation: () => ({}),
78432
+ toExcelDataSets: () => ({
78433
+ dataSets: [],
78434
+ labelRange: void 0
78435
+ })
78436
+ };
78437
+ chartDataSourceRegistry.add("range", ChartRangeDataSourceHandler);
78438
+ chartDataSourceRegistry.add("none", ChartNeverDataSourceHandler);
78439
+
78416
78440
  //#endregion
78417
78441
  //#region src/registries/auto_completes/data_validation_auto_complete.ts
78418
78442
  autoCompleteProviders.add("dataValidation", {
@@ -87997,6 +88021,6 @@ exports.stores = stores;
87997
88021
  exports.tokenColors = tokenColors;
87998
88022
  exports.tokenize = tokenize;
87999
88023
 
88000
- __info__.version = "19.4.11";
88001
- __info__.date = "2026-09-04T07:50:39.272Z";
88002
- __info__.hash = "7660254";
88024
+ __info__.version = "19.4.12";
88025
+ __info__.date = "2026-09-10T05:38:01.898Z";
88026
+ __info__.hash = "cdb63b4";