@odoo/o-spreadsheet 16.3.36 → 16.3.38

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
  }
@@ -5323,8 +5352,7 @@
5323
5352
  */
5324
5353
  function useSpreadsheetRect() {
5325
5354
  const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
5326
- let spreadsheetElement = document.querySelector(".o-spreadsheet");
5327
- updatePosition();
5355
+ let spreadsheetElement = null;
5328
5356
  function updatePosition() {
5329
5357
  if (!spreadsheetElement) {
5330
5358
  spreadsheetElement = document.querySelector(".o-spreadsheet");
@@ -7024,7 +7052,7 @@
7024
7052
  constructor(definition, sheetId, getters) {
7025
7053
  super(definition, sheetId, getters);
7026
7054
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7027
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7055
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7028
7056
  this.background = definition.background;
7029
7057
  this.verticalAxisPosition = definition.verticalAxisPosition;
7030
7058
  this.legendPosition = definition.legendPosition;
@@ -7268,7 +7296,7 @@
7268
7296
  type = "gauge";
7269
7297
  constructor(definition, sheetId, getters) {
7270
7298
  super(definition, sheetId, getters);
7271
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
7299
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
7272
7300
  this.sectionRule = definition.sectionRule;
7273
7301
  this.background = definition.background;
7274
7302
  }
@@ -7604,7 +7632,7 @@
7604
7632
  constructor(definition, sheetId, getters) {
7605
7633
  super(definition, sheetId, getters);
7606
7634
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7607
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
7635
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
7608
7636
  this.background = definition.background;
7609
7637
  this.verticalAxisPosition = definition.verticalAxisPosition;
7610
7638
  this.legendPosition = definition.legendPosition;
@@ -7900,7 +7928,7 @@
7900
7928
  constructor(definition, sheetId, getters) {
7901
7929
  super(definition, sheetId, getters);
7902
7930
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7903
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7931
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7904
7932
  this.background = definition.background;
7905
7933
  this.legendPosition = definition.legendPosition;
7906
7934
  this.aggregated = definition.aggregated;
@@ -8067,8 +8095,8 @@
8067
8095
  type = "scorecard";
8068
8096
  constructor(definition, sheetId, getters) {
8069
8097
  super(definition, sheetId, getters);
8070
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
8071
- this.baseline = createRange(getters, sheetId, definition.baseline);
8098
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
8099
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
8072
8100
  this.baselineMode = definition.baselineMode;
8073
8101
  this.baselineDescr = definition.baselineDescr;
8074
8102
  this.background = definition.background;
@@ -18099,7 +18127,7 @@
18099
18127
  }
18100
18128
  const getters = this.env.model.getters;
18101
18129
  const sheetId = getters.getActiveSheetId();
18102
- const labelRange = createRange(getters, sheetId, this.labelRange);
18130
+ const labelRange = createValidRange(getters, sheetId, this.labelRange);
18103
18131
  const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
18104
18132
  if (dataSets.length) {
18105
18133
  return dataSets[0].dataRange.zone.top + 1;
@@ -20263,14 +20291,14 @@
20263
20291
  }
20264
20292
  onKeyDown(ev) {
20265
20293
  const figure = this.props.figure;
20266
- switch (ev.key) {
20294
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
20295
+ switch (keyDownShortcut) {
20267
20296
  case "Delete":
20268
20297
  this.env.model.dispatch("DELETE_FIGURE", {
20269
20298
  sheetId: this.env.model.getters.getActiveSheetId(),
20270
20299
  id: figure.id,
20271
20300
  });
20272
20301
  this.props.onFigureDeleted();
20273
- ev.stopPropagation();
20274
20302
  ev.preventDefault();
20275
20303
  ev.stopPropagation();
20276
20304
  break;
@@ -20291,7 +20319,22 @@
20291
20319
  x: figure.x + delta[0],
20292
20320
  y: figure.y + delta[1],
20293
20321
  });
20322
+ ev.preventDefault();
20294
20323
  ev.stopPropagation();
20324
+ break;
20325
+ case "Ctrl+A":
20326
+ // Maybe in the future we will implement a way to select all figures
20327
+ ev.preventDefault();
20328
+ ev.stopPropagation();
20329
+ break;
20330
+ case "Ctrl+Y":
20331
+ case "Ctrl+Z":
20332
+ if (keyDownShortcut === "Ctrl+Y") {
20333
+ this.env.model.dispatch("REQUEST_REDO");
20334
+ }
20335
+ else if (keyDownShortcut === "Ctrl+Z") {
20336
+ this.env.model.dispatch("REQUEST_UNDO");
20337
+ }
20295
20338
  ev.preventDefault();
20296
20339
  ev.stopPropagation();
20297
20340
  break;
@@ -21237,8 +21280,15 @@
21237
21280
  }
21238
21281
  onPaste(ev) {
21239
21282
  if (this.env.model.getters.getEditionMode() !== "inactive") {
21283
+ // let the browser clipboard work
21240
21284
  ev.stopPropagation();
21241
21285
  }
21286
+ else {
21287
+ // the user meant to paste in the sheet, not open the composer with the pasted content
21288
+ // While we're not editing, we still have the focus and should therefore prevent
21289
+ // the native "paste" to occur.
21290
+ ev.preventDefault();
21291
+ }
21242
21292
  }
21243
21293
  /*
21244
21294
  * Triggered automatically by the content-editable between the keydown and key up
@@ -21247,10 +21297,6 @@
21247
21297
  if (!this.shouldProcessInputEvents) {
21248
21298
  return;
21249
21299
  }
21250
- if (ev.inputType === "insertFromPaste" &&
21251
- this.env.model.getters.getEditionMode() === "inactive") {
21252
- return;
21253
- }
21254
21300
  ev.stopPropagation();
21255
21301
  let content;
21256
21302
  if (this.env.model.getters.getEditionMode() === "inactive") {
@@ -21651,10 +21697,7 @@
21651
21697
  }
21652
21698
  get containerStyle() {
21653
21699
  if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
21654
- return `
21655
- position: absolute;
21656
- z-index: -1000;
21657
- `;
21700
+ return `z-index: -1000;`;
21658
21701
  }
21659
21702
  const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
21660
21703
  const cell = this.env.model.getters.getActiveCell();
@@ -32513,6 +32556,9 @@
32513
32556
  if (range.invalidXc) {
32514
32557
  return range.invalidXc;
32515
32558
  }
32559
+ if (!this.getters.tryGetSheet(range.sheetId)) {
32560
+ return INCORRECT_RANGE_STRING;
32561
+ }
32516
32562
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
32517
32563
  return INCORRECT_RANGE_STRING;
32518
32564
  }
@@ -42526,9 +42572,11 @@
42526
42572
  if (ev.key === "Enter") {
42527
42573
  ev.preventDefault();
42528
42574
  this.stopEdition();
42575
+ this.env.focusableElement.focus();
42529
42576
  }
42530
42577
  if (ev.key === "Escape") {
42531
42578
  this.cancelEdition();
42579
+ this.env.focusableElement.focus();
42532
42580
  }
42533
42581
  }
42534
42582
  onClickSheetName(ev) {
@@ -46316,6 +46364,12 @@
46316
46364
  else {
46317
46365
  // Shouldn't we always output the value then ?
46318
46366
  const value = cell.value;
46367
+ // If the cell contains a non-exported formula and that is evaluates to
46368
+ // nothing* ,we don't export it.
46369
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
46370
+ // the empty string.
46371
+ if (value === "")
46372
+ return undefined;
46319
46373
  const type = getCellType(value);
46320
46374
  attrs.push(["t", type]);
46321
46375
  node = escapeXml /*xml*/ `<v>${value}</v>`;
@@ -47119,7 +47173,11 @@
47119
47173
  let cellNode = escapeXml ``;
47120
47174
  // Either formula or static value inside the cell
47121
47175
  if (cell.isFormula) {
47122
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
47176
+ const res = addFormula(cell);
47177
+ if (!res) {
47178
+ continue;
47179
+ }
47180
+ ({ attrs: additionalAttrs, node: cellNode } = res);
47123
47181
  }
47124
47182
  else if (cell.content && isMarkdownLink(cell.content)) {
47125
47183
  const { label } = parseMarkdownLink(cell.content);
@@ -48102,9 +48160,9 @@
48102
48160
  Object.defineProperty(exports, '__esModule', { value: true });
48103
48161
 
48104
48162
 
48105
- __info__.version = '16.3.36';
48106
- __info__.date = '2024-05-24T11:25:00.243Z';
48107
- __info__.hash = 'b038fad';
48163
+ __info__.version = '16.3.38';
48164
+ __info__.date = '2024-06-10T09:33:40.314Z';
48165
+ __info__.hash = '2fcf01c';
48108
48166
 
48109
48167
 
48110
48168
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);