@odoo/o-spreadsheet 19.3.17 → 19.3.19

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.17
6
- * @date 2026-08-21T15:31:50.940Z
7
- * @hash cf8c614
5
+ * @version 19.3.19
6
+ * @date 2026-09-04T07:38:14.356Z
7
+ * @hash c8c526d
8
8
  */
9
9
 
10
10
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -9593,16 +9593,16 @@ const chartShowValuesPlugin = {
9593
9593
  drawLineOrBarOrRadarChartValues(chart, options, ctx);
9594
9594
  break;
9595
9595
  case "bar":
9596
- options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9596
+ options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true }) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9597
9597
  break;
9598
9598
  case "pyramid":
9599
- drawHorizontalBarChartValues(chart, options, ctx);
9599
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true });
9600
9600
  break;
9601
9601
  case "calendar":
9602
9602
  drawBarChartValues(chart, options, ctx);
9603
9603
  break;
9604
9604
  case "funnel":
9605
- drawHorizontalBarChartValues(chart, options, ctx);
9605
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: false });
9606
9606
  break;
9607
9607
  }
9608
9608
  ctx.restore();
@@ -9672,7 +9672,7 @@ function drawBarChartValues(chart, options, ctx) {
9672
9672
  }
9673
9673
  }
9674
9674
  }
9675
- function drawHorizontalBarChartValues(chart, options, ctx) {
9675
+ function drawHorizontalBarChartValues(chart, options, ctx, args) {
9676
9676
  const textsPositions = {};
9677
9677
  for (const dataset of chart._metasets) {
9678
9678
  if (isTrendLineAxis(dataset.xAxisID)) return;
@@ -9687,7 +9687,7 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
9687
9687
  const distanceFromAxisOrigin = Math.abs(point.x - xZeroLine);
9688
9688
  const PADDING = 3;
9689
9689
  let xPosition;
9690
- if (distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9690
+ if (args.offsetFromAxisOrigin && distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9691
9691
  else xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
9692
9692
  if (!textsPositions[yPosition]) textsPositions[yPosition] = [];
9693
9693
  for (const otherPosition of textsPositions[yPosition]) if (Math.abs(otherPosition - xPosition) < textWidth) xPosition = value < 0 ? otherPosition - textWidth - PADDING : otherPosition + textWidth + PADDING;
@@ -10486,6 +10486,7 @@ function getRadarChartDatasets(definition, args) {
10486
10486
  hidden,
10487
10487
  borderColor,
10488
10488
  backgroundColor: borderColor,
10489
+ pointBackgroundColor: borderColor,
10489
10490
  pointRadius: definition.hideDataMarkers ? 0 : 3
10490
10491
  };
10491
10492
  if (fill) {
@@ -25445,9 +25446,10 @@ var Composer = class extends _odoo_owl.Component {
25445
25446
  compositionActive = false;
25446
25447
  spreadsheetRect = useSpreadsheetRect();
25447
25448
  lastHoveredTokenIndex = void 0;
25448
- debouncedHover = debounce((tokenIndex, hoveredRect) => {
25449
+ debouncedHover = debounce((tokenIndex, composerContent, hoveredRect) => {
25449
25450
  const selection = this.contentHelper.getCurrentSelection();
25450
- if (selection.start !== selection.end) return;
25451
+ const currentContent = this.props.composerStore.currentContent;
25452
+ if (selection.start !== selection.end || currentContent !== composerContent) return;
25451
25453
  const currentHoveredContext = this.props.composerStore.hoveredTokens;
25452
25454
  this.props.composerStore.hoverToken(tokenIndex);
25453
25455
  if (!deepEquals(currentHoveredContext, this.props.composerStore.hoveredTokens)) this.composerState.hoveredRect = hoveredRect;
@@ -25765,7 +25767,8 @@ var Composer = class extends _odoo_owl.Component {
25765
25767
  onTokenHover(tokenIndex, hoveredRect) {
25766
25768
  if (this.lastHoveredTokenIndex !== tokenIndex) {
25767
25769
  this.lastHoveredTokenIndex = tokenIndex;
25768
- this.debouncedHover(tokenIndex, hoveredRect);
25770
+ const composerContent = this.props.composerStore.currentContent;
25771
+ this.debouncedHover(tokenIndex, composerContent, hoveredRect);
25769
25772
  }
25770
25773
  }
25771
25774
  /**
@@ -40076,7 +40079,13 @@ var PivotSpreadsheetSidePanel = class extends _odoo_owl.Component {
40076
40079
  }
40077
40080
  onSelectionChanged(ranges) {
40078
40081
  this.state.rangeHasChanged = true;
40079
- this.state.range = ranges[0];
40082
+ if (ranges.length === 0) {
40083
+ this.state.range = void 0;
40084
+ return;
40085
+ }
40086
+ const sheetId = this.env.model.getters.getActiveSheetId();
40087
+ const range = this.env.model.getters.getRangeFromSheetXC(sheetId, ranges[0]);
40088
+ this.state.range = this.env.model.getters.getRangeString(range, "forceSheetReference", { useBoundedReference: true });
40080
40089
  }
40081
40090
  onSelectionConfirmed() {
40082
40091
  if (this.state.range) {
@@ -49735,6 +49744,7 @@ var CarouselPlugin = class extends CorePlugin {
49735
49744
  return "Success";
49736
49745
  case "UPDATE_CAROUSEL":
49737
49746
  if (!this.carousels[cmd.sheetId]?.[cmd.figureId]) return "InvalidFigureId";
49747
+ for (const item of cmd.definition.items) if (item.type === "chart" && !this.getters.getChart(item.chartId)) return "ChartDoesNotExist";
49738
49748
  return "Success";
49739
49749
  }
49740
49750
  return "Success";
@@ -49839,6 +49849,7 @@ var Squisher = class {
49839
49849
  baseFormulaWasTransformed = false;
49840
49850
  rangeToStringOptions = { doNotSimplifyRange: true };
49841
49851
  baseNumber = void 0;
49852
+ baseNumberFormat = void 0;
49842
49853
  constructor(getters) {
49843
49854
  this.getters = getters;
49844
49855
  }
@@ -49873,6 +49884,11 @@ var Squisher = class {
49873
49884
  this.baseFormulaWasTransformed = false;
49874
49885
  }
49875
49886
  }
49887
+ /** Reset the base number literal chain, so the next literal number cannot be squished as an offset of it */
49888
+ resetBaseNumber() {
49889
+ this.baseNumber = void 0;
49890
+ this.baseNumberFormat = void 0;
49891
+ }
49876
49892
  /**
49877
49893
  * Takes a cell and squish their formulas against the previous one (in the previous call).
49878
49894
  * We should call this method for each cell in the sheet, in order from top to bottom, then from left to right (all cells of a columns, for each columns left to right).
@@ -49911,8 +49927,9 @@ var Squisher = class {
49911
49927
  if (typeof cell.parsedValue === "number" && cell.parsedValue % 1 === 0) {
49912
49928
  this.resetBaseFormula();
49913
49929
  const numberValue = cell.parsedValue;
49914
- if (this.baseNumber === void 0) {
49930
+ if (this.baseNumber === void 0 || cell.format !== this.baseNumberFormat) {
49915
49931
  this.baseNumber = numberValue;
49932
+ this.baseNumberFormat = cell.format;
49916
49933
  return cell.content;
49917
49934
  }
49918
49935
  const numberOffset = numberValue - this.baseNumber;
@@ -49923,7 +49940,7 @@ var Squisher = class {
49923
49940
  }
49924
49941
  }
49925
49942
  this.resetBaseFormula();
49926
- this.baseNumber = void 0;
49943
+ this.resetBaseNumber();
49927
49944
  return cell.content;
49928
49945
  }
49929
49946
  squishCommand(command) {
@@ -49932,6 +49949,8 @@ var Squisher = class {
49932
49949
  const squished = this.squish(cell, command.sheetId);
49933
49950
  return typeof squished === "string" ? command.content : squished;
49934
49951
  }
49952
+ this.resetBaseFormula();
49953
+ this.resetBaseNumber();
49935
49954
  return command.content;
49936
49955
  }
49937
49956
  /**
@@ -50085,8 +50104,10 @@ var Unsquisher = class {
50085
50104
  continue;
50086
50105
  }
50087
50106
  const current = command.content;
50088
- if (current === void 0 || current === null || current === "") strategy = "NOT_A_FORMULA";
50089
- else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
50107
+ if (current === void 0 || current === null || current === "") {
50108
+ this.rebase();
50109
+ strategy = "NOT_A_FORMULA";
50110
+ } else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
50090
50111
  let targetPositions;
50091
50112
  if (command.type === "SQUISHED_UPDATE_CELL" && "targetRange" in command) {
50092
50113
  const [start, end] = command.targetRange.split(":");
@@ -50131,8 +50152,11 @@ var Unsquisher = class {
50131
50152
  let strategy;
50132
50153
  for (const { key } of keys) {
50133
50154
  const current = squished[key];
50134
- if (current === void 0 || current === null || current === "") continue;
50135
- else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
50155
+ if (current === void 0 || current === null || current === "") {
50156
+ this.rebase();
50157
+ strategy = void 0;
50158
+ continue;
50159
+ } else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
50136
50160
  const parts = key.split(":");
50137
50161
  const targetPositions = parts.length === 1 ? expandXc(key) : expandRange(parts[0], parts[1]);
50138
50162
  yield* this.applyStrategy(strategy, targetPositions, current, sheetId, getters);
@@ -50178,6 +50202,9 @@ var Unsquisher = class {
50178
50202
  case "FIRST_OFFSET":
50179
50203
  strategy = "COMBINE_OFFSET";
50180
50204
  break;
50205
+ case "COMBINE_OFFSET":
50206
+ case "OFFSET_NUMBER": break;
50207
+ default: throw new Error(`Cannot unsquish an offset without a preceding base cell: ${strategy}`);
50181
50208
  }
50182
50209
  }
50183
50210
  return strategy;
@@ -54896,6 +54923,7 @@ var FormulaDependencyGraph = class {
54896
54923
  }
54897
54924
  getCellsDependingOn(ranges, visited = new RangeSet()) {
54898
54925
  visited = visited.copy();
54926
+ let initialRangesToRemove = visited.copy();
54899
54927
  const queue = Array.from(ranges).reverse();
54900
54928
  while (queue.length > 0) {
54901
54929
  const range = queue.pop();
@@ -54911,8 +54939,9 @@ var FormulaDependencyGraph = class {
54911
54939
  for (const interval of overlappingIntervals) impactedRanges.add(interval.dependents);
54912
54940
  }
54913
54941
  queue.push(...impactedRanges.difference(visited));
54942
+ initialRangesToRemove = initialRangesToRemove.difference(impactedRanges);
54914
54943
  }
54915
- for (const range of ranges) visited.delete(range);
54944
+ for (const range of initialRangesToRemove) visited.delete(range);
54916
54945
  return visited;
54917
54946
  }
54918
54947
  getOrCreateIntervalTree(sheetId, col) {
@@ -60960,6 +60989,7 @@ var Session = class extends EventBus {
60960
60989
  transportService;
60961
60990
  serverRevisionId;
60962
60991
  commandSquisher;
60992
+ shouldVerifySquish;
60963
60993
  /**
60964
60994
  * Positions of the others client.
60965
60995
  */
@@ -60994,13 +61024,15 @@ var Session = class extends EventBus {
60994
61024
  * between all connected clients
60995
61025
  * @param serverRevisionId
60996
61026
  * @param commandSquisher used to squish and unsquish commands to reduce the size of messages sent to the server
61027
+ * @param shouldVerifySquish either the commands should be unsquished and verified before being sent to the server
60997
61028
  */
60998
- constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher) {
61029
+ constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher, shouldVerifySquish = true) {
60999
61030
  super();
61000
61031
  this.revisions = revisions;
61001
61032
  this.transportService = transportService;
61002
61033
  this.serverRevisionId = serverRevisionId;
61003
61034
  this.commandSquisher = commandSquisher;
61035
+ this.shouldVerifySquish = shouldVerifySquish;
61004
61036
  }
61005
61037
  canApplyOptimisticUpdate() {
61006
61038
  return !this.waitingUndoRedoAck;
@@ -61256,10 +61288,20 @@ var Session = class extends EventBus {
61256
61288
  this.revisions.rebase(revision.id);
61257
61289
  revision = this.revisions.get(message.nextRevisionId);
61258
61290
  }
61259
- message = {
61291
+ const squishedCommands = this.commandSquisher.squish(revision.commands);
61292
+ if (!squishedCommands.some((x) => x.type === "SQUISHED_UPDATE_CELL")) message = {
61260
61293
  ...message,
61261
61294
  commands: revision.commands
61262
61295
  };
61296
+ else if (this.shouldVerifySquish && !deepEquals(revision.commands, this.commandSquisher.unsquish(squishedCommands))) message = {
61297
+ ...message,
61298
+ commands: revision.commands,
61299
+ squishedFailed: true
61300
+ };
61301
+ else message = {
61302
+ ...message,
61303
+ commands: squishedCommands
61304
+ };
61263
61305
  }
61264
61306
  if (this.isReplayingInitialRevisions) throw new Error(`Trying to send a new revision while replaying initial revision. This can lead to endless dispatches every time the spreadsheet is open.
61265
61307
  ${JSON.stringify(message)}`);
@@ -68956,7 +68998,7 @@ var FigureRendererStore = class extends DisposableStore {
68956
68998
  if (!this.getters.isDashboard()) {
68957
68999
  ctx.strokeStyle = GRAY_400;
68958
69000
  ctx.lineWidth = 1;
68959
- ctx.strokeRect(x, y, figure.width, figure.height);
69001
+ ctx.strokeRect(x + .5, y + .5, figure.width - 1, figure.height - 1);
68960
69002
  }
68961
69003
  }
68962
69004
  }
@@ -84971,6 +85013,6 @@ exports.stores = stores;
84971
85013
  exports.tokenColors = tokenColors;
84972
85014
  exports.tokenize = tokenize;
84973
85015
 
84974
- __info__.version = "19.3.17";
84975
- __info__.date = "2026-08-21T15:31:50.940Z";
84976
- __info__.hash = "cf8c614";
85016
+ __info__.version = "19.3.19";
85017
+ __info__.date = "2026-09-04T07:38:14.356Z";
85018
+ __info__.hash = "c8c526d";
@@ -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.17
6
- * @date 2026-08-21T15:31:52.347Z
7
- * @hash cf8c614
5
+ * @version 19.3.19
6
+ * @date 2026-09-04T07:38:15.963Z
7
+ * @hash c8c526d
8
8
  */
9
9
  :root {
10
10
  --os-gray-100: light-dark(#f9fafb, #1b1d26);
@@ -22,7 +22,7 @@
22
22
  --os-white-bg: light-dark(#ffffff, var(--os-gray-200));
23
23
  --os-popover-bg: light-dark(#ffffff, var(--os-gray-300));
24
24
 
25
- --os-default-font: "Roboto", "Arial";
25
+ --os-default-font: "Roboto", "Arial", "Liberation Sans";
26
26
  --os-default-font-size: 10px;
27
27
  --os-link-color: light-dark(#017e84, #02c7b5);
28
28
  --os-link-hover-color: light-dark(#01585c, #4ed8cb);
@@ -1480,6 +1480,12 @@
1480
1480
  background-color: var(--os-action-color);
1481
1481
  border-color: var(--os-action-color) !important;
1482
1482
  }
1483
+
1484
+ &:focus {
1485
+ outline: none;
1486
+ box-shadow: 0 0 0 0.25rem rgba(113, 75, 103, 0.25);
1487
+ border-color: var(--os-action-color);
1488
+ }
1483
1489
  }
1484
1490
  }
1485
1491
  }
@@ -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.17
6
- * @date 2026-08-21T15:31:50.940Z
7
- * @hash cf8c614
5
+ * @version 19.3.19
6
+ * @date 2026-09-04T07:38:14.356Z
7
+ * @hash c8c526d
8
8
  */
9
9
 
10
10
  import { App, Component, blockDom, markRaw, onMounted, onPatched, onWillPatch, onWillStart, onWillUnmount, onWillUpdateProps, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, whenReady, xml } from "@odoo/owl";
@@ -9592,16 +9592,16 @@ const chartShowValuesPlugin = {
9592
9592
  drawLineOrBarOrRadarChartValues(chart, options, ctx);
9593
9593
  break;
9594
9594
  case "bar":
9595
- options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9595
+ options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true }) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
9596
9596
  break;
9597
9597
  case "pyramid":
9598
- drawHorizontalBarChartValues(chart, options, ctx);
9598
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: true });
9599
9599
  break;
9600
9600
  case "calendar":
9601
9601
  drawBarChartValues(chart, options, ctx);
9602
9602
  break;
9603
9603
  case "funnel":
9604
- drawHorizontalBarChartValues(chart, options, ctx);
9604
+ drawHorizontalBarChartValues(chart, options, ctx, { offsetFromAxisOrigin: false });
9605
9605
  break;
9606
9606
  }
9607
9607
  ctx.restore();
@@ -9671,7 +9671,7 @@ function drawBarChartValues(chart, options, ctx) {
9671
9671
  }
9672
9672
  }
9673
9673
  }
9674
- function drawHorizontalBarChartValues(chart, options, ctx) {
9674
+ function drawHorizontalBarChartValues(chart, options, ctx, args) {
9675
9675
  const textsPositions = {};
9676
9676
  for (const dataset of chart._metasets) {
9677
9677
  if (isTrendLineAxis(dataset.xAxisID)) return;
@@ -9686,7 +9686,7 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
9686
9686
  const distanceFromAxisOrigin = Math.abs(point.x - xZeroLine);
9687
9687
  const PADDING = 3;
9688
9688
  let xPosition;
9689
- if (distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9689
+ if (args.offsetFromAxisOrigin && distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
9690
9690
  else xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
9691
9691
  if (!textsPositions[yPosition]) textsPositions[yPosition] = [];
9692
9692
  for (const otherPosition of textsPositions[yPosition]) if (Math.abs(otherPosition - xPosition) < textWidth) xPosition = value < 0 ? otherPosition - textWidth - PADDING : otherPosition + textWidth + PADDING;
@@ -10485,6 +10485,7 @@ function getRadarChartDatasets(definition, args) {
10485
10485
  hidden,
10486
10486
  borderColor,
10487
10487
  backgroundColor: borderColor,
10488
+ pointBackgroundColor: borderColor,
10488
10489
  pointRadius: definition.hideDataMarkers ? 0 : 3
10489
10490
  };
10490
10491
  if (fill) {
@@ -25444,9 +25445,10 @@ var Composer = class extends Component {
25444
25445
  compositionActive = false;
25445
25446
  spreadsheetRect = useSpreadsheetRect();
25446
25447
  lastHoveredTokenIndex = void 0;
25447
- debouncedHover = debounce((tokenIndex, hoveredRect) => {
25448
+ debouncedHover = debounce((tokenIndex, composerContent, hoveredRect) => {
25448
25449
  const selection = this.contentHelper.getCurrentSelection();
25449
- if (selection.start !== selection.end) return;
25450
+ const currentContent = this.props.composerStore.currentContent;
25451
+ if (selection.start !== selection.end || currentContent !== composerContent) return;
25450
25452
  const currentHoveredContext = this.props.composerStore.hoveredTokens;
25451
25453
  this.props.composerStore.hoverToken(tokenIndex);
25452
25454
  if (!deepEquals(currentHoveredContext, this.props.composerStore.hoveredTokens)) this.composerState.hoveredRect = hoveredRect;
@@ -25764,7 +25766,8 @@ var Composer = class extends Component {
25764
25766
  onTokenHover(tokenIndex, hoveredRect) {
25765
25767
  if (this.lastHoveredTokenIndex !== tokenIndex) {
25766
25768
  this.lastHoveredTokenIndex = tokenIndex;
25767
- this.debouncedHover(tokenIndex, hoveredRect);
25769
+ const composerContent = this.props.composerStore.currentContent;
25770
+ this.debouncedHover(tokenIndex, composerContent, hoveredRect);
25768
25771
  }
25769
25772
  }
25770
25773
  /**
@@ -40075,7 +40078,13 @@ var PivotSpreadsheetSidePanel = class extends Component {
40075
40078
  }
40076
40079
  onSelectionChanged(ranges) {
40077
40080
  this.state.rangeHasChanged = true;
40078
- this.state.range = ranges[0];
40081
+ if (ranges.length === 0) {
40082
+ this.state.range = void 0;
40083
+ return;
40084
+ }
40085
+ const sheetId = this.env.model.getters.getActiveSheetId();
40086
+ const range = this.env.model.getters.getRangeFromSheetXC(sheetId, ranges[0]);
40087
+ this.state.range = this.env.model.getters.getRangeString(range, "forceSheetReference", { useBoundedReference: true });
40079
40088
  }
40080
40089
  onSelectionConfirmed() {
40081
40090
  if (this.state.range) {
@@ -49734,6 +49743,7 @@ var CarouselPlugin = class extends CorePlugin {
49734
49743
  return "Success";
49735
49744
  case "UPDATE_CAROUSEL":
49736
49745
  if (!this.carousels[cmd.sheetId]?.[cmd.figureId]) return "InvalidFigureId";
49746
+ for (const item of cmd.definition.items) if (item.type === "chart" && !this.getters.getChart(item.chartId)) return "ChartDoesNotExist";
49737
49747
  return "Success";
49738
49748
  }
49739
49749
  return "Success";
@@ -49838,6 +49848,7 @@ var Squisher = class {
49838
49848
  baseFormulaWasTransformed = false;
49839
49849
  rangeToStringOptions = { doNotSimplifyRange: true };
49840
49850
  baseNumber = void 0;
49851
+ baseNumberFormat = void 0;
49841
49852
  constructor(getters) {
49842
49853
  this.getters = getters;
49843
49854
  }
@@ -49872,6 +49883,11 @@ var Squisher = class {
49872
49883
  this.baseFormulaWasTransformed = false;
49873
49884
  }
49874
49885
  }
49886
+ /** Reset the base number literal chain, so the next literal number cannot be squished as an offset of it */
49887
+ resetBaseNumber() {
49888
+ this.baseNumber = void 0;
49889
+ this.baseNumberFormat = void 0;
49890
+ }
49875
49891
  /**
49876
49892
  * Takes a cell and squish their formulas against the previous one (in the previous call).
49877
49893
  * We should call this method for each cell in the sheet, in order from top to bottom, then from left to right (all cells of a columns, for each columns left to right).
@@ -49910,8 +49926,9 @@ var Squisher = class {
49910
49926
  if (typeof cell.parsedValue === "number" && cell.parsedValue % 1 === 0) {
49911
49927
  this.resetBaseFormula();
49912
49928
  const numberValue = cell.parsedValue;
49913
- if (this.baseNumber === void 0) {
49929
+ if (this.baseNumber === void 0 || cell.format !== this.baseNumberFormat) {
49914
49930
  this.baseNumber = numberValue;
49931
+ this.baseNumberFormat = cell.format;
49915
49932
  return cell.content;
49916
49933
  }
49917
49934
  const numberOffset = numberValue - this.baseNumber;
@@ -49922,7 +49939,7 @@ var Squisher = class {
49922
49939
  }
49923
49940
  }
49924
49941
  this.resetBaseFormula();
49925
- this.baseNumber = void 0;
49942
+ this.resetBaseNumber();
49926
49943
  return cell.content;
49927
49944
  }
49928
49945
  squishCommand(command) {
@@ -49931,6 +49948,8 @@ var Squisher = class {
49931
49948
  const squished = this.squish(cell, command.sheetId);
49932
49949
  return typeof squished === "string" ? command.content : squished;
49933
49950
  }
49951
+ this.resetBaseFormula();
49952
+ this.resetBaseNumber();
49934
49953
  return command.content;
49935
49954
  }
49936
49955
  /**
@@ -50084,8 +50103,10 @@ var Unsquisher = class {
50084
50103
  continue;
50085
50104
  }
50086
50105
  const current = command.content;
50087
- if (current === void 0 || current === null || current === "") strategy = "NOT_A_FORMULA";
50088
- else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
50106
+ if (current === void 0 || current === null || current === "") {
50107
+ this.rebase();
50108
+ strategy = "NOT_A_FORMULA";
50109
+ } else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
50089
50110
  let targetPositions;
50090
50111
  if (command.type === "SQUISHED_UPDATE_CELL" && "targetRange" in command) {
50091
50112
  const [start, end] = command.targetRange.split(":");
@@ -50130,8 +50151,11 @@ var Unsquisher = class {
50130
50151
  let strategy;
50131
50152
  for (const { key } of keys) {
50132
50153
  const current = squished[key];
50133
- if (current === void 0 || current === null || current === "") continue;
50134
- else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
50154
+ if (current === void 0 || current === null || current === "") {
50155
+ this.rebase();
50156
+ strategy = void 0;
50157
+ continue;
50158
+ } else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
50135
50159
  const parts = key.split(":");
50136
50160
  const targetPositions = parts.length === 1 ? expandXc(key) : expandRange(parts[0], parts[1]);
50137
50161
  yield* this.applyStrategy(strategy, targetPositions, current, sheetId, getters);
@@ -50177,6 +50201,9 @@ var Unsquisher = class {
50177
50201
  case "FIRST_OFFSET":
50178
50202
  strategy = "COMBINE_OFFSET";
50179
50203
  break;
50204
+ case "COMBINE_OFFSET":
50205
+ case "OFFSET_NUMBER": break;
50206
+ default: throw new Error(`Cannot unsquish an offset without a preceding base cell: ${strategy}`);
50180
50207
  }
50181
50208
  }
50182
50209
  return strategy;
@@ -54895,6 +54922,7 @@ var FormulaDependencyGraph = class {
54895
54922
  }
54896
54923
  getCellsDependingOn(ranges, visited = new RangeSet()) {
54897
54924
  visited = visited.copy();
54925
+ let initialRangesToRemove = visited.copy();
54898
54926
  const queue = Array.from(ranges).reverse();
54899
54927
  while (queue.length > 0) {
54900
54928
  const range = queue.pop();
@@ -54910,8 +54938,9 @@ var FormulaDependencyGraph = class {
54910
54938
  for (const interval of overlappingIntervals) impactedRanges.add(interval.dependents);
54911
54939
  }
54912
54940
  queue.push(...impactedRanges.difference(visited));
54941
+ initialRangesToRemove = initialRangesToRemove.difference(impactedRanges);
54913
54942
  }
54914
- for (const range of ranges) visited.delete(range);
54943
+ for (const range of initialRangesToRemove) visited.delete(range);
54915
54944
  return visited;
54916
54945
  }
54917
54946
  getOrCreateIntervalTree(sheetId, col) {
@@ -60775,6 +60804,7 @@ var Session = class extends EventBus {
60775
60804
  transportService;
60776
60805
  serverRevisionId;
60777
60806
  commandSquisher;
60807
+ shouldVerifySquish;
60778
60808
  /**
60779
60809
  * Positions of the others client.
60780
60810
  */
@@ -60809,13 +60839,15 @@ var Session = class extends EventBus {
60809
60839
  * between all connected clients
60810
60840
  * @param serverRevisionId
60811
60841
  * @param commandSquisher used to squish and unsquish commands to reduce the size of messages sent to the server
60842
+ * @param shouldVerifySquish either the commands should be unsquished and verified before being sent to the server
60812
60843
  */
60813
- constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher) {
60844
+ constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher, shouldVerifySquish = true) {
60814
60845
  super();
60815
60846
  this.revisions = revisions;
60816
60847
  this.transportService = transportService;
60817
60848
  this.serverRevisionId = serverRevisionId;
60818
60849
  this.commandSquisher = commandSquisher;
60850
+ this.shouldVerifySquish = shouldVerifySquish;
60819
60851
  }
60820
60852
  canApplyOptimisticUpdate() {
60821
60853
  return !this.waitingUndoRedoAck;
@@ -61071,10 +61103,20 @@ var Session = class extends EventBus {
61071
61103
  this.revisions.rebase(revision.id);
61072
61104
  revision = this.revisions.get(message.nextRevisionId);
61073
61105
  }
61074
- message = {
61106
+ const squishedCommands = this.commandSquisher.squish(revision.commands);
61107
+ if (!squishedCommands.some((x) => x.type === "SQUISHED_UPDATE_CELL")) message = {
61075
61108
  ...message,
61076
61109
  commands: revision.commands
61077
61110
  };
61111
+ else if (this.shouldVerifySquish && !deepEquals(revision.commands, this.commandSquisher.unsquish(squishedCommands))) message = {
61112
+ ...message,
61113
+ commands: revision.commands,
61114
+ squishedFailed: true
61115
+ };
61116
+ else message = {
61117
+ ...message,
61118
+ commands: squishedCommands
61119
+ };
61078
61120
  }
61079
61121
  if (this.isReplayingInitialRevisions) throw new Error(`Trying to send a new revision while replaying initial revision. This can lead to endless dispatches every time the spreadsheet is open.
61080
61122
  ${JSON.stringify(message)}`);
@@ -68771,7 +68813,7 @@ var FigureRendererStore = class extends DisposableStore {
68771
68813
  if (!this.getters.isDashboard()) {
68772
68814
  ctx.strokeStyle = GRAY_400;
68773
68815
  ctx.lineWidth = 1;
68774
- ctx.strokeRect(x, y, figure.width, figure.height);
68816
+ ctx.strokeRect(x + .5, y + .5, figure.width - 1, figure.height - 1);
68775
68817
  }
68776
68818
  }
68777
68819
  }
@@ -84728,6 +84770,6 @@ const chartHelpers = {
84728
84770
  //#endregion
84729
84771
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CompiledFormula, CorePlugin, CoreViewPlugin, DEFAULT_LOCALE, DEFAULT_LOCALES, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, canExecuteInReadonly, categories, chartHelpers, components, constants, convertAstNodes, coreTypes, createAutocompleteArgumentsProvider, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, isCoreCommand, isSheetDependent, iterateAstNodes, links, load, lockedSheetAllowedCommands, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
84730
84772
 
84731
- __info__.version = "19.3.17";
84732
- __info__.date = "2026-08-21T15:31:50.940Z";
84733
- __info__.hash = "cf8c614";
84773
+ __info__.version = "19.3.19";
84774
+ __info__.date = "2026-09-04T07:38:14.356Z";
84775
+ __info__.hash = "c8c526d";