@odoo/o-spreadsheet 16.3.24 → 16.3.25

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.
@@ -1746,6 +1746,9 @@ function parseFormat(formatString) {
1746
1746
  function formatValue(value, format) {
1747
1747
  switch (typeof value) {
1748
1748
  case "string":
1749
+ if (value.includes('\\"')) {
1750
+ return value.replace(/\\"/g, '"');
1751
+ }
1749
1752
  return value;
1750
1753
  case "boolean":
1751
1754
  return value ? "TRUE" : "FALSE";
@@ -20984,6 +20987,7 @@ class Composer extends owl.Component {
20984
20987
  static components = { TextValueProvider, FunctionDescriptionProvider };
20985
20988
  static defaultProps = {
20986
20989
  inputStyle: "",
20990
+ isDefaultFocus: false,
20987
20991
  };
20988
20992
  composerRef = owl.useRef("o_composer");
20989
20993
  contentHelper = new ContentEditableHelper(this.composerRef.el);
@@ -21041,13 +21045,13 @@ class Composer extends owl.Component {
21041
21045
  setup() {
21042
21046
  owl.onMounted(() => {
21043
21047
  const el = this.composerRef.el;
21048
+ if (this.props.isDefaultFocus) {
21049
+ this.env.focusableElement.setFocusableElement(el);
21050
+ }
21044
21051
  this.contentHelper.updateEl(el);
21045
21052
  this.processContent();
21046
21053
  this.contentHelper.scrollSelectionIntoView();
21047
21054
  });
21048
- owl.onWillUnmount(() => {
21049
- this.props.onComposerUnmounted?.();
21050
- });
21051
21055
  owl.onPatched(() => {
21052
21056
  if (!this.isKeyStillDown) {
21053
21057
  this.processContent();
@@ -21058,7 +21062,8 @@ class Composer extends owl.Component {
21058
21062
  // Handlers
21059
21063
  // ---------------------------------------------------------------------------
21060
21064
  processArrowKeys(ev) {
21061
- if (this.env.model.getters.isSelectingForComposer()) {
21065
+ if (this.env.model.getters.isSelectingForComposer() ||
21066
+ this.env.model.getters.getEditionMode() === "inactive") {
21062
21067
  this.functionDescriptionState.showDescription = false;
21063
21068
  // Prevent the default content editable behavior which moves the cursor
21064
21069
  ev.preventDefault();
@@ -21098,21 +21103,23 @@ class Composer extends owl.Component {
21098
21103
  processTabKey(ev) {
21099
21104
  ev.preventDefault();
21100
21105
  ev.stopPropagation();
21101
- if (this.autoCompleteState.showProvider) {
21102
- const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
21103
- if (autoCompleteValue) {
21104
- this.autoComplete(autoCompleteValue);
21105
- return;
21106
+ if (this.env.model.getters.getEditionMode() !== "inactive") {
21107
+ if (this.autoCompleteState.showProvider) {
21108
+ const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
21109
+ if (autoCompleteValue) {
21110
+ this.autoComplete(autoCompleteValue);
21111
+ return;
21112
+ }
21106
21113
  }
21107
- }
21108
- else {
21109
- // when completing with tab, if there is no value to complete, the active cell will be moved to the right.
21110
- // we can't let the model think that it is for a ref selection.
21111
- // todo: check if this can be removed someday
21112
- this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21114
+ else {
21115
+ // when completing with tab, if there is no value to complete, the active cell will be moved to the right.
21116
+ // we can't let the model think that it is for a ref selection.
21117
+ // todo: check if this can be removed someday
21118
+ this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21119
+ }
21120
+ this.env.model.dispatch("STOP_EDITION");
21113
21121
  }
21114
21122
  const direction = ev.shiftKey ? "left" : "right";
21115
- this.env.model.dispatch("STOP_EDITION");
21116
21123
  this.env.model.selection.moveAnchorCell(direction, 1);
21117
21124
  }
21118
21125
  processEnterKey(ev) {
@@ -21156,6 +21163,9 @@ class Composer extends owl.Component {
21156
21163
  this.compositionActive = false;
21157
21164
  }
21158
21165
  onKeydown(ev) {
21166
+ if (this.env.model.getters.getEditionMode() === "inactive") {
21167
+ return;
21168
+ }
21159
21169
  let handler = this.keyMapping[ev.key];
21160
21170
  if (handler) {
21161
21171
  handler.call(this, ev);
@@ -21166,22 +21176,44 @@ class Composer extends owl.Component {
21166
21176
  }
21167
21177
  }
21168
21178
  updateCursorIfNeeded() {
21169
- if (!this.env.model.getters.isSelectingForComposer()) {
21179
+ const moveCursor = !this.env.model.getters.isSelectingForComposer() &&
21180
+ !(this.env.model.getters.getEditionMode() === "inactive");
21181
+ if (moveCursor) {
21170
21182
  const { start, end } = this.contentHelper.getCurrentSelection();
21171
21183
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
21172
21184
  this.isKeyStillDown = true;
21173
21185
  }
21174
21186
  }
21187
+ onPaste(ev) {
21188
+ if (this.env.model.getters.getEditionMode() !== "inactive") {
21189
+ ev.stopPropagation();
21190
+ }
21191
+ }
21175
21192
  /*
21176
21193
  * Triggered automatically by the content-editable between the keydown and key up
21177
21194
  * */
21178
- onInput() {
21179
- if (this.props.focus === "inactive" || !this.shouldProcessInputEvents) {
21195
+ onInput(ev) {
21196
+ if (!this.shouldProcessInputEvents) {
21197
+ return;
21198
+ }
21199
+ if (ev.inputType === "insertFromPaste" &&
21200
+ this.env.model.getters.getEditionMode() === "inactive") {
21180
21201
  return;
21181
21202
  }
21203
+ ev.stopPropagation();
21204
+ let content;
21205
+ if (this.env.model.getters.getEditionMode() === "inactive") {
21206
+ content = ev.data || "";
21207
+ }
21208
+ else {
21209
+ content = this.contentHelper.getText();
21210
+ }
21211
+ if (this.props.focus === "inactive") {
21212
+ return this.props.onComposerCellFocused?.(content);
21213
+ }
21182
21214
  this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21183
21215
  this.env.model.dispatch("SET_CURRENT_CONTENT", {
21184
- content: this.contentHelper.getText(),
21216
+ content,
21185
21217
  selection: this.contentHelper.getCurrentSelection(),
21186
21218
  });
21187
21219
  }
@@ -21252,9 +21284,8 @@ class Composer extends owl.Component {
21252
21284
  }
21253
21285
  const newSelection = this.contentHelper.getCurrentSelection();
21254
21286
  this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21255
- if (this.props.focus === "inactive") {
21256
- this.props.onComposerContentFocused(newSelection);
21257
- }
21287
+ this.props.onComposerContentFocused();
21288
+ if (this.props.focus === "inactive") ;
21258
21289
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
21259
21290
  this.processTokenAtCursor();
21260
21291
  }
@@ -21398,7 +21429,7 @@ class Composer extends owl.Component {
21398
21429
  const highlights = this.env.model.getters.getHighlights();
21399
21430
  const refSheet = sheetName
21400
21431
  ? this.env.model.getters.getSheetIdByName(sheetName)
21401
- : this.env.model.getters.getCurrentEditedCell().sheetId;
21432
+ : this.env.model.getters.getCurrentEditedCell()?.sheetId;
21402
21433
  const highlight = highlights.find((highlight) => {
21403
21434
  if (highlight.sheetId !== refSheet)
21404
21435
  return false;
@@ -21475,12 +21506,13 @@ class Composer extends owl.Component {
21475
21506
  }
21476
21507
  }
21477
21508
  Composer.props = {
21478
- focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
21479
- onComposerContentFocused: Function,
21480
21509
  inputStyle: { type: String, optional: true },
21481
21510
  rect: { type: Object, optional: true },
21482
21511
  delimitation: { type: Object, optional: true },
21483
- onComposerUnmounted: { type: Function, optional: true },
21512
+ focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
21513
+ onComposerCellFocused: { type: Function, optional: true },
21514
+ onComposerContentFocused: Function,
21515
+ isDefaultFocus: { type: Boolean, optional: true },
21484
21516
  };
21485
21517
 
21486
21518
  const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
@@ -21514,51 +21546,26 @@ css /* scss */ `
21514
21546
  class GridComposer extends owl.Component {
21515
21547
  static template = "o-spreadsheet-GridComposer";
21516
21548
  static components = { Composer };
21517
- gridComposerRef;
21518
- zone;
21519
- rect;
21549
+ // TODORAR see if we can keep it undefined
21550
+ rect = this.defaultRect;
21551
+ isEditing = false;
21520
21552
  isCellReferenceVisible;
21521
- composerState;
21553
+ get defaultRect() {
21554
+ return { x: 0, y: 0, width: 0, height: 0 };
21555
+ }
21522
21556
  setup() {
21523
- this.gridComposerRef = owl.useRef("gridComposer");
21524
- this.composerState = owl.useState({
21525
- rect: undefined,
21526
- delimitation: undefined,
21527
- });
21528
- const { sheetId, col, row } = this.env.model.getters.getActivePosition();
21529
- this.zone = this.env.model.getters.expandZone(sheetId, positionToZone({ col, row }));
21530
- this.rect = this.env.model.getters.getVisibleRect(this.zone);
21531
- this.isCellReferenceVisible = false;
21532
- owl.onMounted(() => {
21533
- const el = this.gridComposerRef.el;
21534
- this.composerState.rect = {
21535
- x: this.rect.x,
21536
- y: this.rect.y,
21537
- width: el.clientWidth,
21538
- height: el.clientHeight,
21539
- };
21540
- this.composerState.delimitation = {
21541
- width: el.parentElement.clientWidth,
21542
- height: el.parentElement.clientHeight,
21543
- };
21544
- });
21545
21557
  owl.onWillUpdateProps(() => {
21546
- if (this.isCellReferenceVisible) {
21547
- return;
21548
- }
21549
- const sheetId = this.env.model.getters.getActiveSheetId();
21550
- const zone = this.env.model.getters.getSelectedZone();
21551
- const rect = this.env.model.getters.getVisibleRect(zone);
21552
- if (!deepEquals(rect, this.rect) ||
21553
- sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
21554
- this.isCellReferenceVisible = true;
21555
- }
21558
+ this.updateComponentPosition();
21559
+ this.updateCellReferenceVisibility();
21556
21560
  });
21557
21561
  }
21558
21562
  get shouldDisplayCellReference() {
21559
21563
  return this.isCellReferenceVisible;
21560
21564
  }
21561
21565
  get cellReference() {
21566
+ if (!this.env.model.getters.getCurrentEditedCell()) {
21567
+ return "";
21568
+ }
21562
21569
  const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
21563
21570
  const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
21564
21571
  return `${prefixSheet ? getCanonicalSheetName(this.env.model.getters.getSheetName(sheetId)) + "!" : ""}${toXC(col, row)}`;
@@ -21570,7 +21577,27 @@ class GridComposer extends owl.Component {
21570
21577
  top: `${top - GRID_CELL_REFERENCE_TOP_OFFSET}px`,
21571
21578
  });
21572
21579
  }
21580
+ get composerProps() {
21581
+ const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
21582
+ return {
21583
+ rect: { ...this.rect },
21584
+ delimitation: {
21585
+ width,
21586
+ height,
21587
+ },
21588
+ focus: this.props.focus,
21589
+ isDefaultFocus: true,
21590
+ onComposerContentFocused: this.props.onComposerContentFocused,
21591
+ onComposerCellFocused: this.props.onComposerCellFocused,
21592
+ };
21593
+ }
21573
21594
  get containerStyle() {
21595
+ if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
21596
+ return `
21597
+ position: absolute;
21598
+ z-index: -1000;
21599
+ `;
21600
+ }
21574
21601
  const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
21575
21602
  const cell = this.env.model.getters.getActiveCell();
21576
21603
  const position = this.env.model.getters.getActivePosition();
@@ -21590,6 +21617,8 @@ class GridComposer extends owl.Component {
21590
21617
  if (!isFormula) {
21591
21618
  textAlign = style.align || cell.defaultAlign;
21592
21619
  }
21620
+ const maxHeight = this.props.gridDims.height - this.rect.y;
21621
+ const maxWidth = this.props.gridDims.width - this.rect.x;
21593
21622
  /**
21594
21623
  * min-size is on the container, not the composer element, because we want to have the same size as the cell by default,
21595
21624
  * including all the paddings/margins of the composer
@@ -21601,6 +21630,8 @@ class GridComposer extends owl.Component {
21601
21630
  top: `${top}px`,
21602
21631
  "min-width": `${width + 1}px`,
21603
21632
  "min-height": `${height + 1}px`,
21633
+ "max-width": `${maxWidth}px`,
21634
+ "max-height": `${maxHeight}px`,
21604
21635
  background,
21605
21636
  color,
21606
21637
  "font-size": `${fontSizeInPixels(fontSize)}px`,
@@ -21610,20 +21641,38 @@ class GridComposer extends owl.Component {
21610
21641
  "text-align": textAlign,
21611
21642
  });
21612
21643
  }
21613
- get composerStyle() {
21614
- const maxHeight = this.props.gridDims.height - this.rect.y;
21615
- const maxWidth = this.props.gridDims.width - this.rect.x;
21616
- return cssPropertiesToCss({
21617
- "max-width": `${maxWidth}px`,
21618
- "max-height": `${maxHeight}px`,
21619
- });
21644
+ updateComponentPosition() {
21645
+ const isEditing = this.env.model.getters.getEditionMode() !== "inactive";
21646
+ if (this.isEditing !== isEditing) {
21647
+ this.isEditing = isEditing;
21648
+ if (!isEditing) {
21649
+ this.rect = this.defaultRect;
21650
+ this.env.focusableElement.focus();
21651
+ return;
21652
+ }
21653
+ const position = this.env.model.getters.getActivePosition();
21654
+ const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
21655
+ this.rect = this.env.model.getters.getVisibleRect(zone);
21656
+ }
21657
+ }
21658
+ updateCellReferenceVisibility() {
21659
+ if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
21660
+ return;
21661
+ }
21662
+ const sheetId = this.env.model.getters.getActiveSheetId();
21663
+ const zone = this.env.model.getters.getSelectedZone();
21664
+ const rect = this.env.model.getters.getVisibleRect(zone);
21665
+ if (!deepEquals(rect, this.rect) ||
21666
+ sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
21667
+ this.isCellReferenceVisible = true;
21668
+ }
21620
21669
  }
21621
21670
  }
21622
21671
  GridComposer.props = {
21623
21672
  focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
21624
- onComposerUnmounted: Function,
21625
21673
  onComposerContentFocused: Function,
21626
21674
  gridDims: Object,
21675
+ onComposerCellFocused: Function,
21627
21676
  };
21628
21677
 
21629
21678
  const CSS$1 = css /* scss */ `
@@ -22492,7 +22541,6 @@ class GridOverlay extends owl.Component {
22492
22541
  this.props.onCellDoubleClicked(col, row);
22493
22542
  }
22494
22543
  onContextMenu(ev) {
22495
- ev.preventDefault();
22496
22544
  const [col, row] = this.getCartesianCoordinates(ev);
22497
22545
  this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
22498
22546
  }
@@ -23586,7 +23634,6 @@ class Grid extends owl.Component {
23586
23634
  HEADER_WIDTH = HEADER_WIDTH;
23587
23635
  menuState;
23588
23636
  gridRef;
23589
- hiddenInput;
23590
23637
  onMouseWheel;
23591
23638
  canvasPosition;
23592
23639
  hoveredCell;
@@ -23597,17 +23644,16 @@ class Grid extends owl.Component {
23597
23644
  menuItems: [],
23598
23645
  });
23599
23646
  this.gridRef = owl.useRef("grid");
23600
- this.hiddenInput = owl.useRef("hiddenInput");
23601
23647
  this.canvasPosition = useAbsoluteBoundingRect(this.gridRef);
23602
23648
  this.hoveredCell = owl.useState({ col: undefined, row: undefined });
23603
23649
  owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
23604
23650
  owl.useExternalListener(document.body, "cut", this.copy.bind(this, true));
23605
23651
  owl.useExternalListener(document.body, "copy", this.copy.bind(this, false));
23606
23652
  owl.useExternalListener(document.body, "paste", this.paste);
23607
- owl.onMounted(() => this.focus());
23608
- this.props.exposeFocus(() => this.focus());
23653
+ owl.onMounted(() => this.focusDefaultElement());
23654
+ this.props.exposeFocus(() => this.focusDefaultElement());
23609
23655
  useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
23610
- owl.useEffect(() => this.focus(), () => [this.env.model.getters.getActiveSheetId()]);
23656
+ owl.useEffect(() => this.focusDefaultElement(), () => [this.env.model.getters.getActiveSheetId()]);
23611
23657
  this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
23612
23658
  this.moveCanvas(deltaX, deltaY);
23613
23659
  this.hoveredCell.col = undefined;
@@ -23630,7 +23676,7 @@ class Grid extends owl.Component {
23630
23676
  if (this.env.model.getters.hasOpenedPopover()) {
23631
23677
  this.closeOpenedPopover();
23632
23678
  }
23633
- this.focus();
23679
+ this.focusDefaultElement();
23634
23680
  }
23635
23681
  // this map will handle most of the actions that should happen on key down. The arrow keys are managed in the key
23636
23682
  // down itself
@@ -23800,10 +23846,10 @@ class Grid extends owl.Component {
23800
23846
  PAGEUP: () => this.env.model.dispatch("SHIFT_VIEWPORT_UP"),
23801
23847
  "CTRL+K": () => INSERT_LINK(this.env),
23802
23848
  };
23803
- focus() {
23849
+ focusDefaultElement() {
23804
23850
  if (!this.env.model.getters.getSelectedFigureId() &&
23805
23851
  this.env.model.getters.getEditionMode() === "inactive") {
23806
- this.hiddenInput.el?.focus();
23852
+ this.env.focusableElement.focus();
23807
23853
  }
23808
23854
  }
23809
23855
  get gridEl() {
@@ -23947,19 +23993,6 @@ class Grid extends owl.Component {
23947
23993
  return;
23948
23994
  }
23949
23995
  }
23950
- onInput(ev) {
23951
- // the user meant to paste in the sheet, not open the composer with the pasted content
23952
- if (!ev.isComposing && ev.inputType === "insertFromPaste") {
23953
- return;
23954
- }
23955
- if (ev.data) {
23956
- // if the user types a character on the grid, it means he wants to start composing the selected cell with that
23957
- // character
23958
- ev.preventDefault();
23959
- ev.stopPropagation();
23960
- this.props.onGridComposerCellFocused(ev.data);
23961
- }
23962
- }
23963
23996
  // ---------------------------------------------------------------------------
23964
23997
  // Context Menu
23965
23998
  // ---------------------------------------------------------------------------
@@ -24069,7 +24102,7 @@ class Grid extends owl.Component {
24069
24102
  }
24070
24103
  closeMenu() {
24071
24104
  this.menuState.isOpen = false;
24072
- this.focus();
24105
+ this.focusDefaultElement();
24073
24106
  }
24074
24107
  }
24075
24108
  Grid.props = {
@@ -28729,6 +28762,31 @@ const MIGRATIONS = [
28729
28762
  return data;
28730
28763
  },
28731
28764
  },
28765
+ {
28766
+ description: "Fix datafilter duplication",
28767
+ from: 12,
28768
+ to: 12.5,
28769
+ applyMigration(data) {
28770
+ for (let sheet of data.sheets || []) {
28771
+ let knownDataFilterZones = [];
28772
+ for (let filterTable of sheet.filterTables || []) {
28773
+ const zone = toZone(filterTable.range);
28774
+ // See commit message for the details
28775
+ const intersectZoneIndex = knownDataFilterZones.findIndex((knownZone) => overlap(knownZone, zone));
28776
+ if (intersectZoneIndex !== -1) {
28777
+ knownDataFilterZones[intersectZoneIndex] = zone;
28778
+ }
28779
+ else {
28780
+ knownDataFilterZones.push(zone);
28781
+ }
28782
+ }
28783
+ sheet.filterTables = knownDataFilterZones.map((zone) => ({
28784
+ range: zoneToXc(zone),
28785
+ }));
28786
+ }
28787
+ return data;
28788
+ },
28789
+ },
28732
28790
  {
28733
28791
  description: "Change Border description structure",
28734
28792
  from: 12,
@@ -29764,10 +29822,6 @@ class CellPlugin extends CorePlugin {
29764
29822
  format: cell.format ? getItemId(cell.format, formats) : undefined,
29765
29823
  content: cell.content || undefined,
29766
29824
  };
29767
- // if there is a formula but no dependencies (maybe because the cell is in error), no need to recompute the formula text
29768
- if (cell.isFormula && cell.dependencies.length) {
29769
- cells[xc].content = this.buildFormulaContent(_sheet.id, cell, cell.dependencies, true);
29770
- }
29771
29825
  }
29772
29826
  _sheet.cells = cells;
29773
29827
  }
@@ -33842,6 +33896,10 @@ class EvaluationPlugin extends UIPlugin {
33842
33896
  if (cell.format !== evaluatedCell.format) {
33843
33897
  exportedCellData.computedFormat = evaluatedCell.format;
33844
33898
  }
33899
+ // if there is a formula but no dependencies (maybe because the cell is in error), no need to recompute the formula text
33900
+ if (cell.isFormula && cell.dependencies.length) {
33901
+ exportedCellData.content = this.getters.buildFormulaContent(sheet.id, cell, cell.dependencies, true);
33902
+ }
33845
33903
  }
33846
33904
  }
33847
33905
  }
@@ -41186,7 +41244,7 @@ class EditionPlugin extends UIPlugin {
41186
41244
  getZoneReference(zone, fixedParts = [{ colFixed: false, rowFixed: false }]) {
41187
41245
  const sheetId = this.getters.getActiveSheetId();
41188
41246
  let selectedXc = this.getters.zoneToXC(sheetId, zone, fixedParts);
41189
- if (this.getters.getCurrentEditedCell().sheetId !== this.getters.getActiveSheetId()) {
41247
+ if (this.getters.getCurrentEditedCell()?.sheetId !== this.getters.getActiveSheetId()) {
41190
41248
  const sheetName = getCanonicalSheetName(this.getters.getSheetName(this.getters.getActiveSheetId()));
41191
41249
  selectedXc = `${sheetName}!${selectedXc}`;
41192
41250
  }
@@ -41201,7 +41259,7 @@ class EditionPlugin extends UIPlugin {
41201
41259
  _fixedParts.pop();
41202
41260
  }
41203
41261
  const newRange = range.clone({ parts: _fixedParts });
41204
- return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell().sheetId);
41262
+ return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId());
41205
41263
  }
41206
41264
  /**
41207
41265
  * Replace the current selection by a new text.
@@ -41234,7 +41292,7 @@ class EditionPlugin extends UIPlugin {
41234
41292
  if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
41235
41293
  return;
41236
41294
  }
41237
- const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
41295
+ const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
41238
41296
  const XCs = this.getReferencedRanges().map((range) => this.getters.getRangeString(range, editionSheetId));
41239
41297
  const colorsToKeep = {};
41240
41298
  for (const xc of XCs) {
@@ -41263,7 +41321,7 @@ class EditionPlugin extends UIPlugin {
41263
41321
  if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
41264
41322
  return [];
41265
41323
  }
41266
- const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
41324
+ const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
41267
41325
  const rangeColor = (rangeString) => {
41268
41326
  const colorIndex = this.colorIndexByRange[rangeString];
41269
41327
  return colors$1[colorIndex % colors$1.length];
@@ -41281,7 +41339,7 @@ class EditionPlugin extends UIPlugin {
41281
41339
  * Return ranges currently referenced in the composer
41282
41340
  */
41283
41341
  getReferencedRanges() {
41284
- const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
41342
+ const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
41285
41343
  const referenceRanges = this.currentTokens
41286
41344
  .filter((token) => token.type === "REFERENCE")
41287
41345
  .map((token) => this.getters.getRangeFromSheetXC(editionSheetId, token.value));
@@ -42092,6 +42150,16 @@ class ImageProvider {
42092
42150
  }
42093
42151
  }
42094
42152
 
42153
+ class FocusableElement {
42154
+ focusableElement = undefined;
42155
+ setFocusableElement(element) {
42156
+ this.focusableElement = element;
42157
+ }
42158
+ focus() {
42159
+ this.focusableElement?.focus();
42160
+ }
42161
+ }
42162
+
42095
42163
  const RIPPLE_KEY_FRAMES = [
42096
42164
  { transform: "scale(0)" },
42097
42165
  { transform: "scale(0.8)", offset: 0.33 },
@@ -44120,6 +44188,7 @@ class Spreadsheet extends owl.Component {
44120
44188
  _t: Spreadsheet._t,
44121
44189
  clipboard: this.env.clipboard || instantiateClipboard(),
44122
44190
  startCellEdition: (content) => this.onGridComposerCellFocused(content),
44191
+ focusableElement: new FocusableElement(),
44123
44192
  });
44124
44193
  owl.useExternalListener(window, "resize", () => this.render(true));
44125
44194
  owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
@@ -44226,17 +44295,18 @@ class Spreadsheet extends owl.Component {
44226
44295
  this.model.dispatch("UNFOCUS_SELECTION_INPUT");
44227
44296
  this.composer.topBarFocus = "contentFocus";
44228
44297
  this.composer.gridFocusMode = "inactive";
44229
- this.setComposerContent({ selection } || {});
44298
+ this.setComposerContent({ selection });
44230
44299
  }
44231
- onGridComposerContentFocused() {
44300
+ onGridComposerContentFocused(selection) {
44232
44301
  if (this.model.getters.isReadonly()) {
44233
44302
  return;
44234
44303
  }
44235
44304
  this.model.dispatch("UNFOCUS_SELECTION_INPUT");
44236
44305
  this.composer.topBarFocus = "inactive";
44237
44306
  this.composer.gridFocusMode = "contentFocus";
44238
- this.setComposerContent({});
44307
+ this.setComposerContent({ selection });
44239
44308
  }
44309
+ // TODO: either both are defined or none of them. change those args to an object
44240
44310
  onGridComposerCellFocused(content, selection) {
44241
44311
  if (this.model.getters.isReadonly()) {
44242
44312
  return;
@@ -47938,6 +48008,6 @@ exports.setTranslationMethod = setTranslationMethod;
47938
48008
  exports.tokenize = tokenize;
47939
48009
 
47940
48010
 
47941
- __info__.version = '16.3.24';
47942
- __info__.date = '2024-02-02T13:45:48.440Z';
47943
- __info__.hash = '0bf5f45';
48011
+ __info__.version = '16.3.25';
48012
+ __info__.date = '2024-02-09T13:07:06.947Z';
48013
+ __info__.hash = 'b53bf1b';