@odoo/o-spreadsheet 18.4.22 → 18.4.24

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 18.4.22
6
- * @date 2025-12-26T10:19:07.786Z
7
- * @hash 6ddac00
5
+ * @version 18.4.24
6
+ * @date 2026-01-14T10:00:55.867Z
7
+ * @hash 0364f56
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -19069,9 +19069,10 @@ stores.inject(MyMetaStore, storeInstance);
19069
19069
  throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
19070
19070
  }
19071
19071
  }
19072
- function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
19072
+ function addPivotDependencies(evalContext, pivotId, forMeasures) {
19073
19073
  //TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
19074
19074
  const dependencies = [];
19075
+ const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
19075
19076
  if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
19076
19077
  const { sheetId, zone } = coreDefinition.dataSet;
19077
19078
  const xc = zoneToXc(zone);
@@ -19088,8 +19089,7 @@ stores.inject(MyMetaStore, storeInstance);
19088
19089
  }
19089
19090
  for (const measure of forMeasures) {
19090
19091
  if (measure.computedBy) {
19091
- const formula = evalContext.getters.getMeasureCompiledFormula(measure);
19092
- dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
19092
+ dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
19093
19093
  }
19094
19094
  }
19095
19095
  const originPosition = evalContext.__originCellPosition;
@@ -19558,7 +19558,7 @@ stores.inject(MyMetaStore, storeInstance);
19558
19558
  assertDomainLength(domainArgs);
19559
19559
  const pivot = this.getters.getPivot(pivotId);
19560
19560
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
19561
- addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
19561
+ addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
19562
19562
  pivot.init({ reload: pivot.needsReevaluation });
19563
19563
  const error = pivot.assertIsValid({ throwOnError: false });
19564
19564
  if (error) {
@@ -19591,8 +19591,7 @@ stores.inject(MyMetaStore, storeInstance);
19591
19591
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
19592
19592
  assertDomainLength(domainArgs);
19593
19593
  const pivot = this.getters.getPivot(_pivotId);
19594
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
19595
- addPivotDependencies(this, coreDefinition, []);
19594
+ addPivotDependencies(this, _pivotId, []);
19596
19595
  pivot.init({ reload: pivot.needsReevaluation });
19597
19596
  const error = pivot.assertIsValid({ throwOnError: false });
19598
19597
  if (error) {
@@ -19650,7 +19649,7 @@ stores.inject(MyMetaStore, storeInstance);
19650
19649
  const pivotId = getPivotId(_pivotFormulaId, this.getters);
19651
19650
  const pivot = this.getters.getPivot(pivotId);
19652
19651
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
19653
- addPivotDependencies(this, coreDefinition, coreDefinition.measures);
19652
+ addPivotDependencies(this, pivotId, coreDefinition.measures);
19654
19653
  pivot.init({ reload: pivot.needsReevaluation });
19655
19654
  const error = pivot.assertIsValid({ throwOnError: false });
19656
19655
  if (error) {
@@ -32904,7 +32903,7 @@ stores.inject(MyMetaStore, storeInstance);
32904
32903
  }
32905
32904
  captureSelection(zone, col, row) {
32906
32905
  this.model.selection.capture(this, {
32907
- cell: { col: col ?? zone.left, row: row ?? zone.right },
32906
+ cell: { col: col ?? zone.left, row: row ?? zone.top },
32908
32907
  zone,
32909
32908
  }, {
32910
32909
  handleEvent: this.handleEvent.bind(this),
@@ -47105,7 +47104,6 @@ stores.inject(MyMetaStore, storeInstance);
47105
47104
  onGridMoved: Function,
47106
47105
  gridOverlayDimensions: String,
47107
47106
  slots: { type: Object, optional: true },
47108
- getGridSize: Function,
47109
47107
  };
47110
47108
  static components = {
47111
47109
  FiguresContainer,
@@ -47124,14 +47122,7 @@ stores.inject(MyMetaStore, storeInstance);
47124
47122
  setup() {
47125
47123
  useCellHovered(this.env, this.gridOverlay);
47126
47124
  const resizeObserver = new ResizeObserver(() => {
47127
- const boundingRect = this.gridOverlayEl.getBoundingClientRect();
47128
- const { width, height } = this.props.getGridSize();
47129
- this.props.onGridResized({
47130
- x: boundingRect.left,
47131
- y: boundingRect.top,
47132
- height: height,
47133
- width: width,
47134
- });
47125
+ this.props.onGridResized();
47135
47126
  });
47136
47127
  owl.onMounted(() => {
47137
47128
  resizeObserver.observe(this.gridOverlayEl);
@@ -53212,6 +53203,12 @@ stores.inject(MyMetaStore, storeInstance);
53212
53203
  case "ACTIVATE_SHEET":
53213
53204
  this.isSearchDirty = true;
53214
53205
  this.shouldFinalizeUpdateSelection = true;
53206
+ if (this.searchOptions.specificRange) {
53207
+ this.searchOptions.specificRange = {
53208
+ ...this.searchOptions.specificRange,
53209
+ sheetId: this.getters.getActiveSheetId(),
53210
+ };
53211
+ }
53215
53212
  break;
53216
53213
  case "REPLACE_SEARCH":
53217
53214
  for (const match of cmd.matches) {
@@ -53631,9 +53628,20 @@ stores.inject(MyMetaStore, storeInstance);
53631
53628
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
53632
53629
  this.store.updateSearchOptions({ specificRange });
53633
53630
  }
53631
+ get specificRange() {
53632
+ const range = this.store.searchOptions.specificRange;
53633
+ return range ? this.env.model.getters.getRangeString(range, "forceSheetReference") : "";
53634
+ }
53634
53635
  get pendingSearch() {
53635
53636
  return this.updateSearchContent.isDebouncePending();
53636
53637
  }
53638
+ get selectionInputKey() {
53639
+ // Selections input are made to work with objects linked to a sheet id. They store the active sheet id at their creation,
53640
+ // and have specific behaviour linked to it (eg. go back to the initial sheet after confirmation).
53641
+ // We don't want all those behaviors here, so we force the recreation of the component when the active sheet changes.
53642
+ // The only drawback is that the input loses focus when changing sheet.
53643
+ return this.env.model.getters.getActiveSheetId();
53644
+ }
53637
53645
  }
53638
53646
 
53639
53647
  css /* scss */ `
@@ -58067,7 +58075,8 @@ stores.inject(MyMetaStore, storeInstance);
58067
58075
  });
58068
58076
  return !(rect.width === 0 || rect.height === 0);
58069
58077
  }
58070
- onGridResized({ height, width }) {
58078
+ onGridResized() {
58079
+ const { height, width } = this.props.getGridSize();
58071
58080
  this.env.model.dispatch("RESIZE_SHEETVIEW", {
58072
58081
  width: width - HEADER_WIDTH,
58073
58082
  height: height - HEADER_HEIGHT,
@@ -64259,6 +64268,7 @@ stores.inject(MyMetaStore, storeInstance);
64259
64268
  "getMeasureCompiledFormula",
64260
64269
  "getPivotName",
64261
64270
  "isExistingPivot",
64271
+ "getMeasureFullDependencies",
64262
64272
  ];
64263
64273
  nextFormulaId = 1;
64264
64274
  pivots = {};
@@ -64341,7 +64351,7 @@ stores.inject(MyMetaStore, storeInstance);
64341
64351
  }
64342
64352
  case "UPDATE_PIVOT": {
64343
64353
  this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
64344
- this.compileCalculatedMeasures(cmd.pivot.measures);
64354
+ this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
64345
64355
  break;
64346
64356
  }
64347
64357
  }
@@ -64359,9 +64369,14 @@ stores.inject(MyMetaStore, storeInstance);
64359
64369
  this.history.update("pivots", pivotId, "definition", newDefinition);
64360
64370
  }
64361
64371
  }
64362
- for (const sheetId in this.compiledMeasureFormulas) {
64363
- for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64364
- const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
64372
+ for (const pivotId in this.compiledMeasureFormulas) {
64373
+ for (const measureId in this.compiledMeasureFormulas[pivotId]) {
64374
+ const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
64375
+ if (!measure || !measure.computedBy) {
64376
+ continue;
64377
+ }
64378
+ const sheetId = measure.computedBy.sheetId;
64379
+ const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
64365
64380
  const newDependencies = [];
64366
64381
  for (const range of compiledFormula.dependencies) {
64367
64382
  const change = applyChange(range);
@@ -64373,8 +64388,9 @@ stores.inject(MyMetaStore, storeInstance);
64373
64388
  }
64374
64389
  }
64375
64390
  const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
64376
- if (newFormulaString !== formulaString) {
64377
- this.replaceMeasureFormula(sheetId, formulaString, newFormulaString);
64391
+ const oldFormulaString = measure.computedBy.formula;
64392
+ if (newFormulaString !== oldFormulaString) {
64393
+ this.replaceMeasureFormula(pivotId, measure, newFormulaString);
64378
64394
  }
64379
64395
  }
64380
64396
  }
@@ -64412,31 +64428,60 @@ stores.inject(MyMetaStore, storeInstance);
64412
64428
  isExistingPivot(pivotId) {
64413
64429
  return pivotId in this.pivots;
64414
64430
  }
64415
- getMeasureCompiledFormula(measure) {
64431
+ getMeasureCompiledFormula(pivotId, measure) {
64416
64432
  if (!measure.computedBy) {
64417
64433
  throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
64418
64434
  }
64419
- const sheetId = measure.computedBy.sheetId;
64420
- return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
64435
+ return this.compiledMeasureFormulas[pivotId][measure.id].formula;
64436
+ }
64437
+ getMeasureFullDependencies(pivotId, measure) {
64438
+ if (!measure.computedBy) {
64439
+ throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
64440
+ }
64441
+ return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
64421
64442
  }
64422
64443
  // -------------------------------------------------------------------------
64423
64444
  // Private
64424
64445
  // -------------------------------------------------------------------------
64425
64446
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
64426
64447
  this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
64427
- this.compileCalculatedMeasures(pivot.measures);
64448
+ this.compileCalculatedMeasures(pivotId, pivot.measures);
64428
64449
  this.history.update("formulaIds", formulaId, pivotId);
64429
64450
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
64430
64451
  }
64431
- compileCalculatedMeasures(measures) {
64452
+ compileCalculatedMeasures(pivotId, measures) {
64432
64453
  for (const measure of measures) {
64433
64454
  if (measure.computedBy) {
64434
- const sheetId = measure.computedBy.sheetId;
64435
64455
  const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
64436
- this.history.update("compiledMeasureFormulas", sheetId, measure.computedBy.formula, compiledFormula);
64456
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
64457
+ }
64458
+ }
64459
+ for (const measure of measures) {
64460
+ if (measure.computedBy) {
64461
+ const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
64462
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
64437
64463
  }
64438
64464
  }
64439
64465
  }
64466
+ computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
64467
+ const rangeDependencies = [];
64468
+ const definition = this.getPivotCoreDefinition(pivotId);
64469
+ const formula = this.getMeasureCompiledFormula(pivotId, measure);
64470
+ exploredMeasures.add(measure.id);
64471
+ for (const token of formula.tokens) {
64472
+ if (token.type !== "SYMBOL") {
64473
+ continue;
64474
+ }
64475
+ const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
64476
+ measure.id !== measureCandidate.id);
64477
+ if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
64478
+ continue;
64479
+ }
64480
+ rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
64481
+ }
64482
+ rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
64483
+ return rangeDependencies;
64484
+ }
64440
64485
  insertPivot(position, formulaId, table) {
64441
64486
  this.resizeSheet(position.sheetId, position, table);
64442
64487
  const pivotCells = table.getPivotCells();
@@ -64495,21 +64540,17 @@ stores.inject(MyMetaStore, storeInstance);
64495
64540
  dependencies: rangeDependencies,
64496
64541
  };
64497
64542
  }
64498
- replaceMeasureFormula(sheetId, formulaString, newFormulaString) {
64499
- this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
64500
- this.history.update("compiledMeasureFormulas", sheetId, newFormulaString, this.compileMeasureFormula(sheetId, newFormulaString));
64501
- for (const pivotId in this.pivots) {
64502
- const pivot = this.pivots[pivotId];
64503
- if (!pivot) {
64504
- continue;
64505
- }
64506
- for (const measure of pivot.definition.measures) {
64507
- if (measure.computedBy?.formula === formulaString) {
64508
- const measureIndex = pivot.definition.measures.indexOf(measure);
64509
- this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
64510
- }
64511
- }
64543
+ replaceMeasureFormula(pivotId, measure, newFormulaString) {
64544
+ const pivot = this.pivots[pivotId];
64545
+ if (!pivot) {
64546
+ return;
64512
64547
  }
64548
+ const measureIndex = pivot.definition.measures.indexOf(measure);
64549
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
64550
+ formula: newFormulaString,
64551
+ sheetId: measure.computedBy.sheetId,
64552
+ });
64553
+ this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
64513
64554
  }
64514
64555
  checkSortedColumnInMeasures(definition) {
64515
64556
  const measures = definition.measures.map((measure) => measure.id);
@@ -68037,14 +68078,16 @@ stores.inject(MyMetaStore, storeInstance);
68037
68078
  function withPivotPresentationLayer (PivotClass) {
68038
68079
  class PivotPresentationLayer extends PivotClass {
68039
68080
  getters;
68081
+ pivotId;
68040
68082
  cache = {};
68041
68083
  rankAsc = {};
68042
68084
  rankDesc = {};
68043
68085
  runningTotal = {};
68044
68086
  runningTotalInPercent = {};
68045
- constructor(custom, params) {
68087
+ constructor(pivotId, custom, params) {
68046
68088
  super(custom, params);
68047
68089
  this.getters = params.getters;
68090
+ this.pivotId = pivotId;
68048
68091
  }
68049
68092
  markAsDirtyForEvaluation() {
68050
68093
  this.cache = {};
@@ -68094,7 +68137,7 @@ stores.inject(MyMetaStore, storeInstance);
68094
68137
  return handleError(error, measure.aggregator.toUpperCase());
68095
68138
  }
68096
68139
  }
68097
- const formula = this.getters.getMeasureCompiledFormula(measure);
68140
+ const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
68098
68141
  const getSymbolValue = (symbolName) => {
68099
68142
  const { columns, rows } = this.definition;
68100
68143
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
@@ -68834,7 +68877,7 @@ stores.inject(MyMetaStore, storeInstance);
68834
68877
  const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
68835
68878
  if (!(pivotId in this.pivots)) {
68836
68879
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
68837
- this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
68880
+ this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
68838
68881
  }
68839
68882
  else if (recreate) {
68840
68883
  this.pivots[pivotId].onDefinitionChange(definition);
@@ -78173,10 +78216,8 @@ stores.inject(MyMetaStore, storeInstance);
78173
78216
  });
78174
78217
  }
78175
78218
  get gridContainer() {
78176
- const sheetId = this.env.model.getters.getActiveSheetId();
78177
- const { right } = this.env.model.getters.getSheetZone(sheetId);
78178
- const { end } = this.env.model.getters.getColDimensions(sheetId, right);
78179
- return cssPropertiesToCss({ "max-width": `${end}px` });
78219
+ const maxWidth = this.getMaxSheetWidth();
78220
+ return cssPropertiesToCss({ "max-width": `${maxWidth}px` });
78180
78221
  }
78181
78222
  get gridOverlayDimensions() {
78182
78223
  return cssPropertiesToCss({
@@ -78208,10 +78249,12 @@ stores.inject(MyMetaStore, storeInstance);
78208
78249
  onClosePopover() {
78209
78250
  this.cellPopovers.close();
78210
78251
  }
78211
- onGridResized({ height, width }) {
78252
+ onGridResized() {
78253
+ const { height, width } = this.props.getGridSize();
78254
+ const maxWidth = this.getMaxSheetWidth();
78212
78255
  this.env.model.dispatch("RESIZE_SHEETVIEW", {
78213
- width: width,
78214
- height: height,
78256
+ width: Math.min(maxWidth, width),
78257
+ height,
78215
78258
  gridOffsetX: 0,
78216
78259
  gridOffsetY: 0,
78217
78260
  });
@@ -78229,6 +78272,11 @@ stores.inject(MyMetaStore, storeInstance);
78229
78272
  ...this.env.model.getters.getSheetViewDimensionWithHeaders(),
78230
78273
  };
78231
78274
  }
78275
+ getMaxSheetWidth() {
78276
+ const sheetId = this.env.model.getters.getActiveSheetId();
78277
+ const { right } = this.env.model.getters.getSheetZone(sheetId);
78278
+ return this.env.model.getters.getColDimensions(sheetId, right).end;
78279
+ }
78232
78280
  }
78233
78281
 
78234
78282
  css /* scss */ `
@@ -80469,22 +80517,20 @@ stores.inject(MyMetaStore, storeInstance);
80469
80517
  return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
80470
80518
  }
80471
80519
  getGridSize() {
80472
- const topBarHeight = this.spreadsheetRef.el
80473
- ?.querySelector(".o-spreadsheet-topbar-wrapper")
80474
- ?.getBoundingClientRect().height || 0;
80475
- const bottomBarHeight = this.spreadsheetRef.el
80476
- ?.querySelector(".o-spreadsheet-bottombar-wrapper")
80477
- ?.getBoundingClientRect().height || 0;
80478
- const gridWidth = this.spreadsheetRef.el?.querySelector(".o-grid")?.getBoundingClientRect().width || 0;
80479
- const gridHeight = (this.spreadsheetRef.el?.getBoundingClientRect().height || 0) -
80480
- (this.spreadsheetRef.el?.querySelector(".o-column-groups")?.getBoundingClientRect().height ||
80481
- 0) -
80482
- topBarHeight -
80483
- bottomBarHeight;
80484
- return {
80485
- width: Math.max(gridWidth - SCROLLBAR_WIDTH, 0),
80486
- height: Math.max(gridHeight - SCROLLBAR_WIDTH, 0),
80487
- };
80520
+ const el = this.spreadsheetRef.el;
80521
+ if (!el) {
80522
+ return { width: 0, height: 0 };
80523
+ }
80524
+ const getHeight = (selector) => el.querySelector(selector)?.getBoundingClientRect().height || 0;
80525
+ const getWidth = (selector) => el.querySelector(selector)?.getBoundingClientRect().width || 0;
80526
+ const rect = el.getBoundingClientRect();
80527
+ const topBarHeight = getHeight(".o-spreadsheet-topbar-wrapper");
80528
+ const bottomBarHeight = getHeight(".o-spreadsheet-bottombar-wrapper");
80529
+ const colGroupHeight = getHeight(".o-column-groups");
80530
+ const gridWidth = getWidth(".o-grid");
80531
+ const width = Math.max(gridWidth - SCROLLBAR_WIDTH, 0);
80532
+ const height = Math.max(rect.height - topBarHeight - bottomBarHeight - colGroupHeight - SCROLLBAR_WIDTH, 0);
80533
+ return { width, height };
80488
80534
  }
80489
80535
  }
80490
80536
 
@@ -85017,9 +85063,9 @@ stores.inject(MyMetaStore, storeInstance);
85017
85063
  exports.tokenize = tokenize;
85018
85064
 
85019
85065
 
85020
- __info__.version = "18.4.22";
85021
- __info__.date = "2025-12-26T10:19:07.786Z";
85022
- __info__.hash = "6ddac00";
85066
+ __info__.version = "18.4.24";
85067
+ __info__.date = "2026-01-14T10:00:55.867Z";
85068
+ __info__.hash = "0364f56";
85023
85069
 
85024
85070
 
85025
85071
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);