@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.
@@ -1743,6 +1743,9 @@
1743
1743
  function formatValue(value, format) {
1744
1744
  switch (typeof value) {
1745
1745
  case "string":
1746
+ if (value.includes('\\"')) {
1747
+ return value.replace(/\\"/g, '"');
1748
+ }
1746
1749
  return value;
1747
1750
  case "boolean":
1748
1751
  return value ? "TRUE" : "FALSE";
@@ -20981,6 +20984,7 @@
20981
20984
  static components = { TextValueProvider, FunctionDescriptionProvider };
20982
20985
  static defaultProps = {
20983
20986
  inputStyle: "",
20987
+ isDefaultFocus: false,
20984
20988
  };
20985
20989
  composerRef = owl.useRef("o_composer");
20986
20990
  contentHelper = new ContentEditableHelper(this.composerRef.el);
@@ -21038,13 +21042,13 @@
21038
21042
  setup() {
21039
21043
  owl.onMounted(() => {
21040
21044
  const el = this.composerRef.el;
21045
+ if (this.props.isDefaultFocus) {
21046
+ this.env.focusableElement.setFocusableElement(el);
21047
+ }
21041
21048
  this.contentHelper.updateEl(el);
21042
21049
  this.processContent();
21043
21050
  this.contentHelper.scrollSelectionIntoView();
21044
21051
  });
21045
- owl.onWillUnmount(() => {
21046
- this.props.onComposerUnmounted?.();
21047
- });
21048
21052
  owl.onPatched(() => {
21049
21053
  if (!this.isKeyStillDown) {
21050
21054
  this.processContent();
@@ -21055,7 +21059,8 @@
21055
21059
  // Handlers
21056
21060
  // ---------------------------------------------------------------------------
21057
21061
  processArrowKeys(ev) {
21058
- if (this.env.model.getters.isSelectingForComposer()) {
21062
+ if (this.env.model.getters.isSelectingForComposer() ||
21063
+ this.env.model.getters.getEditionMode() === "inactive") {
21059
21064
  this.functionDescriptionState.showDescription = false;
21060
21065
  // Prevent the default content editable behavior which moves the cursor
21061
21066
  ev.preventDefault();
@@ -21095,21 +21100,23 @@
21095
21100
  processTabKey(ev) {
21096
21101
  ev.preventDefault();
21097
21102
  ev.stopPropagation();
21098
- if (this.autoCompleteState.showProvider) {
21099
- const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
21100
- if (autoCompleteValue) {
21101
- this.autoComplete(autoCompleteValue);
21102
- return;
21103
+ if (this.env.model.getters.getEditionMode() !== "inactive") {
21104
+ if (this.autoCompleteState.showProvider) {
21105
+ const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
21106
+ if (autoCompleteValue) {
21107
+ this.autoComplete(autoCompleteValue);
21108
+ return;
21109
+ }
21103
21110
  }
21104
- }
21105
- else {
21106
- // when completing with tab, if there is no value to complete, the active cell will be moved to the right.
21107
- // we can't let the model think that it is for a ref selection.
21108
- // todo: check if this can be removed someday
21109
- this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21111
+ else {
21112
+ // when completing with tab, if there is no value to complete, the active cell will be moved to the right.
21113
+ // we can't let the model think that it is for a ref selection.
21114
+ // todo: check if this can be removed someday
21115
+ this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21116
+ }
21117
+ this.env.model.dispatch("STOP_EDITION");
21110
21118
  }
21111
21119
  const direction = ev.shiftKey ? "left" : "right";
21112
- this.env.model.dispatch("STOP_EDITION");
21113
21120
  this.env.model.selection.moveAnchorCell(direction, 1);
21114
21121
  }
21115
21122
  processEnterKey(ev) {
@@ -21153,6 +21160,9 @@
21153
21160
  this.compositionActive = false;
21154
21161
  }
21155
21162
  onKeydown(ev) {
21163
+ if (this.env.model.getters.getEditionMode() === "inactive") {
21164
+ return;
21165
+ }
21156
21166
  let handler = this.keyMapping[ev.key];
21157
21167
  if (handler) {
21158
21168
  handler.call(this, ev);
@@ -21163,22 +21173,44 @@
21163
21173
  }
21164
21174
  }
21165
21175
  updateCursorIfNeeded() {
21166
- if (!this.env.model.getters.isSelectingForComposer()) {
21176
+ const moveCursor = !this.env.model.getters.isSelectingForComposer() &&
21177
+ !(this.env.model.getters.getEditionMode() === "inactive");
21178
+ if (moveCursor) {
21167
21179
  const { start, end } = this.contentHelper.getCurrentSelection();
21168
21180
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
21169
21181
  this.isKeyStillDown = true;
21170
21182
  }
21171
21183
  }
21184
+ onPaste(ev) {
21185
+ if (this.env.model.getters.getEditionMode() !== "inactive") {
21186
+ ev.stopPropagation();
21187
+ }
21188
+ }
21172
21189
  /*
21173
21190
  * Triggered automatically by the content-editable between the keydown and key up
21174
21191
  * */
21175
- onInput() {
21176
- if (this.props.focus === "inactive" || !this.shouldProcessInputEvents) {
21192
+ onInput(ev) {
21193
+ if (!this.shouldProcessInputEvents) {
21194
+ return;
21195
+ }
21196
+ if (ev.inputType === "insertFromPaste" &&
21197
+ this.env.model.getters.getEditionMode() === "inactive") {
21177
21198
  return;
21178
21199
  }
21200
+ ev.stopPropagation();
21201
+ let content;
21202
+ if (this.env.model.getters.getEditionMode() === "inactive") {
21203
+ content = ev.data || "";
21204
+ }
21205
+ else {
21206
+ content = this.contentHelper.getText();
21207
+ }
21208
+ if (this.props.focus === "inactive") {
21209
+ return this.props.onComposerCellFocused?.(content);
21210
+ }
21179
21211
  this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21180
21212
  this.env.model.dispatch("SET_CURRENT_CONTENT", {
21181
- content: this.contentHelper.getText(),
21213
+ content,
21182
21214
  selection: this.contentHelper.getCurrentSelection(),
21183
21215
  });
21184
21216
  }
@@ -21249,9 +21281,8 @@
21249
21281
  }
21250
21282
  const newSelection = this.contentHelper.getCurrentSelection();
21251
21283
  this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21252
- if (this.props.focus === "inactive") {
21253
- this.props.onComposerContentFocused(newSelection);
21254
- }
21284
+ this.props.onComposerContentFocused();
21285
+ if (this.props.focus === "inactive") ;
21255
21286
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
21256
21287
  this.processTokenAtCursor();
21257
21288
  }
@@ -21395,7 +21426,7 @@
21395
21426
  const highlights = this.env.model.getters.getHighlights();
21396
21427
  const refSheet = sheetName
21397
21428
  ? this.env.model.getters.getSheetIdByName(sheetName)
21398
- : this.env.model.getters.getCurrentEditedCell().sheetId;
21429
+ : this.env.model.getters.getCurrentEditedCell()?.sheetId;
21399
21430
  const highlight = highlights.find((highlight) => {
21400
21431
  if (highlight.sheetId !== refSheet)
21401
21432
  return false;
@@ -21472,12 +21503,13 @@
21472
21503
  }
21473
21504
  }
21474
21505
  Composer.props = {
21475
- focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
21476
- onComposerContentFocused: Function,
21477
21506
  inputStyle: { type: String, optional: true },
21478
21507
  rect: { type: Object, optional: true },
21479
21508
  delimitation: { type: Object, optional: true },
21480
- onComposerUnmounted: { type: Function, optional: true },
21509
+ focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
21510
+ onComposerCellFocused: { type: Function, optional: true },
21511
+ onComposerContentFocused: Function,
21512
+ isDefaultFocus: { type: Boolean, optional: true },
21481
21513
  };
21482
21514
 
21483
21515
  const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
@@ -21511,51 +21543,26 @@
21511
21543
  class GridComposer extends owl.Component {
21512
21544
  static template = "o-spreadsheet-GridComposer";
21513
21545
  static components = { Composer };
21514
- gridComposerRef;
21515
- zone;
21516
- rect;
21546
+ // TODORAR see if we can keep it undefined
21547
+ rect = this.defaultRect;
21548
+ isEditing = false;
21517
21549
  isCellReferenceVisible;
21518
- composerState;
21550
+ get defaultRect() {
21551
+ return { x: 0, y: 0, width: 0, height: 0 };
21552
+ }
21519
21553
  setup() {
21520
- this.gridComposerRef = owl.useRef("gridComposer");
21521
- this.composerState = owl.useState({
21522
- rect: undefined,
21523
- delimitation: undefined,
21524
- });
21525
- const { sheetId, col, row } = this.env.model.getters.getActivePosition();
21526
- this.zone = this.env.model.getters.expandZone(sheetId, positionToZone({ col, row }));
21527
- this.rect = this.env.model.getters.getVisibleRect(this.zone);
21528
- this.isCellReferenceVisible = false;
21529
- owl.onMounted(() => {
21530
- const el = this.gridComposerRef.el;
21531
- this.composerState.rect = {
21532
- x: this.rect.x,
21533
- y: this.rect.y,
21534
- width: el.clientWidth,
21535
- height: el.clientHeight,
21536
- };
21537
- this.composerState.delimitation = {
21538
- width: el.parentElement.clientWidth,
21539
- height: el.parentElement.clientHeight,
21540
- };
21541
- });
21542
21554
  owl.onWillUpdateProps(() => {
21543
- if (this.isCellReferenceVisible) {
21544
- return;
21545
- }
21546
- const sheetId = this.env.model.getters.getActiveSheetId();
21547
- const zone = this.env.model.getters.getSelectedZone();
21548
- const rect = this.env.model.getters.getVisibleRect(zone);
21549
- if (!deepEquals(rect, this.rect) ||
21550
- sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
21551
- this.isCellReferenceVisible = true;
21552
- }
21555
+ this.updateComponentPosition();
21556
+ this.updateCellReferenceVisibility();
21553
21557
  });
21554
21558
  }
21555
21559
  get shouldDisplayCellReference() {
21556
21560
  return this.isCellReferenceVisible;
21557
21561
  }
21558
21562
  get cellReference() {
21563
+ if (!this.env.model.getters.getCurrentEditedCell()) {
21564
+ return "";
21565
+ }
21559
21566
  const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
21560
21567
  const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
21561
21568
  return `${prefixSheet ? getCanonicalSheetName(this.env.model.getters.getSheetName(sheetId)) + "!" : ""}${toXC(col, row)}`;
@@ -21567,7 +21574,27 @@
21567
21574
  top: `${top - GRID_CELL_REFERENCE_TOP_OFFSET}px`,
21568
21575
  });
21569
21576
  }
21577
+ get composerProps() {
21578
+ const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
21579
+ return {
21580
+ rect: { ...this.rect },
21581
+ delimitation: {
21582
+ width,
21583
+ height,
21584
+ },
21585
+ focus: this.props.focus,
21586
+ isDefaultFocus: true,
21587
+ onComposerContentFocused: this.props.onComposerContentFocused,
21588
+ onComposerCellFocused: this.props.onComposerCellFocused,
21589
+ };
21590
+ }
21570
21591
  get containerStyle() {
21592
+ if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
21593
+ return `
21594
+ position: absolute;
21595
+ z-index: -1000;
21596
+ `;
21597
+ }
21571
21598
  const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
21572
21599
  const cell = this.env.model.getters.getActiveCell();
21573
21600
  const position = this.env.model.getters.getActivePosition();
@@ -21587,6 +21614,8 @@
21587
21614
  if (!isFormula) {
21588
21615
  textAlign = style.align || cell.defaultAlign;
21589
21616
  }
21617
+ const maxHeight = this.props.gridDims.height - this.rect.y;
21618
+ const maxWidth = this.props.gridDims.width - this.rect.x;
21590
21619
  /**
21591
21620
  * min-size is on the container, not the composer element, because we want to have the same size as the cell by default,
21592
21621
  * including all the paddings/margins of the composer
@@ -21598,6 +21627,8 @@
21598
21627
  top: `${top}px`,
21599
21628
  "min-width": `${width + 1}px`,
21600
21629
  "min-height": `${height + 1}px`,
21630
+ "max-width": `${maxWidth}px`,
21631
+ "max-height": `${maxHeight}px`,
21601
21632
  background,
21602
21633
  color,
21603
21634
  "font-size": `${fontSizeInPixels(fontSize)}px`,
@@ -21607,20 +21638,38 @@
21607
21638
  "text-align": textAlign,
21608
21639
  });
21609
21640
  }
21610
- get composerStyle() {
21611
- const maxHeight = this.props.gridDims.height - this.rect.y;
21612
- const maxWidth = this.props.gridDims.width - this.rect.x;
21613
- return cssPropertiesToCss({
21614
- "max-width": `${maxWidth}px`,
21615
- "max-height": `${maxHeight}px`,
21616
- });
21641
+ updateComponentPosition() {
21642
+ const isEditing = this.env.model.getters.getEditionMode() !== "inactive";
21643
+ if (this.isEditing !== isEditing) {
21644
+ this.isEditing = isEditing;
21645
+ if (!isEditing) {
21646
+ this.rect = this.defaultRect;
21647
+ this.env.focusableElement.focus();
21648
+ return;
21649
+ }
21650
+ const position = this.env.model.getters.getActivePosition();
21651
+ const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
21652
+ this.rect = this.env.model.getters.getVisibleRect(zone);
21653
+ }
21654
+ }
21655
+ updateCellReferenceVisibility() {
21656
+ if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
21657
+ return;
21658
+ }
21659
+ const sheetId = this.env.model.getters.getActiveSheetId();
21660
+ const zone = this.env.model.getters.getSelectedZone();
21661
+ const rect = this.env.model.getters.getVisibleRect(zone);
21662
+ if (!deepEquals(rect, this.rect) ||
21663
+ sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
21664
+ this.isCellReferenceVisible = true;
21665
+ }
21617
21666
  }
21618
21667
  }
21619
21668
  GridComposer.props = {
21620
21669
  focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
21621
- onComposerUnmounted: Function,
21622
21670
  onComposerContentFocused: Function,
21623
21671
  gridDims: Object,
21672
+ onComposerCellFocused: Function,
21624
21673
  };
21625
21674
 
21626
21675
  const CSS$1 = css /* scss */ `
@@ -22489,7 +22538,6 @@
22489
22538
  this.props.onCellDoubleClicked(col, row);
22490
22539
  }
22491
22540
  onContextMenu(ev) {
22492
- ev.preventDefault();
22493
22541
  const [col, row] = this.getCartesianCoordinates(ev);
22494
22542
  this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
22495
22543
  }
@@ -23583,7 +23631,6 @@
23583
23631
  HEADER_WIDTH = HEADER_WIDTH;
23584
23632
  menuState;
23585
23633
  gridRef;
23586
- hiddenInput;
23587
23634
  onMouseWheel;
23588
23635
  canvasPosition;
23589
23636
  hoveredCell;
@@ -23594,17 +23641,16 @@
23594
23641
  menuItems: [],
23595
23642
  });
23596
23643
  this.gridRef = owl.useRef("grid");
23597
- this.hiddenInput = owl.useRef("hiddenInput");
23598
23644
  this.canvasPosition = useAbsoluteBoundingRect(this.gridRef);
23599
23645
  this.hoveredCell = owl.useState({ col: undefined, row: undefined });
23600
23646
  owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
23601
23647
  owl.useExternalListener(document.body, "cut", this.copy.bind(this, true));
23602
23648
  owl.useExternalListener(document.body, "copy", this.copy.bind(this, false));
23603
23649
  owl.useExternalListener(document.body, "paste", this.paste);
23604
- owl.onMounted(() => this.focus());
23605
- this.props.exposeFocus(() => this.focus());
23650
+ owl.onMounted(() => this.focusDefaultElement());
23651
+ this.props.exposeFocus(() => this.focusDefaultElement());
23606
23652
  useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
23607
- owl.useEffect(() => this.focus(), () => [this.env.model.getters.getActiveSheetId()]);
23653
+ owl.useEffect(() => this.focusDefaultElement(), () => [this.env.model.getters.getActiveSheetId()]);
23608
23654
  this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
23609
23655
  this.moveCanvas(deltaX, deltaY);
23610
23656
  this.hoveredCell.col = undefined;
@@ -23627,7 +23673,7 @@
23627
23673
  if (this.env.model.getters.hasOpenedPopover()) {
23628
23674
  this.closeOpenedPopover();
23629
23675
  }
23630
- this.focus();
23676
+ this.focusDefaultElement();
23631
23677
  }
23632
23678
  // this map will handle most of the actions that should happen on key down. The arrow keys are managed in the key
23633
23679
  // down itself
@@ -23797,10 +23843,10 @@
23797
23843
  PAGEUP: () => this.env.model.dispatch("SHIFT_VIEWPORT_UP"),
23798
23844
  "CTRL+K": () => INSERT_LINK(this.env),
23799
23845
  };
23800
- focus() {
23846
+ focusDefaultElement() {
23801
23847
  if (!this.env.model.getters.getSelectedFigureId() &&
23802
23848
  this.env.model.getters.getEditionMode() === "inactive") {
23803
- this.hiddenInput.el?.focus();
23849
+ this.env.focusableElement.focus();
23804
23850
  }
23805
23851
  }
23806
23852
  get gridEl() {
@@ -23944,19 +23990,6 @@
23944
23990
  return;
23945
23991
  }
23946
23992
  }
23947
- onInput(ev) {
23948
- // the user meant to paste in the sheet, not open the composer with the pasted content
23949
- if (!ev.isComposing && ev.inputType === "insertFromPaste") {
23950
- return;
23951
- }
23952
- if (ev.data) {
23953
- // if the user types a character on the grid, it means he wants to start composing the selected cell with that
23954
- // character
23955
- ev.preventDefault();
23956
- ev.stopPropagation();
23957
- this.props.onGridComposerCellFocused(ev.data);
23958
- }
23959
- }
23960
23993
  // ---------------------------------------------------------------------------
23961
23994
  // Context Menu
23962
23995
  // ---------------------------------------------------------------------------
@@ -24066,7 +24099,7 @@
24066
24099
  }
24067
24100
  closeMenu() {
24068
24101
  this.menuState.isOpen = false;
24069
- this.focus();
24102
+ this.focusDefaultElement();
24070
24103
  }
24071
24104
  }
24072
24105
  Grid.props = {
@@ -28726,6 +28759,31 @@
28726
28759
  return data;
28727
28760
  },
28728
28761
  },
28762
+ {
28763
+ description: "Fix datafilter duplication",
28764
+ from: 12,
28765
+ to: 12.5,
28766
+ applyMigration(data) {
28767
+ for (let sheet of data.sheets || []) {
28768
+ let knownDataFilterZones = [];
28769
+ for (let filterTable of sheet.filterTables || []) {
28770
+ const zone = toZone(filterTable.range);
28771
+ // See commit message for the details
28772
+ const intersectZoneIndex = knownDataFilterZones.findIndex((knownZone) => overlap(knownZone, zone));
28773
+ if (intersectZoneIndex !== -1) {
28774
+ knownDataFilterZones[intersectZoneIndex] = zone;
28775
+ }
28776
+ else {
28777
+ knownDataFilterZones.push(zone);
28778
+ }
28779
+ }
28780
+ sheet.filterTables = knownDataFilterZones.map((zone) => ({
28781
+ range: zoneToXc(zone),
28782
+ }));
28783
+ }
28784
+ return data;
28785
+ },
28786
+ },
28729
28787
  {
28730
28788
  description: "Change Border description structure",
28731
28789
  from: 12,
@@ -29761,10 +29819,6 @@
29761
29819
  format: cell.format ? getItemId(cell.format, formats) : undefined,
29762
29820
  content: cell.content || undefined,
29763
29821
  };
29764
- // if there is a formula but no dependencies (maybe because the cell is in error), no need to recompute the formula text
29765
- if (cell.isFormula && cell.dependencies.length) {
29766
- cells[xc].content = this.buildFormulaContent(_sheet.id, cell, cell.dependencies, true);
29767
- }
29768
29822
  }
29769
29823
  _sheet.cells = cells;
29770
29824
  }
@@ -33839,6 +33893,10 @@
33839
33893
  if (cell.format !== evaluatedCell.format) {
33840
33894
  exportedCellData.computedFormat = evaluatedCell.format;
33841
33895
  }
33896
+ // if there is a formula but no dependencies (maybe because the cell is in error), no need to recompute the formula text
33897
+ if (cell.isFormula && cell.dependencies.length) {
33898
+ exportedCellData.content = this.getters.buildFormulaContent(sheet.id, cell, cell.dependencies, true);
33899
+ }
33842
33900
  }
33843
33901
  }
33844
33902
  }
@@ -41183,7 +41241,7 @@
41183
41241
  getZoneReference(zone, fixedParts = [{ colFixed: false, rowFixed: false }]) {
41184
41242
  const sheetId = this.getters.getActiveSheetId();
41185
41243
  let selectedXc = this.getters.zoneToXC(sheetId, zone, fixedParts);
41186
- if (this.getters.getCurrentEditedCell().sheetId !== this.getters.getActiveSheetId()) {
41244
+ if (this.getters.getCurrentEditedCell()?.sheetId !== this.getters.getActiveSheetId()) {
41187
41245
  const sheetName = getCanonicalSheetName(this.getters.getSheetName(this.getters.getActiveSheetId()));
41188
41246
  selectedXc = `${sheetName}!${selectedXc}`;
41189
41247
  }
@@ -41198,7 +41256,7 @@
41198
41256
  _fixedParts.pop();
41199
41257
  }
41200
41258
  const newRange = range.clone({ parts: _fixedParts });
41201
- return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell().sheetId);
41259
+ return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId());
41202
41260
  }
41203
41261
  /**
41204
41262
  * Replace the current selection by a new text.
@@ -41231,7 +41289,7 @@
41231
41289
  if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
41232
41290
  return;
41233
41291
  }
41234
- const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
41292
+ const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
41235
41293
  const XCs = this.getReferencedRanges().map((range) => this.getters.getRangeString(range, editionSheetId));
41236
41294
  const colorsToKeep = {};
41237
41295
  for (const xc of XCs) {
@@ -41260,7 +41318,7 @@
41260
41318
  if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
41261
41319
  return [];
41262
41320
  }
41263
- const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
41321
+ const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
41264
41322
  const rangeColor = (rangeString) => {
41265
41323
  const colorIndex = this.colorIndexByRange[rangeString];
41266
41324
  return colors$1[colorIndex % colors$1.length];
@@ -41278,7 +41336,7 @@
41278
41336
  * Return ranges currently referenced in the composer
41279
41337
  */
41280
41338
  getReferencedRanges() {
41281
- const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
41339
+ const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
41282
41340
  const referenceRanges = this.currentTokens
41283
41341
  .filter((token) => token.type === "REFERENCE")
41284
41342
  .map((token) => this.getters.getRangeFromSheetXC(editionSheetId, token.value));
@@ -42089,6 +42147,16 @@
42089
42147
  }
42090
42148
  }
42091
42149
 
42150
+ class FocusableElement {
42151
+ focusableElement = undefined;
42152
+ setFocusableElement(element) {
42153
+ this.focusableElement = element;
42154
+ }
42155
+ focus() {
42156
+ this.focusableElement?.focus();
42157
+ }
42158
+ }
42159
+
42092
42160
  const RIPPLE_KEY_FRAMES = [
42093
42161
  { transform: "scale(0)" },
42094
42162
  { transform: "scale(0.8)", offset: 0.33 },
@@ -44117,6 +44185,7 @@
44117
44185
  _t: Spreadsheet._t,
44118
44186
  clipboard: this.env.clipboard || instantiateClipboard(),
44119
44187
  startCellEdition: (content) => this.onGridComposerCellFocused(content),
44188
+ focusableElement: new FocusableElement(),
44120
44189
  });
44121
44190
  owl.useExternalListener(window, "resize", () => this.render(true));
44122
44191
  owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
@@ -44223,17 +44292,18 @@
44223
44292
  this.model.dispatch("UNFOCUS_SELECTION_INPUT");
44224
44293
  this.composer.topBarFocus = "contentFocus";
44225
44294
  this.composer.gridFocusMode = "inactive";
44226
- this.setComposerContent({ selection } || {});
44295
+ this.setComposerContent({ selection });
44227
44296
  }
44228
- onGridComposerContentFocused() {
44297
+ onGridComposerContentFocused(selection) {
44229
44298
  if (this.model.getters.isReadonly()) {
44230
44299
  return;
44231
44300
  }
44232
44301
  this.model.dispatch("UNFOCUS_SELECTION_INPUT");
44233
44302
  this.composer.topBarFocus = "inactive";
44234
44303
  this.composer.gridFocusMode = "contentFocus";
44235
- this.setComposerContent({});
44304
+ this.setComposerContent({ selection });
44236
44305
  }
44306
+ // TODO: either both are defined or none of them. change those args to an object
44237
44307
  onGridComposerCellFocused(content, selection) {
44238
44308
  if (this.model.getters.isReadonly()) {
44239
44309
  return;
@@ -47937,9 +48007,9 @@
47937
48007
  Object.defineProperty(exports, '__esModule', { value: true });
47938
48008
 
47939
48009
 
47940
- __info__.version = '16.3.24';
47941
- __info__.date = '2024-02-02T13:45:48.440Z';
47942
- __info__.hash = '0bf5f45';
48010
+ __info__.version = '16.3.25';
48011
+ __info__.date = '2024-02-09T13:07:06.947Z';
48012
+ __info__.hash = 'b53bf1b';
47943
48013
 
47944
48014
 
47945
48015
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);