@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.
@@ -2488,8 +2488,11 @@ function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
2488
2488
  /**
2489
2489
  * Create a range from a xc. If the xc is empty, this function returns undefined.
2490
2490
  */
2491
- function createRange(getters, sheetId, range) {
2492
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
2491
+ function createValidRange(getters, sheetId, xc) {
2492
+ if (!xc)
2493
+ return;
2494
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
2495
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
2493
2496
  }
2494
2497
 
2495
2498
  /** Methods from Odoo Web Utils */
@@ -5262,6 +5265,7 @@ const FilterMenuPopoverBuilder = {
5262
5265
  };
5263
5266
 
5264
5267
  const macRegex = /Mac/i;
5268
+ const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
5265
5269
  /**
5266
5270
  * Return true if the event was triggered from
5267
5271
  * a child element.
@@ -5308,6 +5312,31 @@ function setElementScrollTop(el, scroll) {
5308
5312
  function getOpenedMenus() {
5309
5313
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5310
5314
  }
5315
+ const letterRegex = /^[a-zA-Z]$/;
5316
+ /**
5317
+ * Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
5318
+ *
5319
+ * @argument ev - The keyboard event to transform
5320
+ * @argument mode - Use either ev.key of ev.code to get the string shortcut
5321
+ *
5322
+ * @example
5323
+ * event : { ctrlKey: true, key: "a" } => "Ctrl+A"
5324
+ * event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
5325
+ */
5326
+ function keyboardEventToShortcutString(ev, mode = "key") {
5327
+ let keyDownString = "";
5328
+ if (!MODIFIER_KEYS.includes(ev.key)) {
5329
+ if (isCtrlKey(ev))
5330
+ keyDownString += "Ctrl+";
5331
+ if (ev.altKey)
5332
+ keyDownString += "Alt+";
5333
+ if (ev.shiftKey)
5334
+ keyDownString += "Shift+";
5335
+ }
5336
+ const key = mode === "key" ? ev.key : ev.code;
5337
+ keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
5338
+ return keyDownString;
5339
+ }
5311
5340
  function isMacOS() {
5312
5341
  return Boolean(macRegex.test(navigator.userAgent));
5313
5342
  }
@@ -5326,8 +5355,7 @@ function isCtrlKey(ev) {
5326
5355
  */
5327
5356
  function useSpreadsheetRect() {
5328
5357
  const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
5329
- let spreadsheetElement = document.querySelector(".o-spreadsheet");
5330
- updatePosition();
5358
+ let spreadsheetElement = null;
5331
5359
  function updatePosition() {
5332
5360
  if (!spreadsheetElement) {
5333
5361
  spreadsheetElement = document.querySelector(".o-spreadsheet");
@@ -7027,7 +7055,7 @@ class BarChart extends AbstractChart {
7027
7055
  constructor(definition, sheetId, getters) {
7028
7056
  super(definition, sheetId, getters);
7029
7057
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7030
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7058
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7031
7059
  this.background = definition.background;
7032
7060
  this.verticalAxisPosition = definition.verticalAxisPosition;
7033
7061
  this.legendPosition = definition.legendPosition;
@@ -7271,7 +7299,7 @@ class GaugeChart extends AbstractChart {
7271
7299
  type = "gauge";
7272
7300
  constructor(definition, sheetId, getters) {
7273
7301
  super(definition, sheetId, getters);
7274
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
7302
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
7275
7303
  this.sectionRule = definition.sectionRule;
7276
7304
  this.background = definition.background;
7277
7305
  }
@@ -7607,7 +7635,7 @@ class LineChart extends AbstractChart {
7607
7635
  constructor(definition, sheetId, getters) {
7608
7636
  super(definition, sheetId, getters);
7609
7637
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7610
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
7638
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
7611
7639
  this.background = definition.background;
7612
7640
  this.verticalAxisPosition = definition.verticalAxisPosition;
7613
7641
  this.legendPosition = definition.legendPosition;
@@ -7903,7 +7931,7 @@ class PieChart extends AbstractChart {
7903
7931
  constructor(definition, sheetId, getters) {
7904
7932
  super(definition, sheetId, getters);
7905
7933
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7906
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7934
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7907
7935
  this.background = definition.background;
7908
7936
  this.legendPosition = definition.legendPosition;
7909
7937
  this.aggregated = definition.aggregated;
@@ -8070,8 +8098,8 @@ class ScorecardChart extends AbstractChart {
8070
8098
  type = "scorecard";
8071
8099
  constructor(definition, sheetId, getters) {
8072
8100
  super(definition, sheetId, getters);
8073
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
8074
- this.baseline = createRange(getters, sheetId, definition.baseline);
8101
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
8102
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
8075
8103
  this.baselineMode = definition.baselineMode;
8076
8104
  this.baselineDescr = definition.baselineDescr;
8077
8105
  this.background = definition.background;
@@ -18102,7 +18130,7 @@ class LineBarPieConfigPanel extends owl.Component {
18102
18130
  }
18103
18131
  const getters = this.env.model.getters;
18104
18132
  const sheetId = getters.getActiveSheetId();
18105
- const labelRange = createRange(getters, sheetId, this.labelRange);
18133
+ const labelRange = createValidRange(getters, sheetId, this.labelRange);
18106
18134
  const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
18107
18135
  if (dataSets.length) {
18108
18136
  return dataSets[0].dataRange.zone.top + 1;
@@ -20266,14 +20294,14 @@ class FigureComponent extends owl.Component {
20266
20294
  }
20267
20295
  onKeyDown(ev) {
20268
20296
  const figure = this.props.figure;
20269
- switch (ev.key) {
20297
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
20298
+ switch (keyDownShortcut) {
20270
20299
  case "Delete":
20271
20300
  this.env.model.dispatch("DELETE_FIGURE", {
20272
20301
  sheetId: this.env.model.getters.getActiveSheetId(),
20273
20302
  id: figure.id,
20274
20303
  });
20275
20304
  this.props.onFigureDeleted();
20276
- ev.stopPropagation();
20277
20305
  ev.preventDefault();
20278
20306
  ev.stopPropagation();
20279
20307
  break;
@@ -20294,7 +20322,22 @@ class FigureComponent extends owl.Component {
20294
20322
  x: figure.x + delta[0],
20295
20323
  y: figure.y + delta[1],
20296
20324
  });
20325
+ ev.preventDefault();
20297
20326
  ev.stopPropagation();
20327
+ break;
20328
+ case "Ctrl+A":
20329
+ // Maybe in the future we will implement a way to select all figures
20330
+ ev.preventDefault();
20331
+ ev.stopPropagation();
20332
+ break;
20333
+ case "Ctrl+Y":
20334
+ case "Ctrl+Z":
20335
+ if (keyDownShortcut === "Ctrl+Y") {
20336
+ this.env.model.dispatch("REQUEST_REDO");
20337
+ }
20338
+ else if (keyDownShortcut === "Ctrl+Z") {
20339
+ this.env.model.dispatch("REQUEST_UNDO");
20340
+ }
20298
20341
  ev.preventDefault();
20299
20342
  ev.stopPropagation();
20300
20343
  break;
@@ -21240,8 +21283,15 @@ class Composer extends owl.Component {
21240
21283
  }
21241
21284
  onPaste(ev) {
21242
21285
  if (this.env.model.getters.getEditionMode() !== "inactive") {
21286
+ // let the browser clipboard work
21243
21287
  ev.stopPropagation();
21244
21288
  }
21289
+ else {
21290
+ // the user meant to paste in the sheet, not open the composer with the pasted content
21291
+ // While we're not editing, we still have the focus and should therefore prevent
21292
+ // the native "paste" to occur.
21293
+ ev.preventDefault();
21294
+ }
21245
21295
  }
21246
21296
  /*
21247
21297
  * Triggered automatically by the content-editable between the keydown and key up
@@ -21250,10 +21300,6 @@ class Composer extends owl.Component {
21250
21300
  if (!this.shouldProcessInputEvents) {
21251
21301
  return;
21252
21302
  }
21253
- if (ev.inputType === "insertFromPaste" &&
21254
- this.env.model.getters.getEditionMode() === "inactive") {
21255
- return;
21256
- }
21257
21303
  ev.stopPropagation();
21258
21304
  let content;
21259
21305
  if (this.env.model.getters.getEditionMode() === "inactive") {
@@ -21654,10 +21700,7 @@ class GridComposer extends owl.Component {
21654
21700
  }
21655
21701
  get containerStyle() {
21656
21702
  if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
21657
- return `
21658
- position: absolute;
21659
- z-index: -1000;
21660
- `;
21703
+ return `z-index: -1000;`;
21661
21704
  }
21662
21705
  const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
21663
21706
  const cell = this.env.model.getters.getActiveCell();
@@ -32516,6 +32559,9 @@ class RangeAdapter {
32516
32559
  if (range.invalidXc) {
32517
32560
  return range.invalidXc;
32518
32561
  }
32562
+ if (!this.getters.tryGetSheet(range.sheetId)) {
32563
+ return INCORRECT_RANGE_STRING;
32564
+ }
32519
32565
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
32520
32566
  return INCORRECT_RANGE_STRING;
32521
32567
  }
@@ -42529,9 +42575,11 @@ class BottomBarSheet extends owl.Component {
42529
42575
  if (ev.key === "Enter") {
42530
42576
  ev.preventDefault();
42531
42577
  this.stopEdition();
42578
+ this.env.focusableElement.focus();
42532
42579
  }
42533
42580
  if (ev.key === "Escape") {
42534
42581
  this.cancelEdition();
42582
+ this.env.focusableElement.focus();
42535
42583
  }
42536
42584
  }
42537
42585
  onClickSheetName(ev) {
@@ -46319,6 +46367,12 @@ function addFormula(cell) {
46319
46367
  else {
46320
46368
  // Shouldn't we always output the value then ?
46321
46369
  const value = cell.value;
46370
+ // If the cell contains a non-exported formula and that is evaluates to
46371
+ // nothing* ,we don't export it.
46372
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
46373
+ // the empty string.
46374
+ if (value === "")
46375
+ return undefined;
46322
46376
  const type = getCellType(value);
46323
46377
  attrs.push(["t", type]);
46324
46378
  node = escapeXml /*xml*/ `<v>${value}</v>`;
@@ -47122,7 +47176,11 @@ function addRows(construct, data, sheet) {
47122
47176
  let cellNode = escapeXml ``;
47123
47177
  // Either formula or static value inside the cell
47124
47178
  if (cell.isFormula) {
47125
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
47179
+ const res = addFormula(cell);
47180
+ if (!res) {
47181
+ continue;
47182
+ }
47183
+ ({ attrs: additionalAttrs, node: cellNode } = res);
47126
47184
  }
47127
47185
  else if (cell.content && isMarkdownLink(cell.content)) {
47128
47186
  const { label } = parseMarkdownLink(cell.content);
@@ -48103,6 +48161,6 @@ exports.setTranslationMethod = setTranslationMethod;
48103
48161
  exports.tokenize = tokenize;
48104
48162
 
48105
48163
 
48106
- __info__.version = '16.3.36';
48107
- __info__.date = '2024-05-24T11:25:00.243Z';
48108
- __info__.hash = 'b038fad';
48164
+ __info__.version = '16.3.38';
48165
+ __info__.date = '2024-06-10T09:33:40.314Z';
48166
+ __info__.hash = '2fcf01c';
@@ -2484,8 +2484,11 @@ function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
2484
2484
  /**
2485
2485
  * Create a range from a xc. If the xc is empty, this function returns undefined.
2486
2486
  */
2487
- function createRange(getters, sheetId, range) {
2488
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
2487
+ function createValidRange(getters, sheetId, xc) {
2488
+ if (!xc)
2489
+ return;
2490
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
2491
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
2489
2492
  }
2490
2493
 
2491
2494
  /** Methods from Odoo Web Utils */
@@ -5258,6 +5261,7 @@ const FilterMenuPopoverBuilder = {
5258
5261
  };
5259
5262
 
5260
5263
  const macRegex = /Mac/i;
5264
+ const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
5261
5265
  /**
5262
5266
  * Return true if the event was triggered from
5263
5267
  * a child element.
@@ -5304,6 +5308,31 @@ function setElementScrollTop(el, scroll) {
5304
5308
  function getOpenedMenus() {
5305
5309
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5306
5310
  }
5311
+ const letterRegex = /^[a-zA-Z]$/;
5312
+ /**
5313
+ * Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
5314
+ *
5315
+ * @argument ev - The keyboard event to transform
5316
+ * @argument mode - Use either ev.key of ev.code to get the string shortcut
5317
+ *
5318
+ * @example
5319
+ * event : { ctrlKey: true, key: "a" } => "Ctrl+A"
5320
+ * event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
5321
+ */
5322
+ function keyboardEventToShortcutString(ev, mode = "key") {
5323
+ let keyDownString = "";
5324
+ if (!MODIFIER_KEYS.includes(ev.key)) {
5325
+ if (isCtrlKey(ev))
5326
+ keyDownString += "Ctrl+";
5327
+ if (ev.altKey)
5328
+ keyDownString += "Alt+";
5329
+ if (ev.shiftKey)
5330
+ keyDownString += "Shift+";
5331
+ }
5332
+ const key = mode === "key" ? ev.key : ev.code;
5333
+ keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
5334
+ return keyDownString;
5335
+ }
5307
5336
  function isMacOS() {
5308
5337
  return Boolean(macRegex.test(navigator.userAgent));
5309
5338
  }
@@ -5322,8 +5351,7 @@ function isCtrlKey(ev) {
5322
5351
  */
5323
5352
  function useSpreadsheetRect() {
5324
5353
  const position = useState({ x: 0, y: 0, width: 0, height: 0 });
5325
- let spreadsheetElement = document.querySelector(".o-spreadsheet");
5326
- updatePosition();
5354
+ let spreadsheetElement = null;
5327
5355
  function updatePosition() {
5328
5356
  if (!spreadsheetElement) {
5329
5357
  spreadsheetElement = document.querySelector(".o-spreadsheet");
@@ -7023,7 +7051,7 @@ class BarChart extends AbstractChart {
7023
7051
  constructor(definition, sheetId, getters) {
7024
7052
  super(definition, sheetId, getters);
7025
7053
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7026
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7054
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7027
7055
  this.background = definition.background;
7028
7056
  this.verticalAxisPosition = definition.verticalAxisPosition;
7029
7057
  this.legendPosition = definition.legendPosition;
@@ -7267,7 +7295,7 @@ class GaugeChart extends AbstractChart {
7267
7295
  type = "gauge";
7268
7296
  constructor(definition, sheetId, getters) {
7269
7297
  super(definition, sheetId, getters);
7270
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
7298
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
7271
7299
  this.sectionRule = definition.sectionRule;
7272
7300
  this.background = definition.background;
7273
7301
  }
@@ -7603,7 +7631,7 @@ class LineChart extends AbstractChart {
7603
7631
  constructor(definition, sheetId, getters) {
7604
7632
  super(definition, sheetId, getters);
7605
7633
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7606
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
7634
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
7607
7635
  this.background = definition.background;
7608
7636
  this.verticalAxisPosition = definition.verticalAxisPosition;
7609
7637
  this.legendPosition = definition.legendPosition;
@@ -7899,7 +7927,7 @@ class PieChart extends AbstractChart {
7899
7927
  constructor(definition, sheetId, getters) {
7900
7928
  super(definition, sheetId, getters);
7901
7929
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
7902
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
7930
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
7903
7931
  this.background = definition.background;
7904
7932
  this.legendPosition = definition.legendPosition;
7905
7933
  this.aggregated = definition.aggregated;
@@ -8066,8 +8094,8 @@ class ScorecardChart extends AbstractChart {
8066
8094
  type = "scorecard";
8067
8095
  constructor(definition, sheetId, getters) {
8068
8096
  super(definition, sheetId, getters);
8069
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
8070
- this.baseline = createRange(getters, sheetId, definition.baseline);
8097
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
8098
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
8071
8099
  this.baselineMode = definition.baselineMode;
8072
8100
  this.baselineDescr = definition.baselineDescr;
8073
8101
  this.background = definition.background;
@@ -18098,7 +18126,7 @@ class LineBarPieConfigPanel extends Component {
18098
18126
  }
18099
18127
  const getters = this.env.model.getters;
18100
18128
  const sheetId = getters.getActiveSheetId();
18101
- const labelRange = createRange(getters, sheetId, this.labelRange);
18129
+ const labelRange = createValidRange(getters, sheetId, this.labelRange);
18102
18130
  const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
18103
18131
  if (dataSets.length) {
18104
18132
  return dataSets[0].dataRange.zone.top + 1;
@@ -20262,14 +20290,14 @@ class FigureComponent extends Component {
20262
20290
  }
20263
20291
  onKeyDown(ev) {
20264
20292
  const figure = this.props.figure;
20265
- switch (ev.key) {
20293
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
20294
+ switch (keyDownShortcut) {
20266
20295
  case "Delete":
20267
20296
  this.env.model.dispatch("DELETE_FIGURE", {
20268
20297
  sheetId: this.env.model.getters.getActiveSheetId(),
20269
20298
  id: figure.id,
20270
20299
  });
20271
20300
  this.props.onFigureDeleted();
20272
- ev.stopPropagation();
20273
20301
  ev.preventDefault();
20274
20302
  ev.stopPropagation();
20275
20303
  break;
@@ -20290,7 +20318,22 @@ class FigureComponent extends Component {
20290
20318
  x: figure.x + delta[0],
20291
20319
  y: figure.y + delta[1],
20292
20320
  });
20321
+ ev.preventDefault();
20293
20322
  ev.stopPropagation();
20323
+ break;
20324
+ case "Ctrl+A":
20325
+ // Maybe in the future we will implement a way to select all figures
20326
+ ev.preventDefault();
20327
+ ev.stopPropagation();
20328
+ break;
20329
+ case "Ctrl+Y":
20330
+ case "Ctrl+Z":
20331
+ if (keyDownShortcut === "Ctrl+Y") {
20332
+ this.env.model.dispatch("REQUEST_REDO");
20333
+ }
20334
+ else if (keyDownShortcut === "Ctrl+Z") {
20335
+ this.env.model.dispatch("REQUEST_UNDO");
20336
+ }
20294
20337
  ev.preventDefault();
20295
20338
  ev.stopPropagation();
20296
20339
  break;
@@ -21236,8 +21279,15 @@ class Composer extends Component {
21236
21279
  }
21237
21280
  onPaste(ev) {
21238
21281
  if (this.env.model.getters.getEditionMode() !== "inactive") {
21282
+ // let the browser clipboard work
21239
21283
  ev.stopPropagation();
21240
21284
  }
21285
+ else {
21286
+ // the user meant to paste in the sheet, not open the composer with the pasted content
21287
+ // While we're not editing, we still have the focus and should therefore prevent
21288
+ // the native "paste" to occur.
21289
+ ev.preventDefault();
21290
+ }
21241
21291
  }
21242
21292
  /*
21243
21293
  * Triggered automatically by the content-editable between the keydown and key up
@@ -21246,10 +21296,6 @@ class Composer extends Component {
21246
21296
  if (!this.shouldProcessInputEvents) {
21247
21297
  return;
21248
21298
  }
21249
- if (ev.inputType === "insertFromPaste" &&
21250
- this.env.model.getters.getEditionMode() === "inactive") {
21251
- return;
21252
- }
21253
21299
  ev.stopPropagation();
21254
21300
  let content;
21255
21301
  if (this.env.model.getters.getEditionMode() === "inactive") {
@@ -21650,10 +21696,7 @@ class GridComposer extends Component {
21650
21696
  }
21651
21697
  get containerStyle() {
21652
21698
  if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
21653
- return `
21654
- position: absolute;
21655
- z-index: -1000;
21656
- `;
21699
+ return `z-index: -1000;`;
21657
21700
  }
21658
21701
  const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
21659
21702
  const cell = this.env.model.getters.getActiveCell();
@@ -32512,6 +32555,9 @@ class RangeAdapter {
32512
32555
  if (range.invalidXc) {
32513
32556
  return range.invalidXc;
32514
32557
  }
32558
+ if (!this.getters.tryGetSheet(range.sheetId)) {
32559
+ return INCORRECT_RANGE_STRING;
32560
+ }
32515
32561
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
32516
32562
  return INCORRECT_RANGE_STRING;
32517
32563
  }
@@ -42525,9 +42571,11 @@ class BottomBarSheet extends Component {
42525
42571
  if (ev.key === "Enter") {
42526
42572
  ev.preventDefault();
42527
42573
  this.stopEdition();
42574
+ this.env.focusableElement.focus();
42528
42575
  }
42529
42576
  if (ev.key === "Escape") {
42530
42577
  this.cancelEdition();
42578
+ this.env.focusableElement.focus();
42531
42579
  }
42532
42580
  }
42533
42581
  onClickSheetName(ev) {
@@ -46315,6 +46363,12 @@ function addFormula(cell) {
46315
46363
  else {
46316
46364
  // Shouldn't we always output the value then ?
46317
46365
  const value = cell.value;
46366
+ // If the cell contains a non-exported formula and that is evaluates to
46367
+ // nothing* ,we don't export it.
46368
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
46369
+ // the empty string.
46370
+ if (value === "")
46371
+ return undefined;
46318
46372
  const type = getCellType(value);
46319
46373
  attrs.push(["t", type]);
46320
46374
  node = escapeXml /*xml*/ `<v>${value}</v>`;
@@ -47118,7 +47172,11 @@ function addRows(construct, data, sheet) {
47118
47172
  let cellNode = escapeXml ``;
47119
47173
  // Either formula or static value inside the cell
47120
47174
  if (cell.isFormula) {
47121
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
47175
+ const res = addFormula(cell);
47176
+ if (!res) {
47177
+ continue;
47178
+ }
47179
+ ({ attrs: additionalAttrs, node: cellNode } = res);
47122
47180
  }
47123
47181
  else if (cell.content && isMarkdownLink(cell.content)) {
47124
47182
  const { label } = parseMarkdownLink(cell.content);
@@ -48071,6 +48129,6 @@ function addFunction(functionName, functionDescription) {
48071
48129
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
48072
48130
 
48073
48131
 
48074
- __info__.version = '16.3.36';
48075
- __info__.date = '2024-05-24T11:25:00.243Z';
48076
- __info__.hash = 'b038fad';
48132
+ __info__.version = '16.3.38';
48133
+ __info__.date = '2024-06-10T09:33:40.314Z';
48134
+ __info__.hash = '2fcf01c';