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