@odoo/o-spreadsheet 17.4.29 → 17.4.31

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 17.4.29
6
- * @date 2025-04-04T08:40:34.590Z
7
- * @hash 2937d99
5
+ * @version 17.4.31
6
+ * @date 2025-04-18T16:24:47.716Z
7
+ * @hash 7991032
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -2167,6 +2167,7 @@ const coreTypes = new Set([
2167
2167
  "CLEAR_FORMATTING",
2168
2168
  "SET_BORDER",
2169
2169
  "SET_ZONE_BORDERS",
2170
+ "SET_BORDERS_ON_TARGET",
2170
2171
  /** CHART */
2171
2172
  "CREATE_CHART",
2172
2173
  "UPDATE_CHART",
@@ -5650,6 +5651,7 @@ class AbstractCellClipboardHandler extends ClipboardHandler {
5650
5651
  }
5651
5652
 
5652
5653
  class BorderClipboardHandler extends AbstractCellClipboardHandler {
5654
+ queuedBordersToAdd = {};
5653
5655
  copy(data) {
5654
5656
  const sheetId = data.sheetId;
5655
5657
  if (data.zones.length === 0) {
@@ -5680,6 +5682,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5680
5682
  const { left, top } = zones[0];
5681
5683
  this.pasteZone(sheetId, left, top, content.borders);
5682
5684
  }
5685
+ this.executeQueuedChanges(sheetId);
5683
5686
  }
5684
5687
  pasteZone(sheetId, col, row, borders) {
5685
5688
  for (const [r, rowBorders] of borders.entries()) {
@@ -5698,7 +5701,20 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5698
5701
  ...targetBorders,
5699
5702
  ...originBorders,
5700
5703
  };
5701
- this.dispatch("SET_BORDER", { ...target, border });
5704
+ const borderKey = JSON.stringify(border);
5705
+ if (!this.queuedBordersToAdd[borderKey]) {
5706
+ this.queuedBordersToAdd[borderKey] = [];
5707
+ }
5708
+ this.queuedBordersToAdd[borderKey].push(positionToZone(target));
5709
+ }
5710
+ executeQueuedChanges(pasteSheetTarget) {
5711
+ for (const borderKey in this.queuedBordersToAdd) {
5712
+ const zones = this.queuedBordersToAdd[borderKey];
5713
+ const border = JSON.parse(borderKey);
5714
+ const target = recomputeZones(zones, []);
5715
+ this.dispatch("SET_BORDERS_ON_TARGET", { sheetId: pasteSheetTarget, target, border });
5716
+ }
5717
+ this.queuedBordersToAdd = {};
5702
5718
  }
5703
5719
  }
5704
5720
 
@@ -5810,6 +5826,12 @@ function tokenizeString(chars) {
5810
5826
  }
5811
5827
  return null;
5812
5828
  }
5829
+ /**
5830
+ - \p{L} is for any letter (from any language)
5831
+ - \p{N} is for any number
5832
+ - the u flag at the end is for unicode, which enables the `\p{...}` syntax
5833
+ */
5834
+ const unicodeSymbolCharRegexp = /\p{L}|\p{N}|_|\.|!|\$/u;
5813
5835
  const SYMBOL_CHARS = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.!$");
5814
5836
  /**
5815
5837
  * A "Symbol" is just basically any word-like element that can appear in a
@@ -5850,7 +5872,8 @@ function tokenizeSymbol(chars) {
5850
5872
  };
5851
5873
  }
5852
5874
  }
5853
- while (chars.current && SYMBOL_CHARS.has(chars.current)) {
5875
+ while (chars.current &&
5876
+ (SYMBOL_CHARS.has(chars.current) || chars.current.match(unicodeSymbolCharRegexp))) {
5854
5877
  result += chars.shift();
5855
5878
  }
5856
5879
  if (result.length) {
@@ -6962,6 +6985,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
6962
6985
 
6963
6986
  class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
6964
6987
  uuidGenerator = new UuidGenerator();
6988
+ queuedChanges = {};
6965
6989
  copy(data) {
6966
6990
  if (!data.zones.length) {
6967
6991
  return;
@@ -6983,6 +7007,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
6983
7007
  return { cfRules };
6984
7008
  }
6985
7009
  paste(target, clippedContent, options) {
7010
+ this.queuedChanges = {};
6986
7011
  if (options.pasteOption === "asValue") {
6987
7012
  return;
6988
7013
  }
@@ -6994,6 +7019,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
6994
7019
  else {
6995
7020
  this.pasteFromCut(sheetId, zones, clippedContent);
6996
7021
  }
7022
+ this.executeQueuedChanges();
6997
7023
  }
6998
7024
  pasteFromCut(sheetId, target, content) {
6999
7025
  const selection = target[0];
@@ -7011,12 +7037,13 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
7011
7037
  }
7012
7038
  pasteCf(origin, target, isCutOperation) {
7013
7039
  if (origin?.rules && origin.rules.length > 0) {
7040
+ const originZone = positionToZone(origin.position);
7014
7041
  const zone = positionToZone(target);
7015
7042
  for (const rule of origin.rules) {
7016
7043
  const toRemoveZones = [];
7017
7044
  if (isCutOperation) {
7018
7045
  //remove from current rule
7019
- toRemoveZones.push(positionToZone(origin.position));
7046
+ toRemoveZones.push(originZone);
7020
7047
  }
7021
7048
  if (origin.position.sheetId === target.sheetId) {
7022
7049
  this.adaptCFRules(origin.position.sheetId, rule, [zone], toRemoveZones);
@@ -7033,36 +7060,56 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
7033
7060
  * Add or remove cells to a given conditional formatting rule.
7034
7061
  */
7035
7062
  adaptCFRules(sheetId, cf, toAdd, toRemove) {
7036
- const newRangesXc = this.getters.getAdaptedCfRanges(sheetId, cf, toAdd, toRemove);
7037
- if (!newRangesXc) {
7038
- return;
7063
+ if (!this.queuedChanges[sheetId]) {
7064
+ this.queuedChanges[sheetId] = [];
7039
7065
  }
7040
- if (newRangesXc.length === 0) {
7041
- this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
7042
- return;
7066
+ const queuedChange = this.queuedChanges[sheetId].find((queued) => queued.cf.id === cf.id);
7067
+ if (!queuedChange) {
7068
+ this.queuedChanges[sheetId].push({ toAdd, toRemove, cf });
7069
+ }
7070
+ else {
7071
+ queuedChange.toAdd.push(...toAdd);
7072
+ queuedChange.toRemove.push(...toRemove);
7073
+ }
7074
+ }
7075
+ executeQueuedChanges() {
7076
+ for (const sheetId in this.queuedChanges) {
7077
+ for (const { toAdd, toRemove, cf } of this.queuedChanges[sheetId]) {
7078
+ const newRangesXc = this.getters.getAdaptedCfRanges(sheetId, cf, toAdd, toRemove);
7079
+ if (!newRangesXc) {
7080
+ continue;
7081
+ }
7082
+ if (newRangesXc.length === 0) {
7083
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
7084
+ continue;
7085
+ }
7086
+ this.dispatch("ADD_CONDITIONAL_FORMAT", {
7087
+ cf: {
7088
+ id: cf.id,
7089
+ rule: cf.rule,
7090
+ stopIfTrue: cf.stopIfTrue,
7091
+ },
7092
+ ranges: newRangesXc,
7093
+ sheetId,
7094
+ });
7095
+ }
7043
7096
  }
7044
- this.dispatch("ADD_CONDITIONAL_FORMAT", {
7045
- cf: {
7046
- id: cf.id,
7047
- rule: cf.rule,
7048
- stopIfTrue: cf.stopIfTrue,
7049
- },
7050
- ranges: newRangesXc,
7051
- sheetId,
7052
- });
7053
7097
  }
7054
7098
  getCFToCopyTo(targetSheetId, originCF) {
7055
- const cfInTarget = this.getters
7099
+ let targetCF = this.getters
7056
7100
  .getConditionalFormats(targetSheetId)
7057
7101
  .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
7058
- return cfInTarget
7059
- ? cfInTarget
7060
- : { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
7102
+ const queuedCfs = this.queuedChanges[targetSheetId];
7103
+ if (!targetCF && queuedCfs) {
7104
+ targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
7105
+ }
7106
+ return targetCF || { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
7061
7107
  }
7062
7108
  }
7063
7109
 
7064
7110
  class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
7065
7111
  uuidGenerator = new UuidGenerator();
7112
+ queuedChanges = {};
7066
7113
  copy(data) {
7067
7114
  const { rowsIndexes, columnsIndexes } = data;
7068
7115
  const sheetId = data.sheetId;
@@ -7079,6 +7126,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
7079
7126
  return { dvRules };
7080
7127
  }
7081
7128
  paste(target, clippedContent, options) {
7129
+ this.queuedChanges = {};
7082
7130
  if (options.pasteOption) {
7083
7131
  return;
7084
7132
  }
@@ -7090,6 +7138,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
7090
7138
  else {
7091
7139
  this.pasteFromCut(sheetId, zones, clippedContent);
7092
7140
  }
7141
+ this.executeQueuedChanges();
7093
7142
  }
7094
7143
  pasteFromCut(sheetId, target, content) {
7095
7144
  const selection = target[0];
@@ -7108,6 +7157,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
7108
7157
  pasteDataValidation(origin, target, isCutOperation) {
7109
7158
  if (origin) {
7110
7159
  const zone = positionToZone(target);
7160
+ const originZone = positionToZone(origin.position);
7111
7161
  const rule = origin.rule;
7112
7162
  if (!rule) {
7113
7163
  const targetRule = this.getters.getValidationRuleForCell(target);
@@ -7119,7 +7169,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
7119
7169
  }
7120
7170
  const toRemoveZone = [];
7121
7171
  if (isCutOperation) {
7122
- toRemoveZone.push(positionToZone(origin.position));
7172
+ toRemoveZone.push(originZone);
7123
7173
  }
7124
7174
  if (origin.position.sheetId === target.sheetId) {
7125
7175
  const copyToRule = this.getDataValidationRuleToCopyTo(target.sheetId, rule, false);
@@ -7136,29 +7186,55 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
7136
7186
  }
7137
7187
  }
7138
7188
  getDataValidationRuleToCopyTo(targetSheetId, originRule, newId = true) {
7139
- const ruleInTargetSheet = this.getters
7189
+ let targetRule = this.getters
7140
7190
  .getDataValidationRules(targetSheetId)
7141
7191
  .find((rule) => deepEquals(originRule.criterion, rule.criterion) &&
7142
7192
  originRule.isBlocking === rule.isBlocking);
7143
- return ruleInTargetSheet
7144
- ? ruleInTargetSheet
7145
- : { ...originRule, id: newId ? this.uuidGenerator.smallUuid() : originRule.id, ranges: [] };
7193
+ const queuedRules = this.queuedChanges[targetSheetId];
7194
+ if (!targetRule && queuedRules) {
7195
+ targetRule = queuedRules.find((queued) => deepEquals(originRule.criterion, queued.rule.criterion) &&
7196
+ originRule.isBlocking === queued.rule.isBlocking)?.rule;
7197
+ }
7198
+ return (targetRule || {
7199
+ ...originRule,
7200
+ id: newId ? this.uuidGenerator.uuidv4() : originRule.id,
7201
+ ranges: [],
7202
+ });
7146
7203
  }
7147
7204
  /**
7148
7205
  * Add or remove XCs to a given data validation rule.
7149
7206
  */
7150
7207
  adaptDataValidationRule(sheetId, rule, toAdd, toRemove) {
7151
- const dvZones = rule.ranges.map((range) => range.zone);
7152
- const newDvZones = recomputeZones([...dvZones, ...toAdd], toRemove);
7153
- if (newDvZones.length === 0) {
7154
- this.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: rule.id });
7155
- return;
7208
+ if (!this.queuedChanges[sheetId]) {
7209
+ this.queuedChanges[sheetId] = [];
7210
+ }
7211
+ const queuedChange = this.queuedChanges[sheetId].find((queued) => queued.rule.id === rule.id);
7212
+ if (!queuedChange) {
7213
+ this.queuedChanges[sheetId].push({ toAdd, toRemove, rule });
7214
+ }
7215
+ else {
7216
+ queuedChange.toAdd.push(...toAdd);
7217
+ queuedChange.toRemove.push(...toRemove);
7218
+ }
7219
+ }
7220
+ executeQueuedChanges() {
7221
+ for (const sheetId in this.queuedChanges) {
7222
+ for (const { toAdd, toRemove, rule: dv } of this.queuedChanges[sheetId]) {
7223
+ // Remove the zones first in case the same position is in toAdd and toRemove
7224
+ const dvZones = dv.ranges.map((range) => range.zone);
7225
+ const withRemovedZones = recomputeZones(dvZones, toRemove);
7226
+ const newDvZones = recomputeZones([...withRemovedZones, ...toAdd], []);
7227
+ if (newDvZones.length === 0) {
7228
+ this.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: dv.id });
7229
+ continue;
7230
+ }
7231
+ this.dispatch("ADD_DATA_VALIDATION_RULE", {
7232
+ rule: { id: dv.id, criterion: dv.criterion, isBlocking: dv.isBlocking },
7233
+ ranges: newDvZones.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
7234
+ sheetId,
7235
+ });
7236
+ }
7156
7237
  }
7157
- this.dispatch("ADD_DATA_VALIDATION_RULE", {
7158
- rule,
7159
- ranges: newDvZones.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
7160
- sheetId,
7161
- });
7162
7238
  }
7163
7239
  }
7164
7240
 
@@ -7484,7 +7560,7 @@ function transformZone(zone, executed) {
7484
7560
  if (executed.type === "ADD_COLUMNS_ROWS") {
7485
7561
  return expandZoneOnInsertion(zone, executed.dimension === "COL" ? "left" : "top", executed.base, executed.position, executed.quantity);
7486
7562
  }
7487
- return { ...zone };
7563
+ return zone;
7488
7564
  }
7489
7565
  function transformRangeData(range, executed) {
7490
7566
  const deletedSheet = executed.type === "DELETE_SHEET" && executed.sheetId;
@@ -47561,6 +47637,15 @@ class BordersPlugin extends CorePlugin {
47561
47637
  case "SET_BORDER":
47562
47638
  this.setBorder(cmd.sheetId, cmd.col, cmd.row, cmd.border);
47563
47639
  break;
47640
+ case "SET_BORDERS_ON_TARGET":
47641
+ for (const zone of cmd.target) {
47642
+ for (let row = zone.top; row <= zone.bottom; row++) {
47643
+ for (let col = zone.left; col <= zone.right; col++) {
47644
+ this.setBorder(cmd.sheetId, col, row, cmd.border);
47645
+ }
47646
+ }
47647
+ }
47648
+ break;
47564
47649
  case "SET_ZONE_BORDERS":
47565
47650
  if (cmd.border) {
47566
47651
  const target = cmd.target.map((zone) => this.getters.expandZone(cmd.sheetId, zone));
@@ -49039,8 +49124,9 @@ class ConditionalFormatPlugin extends CorePlugin {
49039
49124
  if (replaceIndex > -1) {
49040
49125
  currentRanges = rules[replaceIndex].ranges.map(toUnboundedZone);
49041
49126
  }
49042
- currentRanges = currentRanges.concat(toAdd);
49043
- return recomputeZones(currentRanges, toRemove).map((zone) => this.getters.getRangeDataFromZone(sheetId, zone));
49127
+ // Remove the zones first in case the same position is in toAdd and toRemove
49128
+ const withRemovedZones = recomputeZones(currentRanges, toRemove);
49129
+ return recomputeZones([...toAdd, ...withRemovedZones], []).map((zone) => this.getters.getRangeDataFromZone(sheetId, zone));
49044
49130
  }
49045
49131
  // ---------------------------------------------------------------------------
49046
49132
  // Private
@@ -56551,25 +56637,6 @@ class AutofillPlugin extends UIPlugin {
56551
56637
  case "AUTOFILL_AUTO":
56552
56638
  this.autofillAuto();
56553
56639
  break;
56554
- case "AUTOFILL_CELL":
56555
- this.autoFillMerge(cmd.originCol, cmd.originRow, cmd.col, cmd.row);
56556
- const sheetId = this.getters.getActiveSheetId();
56557
- this.dispatch("UPDATE_CELL", {
56558
- sheetId,
56559
- col: cmd.col,
56560
- row: cmd.row,
56561
- style: cmd.style || null,
56562
- content: cmd.content || "",
56563
- format: cmd.format || "",
56564
- });
56565
- this.dispatch("SET_BORDER", {
56566
- sheetId,
56567
- col: cmd.col,
56568
- row: cmd.row,
56569
- border: cmd.border,
56570
- });
56571
- this.autofillCF(cmd.originCol, cmd.originRow, cmd.col, cmd.row);
56572
- this.autofillDV(cmd.originCol, cmd.originRow, cmd.col, cmd.row);
56573
56640
  }
56574
56641
  }
56575
56642
  // ---------------------------------------------------------------------------
@@ -56593,6 +56660,7 @@ class AutofillPlugin extends UIPlugin {
56593
56660
  }
56594
56661
  const source = this.getters.getSelectedZone();
56595
56662
  const target = this.autofillZone;
56663
+ const autofillCellsData = [];
56596
56664
  switch (this.direction) {
56597
56665
  case "down" /* DIRECTION.DOWN */:
56598
56666
  for (let col = source.left; col <= source.right; col++) {
@@ -56602,7 +56670,7 @@ class AutofillPlugin extends UIPlugin {
56602
56670
  }
56603
56671
  const generator = this.createGenerator(xcs);
56604
56672
  for (let row = target.top; row <= target.bottom; row++) {
56605
- this.computeNewCell(generator, col, row, apply);
56673
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
56606
56674
  }
56607
56675
  }
56608
56676
  break;
@@ -56614,7 +56682,7 @@ class AutofillPlugin extends UIPlugin {
56614
56682
  }
56615
56683
  const generator = this.createGenerator(xcs);
56616
56684
  for (let row = target.bottom; row >= target.top; row--) {
56617
- this.computeNewCell(generator, col, row, apply);
56685
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
56618
56686
  }
56619
56687
  }
56620
56688
  break;
@@ -56626,7 +56694,7 @@ class AutofillPlugin extends UIPlugin {
56626
56694
  }
56627
56695
  const generator = this.createGenerator(xcs);
56628
56696
  for (let col = target.right; col >= target.left; col--) {
56629
- this.computeNewCell(generator, col, row, apply);
56697
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
56630
56698
  }
56631
56699
  }
56632
56700
  break;
@@ -56638,12 +56706,26 @@ class AutofillPlugin extends UIPlugin {
56638
56706
  }
56639
56707
  const generator = this.createGenerator(xcs);
56640
56708
  for (let col = target.left; col <= target.right; col++) {
56641
- this.computeNewCell(generator, col, row, apply);
56709
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
56642
56710
  }
56643
56711
  }
56644
56712
  break;
56645
56713
  }
56646
56714
  if (apply) {
56715
+ const bordersZones = {};
56716
+ const cfNewRanges = {};
56717
+ const dvNewZones = {};
56718
+ const sheetId = this.getters.getActiveSheetId();
56719
+ for (const data of autofillCellsData) {
56720
+ this.collectBordersData(data, bordersZones);
56721
+ this.autofillMerge(sheetId, data);
56722
+ this.autofillCell(sheetId, data);
56723
+ this.collectConditionalFormatsData(sheetId, data, cfNewRanges);
56724
+ this.collectDataValidationsData(sheetId, data, dvNewZones);
56725
+ }
56726
+ this.autofillBorders(sheetId, bordersZones);
56727
+ this.autofillConditionalFormats(sheetId, cfNewRanges);
56728
+ this.autofillDataValidations(sheetId, dvNewZones);
56647
56729
  this.autofillZone = undefined;
56648
56730
  this.selection.resizeAnchorZone(this.direction, this.steps);
56649
56731
  this.lastCellSelected = {};
@@ -56652,6 +56734,95 @@ class AutofillPlugin extends UIPlugin {
56652
56734
  this.tooltip = undefined;
56653
56735
  }
56654
56736
  }
56737
+ collectBordersData(data, bordersPositions) {
56738
+ const key = JSON.stringify(data.border);
56739
+ if (!(key in bordersPositions)) {
56740
+ bordersPositions[key] = [];
56741
+ }
56742
+ bordersPositions[key].push(positionToZone({ col: data.col, row: data.row }));
56743
+ }
56744
+ collectConditionalFormatsData(sheetId, data, cfNewRanges) {
56745
+ const { originCol, originRow, col, row } = data;
56746
+ const cfsAtOrigin = this.getters.getRulesByCell(sheetId, originCol, originRow);
56747
+ const xc = toXC(col, row);
56748
+ for (const cf of cfsAtOrigin) {
56749
+ if (!(cf.id in cfNewRanges)) {
56750
+ cfNewRanges[cf.id] = [];
56751
+ }
56752
+ cfNewRanges[cf.id].push(xc);
56753
+ }
56754
+ }
56755
+ collectDataValidationsData(sheetId, data, dvNewZones) {
56756
+ const { originCol, originRow, col, row } = data;
56757
+ const cellPosition = { sheetId, col: originCol, row: originRow };
56758
+ const dvsAtOrigin = this.getters.getValidationRuleForCell(cellPosition);
56759
+ if (!dvsAtOrigin) {
56760
+ return;
56761
+ }
56762
+ if (!(dvsAtOrigin.id in dvNewZones)) {
56763
+ dvNewZones[dvsAtOrigin.id] = [];
56764
+ }
56765
+ dvNewZones[dvsAtOrigin.id].push(positionToZone({ col, row }));
56766
+ }
56767
+ autofillCell(sheetId, data) {
56768
+ this.dispatch("UPDATE_CELL", {
56769
+ sheetId,
56770
+ col: data.col,
56771
+ row: data.row,
56772
+ content: data.content || "",
56773
+ style: data.style || null,
56774
+ format: data.format || "",
56775
+ });
56776
+ // Still usefull in odoo ATM to autofill field sync
56777
+ this.dispatch("AUTOFILL_CELL", data);
56778
+ }
56779
+ autofillBorders(sheetId, bordersPositions) {
56780
+ for (const stringifiedBorder in bordersPositions) {
56781
+ const border = stringifiedBorder === "undefined" ? undefined : JSON.parse(stringifiedBorder);
56782
+ this.dispatch("SET_BORDERS_ON_TARGET", {
56783
+ sheetId,
56784
+ border,
56785
+ target: recomputeZones(bordersPositions[stringifiedBorder]),
56786
+ });
56787
+ }
56788
+ }
56789
+ autofillConditionalFormats(sheetId, cfNewRanges) {
56790
+ for (const cfId in cfNewRanges) {
56791
+ const changes = cfNewRanges[cfId];
56792
+ const cf = this.getters.getConditionalFormats(sheetId).find((cf) => cf.id === cfId);
56793
+ if (!cf) {
56794
+ continue;
56795
+ }
56796
+ const newCfRanges = this.getters.getAdaptedCfRanges(sheetId, cf, changes.map(toZone), []);
56797
+ if (newCfRanges) {
56798
+ this.dispatch("ADD_CONDITIONAL_FORMAT", {
56799
+ cf: {
56800
+ id: cf.id,
56801
+ rule: cf.rule,
56802
+ stopIfTrue: cf.stopIfTrue,
56803
+ },
56804
+ ranges: newCfRanges,
56805
+ sheetId,
56806
+ });
56807
+ }
56808
+ }
56809
+ }
56810
+ autofillDataValidations(sheetId, dvNewZones) {
56811
+ for (const dvId in dvNewZones) {
56812
+ const changes = dvNewZones[dvId];
56813
+ const dvOrigin = this.getters.getDataValidationRule(sheetId, dvId);
56814
+ if (!dvOrigin) {
56815
+ continue;
56816
+ }
56817
+ const dvRangesXcs = dvOrigin.ranges.map((range) => range.zone);
56818
+ const newDvRanges = recomputeZones(dvRangesXcs.concat(changes), []);
56819
+ this.dispatch("ADD_DATA_VALIDATION_RULE", {
56820
+ rule: dvOrigin,
56821
+ ranges: newDvRanges.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
56822
+ sheetId,
56823
+ });
56824
+ }
56825
+ }
56655
56826
  /**
56656
56827
  * Select a cell which becomes the last cell of the autofillZone
56657
56828
  */
@@ -56730,22 +56901,20 @@ class AutofillPlugin extends UIPlugin {
56730
56901
  /**
56731
56902
  * Generate the next cell
56732
56903
  */
56733
- computeNewCell(generator, col, row, apply) {
56904
+ computeNewCell(generator, col, row) {
56734
56905
  const { cellData, tooltip, origin } = generator.next();
56735
56906
  const { content, style, border, format } = cellData;
56736
56907
  this.tooltip = tooltip;
56737
- if (apply) {
56738
- this.dispatch("AUTOFILL_CELL", {
56739
- originCol: origin.col,
56740
- originRow: origin.row,
56741
- col,
56742
- row,
56743
- content,
56744
- style,
56745
- border,
56746
- format,
56747
- });
56748
- }
56908
+ return {
56909
+ originCol: origin.col,
56910
+ originRow: origin.row,
56911
+ col,
56912
+ row,
56913
+ content,
56914
+ style,
56915
+ border,
56916
+ format,
56917
+ };
56749
56918
  }
56750
56919
  /**
56751
56920
  * Get the rule associated to the current cell
@@ -56813,8 +56982,8 @@ class AutofillPlugin extends UIPlugin {
56813
56982
  ? position[first].value
56814
56983
  : position[second].value;
56815
56984
  }
56816
- autoFillMerge(originCol, originRow, col, row) {
56817
- const sheetId = this.getters.getActiveSheetId();
56985
+ autofillMerge(sheetId, data) {
56986
+ const { originCol, originRow, col, row } = data;
56818
56987
  const position = { sheetId, col, row };
56819
56988
  const originPosition = { sheetId, col: originCol, row: originRow };
56820
56989
  if (this.getters.isInMerge(position) && !this.getters.isInMerge(originPosition)) {
@@ -56841,35 +57010,6 @@ class AutofillPlugin extends UIPlugin {
56841
57010
  });
56842
57011
  }
56843
57012
  }
56844
- autofillCF(originCol, originRow, col, row) {
56845
- const sheetId = this.getters.getActiveSheetId();
56846
- const cfOrigin = this.getters.getRulesByCell(sheetId, originCol, originRow);
56847
- for (const cf of cfOrigin) {
56848
- const newCfRanges = this.getters.getAdaptedCfRanges(sheetId, cf, [positionToZone({ col, row })], []);
56849
- if (newCfRanges) {
56850
- this.dispatch("ADD_CONDITIONAL_FORMAT", {
56851
- cf: deepCopy(cf),
56852
- ranges: newCfRanges,
56853
- sheetId,
56854
- });
56855
- }
56856
- }
56857
- }
56858
- autofillDV(originCol, originRow, col, row) {
56859
- const sheetId = this.getters.getActiveSheetId();
56860
- const cellPosition = { sheetId, col: originCol, row: originRow };
56861
- const dvOrigin = this.getters.getValidationRuleForCell(cellPosition);
56862
- if (!dvOrigin) {
56863
- return;
56864
- }
56865
- const dvRangesZones = dvOrigin.ranges.map((range) => range.zone);
56866
- const newDvRanges = recomputeZones(dvRangesZones.concat(positionToZone({ col, row })), []);
56867
- this.dispatch("ADD_DATA_VALIDATION_RULE", {
56868
- rule: dvOrigin,
56869
- ranges: newDvRanges.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
56870
- sheetId,
56871
- });
56872
- }
56873
57013
  // ---------------------------------------------------------------------------
56874
57014
  // Grid rendering
56875
57015
  // ---------------------------------------------------------------------------
@@ -57249,10 +57389,8 @@ function mergeTransformation(toTransform, executed) {
57249
57389
  }
57250
57390
  const target = [];
57251
57391
  for (const zone1 of toTransform.target) {
57252
- for (const zone2 of executed.target) {
57253
- if (!overlap(zone1, zone2)) {
57254
- target.push({ ...zone1 });
57255
- }
57392
+ if (executed.target.every((zone2) => !overlap(zone1, zone2))) {
57393
+ target.push(zone1);
57256
57394
  }
57257
57395
  }
57258
57396
  if (target.length) {
@@ -69198,6 +69336,6 @@ const constants = {
69198
69336
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
69199
69337
 
69200
69338
 
69201
- __info__.version = "17.4.29";
69202
- __info__.date = "2025-04-04T08:40:34.590Z";
69203
- __info__.hash = "2937d99";
69339
+ __info__.version = "17.4.31";
69340
+ __info__.date = "2025-04-18T16:24:47.716Z";
69341
+ __info__.hash = "7991032";