@odoo/o-spreadsheet 16.0.42 → 16.0.43

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.
@@ -2301,8 +2301,11 @@ function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
2301
2301
  /**
2302
2302
  * Create a range from a xc. If the xc is empty, this function returns undefined.
2303
2303
  */
2304
- function createRange(getters, sheetId, range) {
2305
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
2304
+ function createValidRange(getters, sheetId, xc) {
2305
+ if (!xc)
2306
+ return;
2307
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
2308
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
2306
2309
  }
2307
2310
 
2308
2311
  /** Methods from Odoo Web Utils */
@@ -4023,6 +4026,7 @@ function getMenuDescription(node) {
4023
4026
  }
4024
4027
 
4025
4028
  const macRegex = /Mac/i;
4029
+ const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
4026
4030
  /**
4027
4031
  * Return true if the event was triggered from
4028
4032
  * a child element.
@@ -4041,6 +4045,31 @@ function gridOverlayPosition() {
4041
4045
  function getOpenedMenus() {
4042
4046
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
4043
4047
  }
4048
+ const letterRegex = /^[a-zA-Z]$/;
4049
+ /**
4050
+ * Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
4051
+ *
4052
+ * @argument ev - The keyboard event to transform
4053
+ * @argument mode - Use either ev.key of ev.code to get the string shortcut
4054
+ *
4055
+ * @example
4056
+ * event : { ctrlKey: true, key: "a" } => "Ctrl+A"
4057
+ * event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
4058
+ */
4059
+ function keyboardEventToShortcutString(ev, mode = "key") {
4060
+ let keyDownString = "";
4061
+ if (!MODIFIER_KEYS.includes(ev.key)) {
4062
+ if (isCtrlKey(ev))
4063
+ keyDownString += "Ctrl+";
4064
+ if (ev.altKey)
4065
+ keyDownString += "Alt+";
4066
+ if (ev.shiftKey)
4067
+ keyDownString += "Shift+";
4068
+ }
4069
+ const key = mode === "key" ? ev.key : ev.code;
4070
+ keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
4071
+ return keyDownString;
4072
+ }
4044
4073
  function isMacOS() {
4045
4074
  return Boolean(macRegex.test(navigator.userAgent));
4046
4075
  }
@@ -6975,8 +7004,8 @@ function createDataSets(getters, dataSetsString, sheetId, dataSetsHaveTitle) {
6975
7004
  const dataSets = [];
6976
7005
  for (const sheetXC of dataSetsString) {
6977
7006
  const dataRange = getters.getRangeFromSheetXC(sheetId, sheetXC);
6978
- const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName } = dataRange;
6979
- if (invalidSheetName) {
7007
+ const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName, invalidXc } = dataRange;
7008
+ if (invalidSheetName || invalidXc) {
6980
7009
  continue;
6981
7010
  }
6982
7011
  // It's a rectangle. We treat all columns (arbitrary) as different data series.
@@ -7369,7 +7398,7 @@ class BarChart extends AbstractChart {
7369
7398
  super(definition, sheetId, getters);
7370
7399
  this.type = "bar";
7371
7400
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7372
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7401
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7373
7402
  this.background = definition.background;
7374
7403
  this.verticalAxisPosition = definition.verticalAxisPosition;
7375
7404
  this.legendPosition = definition.legendPosition;
@@ -7665,7 +7694,7 @@ class GaugeChart extends AbstractChart {
7665
7694
  constructor(definition, sheetId, getters) {
7666
7695
  super(definition, sheetId, getters);
7667
7696
  this.type = "gauge";
7668
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
7697
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
7669
7698
  this.sectionRule = definition.sectionRule;
7670
7699
  this.background = definition.background;
7671
7700
  }
@@ -7996,7 +8025,7 @@ class LineChart extends AbstractChart {
7996
8025
  super(definition, sheetId, getters);
7997
8026
  this.type = "line";
7998
8027
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7999
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
8028
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
8000
8029
  this.background = definition.background;
8001
8030
  this.verticalAxisPosition = definition.verticalAxisPosition;
8002
8031
  this.legendPosition = definition.legendPosition;
@@ -8270,7 +8299,7 @@ class PieChart extends AbstractChart {
8270
8299
  super(definition, sheetId, getters);
8271
8300
  this.type = "pie";
8272
8301
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
8273
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
8302
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
8274
8303
  this.background = definition.background;
8275
8304
  this.legendPosition = definition.legendPosition;
8276
8305
  }
@@ -8428,8 +8457,8 @@ class ScorecardChart$1 extends AbstractChart {
8428
8457
  constructor(definition, sheetId, getters) {
8429
8458
  super(definition, sheetId, getters);
8430
8459
  this.type = "scorecard";
8431
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
8432
- this.baseline = createRange(getters, sheetId, definition.baseline);
8460
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
8461
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
8433
8462
  this.baselineMode = definition.baselineMode;
8434
8463
  this.baselineDescr = definition.baselineDescr;
8435
8464
  this.background = definition.background;
@@ -21202,7 +21231,8 @@ class FigureComponent extends owl.Component {
21202
21231
  }
21203
21232
  onKeyDown(ev) {
21204
21233
  const figure = this.props.figure;
21205
- switch (ev.key) {
21234
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
21235
+ switch (keyDownShortcut) {
21206
21236
  case "Delete":
21207
21237
  this.env.model.dispatch("DELETE_FIGURE", {
21208
21238
  sheetId: this.env.model.getters.getActiveSheetId(),
@@ -21232,6 +21262,22 @@ class FigureComponent extends owl.Component {
21232
21262
  ev.preventDefault();
21233
21263
  ev.stopPropagation();
21234
21264
  break;
21265
+ case "Ctrl+A":
21266
+ // Maybe in the future we will implement a way to select all figures
21267
+ ev.preventDefault();
21268
+ ev.stopPropagation();
21269
+ break;
21270
+ case "Ctrl+Y":
21271
+ case "Ctrl+Z":
21272
+ if (keyDownShortcut === "Ctrl+Y") {
21273
+ this.env.model.dispatch("REQUEST_REDO");
21274
+ }
21275
+ else if (keyDownShortcut === "Ctrl+Z") {
21276
+ this.env.model.dispatch("REQUEST_UNDO");
21277
+ }
21278
+ ev.preventDefault();
21279
+ ev.stopPropagation();
21280
+ break;
21235
21281
  }
21236
21282
  }
21237
21283
  }
@@ -23254,15 +23300,7 @@ class DateTimeCell extends NumberCell {
23254
23300
  }
23255
23301
  class LinkCell extends AbstractCell {
23256
23302
  constructor(id, content, properties = {}) {
23257
- var _a;
23258
23303
  const link = parseMarkdownLink(content);
23259
- properties = {
23260
- ...properties,
23261
- style: {
23262
- ...properties.style,
23263
- textColor: ((_a = properties.style) === null || _a === void 0 ? void 0 : _a.textColor) || LINK_COLOR,
23264
- },
23265
- };
23266
23304
  link.label = _t(link.label);
23267
23305
  super(id, lazy({ value: link.label, type: CellValueType.text }), properties);
23268
23306
  this.link = link;
@@ -27828,6 +27866,7 @@ class BordersPlugin extends CorePlugin {
27828
27866
  BordersPlugin.getters = ["getCellBorder"];
27829
27867
 
27830
27868
  const nbspRegexp = new RegExp(String.fromCharCode(160), "g");
27869
+ const LINK_STYLE = { textColor: LINK_COLOR };
27831
27870
  /**
27832
27871
  * Core Plugin
27833
27872
  *
@@ -28062,7 +28101,11 @@ class CellPlugin extends CorePlugin {
28062
28101
  return this.buildFormulaContent(sheetId, cell);
28063
28102
  }
28064
28103
  getCellStyle(cell) {
28065
- return (cell && cell.style) || {};
28104
+ if (!cell) {
28105
+ return {};
28106
+ }
28107
+ const linkStyle = cell.isLink() ? LINK_STYLE : {};
28108
+ return { ...linkStyle, ...cell.style };
28066
28109
  }
28067
28110
  /**
28068
28111
  * Converts a zone to a XC coordinate system
@@ -40631,6 +40674,9 @@ class RangeAdapter {
40631
40674
  if (range.invalidXc) {
40632
40675
  return range.invalidXc;
40633
40676
  }
40677
+ if (!this.getters.tryGetSheet(range.sheetId)) {
40678
+ return INCORRECT_RANGE_STRING;
40679
+ }
40634
40680
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
40635
40681
  return INCORRECT_RANGE_STRING;
40636
40682
  }
@@ -41769,6 +41815,12 @@ function addFormula(cell) {
41769
41815
  else {
41770
41816
  // Shouldn't we always output the value then ?
41771
41817
  const value = cell.value;
41818
+ // If the cell contains a non-exported formula and that is evaluates to
41819
+ // nothing* ,we don't export it.
41820
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
41821
+ // the empty string.
41822
+ if (value === "")
41823
+ return undefined;
41772
41824
  const type = getCellType(value);
41773
41825
  attrs.push(["t", type]);
41774
41826
  node = escapeXml /*xml*/ `<v>${value}</v>`;
@@ -42491,7 +42543,11 @@ function addRows(construct, data, sheet) {
42491
42543
  let cellNode = escapeXml ``;
42492
42544
  // Either formula or static value inside the cell
42493
42545
  if (cell.isFormula) {
42494
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
42546
+ const res = addFormula(cell);
42547
+ if (!res) {
42548
+ continue;
42549
+ }
42550
+ ({ attrs: additionalAttrs, node: cellNode } = res);
42495
42551
  }
42496
42552
  else if (cell.content && isMarkdownLink(cell.content)) {
42497
42553
  const { label } = parseMarkdownLink(cell.content);
@@ -43327,6 +43383,6 @@ exports.setTranslationMethod = setTranslationMethod;
43327
43383
  exports.tokenize = tokenize;
43328
43384
 
43329
43385
 
43330
- __info__.version = '16.0.42';
43331
- __info__.date = '2024-05-24T11:24:56.581Z';
43332
- __info__.hash = 'fd11d19';
43386
+ __info__.version = '16.0.43';
43387
+ __info__.date = '2024-06-03T14:49:29.032Z';
43388
+ __info__.hash = '7bff796';
@@ -2297,8 +2297,11 @@ function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
2297
2297
  /**
2298
2298
  * Create a range from a xc. If the xc is empty, this function returns undefined.
2299
2299
  */
2300
- function createRange(getters, sheetId, range) {
2301
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
2300
+ function createValidRange(getters, sheetId, xc) {
2301
+ if (!xc)
2302
+ return;
2303
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
2304
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
2302
2305
  }
2303
2306
 
2304
2307
  /** Methods from Odoo Web Utils */
@@ -4019,6 +4022,7 @@ function getMenuDescription(node) {
4019
4022
  }
4020
4023
 
4021
4024
  const macRegex = /Mac/i;
4025
+ const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
4022
4026
  /**
4023
4027
  * Return true if the event was triggered from
4024
4028
  * a child element.
@@ -4037,6 +4041,31 @@ function gridOverlayPosition() {
4037
4041
  function getOpenedMenus() {
4038
4042
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
4039
4043
  }
4044
+ const letterRegex = /^[a-zA-Z]$/;
4045
+ /**
4046
+ * Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
4047
+ *
4048
+ * @argument ev - The keyboard event to transform
4049
+ * @argument mode - Use either ev.key of ev.code to get the string shortcut
4050
+ *
4051
+ * @example
4052
+ * event : { ctrlKey: true, key: "a" } => "Ctrl+A"
4053
+ * event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
4054
+ */
4055
+ function keyboardEventToShortcutString(ev, mode = "key") {
4056
+ let keyDownString = "";
4057
+ if (!MODIFIER_KEYS.includes(ev.key)) {
4058
+ if (isCtrlKey(ev))
4059
+ keyDownString += "Ctrl+";
4060
+ if (ev.altKey)
4061
+ keyDownString += "Alt+";
4062
+ if (ev.shiftKey)
4063
+ keyDownString += "Shift+";
4064
+ }
4065
+ const key = mode === "key" ? ev.key : ev.code;
4066
+ keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
4067
+ return keyDownString;
4068
+ }
4040
4069
  function isMacOS() {
4041
4070
  return Boolean(macRegex.test(navigator.userAgent));
4042
4071
  }
@@ -6971,8 +7000,8 @@ function createDataSets(getters, dataSetsString, sheetId, dataSetsHaveTitle) {
6971
7000
  const dataSets = [];
6972
7001
  for (const sheetXC of dataSetsString) {
6973
7002
  const dataRange = getters.getRangeFromSheetXC(sheetId, sheetXC);
6974
- const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName } = dataRange;
6975
- if (invalidSheetName) {
7003
+ const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName, invalidXc } = dataRange;
7004
+ if (invalidSheetName || invalidXc) {
6976
7005
  continue;
6977
7006
  }
6978
7007
  // It's a rectangle. We treat all columns (arbitrary) as different data series.
@@ -7365,7 +7394,7 @@ class BarChart extends AbstractChart {
7365
7394
  super(definition, sheetId, getters);
7366
7395
  this.type = "bar";
7367
7396
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7368
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7397
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7369
7398
  this.background = definition.background;
7370
7399
  this.verticalAxisPosition = definition.verticalAxisPosition;
7371
7400
  this.legendPosition = definition.legendPosition;
@@ -7661,7 +7690,7 @@ class GaugeChart extends AbstractChart {
7661
7690
  constructor(definition, sheetId, getters) {
7662
7691
  super(definition, sheetId, getters);
7663
7692
  this.type = "gauge";
7664
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
7693
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
7665
7694
  this.sectionRule = definition.sectionRule;
7666
7695
  this.background = definition.background;
7667
7696
  }
@@ -7992,7 +8021,7 @@ class LineChart extends AbstractChart {
7992
8021
  super(definition, sheetId, getters);
7993
8022
  this.type = "line";
7994
8023
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7995
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
8024
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
7996
8025
  this.background = definition.background;
7997
8026
  this.verticalAxisPosition = definition.verticalAxisPosition;
7998
8027
  this.legendPosition = definition.legendPosition;
@@ -8266,7 +8295,7 @@ class PieChart extends AbstractChart {
8266
8295
  super(definition, sheetId, getters);
8267
8296
  this.type = "pie";
8268
8297
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
8269
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
8298
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
8270
8299
  this.background = definition.background;
8271
8300
  this.legendPosition = definition.legendPosition;
8272
8301
  }
@@ -8424,8 +8453,8 @@ class ScorecardChart$1 extends AbstractChart {
8424
8453
  constructor(definition, sheetId, getters) {
8425
8454
  super(definition, sheetId, getters);
8426
8455
  this.type = "scorecard";
8427
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
8428
- this.baseline = createRange(getters, sheetId, definition.baseline);
8456
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
8457
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
8429
8458
  this.baselineMode = definition.baselineMode;
8430
8459
  this.baselineDescr = definition.baselineDescr;
8431
8460
  this.background = definition.background;
@@ -21198,7 +21227,8 @@ class FigureComponent extends Component {
21198
21227
  }
21199
21228
  onKeyDown(ev) {
21200
21229
  const figure = this.props.figure;
21201
- switch (ev.key) {
21230
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
21231
+ switch (keyDownShortcut) {
21202
21232
  case "Delete":
21203
21233
  this.env.model.dispatch("DELETE_FIGURE", {
21204
21234
  sheetId: this.env.model.getters.getActiveSheetId(),
@@ -21228,6 +21258,22 @@ class FigureComponent extends Component {
21228
21258
  ev.preventDefault();
21229
21259
  ev.stopPropagation();
21230
21260
  break;
21261
+ case "Ctrl+A":
21262
+ // Maybe in the future we will implement a way to select all figures
21263
+ ev.preventDefault();
21264
+ ev.stopPropagation();
21265
+ break;
21266
+ case "Ctrl+Y":
21267
+ case "Ctrl+Z":
21268
+ if (keyDownShortcut === "Ctrl+Y") {
21269
+ this.env.model.dispatch("REQUEST_REDO");
21270
+ }
21271
+ else if (keyDownShortcut === "Ctrl+Z") {
21272
+ this.env.model.dispatch("REQUEST_UNDO");
21273
+ }
21274
+ ev.preventDefault();
21275
+ ev.stopPropagation();
21276
+ break;
21231
21277
  }
21232
21278
  }
21233
21279
  }
@@ -23250,15 +23296,7 @@ class DateTimeCell extends NumberCell {
23250
23296
  }
23251
23297
  class LinkCell extends AbstractCell {
23252
23298
  constructor(id, content, properties = {}) {
23253
- var _a;
23254
23299
  const link = parseMarkdownLink(content);
23255
- properties = {
23256
- ...properties,
23257
- style: {
23258
- ...properties.style,
23259
- textColor: ((_a = properties.style) === null || _a === void 0 ? void 0 : _a.textColor) || LINK_COLOR,
23260
- },
23261
- };
23262
23300
  link.label = _t(link.label);
23263
23301
  super(id, lazy({ value: link.label, type: CellValueType.text }), properties);
23264
23302
  this.link = link;
@@ -27824,6 +27862,7 @@ class BordersPlugin extends CorePlugin {
27824
27862
  BordersPlugin.getters = ["getCellBorder"];
27825
27863
 
27826
27864
  const nbspRegexp = new RegExp(String.fromCharCode(160), "g");
27865
+ const LINK_STYLE = { textColor: LINK_COLOR };
27827
27866
  /**
27828
27867
  * Core Plugin
27829
27868
  *
@@ -28058,7 +28097,11 @@ class CellPlugin extends CorePlugin {
28058
28097
  return this.buildFormulaContent(sheetId, cell);
28059
28098
  }
28060
28099
  getCellStyle(cell) {
28061
- return (cell && cell.style) || {};
28100
+ if (!cell) {
28101
+ return {};
28102
+ }
28103
+ const linkStyle = cell.isLink() ? LINK_STYLE : {};
28104
+ return { ...linkStyle, ...cell.style };
28062
28105
  }
28063
28106
  /**
28064
28107
  * Converts a zone to a XC coordinate system
@@ -40627,6 +40670,9 @@ class RangeAdapter {
40627
40670
  if (range.invalidXc) {
40628
40671
  return range.invalidXc;
40629
40672
  }
40673
+ if (!this.getters.tryGetSheet(range.sheetId)) {
40674
+ return INCORRECT_RANGE_STRING;
40675
+ }
40630
40676
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
40631
40677
  return INCORRECT_RANGE_STRING;
40632
40678
  }
@@ -41765,6 +41811,12 @@ function addFormula(cell) {
41765
41811
  else {
41766
41812
  // Shouldn't we always output the value then ?
41767
41813
  const value = cell.value;
41814
+ // If the cell contains a non-exported formula and that is evaluates to
41815
+ // nothing* ,we don't export it.
41816
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
41817
+ // the empty string.
41818
+ if (value === "")
41819
+ return undefined;
41768
41820
  const type = getCellType(value);
41769
41821
  attrs.push(["t", type]);
41770
41822
  node = escapeXml /*xml*/ `<v>${value}</v>`;
@@ -42487,7 +42539,11 @@ function addRows(construct, data, sheet) {
42487
42539
  let cellNode = escapeXml ``;
42488
42540
  // Either formula or static value inside the cell
42489
42541
  if (cell.isFormula) {
42490
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
42542
+ const res = addFormula(cell);
42543
+ if (!res) {
42544
+ continue;
42545
+ }
42546
+ ({ attrs: additionalAttrs, node: cellNode } = res);
42491
42547
  }
42492
42548
  else if (cell.content && isMarkdownLink(cell.content)) {
42493
42549
  const { label } = parseMarkdownLink(cell.content);
@@ -43295,6 +43351,6 @@ function addFunction(functionName, functionDescription) {
43295
43351
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
43296
43352
 
43297
43353
 
43298
- __info__.version = '16.0.42';
43299
- __info__.date = '2024-05-24T11:24:56.581Z';
43300
- __info__.hash = 'fd11d19';
43354
+ __info__.version = '16.0.43';
43355
+ __info__.date = '2024-06-03T14:49:29.032Z';
43356
+ __info__.hash = '7bff796';
@@ -2298,8 +2298,11 @@
2298
2298
  /**
2299
2299
  * Create a range from a xc. If the xc is empty, this function returns undefined.
2300
2300
  */
2301
- function createRange(getters, sheetId, range) {
2302
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
2301
+ function createValidRange(getters, sheetId, xc) {
2302
+ if (!xc)
2303
+ return;
2304
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
2305
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
2303
2306
  }
2304
2307
 
2305
2308
  /** Methods from Odoo Web Utils */
@@ -4020,6 +4023,7 @@
4020
4023
  }
4021
4024
 
4022
4025
  const macRegex = /Mac/i;
4026
+ const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
4023
4027
  /**
4024
4028
  * Return true if the event was triggered from
4025
4029
  * a child element.
@@ -4038,6 +4042,31 @@
4038
4042
  function getOpenedMenus() {
4039
4043
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
4040
4044
  }
4045
+ const letterRegex = /^[a-zA-Z]$/;
4046
+ /**
4047
+ * Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
4048
+ *
4049
+ * @argument ev - The keyboard event to transform
4050
+ * @argument mode - Use either ev.key of ev.code to get the string shortcut
4051
+ *
4052
+ * @example
4053
+ * event : { ctrlKey: true, key: "a" } => "Ctrl+A"
4054
+ * event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
4055
+ */
4056
+ function keyboardEventToShortcutString(ev, mode = "key") {
4057
+ let keyDownString = "";
4058
+ if (!MODIFIER_KEYS.includes(ev.key)) {
4059
+ if (isCtrlKey(ev))
4060
+ keyDownString += "Ctrl+";
4061
+ if (ev.altKey)
4062
+ keyDownString += "Alt+";
4063
+ if (ev.shiftKey)
4064
+ keyDownString += "Shift+";
4065
+ }
4066
+ const key = mode === "key" ? ev.key : ev.code;
4067
+ keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
4068
+ return keyDownString;
4069
+ }
4041
4070
  function isMacOS() {
4042
4071
  return Boolean(macRegex.test(navigator.userAgent));
4043
4072
  }
@@ -6972,8 +7001,8 @@
6972
7001
  const dataSets = [];
6973
7002
  for (const sheetXC of dataSetsString) {
6974
7003
  const dataRange = getters.getRangeFromSheetXC(sheetId, sheetXC);
6975
- const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName } = dataRange;
6976
- if (invalidSheetName) {
7004
+ const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName, invalidXc } = dataRange;
7005
+ if (invalidSheetName || invalidXc) {
6977
7006
  continue;
6978
7007
  }
6979
7008
  // It's a rectangle. We treat all columns (arbitrary) as different data series.
@@ -7366,7 +7395,7 @@
7366
7395
  super(definition, sheetId, getters);
7367
7396
  this.type = "bar";
7368
7397
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7369
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7398
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7370
7399
  this.background = definition.background;
7371
7400
  this.verticalAxisPosition = definition.verticalAxisPosition;
7372
7401
  this.legendPosition = definition.legendPosition;
@@ -7662,7 +7691,7 @@
7662
7691
  constructor(definition, sheetId, getters) {
7663
7692
  super(definition, sheetId, getters);
7664
7693
  this.type = "gauge";
7665
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
7694
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
7666
7695
  this.sectionRule = definition.sectionRule;
7667
7696
  this.background = definition.background;
7668
7697
  }
@@ -7993,7 +8022,7 @@
7993
8022
  super(definition, sheetId, getters);
7994
8023
  this.type = "line";
7995
8024
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7996
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
8025
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
7997
8026
  this.background = definition.background;
7998
8027
  this.verticalAxisPosition = definition.verticalAxisPosition;
7999
8028
  this.legendPosition = definition.legendPosition;
@@ -8267,7 +8296,7 @@
8267
8296
  super(definition, sheetId, getters);
8268
8297
  this.type = "pie";
8269
8298
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
8270
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
8299
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
8271
8300
  this.background = definition.background;
8272
8301
  this.legendPosition = definition.legendPosition;
8273
8302
  }
@@ -8425,8 +8454,8 @@
8425
8454
  constructor(definition, sheetId, getters) {
8426
8455
  super(definition, sheetId, getters);
8427
8456
  this.type = "scorecard";
8428
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
8429
- this.baseline = createRange(getters, sheetId, definition.baseline);
8457
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
8458
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
8430
8459
  this.baselineMode = definition.baselineMode;
8431
8460
  this.baselineDescr = definition.baselineDescr;
8432
8461
  this.background = definition.background;
@@ -21199,7 +21228,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
21199
21228
  }
21200
21229
  onKeyDown(ev) {
21201
21230
  const figure = this.props.figure;
21202
- switch (ev.key) {
21231
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
21232
+ switch (keyDownShortcut) {
21203
21233
  case "Delete":
21204
21234
  this.env.model.dispatch("DELETE_FIGURE", {
21205
21235
  sheetId: this.env.model.getters.getActiveSheetId(),
@@ -21229,6 +21259,22 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
21229
21259
  ev.preventDefault();
21230
21260
  ev.stopPropagation();
21231
21261
  break;
21262
+ case "Ctrl+A":
21263
+ // Maybe in the future we will implement a way to select all figures
21264
+ ev.preventDefault();
21265
+ ev.stopPropagation();
21266
+ break;
21267
+ case "Ctrl+Y":
21268
+ case "Ctrl+Z":
21269
+ if (keyDownShortcut === "Ctrl+Y") {
21270
+ this.env.model.dispatch("REQUEST_REDO");
21271
+ }
21272
+ else if (keyDownShortcut === "Ctrl+Z") {
21273
+ this.env.model.dispatch("REQUEST_UNDO");
21274
+ }
21275
+ ev.preventDefault();
21276
+ ev.stopPropagation();
21277
+ break;
21232
21278
  }
21233
21279
  }
21234
21280
  }
@@ -23251,15 +23297,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23251
23297
  }
23252
23298
  class LinkCell extends AbstractCell {
23253
23299
  constructor(id, content, properties = {}) {
23254
- var _a;
23255
23300
  const link = parseMarkdownLink(content);
23256
- properties = {
23257
- ...properties,
23258
- style: {
23259
- ...properties.style,
23260
- textColor: ((_a = properties.style) === null || _a === void 0 ? void 0 : _a.textColor) || LINK_COLOR,
23261
- },
23262
- };
23263
23301
  link.label = _t(link.label);
23264
23302
  super(id, lazy({ value: link.label, type: CellValueType.text }), properties);
23265
23303
  this.link = link;
@@ -27825,6 +27863,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
27825
27863
  BordersPlugin.getters = ["getCellBorder"];
27826
27864
 
27827
27865
  const nbspRegexp = new RegExp(String.fromCharCode(160), "g");
27866
+ const LINK_STYLE = { textColor: LINK_COLOR };
27828
27867
  /**
27829
27868
  * Core Plugin
27830
27869
  *
@@ -28059,7 +28098,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28059
28098
  return this.buildFormulaContent(sheetId, cell);
28060
28099
  }
28061
28100
  getCellStyle(cell) {
28062
- return (cell && cell.style) || {};
28101
+ if (!cell) {
28102
+ return {};
28103
+ }
28104
+ const linkStyle = cell.isLink() ? LINK_STYLE : {};
28105
+ return { ...linkStyle, ...cell.style };
28063
28106
  }
28064
28107
  /**
28065
28108
  * Converts a zone to a XC coordinate system
@@ -40628,6 +40671,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40628
40671
  if (range.invalidXc) {
40629
40672
  return range.invalidXc;
40630
40673
  }
40674
+ if (!this.getters.tryGetSheet(range.sheetId)) {
40675
+ return INCORRECT_RANGE_STRING;
40676
+ }
40631
40677
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
40632
40678
  return INCORRECT_RANGE_STRING;
40633
40679
  }
@@ -41766,6 +41812,12 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
41766
41812
  else {
41767
41813
  // Shouldn't we always output the value then ?
41768
41814
  const value = cell.value;
41815
+ // If the cell contains a non-exported formula and that is evaluates to
41816
+ // nothing* ,we don't export it.
41817
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
41818
+ // the empty string.
41819
+ if (value === "")
41820
+ return undefined;
41769
41821
  const type = getCellType(value);
41770
41822
  attrs.push(["t", type]);
41771
41823
  node = escapeXml /*xml*/ `<v>${value}</v>`;
@@ -42488,7 +42540,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42488
42540
  let cellNode = escapeXml ``;
42489
42541
  // Either formula or static value inside the cell
42490
42542
  if (cell.isFormula) {
42491
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
42543
+ const res = addFormula(cell);
42544
+ if (!res) {
42545
+ continue;
42546
+ }
42547
+ ({ attrs: additionalAttrs, node: cellNode } = res);
42492
42548
  }
42493
42549
  else if (cell.content && isMarkdownLink(cell.content)) {
42494
42550
  const { label } = parseMarkdownLink(cell.content);
@@ -43326,9 +43382,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43326
43382
  Object.defineProperty(exports, '__esModule', { value: true });
43327
43383
 
43328
43384
 
43329
- __info__.version = '16.0.42';
43330
- __info__.date = '2024-05-24T11:24:56.581Z';
43331
- __info__.hash = 'fd11d19';
43385
+ __info__.version = '16.0.43';
43386
+ __info__.date = '2024-06-03T14:49:29.032Z';
43387
+ __info__.hash = '7bff796';
43332
43388
 
43333
43389
 
43334
43390
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);