@odoo/o-spreadsheet 17.1.3 → 17.1.4

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 17.1.3
6
- * @date 2024-02-02T13:46:54.332Z
7
- * @hash 798f979
5
+ * @version 17.1.4
6
+ * @date 2024-02-09T13:09:13.430Z
7
+ * @hash 16d3ece
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -2939,6 +2939,9 @@
2939
2939
  }
2940
2940
  switch (typeof value) {
2941
2941
  case "string":
2942
+ if (value.includes('\\"')) {
2943
+ return value.replace(/\\"/g, '"');
2944
+ }
2942
2945
  return value;
2943
2946
  case "boolean":
2944
2947
  return value ? "TRUE" : "FALSE";
@@ -4992,14 +4995,8 @@
4992
4995
  : undefined));
4993
4996
  }
4994
4997
  }
4995
- else if (zone.left === zone.right && zone.top === zone.bottom) {
4996
- // A single cell. If it's only the title, the dataset is not added.
4997
- if (!dataSetsHaveTitle) {
4998
- dataSets.push(createDataSet(getters, dataSetSheetId, zone, undefined));
4999
- }
5000
- }
5001
4998
  else {
5002
- /* 1 row or 1 column */
4999
+ /* 1 cell, 1 row or 1 column */
5003
5000
  dataSets.push(createDataSet(getters, dataSetSheetId, zone, dataSetsHaveTitle
5004
5001
  ? {
5005
5002
  top: zone.top,
@@ -7442,7 +7439,7 @@
7442
7439
  while (!chars.isOver()) {
7443
7440
  let token = tokenizeSpace(chars) ||
7444
7441
  tokenizeArgsSeparator(chars, locale) ||
7445
- tokenizeMisc(chars) ||
7442
+ tokenizeParenthesis(chars) ||
7446
7443
  tokenizeOperator(chars) ||
7447
7444
  tokenizeString(chars) ||
7448
7445
  tokenizeDebugger(chars) ||
@@ -7463,15 +7460,14 @@
7463
7460
  }
7464
7461
  return null;
7465
7462
  }
7466
- const misc$1 = {
7467
- "(": "LEFT_PAREN",
7468
- ")": "RIGHT_PAREN",
7463
+ const parenthesis = {
7464
+ "(": { type: "LEFT_PAREN", value: "(" },
7465
+ ")": { type: "RIGHT_PAREN", value: ")" },
7469
7466
  };
7470
- function tokenizeMisc(chars) {
7471
- if (chars.current in misc$1) {
7467
+ function tokenizeParenthesis(chars) {
7468
+ if (chars.current === "(" || chars.current === ")") {
7472
7469
  const value = chars.shift();
7473
- const type = misc$1[value];
7474
- return { type, value };
7470
+ return parenthesis[value];
7475
7471
  }
7476
7472
  return null;
7477
7473
  }
@@ -7492,7 +7488,12 @@
7492
7488
  }
7493
7489
  return null;
7494
7490
  }
7491
+ const FIRST_POSSIBLE_NUMBER_CHARS = new Set("0123456789");
7495
7492
  function tokenizeNumber(chars, locale) {
7493
+ if (!FIRST_POSSIBLE_NUMBER_CHARS.has(chars.current) &&
7494
+ chars.current !== locale.decimalSeparator) {
7495
+ return null;
7496
+ }
7496
7497
  const match = chars.remaining().match(getFormulaNumberRegex(locale.decimalSeparator));
7497
7498
  if (match) {
7498
7499
  chars.advanceBy(match[0].length);
@@ -7517,7 +7518,7 @@
7517
7518
  }
7518
7519
  return null;
7519
7520
  }
7520
- const separatorRegexp = /\w|\.|!|\$/;
7521
+ const separatorRegexp = /^[\w\.!\$]+/;
7521
7522
  /**
7522
7523
  * A "Symbol" is just basically any word-like element that can appear in a
7523
7524
  * formula, which is not a string. So:
@@ -7557,8 +7558,11 @@
7557
7558
  };
7558
7559
  }
7559
7560
  }
7560
- while (chars.current && separatorRegexp.test(chars.current)) {
7561
- result += chars.shift();
7561
+ const match = chars.remaining().match(separatorRegexp);
7562
+ if (match) {
7563
+ const value = match[0];
7564
+ result += value;
7565
+ chars.advanceBy(value.length);
7562
7566
  }
7563
7567
  if (result.length) {
7564
7568
  const value = result;
@@ -7620,7 +7624,10 @@
7620
7624
  return this.text.substring(this.currentIndex);
7621
7625
  }
7622
7626
  currentStartsWith(str) {
7623
- for (let j = 0; j < str.length; j++) {
7627
+ if (this.current !== str[0]) {
7628
+ return false;
7629
+ }
7630
+ for (let j = 1; j < str.length; j++) {
7624
7631
  if (this.text[this.currentIndex + j] !== str[j]) {
7625
7632
  return false;
7626
7633
  }
@@ -8652,7 +8659,7 @@
8652
8659
  return undefined;
8653
8660
  const dataSets = this.dataSets
8654
8661
  .map((ds) => toExcelDataset(this.getters, ds))
8655
- .filter((ds) => ds.range !== ""); // && range !== CellErrorType.InvalidReference ? show incorrect #ref ?
8662
+ .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
8656
8663
  const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
8657
8664
  return {
8658
8665
  ...this.getDefinition(),
@@ -9230,7 +9237,7 @@
9230
9237
  return undefined;
9231
9238
  const dataSets = this.dataSets
9232
9239
  .map((ds) => toExcelDataset(this.getters, ds))
9233
- .filter((ds) => ds.range !== ""); // && range !== CellErrorType.InvalidReference ? show incorrect #ref ?
9240
+ .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
9234
9241
  const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
9235
9242
  return {
9236
9243
  ...this.getDefinition(),
@@ -9536,7 +9543,7 @@
9536
9543
  return undefined;
9537
9544
  const dataSets = this.dataSets
9538
9545
  .map((ds) => toExcelDataset(this.getters, ds))
9539
- .filter((ds) => ds.range !== ""); // && range !== CellErrorType.InvalidReference ? show incorrect #ref ?
9546
+ .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
9540
9547
  const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
9541
9548
  return {
9542
9549
  ...this.getDefinition(),
@@ -18683,6 +18690,9 @@
18683
18690
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18684
18691
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18685
18692
  assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18693
+ if (searchKey && isEvaluationError(searchKey.value)) {
18694
+ return searchKey;
18695
+ }
18686
18696
  const getValueFromRange = (range, index) => range[index][0].value;
18687
18697
  const _isSorted = toBoolean(isSorted.value);
18688
18698
  const colIndex = _isSorted
@@ -18850,6 +18860,9 @@
18850
18860
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18851
18861
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18852
18862
  assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18863
+ if (searchKey && isEvaluationError(searchKey.value)) {
18864
+ return searchKey;
18865
+ }
18853
18866
  const getValueFromRange = (range, index) => range[0][index].value;
18854
18867
  const _isSorted = toBoolean(isSorted.value);
18855
18868
  const rowIndex = _isSorted
@@ -18889,6 +18902,9 @@
18889
18902
  assert(() => lookupDirection === "col"
18890
18903
  ? returnRange[0].length === lookupRange[0].length
18891
18904
  : returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18905
+ if (searchKey && isEvaluationError(searchKey.value)) {
18906
+ return [[searchKey]];
18907
+ }
18892
18908
  const getElement = lookupDirection === "col"
18893
18909
  ? (range, index) => range[0][index].value
18894
18910
  : (range, index) => range[index][0].value;
@@ -26970,15 +26986,17 @@
26970
26986
  focus: {
26971
26987
  validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
26972
26988
  },
26973
- onComposerContentFocused: Function,
26974
26989
  inputStyle: { type: String, optional: true },
26975
26990
  rect: { type: Object, optional: true },
26976
26991
  delimitation: { type: Object, optional: true },
26977
- onComposerUnmounted: { type: Function, optional: true },
26992
+ onComposerCellFocused: { type: Function, optional: true },
26993
+ onComposerContentFocused: Function,
26994
+ isDefaultFocus: { type: Boolean, optional: true },
26978
26995
  };
26979
26996
  static components = { TextValueProvider, FunctionDescriptionProvider };
26980
26997
  static defaultProps = {
26981
26998
  inputStyle: "",
26999
+ isDefaultFocus: false,
26982
27000
  };
26983
27001
  composerRef = owl.useRef("o_composer");
26984
27002
  contentHelper = new ContentEditableHelper(this.composerRef.el);
@@ -27035,7 +27053,6 @@
27035
27053
  F4: this.processF4Key,
27036
27054
  Tab: (ev) => this.processTabKey(ev, "right"),
27037
27055
  "Shift+Tab": (ev) => this.processTabKey(ev, "left"),
27038
- "Ctrl+ ": this.processSpaceKey,
27039
27056
  };
27040
27057
  keyCodeMapping = {
27041
27058
  NumpadDecimal: this.processNumpadDecimal,
@@ -27043,12 +27060,12 @@
27043
27060
  setup() {
27044
27061
  owl.onMounted(() => {
27045
27062
  const el = this.composerRef.el;
27063
+ if (this.props.isDefaultFocus) {
27064
+ this.env.focusableElement.setFocusableElement(el);
27065
+ }
27046
27066
  this.contentHelper.updateEl(el);
27047
27067
  this.processTokenAtCursor();
27048
27068
  });
27049
- owl.onWillUnmount(() => {
27050
- this.props.onComposerUnmounted?.();
27051
- });
27052
27069
  owl.useEffect(() => {
27053
27070
  this.processContent();
27054
27071
  });
@@ -27057,7 +27074,8 @@
27057
27074
  // Handlers
27058
27075
  // ---------------------------------------------------------------------------
27059
27076
  processArrowKeys(ev) {
27060
- if (this.env.model.getters.isSelectingForComposer()) {
27077
+ if (this.env.model.getters.isSelectingForComposer() ||
27078
+ this.env.model.getters.getEditionMode() === "inactive") {
27061
27079
  this.functionDescriptionState.showDescription = false;
27062
27080
  // Prevent the default content editable behavior which moves the cursor
27063
27081
  ev.preventDefault();
@@ -27100,23 +27118,19 @@
27100
27118
  processTabKey(ev, direction) {
27101
27119
  ev.preventDefault();
27102
27120
  ev.stopPropagation();
27103
- const state = this.autoCompleteState;
27104
- if (state.showProvider && state.selectedIndex !== undefined) {
27105
- const autoCompleteValue = this.autoCompleteState.values[state.selectedIndex]?.text;
27106
- if (autoCompleteValue) {
27107
- this.autoComplete(autoCompleteValue);
27108
- return;
27121
+ if (this.env.model.getters.getEditionMode() !== "inactive") {
27122
+ const state = this.autoCompleteState;
27123
+ if (state.showProvider && state.selectedIndex !== undefined) {
27124
+ const autoCompleteValue = this.autoCompleteState.values[state.selectedIndex]?.text;
27125
+ if (autoCompleteValue) {
27126
+ this.autoComplete(autoCompleteValue);
27127
+ return;
27128
+ }
27109
27129
  }
27130
+ interactiveStopEdition(this.env);
27110
27131
  }
27111
- interactiveStopEdition(this.env);
27112
27132
  this.env.model.selection.moveAnchorCell(direction, 1);
27113
27133
  }
27114
- processSpaceKey(ev) {
27115
- ev.preventDefault();
27116
- ev.stopPropagation();
27117
- this.showFunctionAutocomplete("");
27118
- this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
27119
- }
27120
27134
  processEnterKey(ev, direction) {
27121
27135
  ev.preventDefault();
27122
27136
  ev.stopPropagation();
@@ -27178,6 +27192,9 @@
27178
27192
  this.compositionActive = false;
27179
27193
  }
27180
27194
  onKeydown(ev) {
27195
+ if (this.env.model.getters.getEditionMode() === "inactive") {
27196
+ return;
27197
+ }
27181
27198
  if (ev.key.startsWith("Arrow")) {
27182
27199
  this.processArrowKeys(ev);
27183
27200
  return;
@@ -27191,14 +27208,33 @@
27191
27208
  ev.stopPropagation();
27192
27209
  }
27193
27210
  }
27211
+ onPaste(ev) {
27212
+ if (this.env.model.getters.getEditionMode() !== "inactive") {
27213
+ ev.stopPropagation();
27214
+ }
27215
+ }
27194
27216
  /*
27195
27217
  * Triggered automatically by the content-editable between the keydown and key up
27196
27218
  * */
27197
27219
  onInput(ev) {
27198
- if (this.props.focus === "inactive" || !this.shouldProcessInputEvents) {
27220
+ if (!this.shouldProcessInputEvents) {
27221
+ return;
27222
+ }
27223
+ if (ev.inputType === "insertFromPaste" &&
27224
+ this.env.model.getters.getEditionMode() === "inactive") {
27199
27225
  return;
27200
27226
  }
27201
- let content = this.contentHelper.getText();
27227
+ ev.stopPropagation();
27228
+ let content;
27229
+ if (this.env.model.getters.getEditionMode() === "inactive") {
27230
+ content = ev.data || "";
27231
+ }
27232
+ else {
27233
+ content = this.contentHelper.getText();
27234
+ }
27235
+ if (this.props.focus === "inactive") {
27236
+ return this.props.onComposerCellFocused?.(content);
27237
+ }
27202
27238
  let selection = this.contentHelper.getCurrentSelection();
27203
27239
  this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
27204
27240
  this.env.model.dispatch("SET_CURRENT_CONTENT", {
@@ -27274,9 +27310,8 @@
27274
27310
  }
27275
27311
  const newSelection = this.contentHelper.getCurrentSelection();
27276
27312
  this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
27277
- if (this.props.focus === "inactive") {
27278
- this.props.onComposerContentFocused(newSelection);
27279
- }
27313
+ this.props.onComposerContentFocused();
27314
+ if (this.props.focus === "inactive") ;
27280
27315
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
27281
27316
  this.processTokenAtCursor();
27282
27317
  }
@@ -27443,7 +27478,7 @@
27443
27478
  const highlights = this.env.model.getters.getHighlights();
27444
27479
  const refSheet = sheetName
27445
27480
  ? this.env.model.getters.getSheetIdByName(sheetName)
27446
- : this.env.model.getters.getCurrentEditedCell().sheetId;
27481
+ : this.env.model.getters.getCurrentEditedCell()?.sheetId;
27447
27482
  const highlight = highlights.find((highlight) => {
27448
27483
  if (highlight.sheetId !== refSheet)
27449
27484
  return false;
@@ -27570,56 +27605,30 @@
27570
27605
  focus: {
27571
27606
  validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
27572
27607
  },
27573
- onComposerUnmounted: Function,
27608
+ onComposerCellFocused: Function,
27574
27609
  onComposerContentFocused: Function,
27575
27610
  gridDims: Object,
27576
27611
  };
27577
27612
  static components = { Composer };
27578
- gridComposerRef;
27579
- zone;
27580
- rect;
27613
+ rect = this.defaultRect;
27614
+ isEditing = false;
27581
27615
  isCellReferenceVisible;
27582
- composerState;
27616
+ get defaultRect() {
27617
+ return { x: 0, y: 0, width: 0, height: 0 };
27618
+ }
27583
27619
  setup() {
27584
- this.gridComposerRef = owl.useRef("gridComposer");
27585
- this.composerState = owl.useState({
27586
- rect: undefined,
27587
- delimitation: undefined,
27588
- });
27589
- const { sheetId, col, row } = this.env.model.getters.getActivePosition();
27590
- this.zone = this.env.model.getters.expandZone(sheetId, positionToZone({ col, row }));
27591
- this.rect = this.env.model.getters.getVisibleRect(this.zone);
27592
- this.isCellReferenceVisible = false;
27593
- owl.onMounted(() => {
27594
- const el = this.gridComposerRef.el;
27595
- this.composerState.rect = {
27596
- x: this.rect.x,
27597
- y: this.rect.y,
27598
- width: el.clientWidth,
27599
- height: el.clientHeight,
27600
- };
27601
- this.composerState.delimitation = {
27602
- width: this.props.gridDims.width,
27603
- height: this.props.gridDims.height,
27604
- };
27605
- });
27606
27620
  owl.onWillUpdateProps(() => {
27607
- if (this.isCellReferenceVisible) {
27608
- return;
27609
- }
27610
- const sheetId = this.env.model.getters.getActiveSheetId();
27611
- const zone = this.env.model.getters.getSelectedZone();
27612
- const rect = this.env.model.getters.getVisibleRect(zone);
27613
- if (!deepEquals(rect, this.rect) ||
27614
- sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
27615
- this.isCellReferenceVisible = true;
27616
- }
27621
+ this.updateComponentPosition();
27622
+ this.updateCellReferenceVisibility();
27617
27623
  });
27618
27624
  }
27619
27625
  get shouldDisplayCellReference() {
27620
27626
  return this.isCellReferenceVisible;
27621
27627
  }
27622
27628
  get cellReference() {
27629
+ if (!this.env.model.getters.getCurrentEditedCell()) {
27630
+ return "";
27631
+ }
27623
27632
  const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
27624
27633
  const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
27625
27634
  return getFullReference(prefixSheet ? this.env.model.getters.getSheetName(sheetId) : undefined, toXC(col, row));
@@ -27631,7 +27640,27 @@
27631
27640
  top: `${top - GRID_CELL_REFERENCE_TOP_OFFSET}px`,
27632
27641
  });
27633
27642
  }
27643
+ get composerProps() {
27644
+ const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
27645
+ return {
27646
+ rect: { ...this.rect },
27647
+ delimitation: {
27648
+ width,
27649
+ height,
27650
+ },
27651
+ focus: this.props.focus,
27652
+ isDefaultFocus: true,
27653
+ onComposerContentFocused: this.props.onComposerContentFocused,
27654
+ onComposerCellFocused: this.props.onComposerCellFocused,
27655
+ };
27656
+ }
27634
27657
  get containerStyle() {
27658
+ if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
27659
+ return `
27660
+ position: absolute;
27661
+ z-index: -1000;
27662
+ `;
27663
+ }
27635
27664
  const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
27636
27665
  const cell = this.env.model.getters.getActiveCell();
27637
27666
  const position = this.env.model.getters.getActivePosition();
@@ -27651,6 +27680,8 @@
27651
27680
  if (!isFormula) {
27652
27681
  textAlign = style.align || cell.defaultAlign;
27653
27682
  }
27683
+ const maxHeight = this.props.gridDims.height - this.rect.y;
27684
+ const maxWidth = this.props.gridDims.width - this.rect.x;
27654
27685
  /**
27655
27686
  * min-size is on the container, not the composer element, because we want to have the same size as the cell by default,
27656
27687
  * including all the paddings/margins of the composer
@@ -27662,6 +27693,8 @@
27662
27693
  top: `${top}px`,
27663
27694
  "min-width": `${width + 1}px`,
27664
27695
  "min-height": `${height + 1}px`,
27696
+ "max-width": `${maxWidth}px`,
27697
+ "max-height": `${maxHeight}px`,
27665
27698
  background,
27666
27699
  color,
27667
27700
  "font-size": `${fontSizeInPixels(fontSize)}px`,
@@ -27671,13 +27704,31 @@
27671
27704
  "text-align": textAlign,
27672
27705
  });
27673
27706
  }
27674
- get composerStyle() {
27675
- const maxHeight = this.props.gridDims.height - this.rect.y;
27676
- const maxWidth = this.props.gridDims.width - this.rect.x;
27677
- return cssPropertiesToCss({
27678
- "max-width": `${maxWidth}px`,
27679
- "max-height": `${maxHeight}px`,
27680
- });
27707
+ updateComponentPosition() {
27708
+ const isEditing = this.env.model.getters.getEditionMode() !== "inactive";
27709
+ if (this.isEditing !== isEditing) {
27710
+ this.isEditing = isEditing;
27711
+ if (!isEditing) {
27712
+ this.rect = this.defaultRect;
27713
+ this.env.focusableElement.focus();
27714
+ return;
27715
+ }
27716
+ const position = this.env.model.getters.getActivePosition();
27717
+ const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
27718
+ this.rect = this.env.model.getters.getVisibleRect(zone);
27719
+ }
27720
+ }
27721
+ updateCellReferenceVisibility() {
27722
+ if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
27723
+ return;
27724
+ }
27725
+ const sheetId = this.env.model.getters.getActiveSheetId();
27726
+ const zone = this.env.model.getters.getSelectedZone();
27727
+ const rect = this.env.model.getters.getVisibleRect(zone);
27728
+ if (!deepEquals(rect, this.rect) ||
27729
+ sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
27730
+ this.isCellReferenceVisible = true;
27731
+ }
27681
27732
  }
27682
27733
  }
27683
27734
 
@@ -28777,7 +28828,6 @@
28777
28828
  this.props.onCellDoubleClicked(col, row);
28778
28829
  }
28779
28830
  onContextMenu(ev) {
28780
- ev.preventDefault();
28781
28831
  const [col, row] = this.getCartesianCoordinates(ev);
28782
28832
  this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
28783
28833
  }
@@ -29842,7 +29892,6 @@
29842
29892
  HEADER_WIDTH = HEADER_WIDTH;
29843
29893
  menuState;
29844
29894
  gridRef;
29845
- hiddenInput;
29846
29895
  onMouseWheel;
29847
29896
  canvasPosition;
29848
29897
  hoveredCell;
@@ -29853,15 +29902,14 @@
29853
29902
  menuItems: [],
29854
29903
  });
29855
29904
  this.gridRef = owl.useRef("grid");
29856
- this.hiddenInput = owl.useRef("hiddenInput");
29857
29905
  this.canvasPosition = useAbsoluteBoundingRect(this.gridRef);
29858
29906
  this.hoveredCell = owl.useState({ col: undefined, row: undefined });
29859
29907
  owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
29860
29908
  owl.useExternalListener(document.body, "cut", this.copy.bind(this, true));
29861
29909
  owl.useExternalListener(document.body, "copy", this.copy.bind(this, false));
29862
29910
  owl.useExternalListener(document.body, "paste", this.paste);
29863
- owl.onMounted(() => this.focus());
29864
- this.props.exposeFocus(() => this.focus());
29911
+ owl.onMounted(() => this.focusDefaultElement());
29912
+ this.props.exposeFocus(() => this.focusDefaultElement());
29865
29913
  useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
29866
29914
  this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
29867
29915
  this.moveCanvas(deltaX, deltaY);
@@ -29885,7 +29933,7 @@
29885
29933
  if (this.env.model.getters.hasOpenedPopover()) {
29886
29934
  this.closeOpenedPopover();
29887
29935
  }
29888
- this.focus();
29936
+ this.focusDefaultElement();
29889
29937
  }
29890
29938
  // this map will handle most of the actions that should happen on key down. The arrow keys are managed in the key
29891
29939
  // down itself
@@ -30064,10 +30112,10 @@
30064
30112
  "Alt+Shift+ArrowUp": () => this.processHeaderGroupingKey("up"),
30065
30113
  "Alt+Shift+ArrowDown": () => this.processHeaderGroupingKey("down"),
30066
30114
  };
30067
- focus() {
30115
+ focusDefaultElement() {
30068
30116
  if (!this.env.model.getters.getSelectedFigureId() &&
30069
30117
  this.env.model.getters.getEditionMode() === "inactive") {
30070
- this.hiddenInput.el?.focus();
30118
+ this.env.focusableElement.focus();
30071
30119
  }
30072
30120
  }
30073
30121
  get gridEl() {
@@ -30203,19 +30251,6 @@
30203
30251
  return;
30204
30252
  }
30205
30253
  }
30206
- onInput(ev) {
30207
- // the user meant to paste in the sheet, not open the composer with the pasted content
30208
- if (!ev.isComposing && ev.inputType === "insertFromPaste") {
30209
- return;
30210
- }
30211
- if (ev.data) {
30212
- // if the user types a character on the grid, it means he wants to start composing the selected cell with that
30213
- // character
30214
- ev.preventDefault();
30215
- ev.stopPropagation();
30216
- this.props.onGridComposerCellFocused(ev.data);
30217
- }
30218
- }
30219
30254
  // ---------------------------------------------------------------------------
30220
30255
  // Context Menu
30221
30256
  // ---------------------------------------------------------------------------
@@ -30330,7 +30365,7 @@
30330
30365
  }
30331
30366
  closeMenu() {
30332
30367
  this.menuState.isOpen = false;
30333
- this.focus();
30368
+ this.focusDefaultElement();
30334
30369
  }
30335
30370
  processHeaderGroupingKey(direction) {
30336
30371
  if (this.env.model.getters.getSelectedZones().length !== 1) {
@@ -34247,6 +34282,31 @@
34247
34282
  return data;
34248
34283
  },
34249
34284
  },
34285
+ {
34286
+ description: "Fix datafilter duplication",
34287
+ from: 12,
34288
+ to: 12.5,
34289
+ applyMigration(data) {
34290
+ for (let sheet of data.sheets || []) {
34291
+ let knownDataFilterZones = [];
34292
+ for (let filterTable of sheet.filterTables || []) {
34293
+ const zone = toZone(filterTable.range);
34294
+ // See commit message for the details
34295
+ const intersectZoneIndex = knownDataFilterZones.findIndex((knownZone) => overlap(knownZone, zone));
34296
+ if (intersectZoneIndex !== -1) {
34297
+ knownDataFilterZones[intersectZoneIndex] = zone;
34298
+ }
34299
+ else {
34300
+ knownDataFilterZones.push(zone);
34301
+ }
34302
+ }
34303
+ sheet.filterTables = knownDataFilterZones.map((zone) => ({
34304
+ range: zoneToXc(zone),
34305
+ }));
34306
+ }
34307
+ return data;
34308
+ },
34309
+ },
34250
34310
  {
34251
34311
  description: "Change Border description structure",
34252
34312
  from: 12,
@@ -36033,9 +36093,6 @@
36033
36093
  format: cell.format ? getItemId(cell.format, formats) : undefined,
36034
36094
  content: cell.content || undefined,
36035
36095
  };
36036
- if (cell instanceof FormulaCellWithDependencies) {
36037
- cells[xc].content = cell.contentWithFixedReferences || undefined;
36038
- }
36039
36096
  }
36040
36097
  _sheet.cells = cells;
36041
36098
  }
@@ -36287,8 +36344,11 @@
36287
36344
  * being a computed property to rebuild the dependencies XC.
36288
36345
  */
36289
36346
  createFormulaCellWithDependencies(id, compiledFormula, format, style, sheetId) {
36290
- const dependencies = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
36291
- return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.getters.getRangeString.bind(this));
36347
+ const dependencies = [];
36348
+ for (const xc of compiledFormula.dependencies) {
36349
+ dependencies.push(this.getters.getRangeFromSheetXC(sheetId, xc));
36350
+ }
36351
+ return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.getters.getRangeString);
36292
36352
  }
36293
36353
  createErrorFormula(id, content, format, style, error) {
36294
36354
  return {
@@ -36342,7 +36402,7 @@
36342
36402
  const tokens = compiledFormula.tokens.map((token) => {
36343
36403
  if (token.type === "REFERENCE") {
36344
36404
  const index = rangeIndex++;
36345
- return new RangeReferenceToken(() => this.getRangeString(dependencies[index], this.sheetId));
36405
+ return new RangeReferenceToken(dependencies, index, this.sheetId, this.getRangeString);
36346
36406
  }
36347
36407
  return token;
36348
36408
  });
@@ -36369,13 +36429,20 @@
36369
36429
  }
36370
36430
  }
36371
36431
  class RangeReferenceToken {
36372
- getValue;
36432
+ ranges;
36433
+ rangeIndex;
36434
+ sheetId;
36435
+ getRangeString;
36373
36436
  type = "REFERENCE";
36374
- constructor(getValue) {
36375
- this.getValue = getValue;
36437
+ constructor(ranges, rangeIndex, sheetId, getRangeString) {
36438
+ this.ranges = ranges;
36439
+ this.rangeIndex = rangeIndex;
36440
+ this.sheetId = sheetId;
36441
+ this.getRangeString = getRangeString;
36376
36442
  }
36377
36443
  get value() {
36378
- return this.getValue();
36444
+ const range = this.ranges[this.rangeIndex];
36445
+ return this.getRangeString(range, this.sheetId);
36379
36446
  }
36380
36447
  }
36381
36448
 
@@ -41910,7 +41977,13 @@
41910
41977
  const format = newFormat
41911
41978
  ? getItemId(newFormat, data.formats)
41912
41979
  : exportedCellData.format;
41913
- const content = !isExported ? newContent : exportedCellData.content;
41980
+ let content;
41981
+ if (formulaCell instanceof FormulaCellWithDependencies) {
41982
+ content = formulaCell.contentWithFixedReferences;
41983
+ }
41984
+ else {
41985
+ content = !isExported ? newContent : exportedCellData.content;
41986
+ }
41914
41987
  exportedSheetData.cells[xc] = { ...exportedCellData, value, isFormula, content, format };
41915
41988
  }
41916
41989
  }
@@ -51094,6 +51167,16 @@
51094
51167
  }
51095
51168
  }
51096
51169
 
51170
+ class FocusableElement {
51171
+ focusableElement = undefined;
51172
+ setFocusableElement(element) {
51173
+ this.focusableElement = element;
51174
+ }
51175
+ focus() {
51176
+ this.focusableElement?.focus();
51177
+ }
51178
+ }
51179
+
51097
51180
  const RIPPLE_KEY_FRAMES = [
51098
51181
  { transform: "scale(0)" },
51099
51182
  { transform: "scale(0.8)", offset: 0.33 },
@@ -53248,6 +53331,7 @@
53248
53331
  toggleSidePanel: this.toggleSidePanel.bind(this),
53249
53332
  clipboard: this.env.clipboard || instantiateClipboard(),
53250
53333
  startCellEdition: (content) => this.onGridComposerCellFocused(content),
53334
+ focusableElement: new FocusableElement(),
53251
53335
  });
53252
53336
  owl.useEffect(() => {
53253
53337
  /**
@@ -53366,16 +53450,17 @@
53366
53450
  }
53367
53451
  this.composer.topBarFocus = "contentFocus";
53368
53452
  this.composer.gridFocusMode = "inactive";
53369
- this.setComposerContent({ selection } || {});
53453
+ this.setComposerContent({ selection });
53370
53454
  }
53371
- onGridComposerContentFocused() {
53455
+ onGridComposerContentFocused(selection) {
53372
53456
  if (this.model.getters.isReadonly()) {
53373
53457
  return;
53374
53458
  }
53375
53459
  this.composer.topBarFocus = "inactive";
53376
53460
  this.composer.gridFocusMode = "contentFocus";
53377
- this.setComposerContent({});
53461
+ this.setComposerContent({ selection });
53378
53462
  }
53463
+ // TODO: either both are defined or none of them. change those args to an object
53379
53464
  onGridComposerCellFocused(content, selection) {
53380
53465
  if (this.model.getters.isReadonly()) {
53381
53466
  return;
@@ -57099,9 +57184,9 @@
57099
57184
  exports.tokenize = tokenize;
57100
57185
 
57101
57186
 
57102
- __info__.version = "17.1.3";
57103
- __info__.date = "2024-02-02T13:46:54.332Z";
57104
- __info__.hash = "798f979";
57187
+ __info__.version = "17.1.4";
57188
+ __info__.date = "2024-02-09T13:09:13.430Z";
57189
+ __info__.hash = "16d3ece";
57105
57190
 
57106
57191
 
57107
57192
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);