@odoo/o-spreadsheet 19.4.9 → 19.4.10

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.9
6
- * @date 2026-08-21T15:33:39.385Z
7
- * @hash b48dbb3
5
+ * @version 19.4.10
6
+ * @date 2026-08-29T09:17:27.429Z
7
+ * @hash d7a0f18
8
8
  */
9
9
 
10
10
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -7896,7 +7896,8 @@ const readonlyAllowedCommands = /* @__PURE__ */ new Set([
7896
7896
  "UPDATE_CHART",
7897
7897
  "UPDATE_CHART_REGION",
7898
7898
  "UPDATE_CAROUSEL_ACTIVE_ITEM",
7899
- "UPDATE_PIVOT"
7899
+ "UPDATE_PIVOT",
7900
+ "UPDATE_COLOR_SCHEME"
7900
7901
  ]);
7901
7902
  const lockedSheetAllowedCommands = /* @__PURE__ */ new Set([
7902
7903
  "LOCK_SHEET",
@@ -11215,6 +11216,7 @@ function getRadarChartDatasets(definition, args) {
11215
11216
  hidden,
11216
11217
  borderColor,
11217
11218
  backgroundColor: borderColor,
11219
+ pointBackgroundColor: borderColor,
11218
11220
  pointRadius: definition.hideDataMarkers ? 0 : 3
11219
11221
  };
11220
11222
  if (fill) {
@@ -37065,7 +37067,7 @@ var FindAndReplacePanel = class extends Component {
37065
37067
  get currentSheetMatchesCount() {
37066
37068
  const { activeSheetMatchesCount: count, activeSheetHiddenMatchesCount: hidden, searchOptions } = this.store;
37067
37069
  const sheetName = this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId());
37068
- let label = count === 1 ? _t("1 match in %(sheetName)s", { sheetName }) : _t("%(count)s matches in %(sheetName)s", {
37070
+ let label = count === 1 ? _t("1 match in '%(sheetName)s'", { sheetName }) : _t("%(count)s matches in '%(sheetName)s'", {
37069
37071
  count,
37070
37072
  sheetName
37071
37073
  });
@@ -37077,10 +37079,10 @@ var FindAndReplacePanel = class extends Component {
37077
37079
  if (!range) return "";
37078
37080
  const { specificRangeMatchesCount: count, specificRangeHiddenMatchesCount: hidden, searchOptions } = this.store;
37079
37081
  const { sheetId, zone } = range;
37080
- let label = count === 1 ? _t("1 match in range %(range)s of %(sheetName)s", {
37082
+ let label = count === 1 ? _t("1 match in range %(range)s of '%(sheetName)s'", {
37081
37083
  range: zoneToXc(zone),
37082
37084
  sheetName: this.env.model.getters.getSheetName(sheetId)
37083
- }) : _t("%(count)s matches in range %(range)s of %(sheetName)s", {
37085
+ }) : _t("%(count)s matches in range %(range)s of '%(sheetName)s'", {
37084
37086
  count,
37085
37087
  range: zoneToXc(zone),
37086
37088
  sheetName: this.env.model.getters.getSheetName(sheetId)
@@ -51130,6 +51132,7 @@ var Squisher = class {
51130
51132
  baseFormulaWasTransformed = false;
51131
51133
  rangeToStringOptions = { doNotSimplifyRange: true };
51132
51134
  baseNumber = void 0;
51135
+ baseNumberFormat = void 0;
51133
51136
  constructor(getters) {
51134
51137
  this.getters = getters;
51135
51138
  }
@@ -51164,6 +51167,11 @@ var Squisher = class {
51164
51167
  this.baseFormulaWasTransformed = false;
51165
51168
  }
51166
51169
  }
51170
+ /** Reset the base number literal chain, so the next literal number cannot be squished as an offset of it */
51171
+ resetBaseNumber() {
51172
+ this.baseNumber = void 0;
51173
+ this.baseNumberFormat = void 0;
51174
+ }
51167
51175
  /**
51168
51176
  * Takes a cell and squish their formulas against the previous one (in the previous call).
51169
51177
  * 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).
@@ -51202,8 +51210,9 @@ var Squisher = class {
51202
51210
  if (typeof cell.parsedValue === "number" && cell.parsedValue % 1 === 0) {
51203
51211
  this.resetBaseFormula();
51204
51212
  const numberValue = cell.parsedValue;
51205
- if (this.baseNumber === void 0) {
51213
+ if (this.baseNumber === void 0 || cell.format !== this.baseNumberFormat) {
51206
51214
  this.baseNumber = numberValue;
51215
+ this.baseNumberFormat = cell.format;
51207
51216
  return cell.content;
51208
51217
  }
51209
51218
  const numberOffset = numberValue - this.baseNumber;
@@ -51214,7 +51223,7 @@ var Squisher = class {
51214
51223
  }
51215
51224
  }
51216
51225
  this.resetBaseFormula();
51217
- this.baseNumber = void 0;
51226
+ this.resetBaseNumber();
51218
51227
  return cell.content;
51219
51228
  }
51220
51229
  squishCommand(command) {
@@ -51223,6 +51232,8 @@ var Squisher = class {
51223
51232
  const squished = this.squish(cell, command.sheetId);
51224
51233
  return typeof squished === "string" ? command.content : squished;
51225
51234
  }
51235
+ this.resetBaseFormula();
51236
+ this.resetBaseNumber();
51226
51237
  return command.content;
51227
51238
  }
51228
51239
  /**
@@ -51376,8 +51387,10 @@ var Unsquisher = class {
51376
51387
  continue;
51377
51388
  }
51378
51389
  const current = command.content;
51379
- if (current === void 0 || current === null || current === "") strategy = "NOT_A_FORMULA";
51380
- else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
51390
+ if (current === void 0 || current === null || current === "") {
51391
+ this.rebase();
51392
+ strategy = "NOT_A_FORMULA";
51393
+ } else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
51381
51394
  let targetPositions;
51382
51395
  if (command.type === "SQUISHED_UPDATE_CELL" && "targetRange" in command) {
51383
51396
  const [start, end] = command.targetRange.split(":");
@@ -51422,8 +51435,11 @@ var Unsquisher = class {
51422
51435
  let strategy;
51423
51436
  for (const { key } of keys) {
51424
51437
  const current = squished[key];
51425
- if (current === void 0 || current === null || current === "") continue;
51426
- else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
51438
+ if (current === void 0 || current === null || current === "") {
51439
+ this.rebase();
51440
+ strategy = void 0;
51441
+ continue;
51442
+ } else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
51427
51443
  const parts = key.split(":");
51428
51444
  const targetPositions = parts.length === 1 ? expandXc(key) : expandRange(parts[0], parts[1]);
51429
51445
  yield* this.applyStrategy(strategy, targetPositions, current, sheetId, getters);
@@ -51469,6 +51485,9 @@ var Unsquisher = class {
51469
51485
  case "FIRST_OFFSET":
51470
51486
  strategy = "COMBINE_OFFSET";
51471
51487
  break;
51488
+ case "COMBINE_OFFSET":
51489
+ case "OFFSET_NUMBER": break;
51490
+ default: throw new Error(`Cannot unsquish an offset without a preceding base cell: ${strategy}`);
51472
51491
  }
51473
51492
  }
51474
51493
  return strategy;
@@ -62331,6 +62350,7 @@ var Session = class extends EventBus {
62331
62350
  transportService;
62332
62351
  serverRevisionId;
62333
62352
  commandSquisher;
62353
+ shouldVerifySquish;
62334
62354
  /**
62335
62355
  * Positions of the others client.
62336
62356
  */
@@ -62364,13 +62384,15 @@ var Session = class extends EventBus {
62364
62384
  * between all connected clients
62365
62385
  * @param serverRevisionId
62366
62386
  * @param commandSquisher used to squish and unsquish commands to reduce the size of messages sent to the server
62387
+ * @param shouldVerifySquish either the commands should be unsquished and verified before being sent to the server
62367
62388
  */
62368
- constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher) {
62389
+ constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher, shouldVerifySquish = true) {
62369
62390
  super();
62370
62391
  this.revisions = revisions;
62371
62392
  this.transportService = transportService;
62372
62393
  this.serverRevisionId = serverRevisionId;
62373
62394
  this.commandSquisher = commandSquisher;
62395
+ this.shouldVerifySquish = shouldVerifySquish;
62374
62396
  }
62375
62397
  canApplyOptimisticUpdate() {
62376
62398
  return !this.waitingUndoRedoAck;
@@ -62626,10 +62648,20 @@ var Session = class extends EventBus {
62626
62648
  this.revisions.rebase(revision.id);
62627
62649
  revision = this.revisions.get(message.nextRevisionId);
62628
62650
  }
62629
- message = {
62651
+ const squishedCommands = this.commandSquisher.squish(revision.commands);
62652
+ if (!squishedCommands.some((x) => x.type === "SQUISHED_UPDATE_CELL")) message = {
62630
62653
  ...message,
62631
62654
  commands: revision.commands
62632
62655
  };
62656
+ else if (this.shouldVerifySquish && !deepEquals(revision.commands, this.commandSquisher.unsquish(squishedCommands))) message = {
62657
+ ...message,
62658
+ commands: revision.commands,
62659
+ squishedFailed: true
62660
+ };
62661
+ else message = {
62662
+ ...message,
62663
+ commands: squishedCommands
62664
+ };
62633
62665
  }
62634
62666
  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.
62635
62667
  ${JSON.stringify(message)}`);
@@ -69862,13 +69894,12 @@ var SpreadsheetDashboard = class extends Component {
69862
69894
  return this.env.model.getters.getColDimensions(sheetId, right).end;
69863
69895
  }
69864
69896
  get dashboardStyle() {
69865
- const style = { zoom: `${this.env.model.getters.getViewportZoomLevel()}` };
69866
- if (this.env.model.getters.getActiveSheet().backgroundColor) style["background-color"] = "transparent";
69867
- return cssPropertiesToCss(style);
69897
+ return cssPropertiesToCss({ zoom: `${this.env.model.getters.getViewportZoomLevel()}` });
69868
69898
  }
69869
69899
  get backgroundStyle() {
69870
69900
  const sheet = this.env.model.getters.getActiveSheet();
69871
- return sheet.backgroundColor ? cssPropertiesToCss({ "background-color": sheet.backgroundColor }) : "";
69901
+ const theme = this.env.model.getters.getSpreadsheetTheme();
69902
+ return cssPropertiesToCss({ "background-color": sheet.backgroundColor || theme.backgroundColor });
69872
69903
  }
69873
69904
  };
69874
69905
 
@@ -87942,6 +87973,6 @@ exports.stores = stores;
87942
87973
  exports.tokenColors = tokenColors;
87943
87974
  exports.tokenize = tokenize;
87944
87975
 
87945
- __info__.version = "19.4.9";
87946
- __info__.date = "2026-08-21T15:33:39.385Z";
87947
- __info__.hash = "b48dbb3";
87976
+ __info__.version = "19.4.10";
87977
+ __info__.date = "2026-08-29T09:17:27.429Z";
87978
+ __info__.hash = "d7a0f18";
@@ -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.9
6
- * @date 2026-08-21T15:33:40.993Z
7
- * @hash b48dbb3
5
+ * @version 19.4.10
6
+ * @date 2026-08-29T09:17:29.105Z
7
+ * @hash d7a0f18
8
8
  */
9
9
  :root {
10
10
  --os-gray-100: light-dark(#f9fafb, #1b1d26);
@@ -1512,6 +1512,12 @@
1512
1512
  background-color: var(--os-action-color);
1513
1513
  border-color: var(--os-action-color) !important;
1514
1514
  }
1515
+
1516
+ &:focus {
1517
+ outline: none;
1518
+ box-shadow: 0 0 0 0.25rem rgba(113, 75, 103, 0.25);
1519
+ border-color: var(--os-action-color);
1520
+ }
1515
1521
  }
1516
1522
  }
1517
1523
  }
@@ -2882,6 +2888,11 @@
2882
2888
  position: absolute;
2883
2889
  cursor: pointer;
2884
2890
  }
2891
+
2892
+ .o-dashboard-grid {
2893
+ /* Grid itself is transparent, background is applied on another div on which the dark mode filter is applied */
2894
+ background-color: transparent;
2895
+ }
2885
2896
  }
2886
2897
 
2887
2898
  /* Originates from src/components/dashboard/clickable_cell_sort_icon/clickable_cell_sort_icon.css */
@@ -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.9
6
- * @date 2026-08-21T15:33:39.385Z
7
- * @hash b48dbb3
5
+ * @version 19.4.10
6
+ * @date 2026-08-29T09:17:27.429Z
7
+ * @hash d7a0f18
8
8
  */
9
9
 
10
10
  import * as owl from "@odoo/owl";
@@ -7895,7 +7895,8 @@ const readonlyAllowedCommands = /* @__PURE__ */ new Set([
7895
7895
  "UPDATE_CHART",
7896
7896
  "UPDATE_CHART_REGION",
7897
7897
  "UPDATE_CAROUSEL_ACTIVE_ITEM",
7898
- "UPDATE_PIVOT"
7898
+ "UPDATE_PIVOT",
7899
+ "UPDATE_COLOR_SCHEME"
7899
7900
  ]);
7900
7901
  const lockedSheetAllowedCommands = /* @__PURE__ */ new Set([
7901
7902
  "LOCK_SHEET",
@@ -11214,6 +11215,7 @@ function getRadarChartDatasets(definition, args) {
11214
11215
  hidden,
11215
11216
  borderColor,
11216
11217
  backgroundColor: borderColor,
11218
+ pointBackgroundColor: borderColor,
11217
11219
  pointRadius: definition.hideDataMarkers ? 0 : 3
11218
11220
  };
11219
11221
  if (fill) {
@@ -37064,7 +37066,7 @@ var FindAndReplacePanel = class extends Component {
37064
37066
  get currentSheetMatchesCount() {
37065
37067
  const { activeSheetMatchesCount: count, activeSheetHiddenMatchesCount: hidden, searchOptions } = this.store;
37066
37068
  const sheetName = this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId());
37067
- let label = count === 1 ? _t("1 match in %(sheetName)s", { sheetName }) : _t("%(count)s matches in %(sheetName)s", {
37069
+ let label = count === 1 ? _t("1 match in '%(sheetName)s'", { sheetName }) : _t("%(count)s matches in '%(sheetName)s'", {
37068
37070
  count,
37069
37071
  sheetName
37070
37072
  });
@@ -37076,10 +37078,10 @@ var FindAndReplacePanel = class extends Component {
37076
37078
  if (!range) return "";
37077
37079
  const { specificRangeMatchesCount: count, specificRangeHiddenMatchesCount: hidden, searchOptions } = this.store;
37078
37080
  const { sheetId, zone } = range;
37079
- let label = count === 1 ? _t("1 match in range %(range)s of %(sheetName)s", {
37081
+ let label = count === 1 ? _t("1 match in range %(range)s of '%(sheetName)s'", {
37080
37082
  range: zoneToXc(zone),
37081
37083
  sheetName: this.env.model.getters.getSheetName(sheetId)
37082
- }) : _t("%(count)s matches in range %(range)s of %(sheetName)s", {
37084
+ }) : _t("%(count)s matches in range %(range)s of '%(sheetName)s'", {
37083
37085
  count,
37084
37086
  range: zoneToXc(zone),
37085
37087
  sheetName: this.env.model.getters.getSheetName(sheetId)
@@ -51129,6 +51131,7 @@ var Squisher = class {
51129
51131
  baseFormulaWasTransformed = false;
51130
51132
  rangeToStringOptions = { doNotSimplifyRange: true };
51131
51133
  baseNumber = void 0;
51134
+ baseNumberFormat = void 0;
51132
51135
  constructor(getters) {
51133
51136
  this.getters = getters;
51134
51137
  }
@@ -51163,6 +51166,11 @@ var Squisher = class {
51163
51166
  this.baseFormulaWasTransformed = false;
51164
51167
  }
51165
51168
  }
51169
+ /** Reset the base number literal chain, so the next literal number cannot be squished as an offset of it */
51170
+ resetBaseNumber() {
51171
+ this.baseNumber = void 0;
51172
+ this.baseNumberFormat = void 0;
51173
+ }
51166
51174
  /**
51167
51175
  * Takes a cell and squish their formulas against the previous one (in the previous call).
51168
51176
  * 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).
@@ -51201,8 +51209,9 @@ var Squisher = class {
51201
51209
  if (typeof cell.parsedValue === "number" && cell.parsedValue % 1 === 0) {
51202
51210
  this.resetBaseFormula();
51203
51211
  const numberValue = cell.parsedValue;
51204
- if (this.baseNumber === void 0) {
51212
+ if (this.baseNumber === void 0 || cell.format !== this.baseNumberFormat) {
51205
51213
  this.baseNumber = numberValue;
51214
+ this.baseNumberFormat = cell.format;
51206
51215
  return cell.content;
51207
51216
  }
51208
51217
  const numberOffset = numberValue - this.baseNumber;
@@ -51213,7 +51222,7 @@ var Squisher = class {
51213
51222
  }
51214
51223
  }
51215
51224
  this.resetBaseFormula();
51216
- this.baseNumber = void 0;
51225
+ this.resetBaseNumber();
51217
51226
  return cell.content;
51218
51227
  }
51219
51228
  squishCommand(command) {
@@ -51222,6 +51231,8 @@ var Squisher = class {
51222
51231
  const squished = this.squish(cell, command.sheetId);
51223
51232
  return typeof squished === "string" ? command.content : squished;
51224
51233
  }
51234
+ this.resetBaseFormula();
51235
+ this.resetBaseNumber();
51225
51236
  return command.content;
51226
51237
  }
51227
51238
  /**
@@ -51375,8 +51386,10 @@ var Unsquisher = class {
51375
51386
  continue;
51376
51387
  }
51377
51388
  const current = command.content;
51378
- if (current === void 0 || current === null || current === "") strategy = "NOT_A_FORMULA";
51379
- else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
51389
+ if (current === void 0 || current === null || current === "") {
51390
+ this.rebase();
51391
+ strategy = "NOT_A_FORMULA";
51392
+ } else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
51380
51393
  let targetPositions;
51381
51394
  if (command.type === "SQUISHED_UPDATE_CELL" && "targetRange" in command) {
51382
51395
  const [start, end] = command.targetRange.split(":");
@@ -51421,8 +51434,11 @@ var Unsquisher = class {
51421
51434
  let strategy;
51422
51435
  for (const { key } of keys) {
51423
51436
  const current = squished[key];
51424
- if (current === void 0 || current === null || current === "") continue;
51425
- else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
51437
+ if (current === void 0 || current === null || current === "") {
51438
+ this.rebase();
51439
+ strategy = void 0;
51440
+ continue;
51441
+ } else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
51426
51442
  const parts = key.split(":");
51427
51443
  const targetPositions = parts.length === 1 ? expandXc(key) : expandRange(parts[0], parts[1]);
51428
51444
  yield* this.applyStrategy(strategy, targetPositions, current, sheetId, getters);
@@ -51468,6 +51484,9 @@ var Unsquisher = class {
51468
51484
  case "FIRST_OFFSET":
51469
51485
  strategy = "COMBINE_OFFSET";
51470
51486
  break;
51487
+ case "COMBINE_OFFSET":
51488
+ case "OFFSET_NUMBER": break;
51489
+ default: throw new Error(`Cannot unsquish an offset without a preceding base cell: ${strategy}`);
51471
51490
  }
51472
51491
  }
51473
51492
  return strategy;
@@ -62146,6 +62165,7 @@ var Session = class extends EventBus {
62146
62165
  transportService;
62147
62166
  serverRevisionId;
62148
62167
  commandSquisher;
62168
+ shouldVerifySquish;
62149
62169
  /**
62150
62170
  * Positions of the others client.
62151
62171
  */
@@ -62179,13 +62199,15 @@ var Session = class extends EventBus {
62179
62199
  * between all connected clients
62180
62200
  * @param serverRevisionId
62181
62201
  * @param commandSquisher used to squish and unsquish commands to reduce the size of messages sent to the server
62202
+ * @param shouldVerifySquish either the commands should be unsquished and verified before being sent to the server
62182
62203
  */
62183
- constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher) {
62204
+ constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher, shouldVerifySquish = true) {
62184
62205
  super();
62185
62206
  this.revisions = revisions;
62186
62207
  this.transportService = transportService;
62187
62208
  this.serverRevisionId = serverRevisionId;
62188
62209
  this.commandSquisher = commandSquisher;
62210
+ this.shouldVerifySquish = shouldVerifySquish;
62189
62211
  }
62190
62212
  canApplyOptimisticUpdate() {
62191
62213
  return !this.waitingUndoRedoAck;
@@ -62441,10 +62463,20 @@ var Session = class extends EventBus {
62441
62463
  this.revisions.rebase(revision.id);
62442
62464
  revision = this.revisions.get(message.nextRevisionId);
62443
62465
  }
62444
- message = {
62466
+ const squishedCommands = this.commandSquisher.squish(revision.commands);
62467
+ if (!squishedCommands.some((x) => x.type === "SQUISHED_UPDATE_CELL")) message = {
62445
62468
  ...message,
62446
62469
  commands: revision.commands
62447
62470
  };
62471
+ else if (this.shouldVerifySquish && !deepEquals(revision.commands, this.commandSquisher.unsquish(squishedCommands))) message = {
62472
+ ...message,
62473
+ commands: revision.commands,
62474
+ squishedFailed: true
62475
+ };
62476
+ else message = {
62477
+ ...message,
62478
+ commands: squishedCommands
62479
+ };
62448
62480
  }
62449
62481
  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.
62450
62482
  ${JSON.stringify(message)}`);
@@ -69677,13 +69709,12 @@ var SpreadsheetDashboard = class extends Component {
69677
69709
  return this.env.model.getters.getColDimensions(sheetId, right).end;
69678
69710
  }
69679
69711
  get dashboardStyle() {
69680
- const style = { zoom: `${this.env.model.getters.getViewportZoomLevel()}` };
69681
- if (this.env.model.getters.getActiveSheet().backgroundColor) style["background-color"] = "transparent";
69682
- return cssPropertiesToCss(style);
69712
+ return cssPropertiesToCss({ zoom: `${this.env.model.getters.getViewportZoomLevel()}` });
69683
69713
  }
69684
69714
  get backgroundStyle() {
69685
69715
  const sheet = this.env.model.getters.getActiveSheet();
69686
- return sheet.backgroundColor ? cssPropertiesToCss({ "background-color": sheet.backgroundColor }) : "";
69716
+ const theme = this.env.model.getters.getSpreadsheetTheme();
69717
+ return cssPropertiesToCss({ "background-color": sheet.backgroundColor || theme.backgroundColor });
69687
69718
  }
69688
69719
  };
69689
69720
 
@@ -87663,6 +87694,6 @@ const chartHelpers = {
87663
87694
  //#endregion
87664
87695
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, BadExpressionError, CHART_TYPES, CellErrorType, CellValueType, CircularDependencyError, ClientDisconnectedError, ClipboardMIMEType, CommandResult, CompiledFormula, CorePlugin, CoreViewPlugin, DEFAULT_LOCALE, DEFAULT_LOCALES, DEFAULT_LOCALE_DIGIT_GROUPING, DIRECTION, DispatchResult, DivisionByZeroError, EvaluationError, InvalidReferenceError, LocalTransportService, Model, NEXT_VALUE, NotAvailableError, NumberTooLargeError, OrderedLayers, PREVIOUS_VALUE, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, SplillBlockedError, Spreadsheet, SpreadsheetPivotTable, UIPlugin, UnknownFunctionError, __info__, addFunction, addRenderingLayer, astToFormula, availableConditionalFormatOperators, availableDataValidationOperators, availableFiltersOperators, borderPositions, borderStyles, canExecuteInReadonly, categories, chartHelpers, compatibility, components, composerFocusTypes, constants, convertAstNodes, coreTypes, createAutocompleteArgumentsProvider, errorTypes, filterDateCriterionOperators, filterNumberCriterionOperators, filterTextCriterionOperators, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidSubtotalFormulasCommands, invalidateBordersCommands, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, isCoreCommand, isHeadersDependant, isMatrix, isPositionDependent, isRangeDependant, isSheetDependent, isTargetDependent, isZoneDependent, iterateAstNodes, links, load, lockedSheetAllowedCommands, parse, parseTokens, readonlyAllowedCommands, registries, schemeToColorScale, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
87665
87696
 
87666
- __info__.version = "19.4.9";
87667
- __info__.date = "2026-08-21T15:33:39.385Z";
87668
- __info__.hash = "b48dbb3";
87697
+ __info__.version = "19.4.10";
87698
+ __info__.date = "2026-08-29T09:17:27.429Z";
87699
+ __info__.hash = "d7a0f18";
@@ -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.9
6
- * @date 2026-08-21T15:33:39.385Z
7
- * @hash b48dbb3
5
+ * @version 19.4.10
6
+ * @date 2026-08-29T09:17:27.429Z
7
+ * @hash d7a0f18
8
8
  */
9
9
 
10
10
  (function(exports, _odoo_owl) {
@@ -7897,7 +7897,8 @@ set(value) {
7897
7897
  "UPDATE_CHART",
7898
7898
  "UPDATE_CHART_REGION",
7899
7899
  "UPDATE_CAROUSEL_ACTIVE_ITEM",
7900
- "UPDATE_PIVOT"
7900
+ "UPDATE_PIVOT",
7901
+ "UPDATE_COLOR_SCHEME"
7901
7902
  ]);
7902
7903
  const lockedSheetAllowedCommands = /* @__PURE__ */ new Set([
7903
7904
  "LOCK_SHEET",
@@ -11216,6 +11217,7 @@ set(value) {
11216
11217
  hidden,
11217
11218
  borderColor,
11218
11219
  backgroundColor: borderColor,
11220
+ pointBackgroundColor: borderColor,
11219
11221
  pointRadius: definition.hideDataMarkers ? 0 : 3
11220
11222
  };
11221
11223
  if (fill) {
@@ -37066,7 +37068,7 @@ set(value) {
37066
37068
  get currentSheetMatchesCount() {
37067
37069
  const { activeSheetMatchesCount: count, activeSheetHiddenMatchesCount: hidden, searchOptions } = this.store;
37068
37070
  const sheetName = this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId());
37069
- let label = count === 1 ? _t("1 match in %(sheetName)s", { sheetName }) : _t("%(count)s matches in %(sheetName)s", {
37071
+ let label = count === 1 ? _t("1 match in '%(sheetName)s'", { sheetName }) : _t("%(count)s matches in '%(sheetName)s'", {
37070
37072
  count,
37071
37073
  sheetName
37072
37074
  });
@@ -37078,10 +37080,10 @@ set(value) {
37078
37080
  if (!range) return "";
37079
37081
  const { specificRangeMatchesCount: count, specificRangeHiddenMatchesCount: hidden, searchOptions } = this.store;
37080
37082
  const { sheetId, zone } = range;
37081
- let label = count === 1 ? _t("1 match in range %(range)s of %(sheetName)s", {
37083
+ let label = count === 1 ? _t("1 match in range %(range)s of '%(sheetName)s'", {
37082
37084
  range: zoneToXc(zone),
37083
37085
  sheetName: this.env.model.getters.getSheetName(sheetId)
37084
- }) : _t("%(count)s matches in range %(range)s of %(sheetName)s", {
37086
+ }) : _t("%(count)s matches in range %(range)s of '%(sheetName)s'", {
37085
37087
  count,
37086
37088
  range: zoneToXc(zone),
37087
37089
  sheetName: this.env.model.getters.getSheetName(sheetId)
@@ -51131,6 +51133,7 @@ set(value) {
51131
51133
  baseFormulaWasTransformed = false;
51132
51134
  rangeToStringOptions = { doNotSimplifyRange: true };
51133
51135
  baseNumber = void 0;
51136
+ baseNumberFormat = void 0;
51134
51137
  constructor(getters) {
51135
51138
  this.getters = getters;
51136
51139
  }
@@ -51165,6 +51168,11 @@ set(value) {
51165
51168
  this.baseFormulaWasTransformed = false;
51166
51169
  }
51167
51170
  }
51171
+ /** Reset the base number literal chain, so the next literal number cannot be squished as an offset of it */
51172
+ resetBaseNumber() {
51173
+ this.baseNumber = void 0;
51174
+ this.baseNumberFormat = void 0;
51175
+ }
51168
51176
  /**
51169
51177
  * Takes a cell and squish their formulas against the previous one (in the previous call).
51170
51178
  * 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).
@@ -51203,8 +51211,9 @@ set(value) {
51203
51211
  if (typeof cell.parsedValue === "number" && cell.parsedValue % 1 === 0) {
51204
51212
  this.resetBaseFormula();
51205
51213
  const numberValue = cell.parsedValue;
51206
- if (this.baseNumber === void 0) {
51214
+ if (this.baseNumber === void 0 || cell.format !== this.baseNumberFormat) {
51207
51215
  this.baseNumber = numberValue;
51216
+ this.baseNumberFormat = cell.format;
51208
51217
  return cell.content;
51209
51218
  }
51210
51219
  const numberOffset = numberValue - this.baseNumber;
@@ -51215,7 +51224,7 @@ set(value) {
51215
51224
  }
51216
51225
  }
51217
51226
  this.resetBaseFormula();
51218
- this.baseNumber = void 0;
51227
+ this.resetBaseNumber();
51219
51228
  return cell.content;
51220
51229
  }
51221
51230
  squishCommand(command) {
@@ -51224,6 +51233,8 @@ set(value) {
51224
51233
  const squished = this.squish(cell, command.sheetId);
51225
51234
  return typeof squished === "string" ? command.content : squished;
51226
51235
  }
51236
+ this.resetBaseFormula();
51237
+ this.resetBaseNumber();
51227
51238
  return command.content;
51228
51239
  }
51229
51240
  /**
@@ -51377,8 +51388,10 @@ set(value) {
51377
51388
  continue;
51378
51389
  }
51379
51390
  const current = command.content;
51380
- if (current === void 0 || current === null || current === "") strategy = "NOT_A_FORMULA";
51381
- else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
51391
+ if (current === void 0 || current === null || current === "") {
51392
+ this.rebase();
51393
+ strategy = "NOT_A_FORMULA";
51394
+ } else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
51382
51395
  let targetPositions;
51383
51396
  if (command.type === "SQUISHED_UPDATE_CELL" && "targetRange" in command) {
51384
51397
  const [start, end] = command.targetRange.split(":");
@@ -51423,8 +51436,11 @@ set(value) {
51423
51436
  let strategy;
51424
51437
  for (const { key } of keys) {
51425
51438
  const current = squished[key];
51426
- if (current === void 0 || current === null || current === "") continue;
51427
- else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
51439
+ if (current === void 0 || current === null || current === "") {
51440
+ this.rebase();
51441
+ strategy = void 0;
51442
+ continue;
51443
+ } else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
51428
51444
  const parts = key.split(":");
51429
51445
  const targetPositions = parts.length === 1 ? expandXc(key) : expandRange(parts[0], parts[1]);
51430
51446
  yield* this.applyStrategy(strategy, targetPositions, current, sheetId, getters);
@@ -51470,6 +51486,9 @@ set(value) {
51470
51486
  case "FIRST_OFFSET":
51471
51487
  strategy = "COMBINE_OFFSET";
51472
51488
  break;
51489
+ case "COMBINE_OFFSET":
51490
+ case "OFFSET_NUMBER": break;
51491
+ default: throw new Error(`Cannot unsquish an offset without a preceding base cell: ${strategy}`);
51473
51492
  }
51474
51493
  }
51475
51494
  return strategy;
@@ -62148,6 +62167,7 @@ set(value) {
62148
62167
  transportService;
62149
62168
  serverRevisionId;
62150
62169
  commandSquisher;
62170
+ shouldVerifySquish;
62151
62171
  /**
62152
62172
  * Positions of the others client.
62153
62173
  */
@@ -62181,13 +62201,15 @@ set(value) {
62181
62201
  * between all connected clients
62182
62202
  * @param serverRevisionId
62183
62203
  * @param commandSquisher used to squish and unsquish commands to reduce the size of messages sent to the server
62204
+ * @param shouldVerifySquish either the commands should be unsquished and verified before being sent to the server
62184
62205
  */
62185
- constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher) {
62206
+ constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher, shouldVerifySquish = true) {
62186
62207
  super();
62187
62208
  this.revisions = revisions;
62188
62209
  this.transportService = transportService;
62189
62210
  this.serverRevisionId = serverRevisionId;
62190
62211
  this.commandSquisher = commandSquisher;
62212
+ this.shouldVerifySquish = shouldVerifySquish;
62191
62213
  }
62192
62214
  canApplyOptimisticUpdate() {
62193
62215
  return !this.waitingUndoRedoAck;
@@ -62443,10 +62465,20 @@ set(value) {
62443
62465
  this.revisions.rebase(revision.id);
62444
62466
  revision = this.revisions.get(message.nextRevisionId);
62445
62467
  }
62446
- message = {
62468
+ const squishedCommands = this.commandSquisher.squish(revision.commands);
62469
+ if (!squishedCommands.some((x) => x.type === "SQUISHED_UPDATE_CELL")) message = {
62447
62470
  ...message,
62448
62471
  commands: revision.commands
62449
62472
  };
62473
+ else if (this.shouldVerifySquish && !deepEquals(revision.commands, this.commandSquisher.unsquish(squishedCommands))) message = {
62474
+ ...message,
62475
+ commands: revision.commands,
62476
+ squishedFailed: true
62477
+ };
62478
+ else message = {
62479
+ ...message,
62480
+ commands: squishedCommands
62481
+ };
62450
62482
  }
62451
62483
  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.
62452
62484
  ${JSON.stringify(message)}`);
@@ -69679,13 +69711,12 @@ set(value) {
69679
69711
  return this.env.model.getters.getColDimensions(sheetId, right).end;
69680
69712
  }
69681
69713
  get dashboardStyle() {
69682
- const style = { zoom: `${this.env.model.getters.getViewportZoomLevel()}` };
69683
- if (this.env.model.getters.getActiveSheet().backgroundColor) style["background-color"] = "transparent";
69684
- return cssPropertiesToCss(style);
69714
+ return cssPropertiesToCss({ zoom: `${this.env.model.getters.getViewportZoomLevel()}` });
69685
69715
  }
69686
69716
  get backgroundStyle() {
69687
69717
  const sheet = this.env.model.getters.getActiveSheet();
69688
- return sheet.backgroundColor ? cssPropertiesToCss({ "background-color": sheet.backgroundColor }) : "";
69718
+ const theme = this.env.model.getters.getSpreadsheetTheme();
69719
+ return cssPropertiesToCss({ "background-color": sheet.backgroundColor || theme.backgroundColor });
69689
69720
  }
69690
69721
  };
69691
69722
 
@@ -87759,8 +87790,8 @@ exports.stores = stores;
87759
87790
  exports.tokenColors = tokenColors;
87760
87791
  exports.tokenize = tokenize;
87761
87792
 
87762
- __info__.version = "19.4.9";
87763
- __info__.date = "2026-08-21T15:33:39.385Z";
87764
- __info__.hash = "b48dbb3";
87793
+ __info__.version = "19.4.10";
87794
+ __info__.date = "2026-08-29T09:17:27.429Z";
87795
+ __info__.hash = "d7a0f18";
87765
87796
 
87766
87797
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);