@odoo/o-spreadsheet 18.2.6 → 18.2.8

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.2.6
6
- * @date 2025-04-04T08:41:26.115Z
7
- * @hash faa00e2
5
+ * @version 18.2.8
6
+ * @date 2025-04-18T16:26:20.673Z
7
+ * @hash 5da9ddc
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -3574,6 +3574,7 @@
3574
3574
  "CLEAR_FORMATTING",
3575
3575
  "SET_BORDER",
3576
3576
  "SET_ZONE_BORDERS",
3577
+ "SET_BORDERS_ON_TARGET",
3577
3578
  /** CHART */
3578
3579
  "CREATE_CHART",
3579
3580
  "UPDATE_CHART",
@@ -6723,6 +6724,7 @@
6723
6724
  }
6724
6725
 
6725
6726
  class BorderClipboardHandler extends AbstractCellClipboardHandler {
6727
+ queuedBordersToAdd = {};
6726
6728
  copy(data) {
6727
6729
  const sheetId = data.sheetId;
6728
6730
  if (data.zones.length === 0) {
@@ -6753,6 +6755,7 @@
6753
6755
  const { left, top } = zones[0];
6754
6756
  this.pasteZone(sheetId, left, top, content.borders);
6755
6757
  }
6758
+ this.executeQueuedChanges(sheetId);
6756
6759
  }
6757
6760
  pasteZone(sheetId, col, row, borders) {
6758
6761
  for (const [r, rowBorders] of borders.entries()) {
@@ -6771,7 +6774,20 @@
6771
6774
  ...targetBorders,
6772
6775
  ...originBorders,
6773
6776
  };
6774
- this.dispatch("SET_BORDER", { ...target, border });
6777
+ const borderKey = JSON.stringify(border);
6778
+ if (!this.queuedBordersToAdd[borderKey]) {
6779
+ this.queuedBordersToAdd[borderKey] = [];
6780
+ }
6781
+ this.queuedBordersToAdd[borderKey].push(positionToZone(target));
6782
+ }
6783
+ executeQueuedChanges(pasteSheetTarget) {
6784
+ for (const borderKey in this.queuedBordersToAdd) {
6785
+ const zones = this.queuedBordersToAdd[borderKey];
6786
+ const border = JSON.parse(borderKey);
6787
+ const target = recomputeZones(zones, []);
6788
+ this.dispatch("SET_BORDERS_ON_TARGET", { sheetId: pasteSheetTarget, target, border });
6789
+ }
6790
+ this.queuedBordersToAdd = {};
6775
6791
  }
6776
6792
  }
6777
6793
 
@@ -6883,6 +6899,12 @@
6883
6899
  }
6884
6900
  return null;
6885
6901
  }
6902
+ /**
6903
+ - \p{L} is for any letter (from any language)
6904
+ - \p{N} is for any number
6905
+ - the u flag at the end is for unicode, which enables the `\p{...}` syntax
6906
+ */
6907
+ const unicodeSymbolCharRegexp = /\p{L}|\p{N}|_|\.|!|\$/u;
6886
6908
  const SYMBOL_CHARS = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.!$");
6887
6909
  /**
6888
6910
  * A "Symbol" is just basically any word-like element that can appear in a
@@ -6923,7 +6945,8 @@
6923
6945
  };
6924
6946
  }
6925
6947
  }
6926
- while (chars.current && SYMBOL_CHARS.has(chars.current)) {
6948
+ while (chars.current &&
6949
+ (SYMBOL_CHARS.has(chars.current) || chars.current.match(unicodeSymbolCharRegexp))) {
6927
6950
  result += chars.shift();
6928
6951
  }
6929
6952
  if (result.length) {
@@ -8711,12 +8734,13 @@
8711
8734
  }
8712
8735
  pasteCf(origin, target, isCutOperation) {
8713
8736
  if (origin?.rules && origin.rules.length > 0) {
8737
+ const originZone = positionToZone(origin.position);
8714
8738
  const zone = positionToZone(target);
8715
8739
  for (const rule of origin.rules) {
8716
8740
  const toRemoveZones = [];
8717
8741
  if (isCutOperation) {
8718
8742
  //remove from current rule
8719
- toRemoveZones.push(positionToZone(origin.position));
8743
+ toRemoveZones.push(originZone);
8720
8744
  }
8721
8745
  if (origin.position.sheetId === target.sheetId) {
8722
8746
  this.adaptCFRules(origin.position.sheetId, rule, [zone], toRemoveZones);
@@ -8830,6 +8854,7 @@
8830
8854
  pasteDataValidation(origin, target, isCutOperation) {
8831
8855
  if (origin) {
8832
8856
  const zone = positionToZone(target);
8857
+ const originZone = positionToZone(origin.position);
8833
8858
  const rule = origin.rule;
8834
8859
  if (!rule) {
8835
8860
  const targetRule = this.getters.getValidationRuleForCell(target);
@@ -8841,7 +8866,7 @@
8841
8866
  }
8842
8867
  const toRemoveZone = [];
8843
8868
  if (isCutOperation) {
8844
- toRemoveZone.push(positionToZone(origin.position));
8869
+ toRemoveZone.push(originZone);
8845
8870
  }
8846
8871
  if (origin.position.sheetId === target.sheetId) {
8847
8872
  const copyToRule = this.getDataValidationRuleToCopyTo(target.sheetId, rule, false);
@@ -8901,7 +8926,7 @@
8901
8926
  continue;
8902
8927
  }
8903
8928
  this.dispatch("ADD_DATA_VALIDATION_RULE", {
8904
- rule: dv,
8929
+ rule: { id: dv.id, criterion: dv.criterion, isBlocking: dv.isBlocking },
8905
8930
  ranges: newDvZones.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
8906
8931
  sheetId,
8907
8932
  });
@@ -9228,7 +9253,7 @@
9228
9253
  if (executed.type === "ADD_COLUMNS_ROWS") {
9229
9254
  return expandZoneOnInsertion(zone, executed.dimension === "COL" ? "left" : "top", executed.base, executed.position, executed.quantity);
9230
9255
  }
9231
- return { ...zone };
9256
+ return zone;
9232
9257
  }
9233
9258
  function transformRangeData(range, executed) {
9234
9259
  const deletedSheet = executed.type === "DELETE_SHEET" && executed.sheetId;
@@ -33619,6 +33644,12 @@ stores.inject(MyMetaStore, storeInstance);
33619
33644
  function isCtrlKey(ev) {
33620
33645
  return isMacOS() ? ev.metaKey : ev.ctrlKey;
33621
33646
  }
33647
+ /**
33648
+ * Detects if the current browser is Firefox
33649
+ */
33650
+ function isBrowserFirefox() {
33651
+ return /Firefox/i.test(navigator.userAgent);
33652
+ }
33622
33653
 
33623
33654
  /**
33624
33655
  * Repeatedly calls a callback function with a time delay between calls.
@@ -50414,39 +50445,6 @@ stores.inject(MyMetaStore, storeInstance);
50414
50445
  }
50415
50446
  return hoveredPosition;
50416
50447
  }
50417
- function useTouchMove(gridRef, handler, canMoveUp) {
50418
- let x = null;
50419
- let y = null;
50420
- function onTouchStart(ev) {
50421
- if (ev.touches.length !== 1)
50422
- return;
50423
- x = ev.touches[0].clientX;
50424
- y = ev.touches[0].clientY;
50425
- }
50426
- function onTouchEnd() {
50427
- x = null;
50428
- y = null;
50429
- }
50430
- function onTouchMove(ev) {
50431
- if (ev.touches.length !== 1)
50432
- return;
50433
- // On mobile browsers, swiping down is often associated with "pull to refresh".
50434
- // We only want this behavior if the grid is already at the top.
50435
- // Otherwise we only want to move the canvas up, without triggering any refresh.
50436
- if (canMoveUp()) {
50437
- ev.preventDefault();
50438
- ev.stopPropagation();
50439
- }
50440
- const currentX = ev.touches[0].clientX;
50441
- const currentY = ev.touches[0].clientY;
50442
- handler(x - currentX, y - currentY);
50443
- x = currentX;
50444
- y = currentY;
50445
- }
50446
- useRefListener(gridRef, "touchstart", onTouchStart);
50447
- useRefListener(gridRef, "touchend", onTouchEnd);
50448
- useRefListener(gridRef, "touchmove", onTouchMove);
50449
- }
50450
50448
  class GridOverlay extends owl.Component {
50451
50449
  static template = "o-spreadsheet-GridOverlay";
50452
50450
  static props = {
@@ -50494,10 +50492,6 @@ stores.inject(MyMetaStore, storeInstance);
50494
50492
  owl.onWillUnmount(() => {
50495
50493
  resizeObserver.disconnect();
50496
50494
  });
50497
- useTouchMove(this.gridOverlay, this.props.onGridMoved, () => {
50498
- const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
50499
- return scrollY > 0;
50500
- });
50501
50495
  this.cellPopovers = useStore(CellPopoverStore);
50502
50496
  this.paintFormatStore = useStore(PaintFormatStore);
50503
50497
  }
@@ -51969,6 +51963,73 @@ stores.inject(MyMetaStore, storeInstance);
51969
51963
  }
51970
51964
  }
51971
51965
 
51966
+ const friction = 0.95;
51967
+ const verticalScrollFactor = 1;
51968
+ const horizontalScrollFactor = 1;
51969
+ function useTouchScroll(ref, updateScroll, canMoveUp) {
51970
+ let lastX = 0;
51971
+ let lastY = 0;
51972
+ let velocityX = 0;
51973
+ let velocityY = 0;
51974
+ let isMouseDown = false;
51975
+ let lastTime = 0;
51976
+ useRefListener(ref, "touchstart", onTouchStart, { capture: false });
51977
+ useRefListener(ref, "touchmove", onTouchMove, { capture: false });
51978
+ useRefListener(ref, "touchend", onTouchEnd, { capture: false });
51979
+ function onTouchStart(event) {
51980
+ isMouseDown = true;
51981
+ ({ clientX: lastX, clientY: lastY } = event.touches[0]);
51982
+ velocityX = 0;
51983
+ velocityY = 0;
51984
+ }
51985
+ function onTouchMove(event) {
51986
+ if (!isMouseDown)
51987
+ return;
51988
+ const currentTime = Date.now();
51989
+ const { clientX, clientY } = event.touches[0];
51990
+ let deltaX = lastX - clientX;
51991
+ let deltaY = lastY - clientY;
51992
+ const elapsedTime = currentTime - lastTime;
51993
+ velocityX = deltaX / elapsedTime;
51994
+ velocityY = deltaY / elapsedTime;
51995
+ lastX = clientX;
51996
+ lastY = clientY;
51997
+ lastTime = currentTime;
51998
+ if (canMoveUp()) {
51999
+ if (event.cancelable) {
52000
+ event.preventDefault();
52001
+ }
52002
+ event.stopPropagation();
52003
+ }
52004
+ updateScroll(deltaX * horizontalScrollFactor, deltaY * verticalScrollFactor);
52005
+ }
52006
+ function onTouchEnd(ev) {
52007
+ isMouseDown = false;
52008
+ lastX = lastY = 0;
52009
+ requestAnimationFrame(scroll);
52010
+ }
52011
+ function scroll() {
52012
+ if (Math.abs(velocityX) < 0.05) {
52013
+ velocityX = 0;
52014
+ }
52015
+ if (Math.abs(velocityY) < 0.05) {
52016
+ velocityY = 0;
52017
+ }
52018
+ if (!velocityX && !velocityY) {
52019
+ return;
52020
+ }
52021
+ const currentTime = Date.now();
52022
+ const elapsedTime = Math.abs(currentTime - lastTime);
52023
+ const deltaX = velocityX * elapsedTime;
52024
+ const deltaY = velocityY * elapsedTime;
52025
+ updateScroll(deltaX * horizontalScrollFactor, deltaY * verticalScrollFactor);
52026
+ lastTime = currentTime;
52027
+ velocityX *= friction;
52028
+ velocityY *= friction;
52029
+ requestAnimationFrame(scroll);
52030
+ }
52031
+ }
52032
+
51972
52033
  function useWheelHandler(handler) {
51973
52034
  function normalize(val, deltaMode) {
51974
52035
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
@@ -52309,7 +52370,7 @@ stores.inject(MyMetaStore, storeInstance);
52309
52370
  left: `${this.props.leftOffset + x}px`,
52310
52371
  bottom: "0px",
52311
52372
  height: `${SCROLLBAR_WIDTH}px`,
52312
- right: `0px`,
52373
+ right: isBrowserFirefox() ? `${SCROLLBAR_WIDTH}px` : "0",
52313
52374
  };
52314
52375
  }
52315
52376
  onScroll(offset) {
@@ -52354,7 +52415,7 @@ stores.inject(MyMetaStore, storeInstance);
52354
52415
  top: `${this.props.topOffset + y}px`,
52355
52416
  right: "0px",
52356
52417
  width: `${SCROLLBAR_WIDTH}px`,
52357
- bottom: `0px`,
52418
+ bottom: isBrowserFirefox() ? `${SCROLLBAR_WIDTH}px` : "0",
52358
52419
  };
52359
52420
  }
52360
52421
  onScroll(offset) {
@@ -52590,6 +52651,10 @@ stores.inject(MyMetaStore, storeInstance);
52590
52651
  this.DOMFocusableElementStore.focusableElement?.focus();
52591
52652
  }
52592
52653
  }, () => [this.sidePanel.isOpen]);
52654
+ useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
52655
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
52656
+ return scrollY > 0;
52657
+ });
52593
52658
  }
52594
52659
  onCellHovered({ col, row }) {
52595
52660
  this.hoveredCell.hover({ col, row });
@@ -53312,6 +53377,15 @@ stores.inject(MyMetaStore, storeInstance);
53312
53377
  case "SET_BORDER":
53313
53378
  this.setBorder(cmd.sheetId, cmd.col, cmd.row, cmd.border);
53314
53379
  break;
53380
+ case "SET_BORDERS_ON_TARGET":
53381
+ for (const zone of cmd.target) {
53382
+ for (let row = zone.top; row <= zone.bottom; row++) {
53383
+ for (let col = zone.left; col <= zone.right; col++) {
53384
+ this.setBorder(cmd.sheetId, col, row, cmd.border);
53385
+ }
53386
+ }
53387
+ }
53388
+ break;
53315
53389
  case "SET_ZONE_BORDERS":
53316
53390
  if (cmd.border) {
53317
53391
  const target = cmd.target.map((zone) => this.getters.expandZone(cmd.sheetId, zone));
@@ -63074,25 +63148,6 @@ stores.inject(MyMetaStore, storeInstance);
63074
63148
  case "AUTOFILL_AUTO":
63075
63149
  this.autofillAuto();
63076
63150
  break;
63077
- case "AUTOFILL_CELL":
63078
- this.autoFillMerge(cmd.originCol, cmd.originRow, cmd.col, cmd.row);
63079
- const sheetId = this.getters.getActiveSheetId();
63080
- this.dispatch("UPDATE_CELL", {
63081
- sheetId,
63082
- col: cmd.col,
63083
- row: cmd.row,
63084
- style: cmd.style || null,
63085
- content: cmd.content || "",
63086
- format: cmd.format || "",
63087
- });
63088
- this.dispatch("SET_BORDER", {
63089
- sheetId,
63090
- col: cmd.col,
63091
- row: cmd.row,
63092
- border: cmd.border,
63093
- });
63094
- this.autofillCF(cmd.originCol, cmd.originRow, cmd.col, cmd.row);
63095
- this.autofillDV(cmd.originCol, cmd.originRow, cmd.col, cmd.row);
63096
63151
  }
63097
63152
  }
63098
63153
  // ---------------------------------------------------------------------------
@@ -63116,6 +63171,7 @@ stores.inject(MyMetaStore, storeInstance);
63116
63171
  }
63117
63172
  const source = this.getters.getSelectedZone();
63118
63173
  const target = this.autofillZone;
63174
+ const autofillCellsData = [];
63119
63175
  switch (this.direction) {
63120
63176
  case "down" /* DIRECTION.DOWN */:
63121
63177
  for (let col = source.left; col <= source.right; col++) {
@@ -63125,7 +63181,7 @@ stores.inject(MyMetaStore, storeInstance);
63125
63181
  }
63126
63182
  const generator = this.createGenerator(xcs);
63127
63183
  for (let row = target.top; row <= target.bottom; row++) {
63128
- this.computeNewCell(generator, col, row, apply);
63184
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
63129
63185
  }
63130
63186
  }
63131
63187
  break;
@@ -63137,7 +63193,7 @@ stores.inject(MyMetaStore, storeInstance);
63137
63193
  }
63138
63194
  const generator = this.createGenerator(xcs);
63139
63195
  for (let row = target.bottom; row >= target.top; row--) {
63140
- this.computeNewCell(generator, col, row, apply);
63196
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
63141
63197
  }
63142
63198
  }
63143
63199
  break;
@@ -63149,7 +63205,7 @@ stores.inject(MyMetaStore, storeInstance);
63149
63205
  }
63150
63206
  const generator = this.createGenerator(xcs);
63151
63207
  for (let col = target.right; col >= target.left; col--) {
63152
- this.computeNewCell(generator, col, row, apply);
63208
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
63153
63209
  }
63154
63210
  }
63155
63211
  break;
@@ -63161,12 +63217,26 @@ stores.inject(MyMetaStore, storeInstance);
63161
63217
  }
63162
63218
  const generator = this.createGenerator(xcs);
63163
63219
  for (let col = target.left; col <= target.right; col++) {
63164
- this.computeNewCell(generator, col, row, apply);
63220
+ autofillCellsData.push(this.computeNewCell(generator, col, row));
63165
63221
  }
63166
63222
  }
63167
63223
  break;
63168
63224
  }
63169
63225
  if (apply) {
63226
+ const bordersZones = {};
63227
+ const cfNewRanges = {};
63228
+ const dvNewZones = {};
63229
+ const sheetId = this.getters.getActiveSheetId();
63230
+ for (const data of autofillCellsData) {
63231
+ this.collectBordersData(data, bordersZones);
63232
+ this.autofillMerge(sheetId, data);
63233
+ this.autofillCell(sheetId, data);
63234
+ this.collectConditionalFormatsData(sheetId, data, cfNewRanges);
63235
+ this.collectDataValidationsData(sheetId, data, dvNewZones);
63236
+ }
63237
+ this.autofillBorders(sheetId, bordersZones);
63238
+ this.autofillConditionalFormats(sheetId, cfNewRanges);
63239
+ this.autofillDataValidations(sheetId, dvNewZones);
63170
63240
  this.autofillZone = undefined;
63171
63241
  this.selection.resizeAnchorZone(this.direction, this.steps);
63172
63242
  this.lastCellSelected = {};
@@ -63175,6 +63245,95 @@ stores.inject(MyMetaStore, storeInstance);
63175
63245
  this.tooltip = undefined;
63176
63246
  }
63177
63247
  }
63248
+ collectBordersData(data, bordersPositions) {
63249
+ const key = JSON.stringify(data.border);
63250
+ if (!(key in bordersPositions)) {
63251
+ bordersPositions[key] = [];
63252
+ }
63253
+ bordersPositions[key].push(positionToZone({ col: data.col, row: data.row }));
63254
+ }
63255
+ collectConditionalFormatsData(sheetId, data, cfNewRanges) {
63256
+ const { originCol, originRow, col, row } = data;
63257
+ const cfsAtOrigin = this.getters.getRulesByCell(sheetId, originCol, originRow);
63258
+ const xc = toXC(col, row);
63259
+ for (const cf of cfsAtOrigin) {
63260
+ if (!(cf.id in cfNewRanges)) {
63261
+ cfNewRanges[cf.id] = [];
63262
+ }
63263
+ cfNewRanges[cf.id].push(xc);
63264
+ }
63265
+ }
63266
+ collectDataValidationsData(sheetId, data, dvNewZones) {
63267
+ const { originCol, originRow, col, row } = data;
63268
+ const cellPosition = { sheetId, col: originCol, row: originRow };
63269
+ const dvsAtOrigin = this.getters.getValidationRuleForCell(cellPosition);
63270
+ if (!dvsAtOrigin) {
63271
+ return;
63272
+ }
63273
+ if (!(dvsAtOrigin.id in dvNewZones)) {
63274
+ dvNewZones[dvsAtOrigin.id] = [];
63275
+ }
63276
+ dvNewZones[dvsAtOrigin.id].push(positionToZone({ col, row }));
63277
+ }
63278
+ autofillCell(sheetId, data) {
63279
+ this.dispatch("UPDATE_CELL", {
63280
+ sheetId,
63281
+ col: data.col,
63282
+ row: data.row,
63283
+ content: data.content || "",
63284
+ style: data.style || null,
63285
+ format: data.format || "",
63286
+ });
63287
+ // Still usefull in odoo ATM to autofill field sync
63288
+ this.dispatch("AUTOFILL_CELL", data);
63289
+ }
63290
+ autofillBorders(sheetId, bordersPositions) {
63291
+ for (const stringifiedBorder in bordersPositions) {
63292
+ const border = stringifiedBorder === "undefined" ? undefined : JSON.parse(stringifiedBorder);
63293
+ this.dispatch("SET_BORDERS_ON_TARGET", {
63294
+ sheetId,
63295
+ border,
63296
+ target: recomputeZones(bordersPositions[stringifiedBorder]),
63297
+ });
63298
+ }
63299
+ }
63300
+ autofillConditionalFormats(sheetId, cfNewRanges) {
63301
+ for (const cfId in cfNewRanges) {
63302
+ const changes = cfNewRanges[cfId];
63303
+ const cf = this.getters.getConditionalFormats(sheetId).find((cf) => cf.id === cfId);
63304
+ if (!cf) {
63305
+ continue;
63306
+ }
63307
+ const newCfRanges = this.getters.getAdaptedCfRanges(sheetId, cf, changes.map(toZone), []);
63308
+ if (newCfRanges) {
63309
+ this.dispatch("ADD_CONDITIONAL_FORMAT", {
63310
+ cf: {
63311
+ id: cf.id,
63312
+ rule: cf.rule,
63313
+ stopIfTrue: cf.stopIfTrue,
63314
+ },
63315
+ ranges: newCfRanges,
63316
+ sheetId,
63317
+ });
63318
+ }
63319
+ }
63320
+ }
63321
+ autofillDataValidations(sheetId, dvNewZones) {
63322
+ for (const dvId in dvNewZones) {
63323
+ const changes = dvNewZones[dvId];
63324
+ const dvOrigin = this.getters.getDataValidationRule(sheetId, dvId);
63325
+ if (!dvOrigin) {
63326
+ continue;
63327
+ }
63328
+ const dvRangesXcs = dvOrigin.ranges.map((range) => range.zone);
63329
+ const newDvRanges = recomputeZones(dvRangesXcs.concat(changes), []);
63330
+ this.dispatch("ADD_DATA_VALIDATION_RULE", {
63331
+ rule: dvOrigin,
63332
+ ranges: newDvRanges.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
63333
+ sheetId,
63334
+ });
63335
+ }
63336
+ }
63178
63337
  /**
63179
63338
  * Select a cell which becomes the last cell of the autofillZone
63180
63339
  */
@@ -63253,22 +63412,20 @@ stores.inject(MyMetaStore, storeInstance);
63253
63412
  /**
63254
63413
  * Generate the next cell
63255
63414
  */
63256
- computeNewCell(generator, col, row, apply) {
63415
+ computeNewCell(generator, col, row) {
63257
63416
  const { cellData, tooltip, origin } = generator.next();
63258
63417
  const { content, style, border, format } = cellData;
63259
63418
  this.tooltip = tooltip;
63260
- if (apply) {
63261
- this.dispatch("AUTOFILL_CELL", {
63262
- originCol: origin.col,
63263
- originRow: origin.row,
63264
- col,
63265
- row,
63266
- content,
63267
- style,
63268
- border,
63269
- format,
63270
- });
63271
- }
63419
+ return {
63420
+ originCol: origin.col,
63421
+ originRow: origin.row,
63422
+ col,
63423
+ row,
63424
+ content,
63425
+ style,
63426
+ border,
63427
+ format,
63428
+ };
63272
63429
  }
63273
63430
  /**
63274
63431
  * Get the rule associated to the current cell
@@ -63336,8 +63493,8 @@ stores.inject(MyMetaStore, storeInstance);
63336
63493
  ? position[first].value
63337
63494
  : position[second].value;
63338
63495
  }
63339
- autoFillMerge(originCol, originRow, col, row) {
63340
- const sheetId = this.getters.getActiveSheetId();
63496
+ autofillMerge(sheetId, data) {
63497
+ const { originCol, originRow, col, row } = data;
63341
63498
  const position = { sheetId, col, row };
63342
63499
  const originPosition = { sheetId, col: originCol, row: originRow };
63343
63500
  if (this.getters.isInMerge(position) && !this.getters.isInMerge(originPosition)) {
@@ -63364,35 +63521,6 @@ stores.inject(MyMetaStore, storeInstance);
63364
63521
  });
63365
63522
  }
63366
63523
  }
63367
- autofillCF(originCol, originRow, col, row) {
63368
- const sheetId = this.getters.getActiveSheetId();
63369
- const cfOrigin = this.getters.getRulesByCell(sheetId, originCol, originRow);
63370
- for (const cf of cfOrigin) {
63371
- const newCfRanges = this.getters.getAdaptedCfRanges(sheetId, cf, [positionToZone({ col, row })], []);
63372
- if (newCfRanges) {
63373
- this.dispatch("ADD_CONDITIONAL_FORMAT", {
63374
- cf: deepCopy(cf),
63375
- ranges: newCfRanges,
63376
- sheetId,
63377
- });
63378
- }
63379
- }
63380
- }
63381
- autofillDV(originCol, originRow, col, row) {
63382
- const sheetId = this.getters.getActiveSheetId();
63383
- const cellPosition = { sheetId, col: originCol, row: originRow };
63384
- const dvOrigin = this.getters.getValidationRuleForCell(cellPosition);
63385
- if (!dvOrigin) {
63386
- return;
63387
- }
63388
- const dvRangesZones = dvOrigin.ranges.map((range) => range.zone);
63389
- const newDvRanges = recomputeZones(dvRangesZones.concat(positionToZone({ col, row })), []);
63390
- this.dispatch("ADD_DATA_VALIDATION_RULE", {
63391
- rule: dvOrigin,
63392
- ranges: newDvRanges.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
63393
- sheetId,
63394
- });
63395
- }
63396
63524
  // ---------------------------------------------------------------------------
63397
63525
  // Grid rendering
63398
63526
  // ---------------------------------------------------------------------------
@@ -63772,10 +63900,8 @@ stores.inject(MyMetaStore, storeInstance);
63772
63900
  }
63773
63901
  const target = [];
63774
63902
  for (const zone1 of toTransform.target) {
63775
- for (const zone2 of executed.target) {
63776
- if (!overlap(zone1, zone2)) {
63777
- target.push({ ...zone1 });
63778
- }
63903
+ if (executed.target.every((zone2) => !overlap(zone1, zone2))) {
63904
+ target.push(zone1);
63779
63905
  }
63780
63906
  }
63781
63907
  if (target.length) {
@@ -67907,24 +68033,14 @@ stores.inject(MyMetaStore, storeInstance);
67907
68033
  first: this.boundaries.top,
67908
68034
  last: this.boundaries.bottom,
67909
68035
  });
67910
- const { end: lastColEnd, size: lastColSize } = this.getters.getColDimensions(this.sheetId, lastCol);
67911
- const { end: lastRowEnd, size: lastRowSize } = this.getters.getRowDimensions(this.sheetId, lastRow);
67912
- const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.viewportWidth, 0);
67913
- const leftColSize = this.getters.getColSize(this.sheetId, leftColIndex);
67914
- const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.viewportHeight, 0);
67915
- const topRowSize = this.getters.getRowSize(this.sheetId, leftRowIndex);
68036
+ const { end: lastColEnd } = this.getters.getColDimensions(this.sheetId, lastCol);
68037
+ const { end: lastRowEnd } = this.getters.getRowDimensions(this.sheetId, lastRow);
67916
68038
  let width = lastColEnd - this.offsetCorrectionX;
67917
68039
  if (this.canScrollHorizontally) {
67918
- width += Math.max(DEFAULT_CELL_WIDTH, // leave some minimal space to let the user know they scrolled all the way
67919
- Math.min(leftColSize, this.viewportWidth - lastColSize) // Add pixels that allows the snapping at maximum horizontal scroll
67920
- );
67921
68040
  width = Math.max(width, this.viewportWidth); // if the viewport grid size is smaller than its client width, return client width
67922
68041
  }
67923
68042
  let height = lastRowEnd - this.offsetCorrectionY;
67924
68043
  if (this.canScrollVertically) {
67925
- height += Math.max(DEFAULT_CELL_HEIGHT + 5, // leave some space to let the user know they scrolled all the way
67926
- Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
67927
- );
67928
68044
  height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
67929
68045
  if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
67930
68046
  height += FOOTER_HEIGHT;
@@ -68489,8 +68605,8 @@ stores.inject(MyMetaStore, storeInstance);
68489
68605
  const { width, height } = this.getMainViewportRect();
68490
68606
  const viewport = this.getMainInternalViewport(sheetId);
68491
68607
  return {
68492
- maxOffsetX: Math.max(0, width - viewport.viewportWidth + 1),
68493
- maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
68608
+ maxOffsetX: Math.max(0, width - viewport.viewportWidth),
68609
+ maxOffsetY: Math.max(0, height - viewport.viewportHeight),
68494
68610
  };
68495
68611
  }
68496
68612
  getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
@@ -70012,6 +70128,10 @@ stores.inject(MyMetaStore, storeInstance);
70012
70128
  this.hoveredCell.clear();
70013
70129
  });
70014
70130
  this.cellPopovers = useStore(CellPopoverStore);
70131
+ useTouchScroll(gridRef, this.moveCanvas.bind(this), () => {
70132
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
70133
+ return scrollY > 0;
70134
+ });
70015
70135
  }
70016
70136
  onCellHovered({ col, row }) {
70017
70137
  this.hoveredCell.hover({ col, row });
@@ -71402,6 +71522,7 @@ stores.inject(MyMetaStore, storeInstance);
71402
71522
  > canvas {
71403
71523
  box-sizing: content-box;
71404
71524
  border-bottom: 1px solid #e2e3e3;
71525
+ border-right: 1px solid #e2e3e3;
71405
71526
  }
71406
71527
 
71407
71528
  .o-grid-overlay {
@@ -76108,9 +76229,9 @@ stores.inject(MyMetaStore, storeInstance);
76108
76229
  exports.tokenize = tokenize;
76109
76230
 
76110
76231
 
76111
- __info__.version = "18.2.6";
76112
- __info__.date = "2025-04-04T08:41:26.115Z";
76113
- __info__.hash = "faa00e2";
76232
+ __info__.version = "18.2.8";
76233
+ __info__.date = "2025-04-18T16:26:20.673Z";
76234
+ __info__.hash = "5da9ddc";
76114
76235
 
76115
76236
 
76116
76237
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);