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