@odoo/o-spreadsheet 16.3.35 → 16.3.37

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.
@@ -2485,8 +2485,11 @@
2485
2485
  /**
2486
2486
  * Create a range from a xc. If the xc is empty, this function returns undefined.
2487
2487
  */
2488
- function createRange(getters, sheetId, range) {
2489
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
2488
+ function createValidRange(getters, sheetId, xc) {
2489
+ if (!xc)
2490
+ return;
2491
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
2492
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
2490
2493
  }
2491
2494
 
2492
2495
  /** Methods from Odoo Web Utils */
@@ -5259,6 +5262,7 @@
5259
5262
  };
5260
5263
 
5261
5264
  const macRegex = /Mac/i;
5265
+ const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
5262
5266
  /**
5263
5267
  * Return true if the event was triggered from
5264
5268
  * a child element.
@@ -5305,6 +5309,31 @@
5305
5309
  function getOpenedMenus() {
5306
5310
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5307
5311
  }
5312
+ const letterRegex = /^[a-zA-Z]$/;
5313
+ /**
5314
+ * Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
5315
+ *
5316
+ * @argument ev - The keyboard event to transform
5317
+ * @argument mode - Use either ev.key of ev.code to get the string shortcut
5318
+ *
5319
+ * @example
5320
+ * event : { ctrlKey: true, key: "a" } => "Ctrl+A"
5321
+ * event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
5322
+ */
5323
+ function keyboardEventToShortcutString(ev, mode = "key") {
5324
+ let keyDownString = "";
5325
+ if (!MODIFIER_KEYS.includes(ev.key)) {
5326
+ if (isCtrlKey(ev))
5327
+ keyDownString += "Ctrl+";
5328
+ if (ev.altKey)
5329
+ keyDownString += "Alt+";
5330
+ if (ev.shiftKey)
5331
+ keyDownString += "Shift+";
5332
+ }
5333
+ const key = mode === "key" ? ev.key : ev.code;
5334
+ keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
5335
+ return keyDownString;
5336
+ }
5308
5337
  function isMacOS() {
5309
5338
  return Boolean(macRegex.test(navigator.userAgent));
5310
5339
  }
@@ -7024,7 +7053,7 @@
7024
7053
  constructor(definition, sheetId, getters) {
7025
7054
  super(definition, sheetId, getters);
7026
7055
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7027
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7056
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7028
7057
  this.background = definition.background;
7029
7058
  this.verticalAxisPosition = definition.verticalAxisPosition;
7030
7059
  this.legendPosition = definition.legendPosition;
@@ -7268,7 +7297,7 @@
7268
7297
  type = "gauge";
7269
7298
  constructor(definition, sheetId, getters) {
7270
7299
  super(definition, sheetId, getters);
7271
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
7300
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
7272
7301
  this.sectionRule = definition.sectionRule;
7273
7302
  this.background = definition.background;
7274
7303
  }
@@ -7604,7 +7633,7 @@
7604
7633
  constructor(definition, sheetId, getters) {
7605
7634
  super(definition, sheetId, getters);
7606
7635
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7607
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
7636
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
7608
7637
  this.background = definition.background;
7609
7638
  this.verticalAxisPosition = definition.verticalAxisPosition;
7610
7639
  this.legendPosition = definition.legendPosition;
@@ -7900,7 +7929,7 @@
7900
7929
  constructor(definition, sheetId, getters) {
7901
7930
  super(definition, sheetId, getters);
7902
7931
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7903
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7932
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7904
7933
  this.background = definition.background;
7905
7934
  this.legendPosition = definition.legendPosition;
7906
7935
  this.aggregated = definition.aggregated;
@@ -8067,8 +8096,8 @@
8067
8096
  type = "scorecard";
8068
8097
  constructor(definition, sheetId, getters) {
8069
8098
  super(definition, sheetId, getters);
8070
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
8071
- this.baseline = createRange(getters, sheetId, definition.baseline);
8099
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
8100
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
8072
8101
  this.baselineMode = definition.baselineMode;
8073
8102
  this.baselineDescr = definition.baselineDescr;
8074
8103
  this.background = definition.background;
@@ -18099,7 +18128,7 @@
18099
18128
  }
18100
18129
  const getters = this.env.model.getters;
18101
18130
  const sheetId = getters.getActiveSheetId();
18102
- const labelRange = createRange(getters, sheetId, this.labelRange);
18131
+ const labelRange = createValidRange(getters, sheetId, this.labelRange);
18103
18132
  const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
18104
18133
  if (dataSets.length) {
18105
18134
  return dataSets[0].dataRange.zone.top + 1;
@@ -20263,14 +20292,14 @@
20263
20292
  }
20264
20293
  onKeyDown(ev) {
20265
20294
  const figure = this.props.figure;
20266
- switch (ev.key) {
20295
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
20296
+ switch (keyDownShortcut) {
20267
20297
  case "Delete":
20268
20298
  this.env.model.dispatch("DELETE_FIGURE", {
20269
20299
  sheetId: this.env.model.getters.getActiveSheetId(),
20270
20300
  id: figure.id,
20271
20301
  });
20272
20302
  this.props.onFigureDeleted();
20273
- ev.stopPropagation();
20274
20303
  ev.preventDefault();
20275
20304
  ev.stopPropagation();
20276
20305
  break;
@@ -20291,7 +20320,22 @@
20291
20320
  x: figure.x + delta[0],
20292
20321
  y: figure.y + delta[1],
20293
20322
  });
20323
+ ev.preventDefault();
20324
+ ev.stopPropagation();
20325
+ break;
20326
+ case "Ctrl+A":
20327
+ // Maybe in the future we will implement a way to select all figures
20328
+ ev.preventDefault();
20294
20329
  ev.stopPropagation();
20330
+ break;
20331
+ case "Ctrl+Y":
20332
+ case "Ctrl+Z":
20333
+ if (keyDownShortcut === "Ctrl+Y") {
20334
+ this.env.model.dispatch("REQUEST_REDO");
20335
+ }
20336
+ else if (keyDownShortcut === "Ctrl+Z") {
20337
+ this.env.model.dispatch("REQUEST_UNDO");
20338
+ }
20295
20339
  ev.preventDefault();
20296
20340
  ev.stopPropagation();
20297
20341
  break;
@@ -21085,7 +21129,7 @@
21085
21129
  Enter: this.processEnterKey,
21086
21130
  Escape: this.processEscapeKey,
21087
21131
  F2: () => console.warn("Not implemented"),
21088
- F4: this.processF4Key,
21132
+ F4: (ev) => this.processF4Key(ev),
21089
21133
  Tab: (ev) => this.processTabKey(ev),
21090
21134
  };
21091
21135
  setup() {
@@ -21202,9 +21246,10 @@
21202
21246
  processEscapeKey() {
21203
21247
  this.env.model.dispatch("STOP_EDITION", { cancel: true });
21204
21248
  }
21205
- processF4Key() {
21249
+ processF4Key(ev) {
21206
21250
  this.env.model.dispatch("CYCLE_EDITION_REFERENCES");
21207
21251
  this.processContent();
21252
+ ev.stopPropagation();
21208
21253
  }
21209
21254
  onCompositionStart() {
21210
21255
  this.compositionActive = true;
@@ -31895,7 +31940,12 @@
31895
31940
  * if they have at least a common cell
31896
31941
  */
31897
31942
  doesIntersectMerge(sheetId, zone) {
31898
- return positions(zone).some(({ col, row }) => this.getMerge({ sheetId, col, row }) !== undefined);
31943
+ for (const merge of this.getMerges(sheetId)) {
31944
+ if (overlap(zone, merge)) {
31945
+ return true;
31946
+ }
31947
+ }
31948
+ return false;
31899
31949
  }
31900
31950
  /**
31901
31951
  * Returns true if two columns have at least one merge in common
@@ -32507,6 +32557,9 @@
32507
32557
  if (range.invalidXc) {
32508
32558
  return range.invalidXc;
32509
32559
  }
32560
+ if (!this.getters.tryGetSheet(range.sheetId)) {
32561
+ return INCORRECT_RANGE_STRING;
32562
+ }
32510
32563
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
32511
32564
  return INCORRECT_RANGE_STRING;
32512
32565
  }
@@ -40605,7 +40658,7 @@
40605
40658
  case "ADD_COLUMNS_ROWS": {
40606
40659
  this.status = "invisible";
40607
40660
  // If we add a col/row inside or before the cut area, we invalidate the clipboard
40608
- if (this.state?.operation !== "CUT") {
40661
+ if (this.state?.operation !== "CUT" || cmd.sheetId !== this.state?.sheetId) {
40609
40662
  return;
40610
40663
  }
40611
40664
  const isClipboardDirty = this.state.isColRowDirtyingClipboard(cmd.position === "before" ? cmd.base : cmd.base + 1, cmd.dimension);
@@ -40617,7 +40670,7 @@
40617
40670
  case "REMOVE_COLUMNS_ROWS": {
40618
40671
  this.status = "invisible";
40619
40672
  // If we remove a col/row inside or before the cut area, we invalidate the clipboard
40620
- if (this.state?.operation !== "CUT") {
40673
+ if (this.state?.operation !== "CUT" || cmd.sheetId !== this.state?.sheetId) {
40621
40674
  return;
40622
40675
  }
40623
40676
  for (let el of cmd.elements) {
@@ -42520,9 +42573,11 @@
42520
42573
  if (ev.key === "Enter") {
42521
42574
  ev.preventDefault();
42522
42575
  this.stopEdition();
42576
+ this.env.focusableElement.focus();
42523
42577
  }
42524
42578
  if (ev.key === "Escape") {
42525
42579
  this.cancelEdition();
42580
+ this.env.focusableElement.focus();
42526
42581
  }
42527
42582
  }
42528
42583
  onClickSheetName(ev) {
@@ -44267,6 +44322,10 @@
44267
44322
  });
44268
44323
  owl.useExternalListener(window, "resize", () => this.render(true));
44269
44324
  owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
44325
+ // For some reason, the wheel event is not properly registered inside templates
44326
+ // in Chromium-based browsers based on chromium 125
44327
+ // This hack ensures the event declared in the template is properly registered/working
44328
+ owl.useExternalListener(document.body, "wheel", () => { });
44270
44329
  this.bindModelEvents();
44271
44330
  owl.onMounted(() => {
44272
44331
  this.checkViewportSize();
@@ -46306,6 +46365,12 @@
46306
46365
  else {
46307
46366
  // Shouldn't we always output the value then ?
46308
46367
  const value = cell.value;
46368
+ // If the cell contains a non-exported formula and that is evaluates to
46369
+ // nothing* ,we don't export it.
46370
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
46371
+ // the empty string.
46372
+ if (value === "")
46373
+ return undefined;
46309
46374
  const type = getCellType(value);
46310
46375
  attrs.push(["t", type]);
46311
46376
  node = escapeXml /*xml*/ `<v>${value}</v>`;
@@ -47109,7 +47174,11 @@
47109
47174
  let cellNode = escapeXml ``;
47110
47175
  // Either formula or static value inside the cell
47111
47176
  if (cell.isFormula) {
47112
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
47177
+ const res = addFormula(cell);
47178
+ if (!res) {
47179
+ continue;
47180
+ }
47181
+ ({ attrs: additionalAttrs, node: cellNode } = res);
47113
47182
  }
47114
47183
  else if (cell.content && isMarkdownLink(cell.content)) {
47115
47184
  const { label } = parseMarkdownLink(cell.content);
@@ -48092,9 +48161,9 @@
48092
48161
  Object.defineProperty(exports, '__esModule', { value: true });
48093
48162
 
48094
48163
 
48095
- __info__.version = '16.3.35';
48096
- __info__.date = '2024-05-15T09:15:19.399Z';
48097
- __info__.hash = '255caa0';
48164
+ __info__.version = '16.3.37';
48165
+ __info__.date = '2024-06-03T14:49:37.305Z';
48166
+ __info__.hash = 'e7bf8e1';
48098
48167
 
48099
48168
 
48100
48169
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);