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