@odoo/o-spreadsheet 17.2.7 → 17.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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.7
7
- * @date 2024-05-15T09:20:44.429Z
8
- * @hash 57e89fa
6
+ * @version 17.2.8
7
+ * @date 2024-05-24T11:29:49.320Z
8
+ * @hash bfbcaa0
9
9
  */
10
10
 
11
11
  'use strict';
@@ -504,6 +504,26 @@ function debounce(func, wait, immediate) {
504
504
  };
505
505
  return debounced;
506
506
  }
507
+ /**
508
+ * Creates a batched version of a callback so that all calls to it in the same
509
+ * microtick will only call the original callback once.
510
+ *
511
+ * @param callback the callback to batch
512
+ * @returns a batched version of the original callback
513
+ *
514
+ * Copied from odoo/owl repo.
515
+ */
516
+ function batched(callback) {
517
+ let scheduled = false;
518
+ return async (...args) => {
519
+ if (!scheduled) {
520
+ scheduled = true;
521
+ await Promise.resolve();
522
+ scheduled = false;
523
+ callback(...args);
524
+ }
525
+ };
526
+ }
507
527
  /*
508
528
  * Concatenate an array of strings.
509
529
  */
@@ -578,8 +598,9 @@ function deepEquals(o1, o2, ignoreFunctions) {
578
598
  return false;
579
599
  }
580
600
  else {
581
- if (ignoreFunctions && typeOfO1Key === "function")
582
- return true;
601
+ if (ignoreFunctions && typeOfO1Key === "function") {
602
+ continue;
603
+ }
583
604
  if (o1[key] !== o2[key])
584
605
  return false;
585
606
  }
@@ -1830,7 +1851,7 @@ class LazyTranslatedString extends String {
1830
1851
  }
1831
1852
  valueOf() {
1832
1853
  const str = super.valueOf();
1833
- return _loaded() ? sprintf(_translate(str), ...this.values) : str;
1854
+ return _loaded() ? sprintf(_translate(str), ...this.values) : sprintf(str, ...this.values);
1834
1855
  }
1835
1856
  toString() {
1836
1857
  return this.valueOf();
@@ -8014,10 +8035,66 @@ function getDateCriterionFormattedValues(criterion, getters) {
8014
8035
  });
8015
8036
  }
8016
8037
 
8038
+ /**
8039
+ * This is a generic event bus based on the Owl event bus.
8040
+ * This bus however ensures type safety across events and subscription callbacks.
8041
+ */
8042
+ class EventBus {
8043
+ subscriptions = {};
8044
+ /**
8045
+ * Add a listener for the 'eventType' events.
8046
+ *
8047
+ * Note that the 'owner' of this event can be anything, but will more likely
8048
+ * be a component or a class. The idea is that the callback will be called with
8049
+ * the proper owner bound.
8050
+ *
8051
+ * Also, the owner should be kind of unique. This will be used to remove the
8052
+ * listener.
8053
+ */
8054
+ on(type, owner, callback) {
8055
+ if (!callback) {
8056
+ throw new Error("Missing callback");
8057
+ }
8058
+ if (!this.subscriptions[type]) {
8059
+ this.subscriptions[type] = [];
8060
+ }
8061
+ this.subscriptions[type].push({
8062
+ owner,
8063
+ callback,
8064
+ });
8065
+ }
8066
+ /**
8067
+ * Emit an event of type 'eventType'. Any extra arguments will be passed to
8068
+ * the listeners callback.
8069
+ */
8070
+ trigger(type, payload) {
8071
+ const subs = this.subscriptions[type] || [];
8072
+ for (let i = 0, iLen = subs.length; i < iLen; i++) {
8073
+ const sub = subs[i];
8074
+ sub.callback.call(sub.owner, payload);
8075
+ }
8076
+ }
8077
+ /**
8078
+ * Remove a listener
8079
+ */
8080
+ off(eventType, owner) {
8081
+ const subs = this.subscriptions[eventType];
8082
+ if (subs) {
8083
+ this.subscriptions[eventType] = subs.filter((s) => s.owner !== owner);
8084
+ }
8085
+ }
8086
+ /**
8087
+ * Remove all subscriptions.
8088
+ */
8089
+ clear() {
8090
+ this.subscriptions = {};
8091
+ }
8092
+ }
8093
+
8017
8094
  /**
8018
8095
  * A type-safe dependency container
8019
8096
  */
8020
- class DependencyContainer {
8097
+ class DependencyContainer extends EventBus {
8021
8098
  dependencies = new Map();
8022
8099
  factory = new StoreFactory(this.get.bind(this));
8023
8100
  /**
@@ -8094,15 +8171,12 @@ stores.inject(MyMetaStore, storeInstance);
8094
8171
  }
8095
8172
  return MetaStore;
8096
8173
  }
8097
- class ReactiveStore {
8174
+ class DisposableStore {
8098
8175
  get;
8176
+ disposeCallbacks = [];
8099
8177
  constructor(get) {
8100
8178
  this.get = get;
8101
- return owl.reactive(this);
8102
8179
  }
8103
- }
8104
- class DisposableStore extends ReactiveStore {
8105
- disposeCallbacks = [];
8106
8180
  onDispose(callback) {
8107
8181
  this.disposeCallbacks.push(callback);
8108
8182
  }
@@ -8122,7 +8196,10 @@ function useStoreProvider() {
8122
8196
  const container = new DependencyContainer();
8123
8197
  owl.useSubEnv({
8124
8198
  __spreadsheet_stores__: container,
8125
- getStore: container.get.bind(container),
8199
+ getStore: (Store) => {
8200
+ const store = container.get(Store);
8201
+ return proxifyStoreMutation(store, () => container.trigger("store-updated"));
8202
+ },
8126
8203
  });
8127
8204
  return container;
8128
8205
  }
@@ -8132,14 +8209,57 @@ function useStoreProvider() {
8132
8209
  function useStore(Store) {
8133
8210
  const env = owl.useEnv();
8134
8211
  const container = getDependencyContainer(env);
8135
- return owl.useState(container.get(Store));
8212
+ const store = container.get(Store);
8213
+ return useStoreRenderProxy(container, store);
8136
8214
  }
8137
8215
  function useLocalStore(Store, ...args) {
8138
8216
  const env = owl.useEnv();
8139
8217
  const container = getDependencyContainer(env);
8140
- const store = owl.useState(container.instantiate(Store, ...args));
8218
+ const store = container.instantiate(Store, ...args);
8141
8219
  owl.onWillUnmount(() => store.dispose());
8142
- return store;
8220
+ return useStoreRenderProxy(container, store);
8221
+ }
8222
+ /**
8223
+ * Trigger an event to re-render the app (deep render) when
8224
+ * a store is mutated by invoking one of its mutator methods.
8225
+ */
8226
+ function useStoreRenderProxy(container, store) {
8227
+ const component = owl.useComponent();
8228
+ const proxy = proxifyStoreMutation(store, () => {
8229
+ if (owl.status(component) === "mounted") {
8230
+ container.trigger("store-updated");
8231
+ }
8232
+ });
8233
+ return proxy;
8234
+ }
8235
+ /**
8236
+ * Creates a proxied version of a store object with mutation tracking.
8237
+ * Whenever a mutator method of the store is called, the provided callback function is invoked.
8238
+ */
8239
+ function proxifyStoreMutation(store, callback) {
8240
+ const proxy = new Proxy(store, {
8241
+ get(target, property, receiver) {
8242
+ const thisStore = target;
8243
+ // The third argument is `thisStore` (target) instead of `receiver`.
8244
+ // The goal is to always have the same `this` value in getter functions
8245
+ // (when `target[property]` is an accessor property).
8246
+ // `thisStore` is always the same object reference. `receiver` however is the
8247
+ // object on which the property is called, which is the Proxy object which is different for each component.
8248
+ const value = Reflect.get(target, property, thisStore);
8249
+ if (store.mutators.includes(property)) {
8250
+ const functionProxy = new Proxy(value, {
8251
+ // trap the function call
8252
+ apply(target, thisArg, argArray) {
8253
+ Reflect.apply(target, thisStore, argArray);
8254
+ callback();
8255
+ },
8256
+ });
8257
+ return functionProxy;
8258
+ }
8259
+ return value;
8260
+ },
8261
+ });
8262
+ return proxy;
8143
8263
  }
8144
8264
  function getDependencyContainer(env) {
8145
8265
  const container = env.__spreadsheet_stores__;
@@ -8151,7 +8271,8 @@ function getDependencyContainer(env) {
8151
8271
 
8152
8272
  const ModelStore = createAbstractStore("Model");
8153
8273
 
8154
- class RendererStore extends ReactiveStore {
8274
+ class RendererStore {
8275
+ mutators = ["register", "unRegister"];
8155
8276
  renderers = {};
8156
8277
  register(renderer) {
8157
8278
  if (!renderer.renderingLayers.length) {
@@ -8185,7 +8306,7 @@ class RendererStore extends ReactiveStore {
8185
8306
  class SpreadsheetStore extends DisposableStore {
8186
8307
  // cast the model store as Model to allow model.dispatch to return the DispatchResult
8187
8308
  model = this.get(ModelStore);
8188
- getters = owl.markRaw(this.model.getters);
8309
+ getters = this.model.getters;
8189
8310
  renderer = this.get(RendererStore);
8190
8311
  constructor(get) {
8191
8312
  super(get);
@@ -8232,6 +8353,7 @@ function drawHighlight(renderingContext, highlight, rect) {
8232
8353
  }
8233
8354
 
8234
8355
  class HighlightStore extends SpreadsheetStore {
8356
+ mutators = ["register", "unRegister"];
8235
8357
  providers = [];
8236
8358
  constructor(get) {
8237
8359
  super(get);
@@ -8262,7 +8384,7 @@ class HighlightStore extends SpreadsheetStore {
8262
8384
  this.providers.push(highlightProvider);
8263
8385
  }
8264
8386
  unRegister(highlightProvider) {
8265
- this.providers = this.providers.filter((h) => owl.toRaw(h) !== owl.toRaw(highlightProvider));
8387
+ this.providers = this.providers.filter((h) => h !== highlightProvider);
8266
8388
  }
8267
8389
  drawLayer(ctx, layer) {
8268
8390
  if (layer === "Highlights") {
@@ -8278,6 +8400,16 @@ const NotificationStore = createAbstractStore("Notifications");
8278
8400
 
8279
8401
  const CELL_DELETED_MESSAGE = _t("The cell you are trying to edit has been deleted.");
8280
8402
  class ComposerStore extends SpreadsheetStore {
8403
+ mutators = [
8404
+ "startEdition",
8405
+ "setCurrentContent",
8406
+ "stopEdition",
8407
+ "stopComposerRangeSelection",
8408
+ "cancelEdition",
8409
+ "cycleReferences",
8410
+ "changeComposerCursorSelection",
8411
+ "replaceComposerCursorSelection",
8412
+ ];
8281
8413
  col = 0;
8282
8414
  row = 0;
8283
8415
  editionMode = "inactive";
@@ -8292,9 +8424,9 @@ class ComposerStore extends SpreadsheetStore {
8292
8424
  highlightStore = this.get(HighlightStore);
8293
8425
  constructor(get) {
8294
8426
  super(get);
8295
- this.highlightStore.register(owl.toRaw(this));
8427
+ this.highlightStore.register(this);
8296
8428
  this.onDispose(() => {
8297
- this.highlightStore.unRegister(owl.toRaw(this));
8429
+ this.highlightStore.unRegister(this);
8298
8430
  });
8299
8431
  }
8300
8432
  canStopEdition() {
@@ -8421,7 +8553,7 @@ class ComposerStore extends SpreadsheetStore {
8421
8553
  if (this.isSelectingRange) {
8422
8554
  this.editionMode = "editing";
8423
8555
  }
8424
- this.model.selection.resetAnchor(owl.toRaw(this), {
8556
+ this.model.selection.resetAnchor(this, {
8425
8557
  cell: { col: left, row: top },
8426
8558
  zone: cmd.zone,
8427
8559
  });
@@ -8439,7 +8571,7 @@ class ComposerStore extends SpreadsheetStore {
8439
8571
  row: activePosition.row,
8440
8572
  });
8441
8573
  const zone = this.getters.expandZone(cmd.sheetIdTo, positionToZone({ col, row }));
8442
- this.model.selection.resetAnchor(owl.toRaw(this), { cell: { col, row }, zone });
8574
+ this.model.selection.resetAnchor(this, { cell: { col, row }, zone });
8443
8575
  }
8444
8576
  break;
8445
8577
  case "DELETE_SHEET":
@@ -8538,7 +8670,7 @@ class ComposerStore extends SpreadsheetStore {
8538
8670
  startComposerRangeSelection() {
8539
8671
  if (this.sheetId === this.getters.getActiveSheetId()) {
8540
8672
  const zone = positionToZone({ col: this.col, row: this.row });
8541
- this.model.selection.resetAnchor(owl.toRaw(this), {
8673
+ this.model.selection.resetAnchor(this, {
8542
8674
  cell: { col: this.col, row: this.row },
8543
8675
  zone,
8544
8676
  });
@@ -8567,7 +8699,7 @@ class ComposerStore extends SpreadsheetStore {
8567
8699
  this.setContent(str || this.initialContent, selection);
8568
8700
  this.colorIndexByRange = {};
8569
8701
  const zone = positionToZone({ col: this.col, row: this.row });
8570
- this.model.selection.capture(owl.toRaw(this), { cell: { col: this.col, row: this.row }, zone }, {
8702
+ this.model.selection.capture(this, { cell: { col: this.col, row: this.row }, zone }, {
8571
8703
  handleEvent: this.handleEvent.bind(this),
8572
8704
  release: () => {
8573
8705
  this._stopEdition();
@@ -8675,7 +8807,7 @@ class ComposerStore extends SpreadsheetStore {
8675
8807
  return;
8676
8808
  }
8677
8809
  this.editionMode = "inactive";
8678
- this.model.selection.release(owl.toRaw(this));
8810
+ this.model.selection.release(this);
8679
8811
  }
8680
8812
  /**
8681
8813
  * Reset the current content to the active cell content
@@ -8997,6 +9129,7 @@ class ComposerStore extends SpreadsheetStore {
8997
9129
  }
8998
9130
 
8999
9131
  class ComposerFocusStore extends SpreadsheetStore {
9132
+ mutators = ["focusTopBarComposer", "focusGridComposerContent", "focusGridComposerCell"];
9000
9133
  composerStore = this.get(ComposerStore);
9001
9134
  topBarFocus = "inactive";
9002
9135
  gridFocusMode = "inactive";
@@ -21453,6 +21586,7 @@ function interactiveAddMerge(env, sheetId, target) {
21453
21586
  }
21454
21587
 
21455
21588
  class HoveredCellStore extends SpreadsheetStore {
21589
+ mutators = ["clear", "hover"];
21456
21590
  col;
21457
21591
  row;
21458
21592
  handle(cmd) {
@@ -21472,6 +21606,7 @@ class HoveredCellStore extends SpreadsheetStore {
21472
21606
  }
21473
21607
 
21474
21608
  class CellPopoverStore extends SpreadsheetStore {
21609
+ mutators = ["open", "close"];
21475
21610
  persistentPopover;
21476
21611
  hoveredCell = this.get(HoveredCellStore);
21477
21612
  handle(cmd) {
@@ -25963,12 +26098,13 @@ function updateSelectionWithArrowKeys(ev, selection) {
25963
26098
 
25964
26099
  // The name is misleading and can be confused with the DOM focus.
25965
26100
  class FocusStore {
26101
+ mutators = ["focus", "unfocus"];
25966
26102
  focusedElement = null;
25967
26103
  focus(element) {
25968
26104
  this.focusedElement = element;
25969
26105
  }
25970
26106
  unfocus(element) {
25971
- if (this.focusedElement && owl.toRaw(this.focusedElement) === owl.toRaw(element)) {
26107
+ if (this.focusedElement && this.focusedElement === element) {
25972
26108
  this.focusedElement = null;
25973
26109
  }
25974
26110
  }
@@ -25984,6 +26120,16 @@ class FocusStore {
25984
26120
  class SelectionInputStore extends SpreadsheetStore {
25985
26121
  initialRanges;
25986
26122
  inputHasSingleRange;
26123
+ mutators = [
26124
+ "resetWithRanges",
26125
+ "focusById",
26126
+ "unfocus",
26127
+ "addEmptyRange",
26128
+ "removeRange",
26129
+ "changeRange",
26130
+ "reset",
26131
+ "confirm",
26132
+ ];
25987
26133
  ranges = [];
25988
26134
  focusedRangeIndex = null;
25989
26135
  inputSheetId;
@@ -26043,7 +26189,7 @@ class SelectionInputStore extends SpreadsheetStore {
26043
26189
  row: 0,
26044
26190
  });
26045
26191
  const zone = this.getters.expandZone(cmd.sheetIdTo, positionToZone({ col, row }));
26046
- this.model.selection.resetAnchor(owl.toRaw(this), { cell: { col, row }, zone });
26192
+ this.model.selection.resetAnchor(this, { cell: { col, row }, zone });
26047
26193
  }
26048
26194
  break;
26049
26195
  }
@@ -26062,7 +26208,7 @@ class SelectionInputStore extends SpreadsheetStore {
26062
26208
  if (focusIndex !== -1) {
26063
26209
  this.focus(focusIndex);
26064
26210
  const { left, top } = newZone;
26065
- this.model.selection.resetAnchor(owl.toRaw(this), {
26211
+ this.model.selection.resetAnchor(this, {
26066
26212
  cell: { col: left, row: top },
26067
26213
  zone: newZone,
26068
26214
  });
@@ -26153,7 +26299,7 @@ class SelectionInputStore extends SpreadsheetStore {
26153
26299
  }
26154
26300
  get hasMainFocus() {
26155
26301
  const focusedElement = this.focusStore.focusedElement;
26156
- return !!focusedElement && owl.toRaw(focusedElement) === owl.toRaw(this);
26302
+ return !!focusedElement && focusedElement === this;
26157
26303
  }
26158
26304
  get highlights() {
26159
26305
  if (!this.hasMainFocus) {
@@ -26182,7 +26328,7 @@ class SelectionInputStore extends SpreadsheetStore {
26182
26328
  unfocus() {
26183
26329
  this.focusedRangeIndex = null;
26184
26330
  this.focusStore.unfocus(this);
26185
- this.model.selection.release(owl.toRaw(this));
26331
+ this.model.selection.release(this);
26186
26332
  }
26187
26333
  captureSelection() {
26188
26334
  if (this.focusedRangeIndex === null) {
@@ -26191,7 +26337,7 @@ class SelectionInputStore extends SpreadsheetStore {
26191
26337
  const range = this.ranges[this.focusedRangeIndex];
26192
26338
  const sheetId = this.getters.getActiveSheetId();
26193
26339
  const zone = this.getters.getRangeFromSheetXC(sheetId, range?.xc || "A1").zone;
26194
- this.model.selection.capture(owl.toRaw(this), { cell: { col: zone.left, row: zone.top }, zone }, {
26340
+ this.model.selection.capture(this, { cell: { col: zone.left, row: zone.top }, zone }, {
26195
26341
  handleEvent: this.handleEvent.bind(this),
26196
26342
  release: this.unfocus.bind(this),
26197
26343
  });
@@ -27659,6 +27805,7 @@ chartSidePanelComponentRegistry
27659
27805
  });
27660
27806
 
27661
27807
  class MainChartPanelStore extends SpreadsheetStore {
27808
+ mutators = ["activatePanel"];
27662
27809
  panel = "configuration";
27663
27810
  activatePanel(panel) {
27664
27811
  this.panel = panel;
@@ -28197,14 +28344,14 @@ function useHoveredElement(ref) {
28197
28344
 
28198
28345
  function useHighlightsOnHover(ref, highlightProvider) {
28199
28346
  const hoverState = useHoveredElement(ref);
28200
- const env = owl.useEnv();
28347
+ const stores = useStoreProvider();
28201
28348
  useHighlights({
28202
28349
  get highlights() {
28203
28350
  return hoverState.hovered ? highlightProvider.highlights : [];
28204
28351
  },
28205
28352
  });
28206
28353
  owl.useEffect(() => {
28207
- env.model.dispatch("RENDER_CANVAS");
28354
+ stores.trigger("store-updated");
28208
28355
  }, () => [hoverState.hovered]);
28209
28356
  }
28210
28357
  function useHighlights(highlightProvider) {
@@ -29660,6 +29807,14 @@ var Direction;
29660
29807
  Direction[Direction["next"] = 1] = "next";
29661
29808
  })(Direction || (Direction = {}));
29662
29809
  class FindAndReplaceStore extends SpreadsheetStore {
29810
+ mutators = [
29811
+ "updateSearchOptions",
29812
+ "updateSearchContent",
29813
+ "searchFormulas",
29814
+ "selectPreviousMatch",
29815
+ "selectNextMatch",
29816
+ "replace",
29817
+ ];
29663
29818
  allSheetsMatches = [];
29664
29819
  activeSheetMatches = [];
29665
29820
  specificRangeMatches = [];
@@ -29684,11 +29839,11 @@ class FindAndReplaceStore extends SpreadsheetStore {
29684
29839
  this.initialShowFormulaState = this.model.getters.shouldShowFormulas();
29685
29840
  this.searchOptions.searchFormulas = this.initialShowFormulaState;
29686
29841
  const highlightStore = get(HighlightStore);
29687
- highlightStore.register(owl.toRaw(this));
29842
+ highlightStore.register(this);
29688
29843
  this.onDispose(() => {
29689
29844
  this.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
29690
29845
  this.updateSearchContent.stopDebounce();
29691
- highlightStore.unRegister(owl.toRaw(this));
29846
+ highlightStore.unRegister(this);
29692
29847
  });
29693
29848
  }
29694
29849
  get searchMatches() {
@@ -31331,6 +31486,7 @@ unGroupHeadersMenuRegistry
31331
31486
  });
31332
31487
 
31333
31488
  class DOMFocusableElementStore {
31489
+ mutators = ["setFocusableElement", "focus"];
31334
31490
  focusableElement = undefined;
31335
31491
  setFocusableElement(element) {
31336
31492
  this.focusableElement = element;
@@ -32067,7 +32223,7 @@ class Composer extends owl.Component {
32067
32223
  "Ctrl+Enter": this.processNewLineEvent,
32068
32224
  Escape: this.processEscapeKey,
32069
32225
  F2: () => console.warn("Not implemented"),
32070
- F4: this.processF4Key,
32226
+ F4: (ev) => this.processF4Key(ev),
32071
32227
  Tab: (ev) => this.processTabKey(ev, "right"),
32072
32228
  "Shift+Tab": (ev) => this.processTabKey(ev, "left"),
32073
32229
  };
@@ -32189,7 +32345,8 @@ class Composer extends owl.Component {
32189
32345
  processEscapeKey() {
32190
32346
  this.composerStore.cancelEdition();
32191
32347
  }
32192
- processF4Key() {
32348
+ processF4Key(ev) {
32349
+ ev.stopPropagation();
32193
32350
  this.composerStore.cycleReferences();
32194
32351
  this.processContent();
32195
32352
  }
@@ -34392,13 +34549,6 @@ class GridRenderer {
34392
34549
  this.getters = get(ModelStore).getters;
34393
34550
  this.renderer = get(RendererStore);
34394
34551
  this.renderer.register(this);
34395
- /**
34396
- * Mark the instance as raw to avoid reactivity as this class is instanciated
34397
- * as a Store by `useGridDrawing` (which casts it as reactive).
34398
- *
34399
- * Calling `this.` on a reactive instance is significantly slower than on a raw object.
34400
- */
34401
- owl.markRaw(this);
34402
34552
  }
34403
34553
  get renderingLayers() {
34404
34554
  return ["Background", "Headers"];
@@ -35028,7 +35178,7 @@ class GridRenderer {
35028
35178
  function useGridDrawing(refName, model, canvasSize) {
35029
35179
  const canvasRef = owl.useRef(refName);
35030
35180
  owl.useEffect(drawGrid);
35031
- const rendererManager = useStore(RendererStore);
35181
+ const rendererStore = useStore(RendererStore);
35032
35182
  useStore(GridRenderer);
35033
35183
  function drawGrid() {
35034
35184
  const canvas = canvasRef.el;
@@ -35056,7 +35206,11 @@ function useGridDrawing(refName, model, canvasSize) {
35056
35206
  ctx.scale(dpr, dpr);
35057
35207
  for (const layer of OrderedLayers()) {
35058
35208
  model.drawLayer(renderingContext, layer);
35059
- rendererManager.drawLayer(renderingContext, layer);
35209
+ // @ts-ignore 'drawLayer' is not declated as a mutator because:
35210
+ // it does not mutate anything. Most importantly it's used
35211
+ // during rendering. Invoking a mutator during rendering would
35212
+ // trigger another rendering, ultimately resulting in an infinite loop.
35213
+ rendererStore.drawLayer(renderingContext, layer);
35060
35214
  }
35061
35215
  }
35062
35216
  }
@@ -35458,6 +35612,7 @@ class VerticalScrollBar extends owl.Component {
35458
35612
  }
35459
35613
 
35460
35614
  class SidePanelStore extends SpreadsheetStore {
35615
+ mutators = ["open", "toggle", "close"];
35461
35616
  initialPanelProps = {};
35462
35617
  componentTag = "";
35463
35618
  get isOpen() {
@@ -43286,7 +43441,12 @@ class MergePlugin extends CorePlugin {
43286
43441
  * if they have at least a common cell
43287
43442
  */
43288
43443
  doesIntersectMerge(sheetId, zone) {
43289
- return positions(zone).some(({ col, row }) => this.getMerge({ sheetId, col, row }) !== undefined);
43444
+ for (const merge of this.getMerges(sheetId)) {
43445
+ if (overlap(zone, merge)) {
43446
+ return true;
43447
+ }
43448
+ }
43449
+ return false;
43290
43450
  }
43291
43451
  /**
43292
43452
  * Returns true if two columns have at least one merge in common
@@ -49606,62 +49766,6 @@ class AutomaticSumPlugin extends UIPlugin {
49606
49766
  }
49607
49767
  }
49608
49768
 
49609
- /**
49610
- * This is a generic event bus based on the Owl event bus.
49611
- * This bus however ensures type safety across events and subscription callbacks.
49612
- */
49613
- class EventBus {
49614
- subscriptions = {};
49615
- /**
49616
- * Add a listener for the 'eventType' events.
49617
- *
49618
- * Note that the 'owner' of this event can be anything, but will more likely
49619
- * be a component or a class. The idea is that the callback will be called with
49620
- * the proper owner bound.
49621
- *
49622
- * Also, the owner should be kind of unique. This will be used to remove the
49623
- * listener.
49624
- */
49625
- on(type, owner, callback) {
49626
- if (!callback) {
49627
- throw new Error("Missing callback");
49628
- }
49629
- if (!this.subscriptions[type]) {
49630
- this.subscriptions[type] = [];
49631
- }
49632
- this.subscriptions[type].push({
49633
- owner,
49634
- callback,
49635
- });
49636
- }
49637
- /**
49638
- * Emit an event of type 'eventType'. Any extra arguments will be passed to
49639
- * the listeners callback.
49640
- */
49641
- trigger(type, payload) {
49642
- const subs = this.subscriptions[type] || [];
49643
- for (let i = 0, iLen = subs.length; i < iLen; i++) {
49644
- const sub = subs[i];
49645
- sub.callback.call(sub.owner, payload);
49646
- }
49647
- }
49648
- /**
49649
- * Remove a listener
49650
- */
49651
- off(eventType, owner) {
49652
- const subs = this.subscriptions[eventType];
49653
- if (subs) {
49654
- this.subscriptions[eventType] = subs.filter((s) => s.owner !== owner);
49655
- }
49656
- }
49657
- /**
49658
- * Remove all subscriptions.
49659
- */
49660
- clear() {
49661
- this.subscriptions = {};
49662
- }
49663
- }
49664
-
49665
49769
  /*
49666
49770
  * This file contains the specifics transformations
49667
49771
  */
@@ -52132,7 +52236,7 @@ class ClipboardPlugin extends UIPlugin {
52132
52236
  case "ADD_COLUMNS_ROWS": {
52133
52237
  this.status = "invisible";
52134
52238
  // If we add a col/row inside or before the cut area, we invalidate the clipboard
52135
- if (this._isCutOperation !== true) {
52239
+ if (this._isCutOperation !== true || cmd.sheetId !== this.copiedData?.sheetId) {
52136
52240
  return;
52137
52241
  }
52138
52242
  const isClipboardDirty = this.isColRowDirtyingClipboard(cmd.position === "before" ? cmd.base : cmd.base + 1, cmd.dimension);
@@ -52144,7 +52248,7 @@ class ClipboardPlugin extends UIPlugin {
52144
52248
  case "REMOVE_COLUMNS_ROWS": {
52145
52249
  this.status = "invisible";
52146
52250
  // If we remove a col/row inside or before the cut area, we invalidate the clipboard
52147
- if (this._isCutOperation !== true) {
52251
+ if (this._isCutOperation !== true || cmd.sheetId !== this.copiedData?.sheetId) {
52148
52252
  return;
52149
52253
  }
52150
52254
  for (let el of cmd.elements) {
@@ -56779,16 +56883,25 @@ class Spreadsheet extends owl.Component {
56779
56883
  }
56780
56884
  }, () => [this.env.model.getters.getActiveSheetId()]);
56781
56885
  owl.useExternalListener(window, "resize", () => this.render(true));
56886
+ // For some reason, the wheel event is not properly registered inside templates
56887
+ // in Chromium-based browsers based on chromium 125
56888
+ // This hack ensures the event declared in the template is properly registered/working
56889
+ owl.useExternalListener(document.body, "wheel", () => { });
56782
56890
  this.bindModelEvents();
56783
56891
  owl.onWillUpdateProps((nextProps) => {
56784
56892
  if (nextProps.model !== this.props.model) {
56785
56893
  throw new Error("Changing the props model is not supported at the moment.");
56786
56894
  }
56787
56895
  });
56896
+ const render = batched(this.render.bind(this, true));
56788
56897
  owl.onMounted(() => {
56789
56898
  this.checkViewportSize();
56899
+ stores.on("store-updated", this, render);
56900
+ });
56901
+ owl.onWillUnmount(() => {
56902
+ this.unbindModelEvents();
56903
+ stores.off("store-updated", this);
56790
56904
  });
56791
- owl.onWillUnmount(() => this.unbindModelEvents());
56792
56905
  owl.onPatched(() => {
56793
56906
  this.checkViewportSize();
56794
56907
  });
@@ -60617,6 +60730,6 @@ exports.tokenColors = tokenColors;
60617
60730
  exports.tokenize = tokenize;
60618
60731
 
60619
60732
 
60620
- __info__.version = "17.2.7";
60621
- __info__.date = "2024-05-15T09:20:44.429Z";
60622
- __info__.hash = "57e89fa";
60733
+ __info__.version = "17.2.8";
60734
+ __info__.date = "2024-05-24T11:29:49.320Z";
60735
+ __info__.hash = "bfbcaa0";