@odoo/o-spreadsheet 18.4.11 → 18.4.13

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 18.4.11
6
- * @date 2025-09-19T07:25:39.033Z
7
- * @hash c7e71ac
5
+ * @version 18.4.13
6
+ * @date 2025-10-07T10:00:55.413Z
7
+ * @hash d4df70e
8
8
  */
9
9
 
10
10
  'use strict';
@@ -906,9 +906,7 @@ function removeIndexesFromArray(array, indexes) {
906
906
  return newArray;
907
907
  }
908
908
  function insertItemsAtIndex(array, items, index) {
909
- const newArray = [...array];
910
- newArray.splice(index, 0, ...items);
911
- return newArray;
909
+ return array.slice(0, index).concat(items).concat(array.slice(index));
912
910
  }
913
911
  function replaceItemAtIndex(array, newItem, index) {
914
912
  const newArray = [...array];
@@ -4315,7 +4313,7 @@ function tokensToTextInternalFormat(tokens) {
4315
4313
  * Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
4316
4314
  *
4317
4315
  * As per OpenXML specification, in date formats if a date token "m" or "mm" is followed by a date token "s" or
4318
- * preceded by a data token "h", then it's not a month but an minute.
4316
+ * preceded by a data token "h", then it's not a month but a minute.
4319
4317
  */
4320
4318
  function convertTokensToMinutesInDateFormat(tokens) {
4321
4319
  const dateParts = tokens.filter((token) => token.type === "DATE_PART");
@@ -4358,6 +4356,9 @@ function internalFormatPartToFormat(internalFormat) {
4358
4356
  case "REPEATED_CHAR":
4359
4357
  format += "*" + token.value;
4360
4358
  break;
4359
+ case "DATE_PART":
4360
+ format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
4361
+ break;
4361
4362
  default:
4362
4363
  format += token.value;
4363
4364
  }
@@ -54246,7 +54247,7 @@ class PivotMeasureEditor extends owl.Component {
54246
54247
  return undefined;
54247
54248
  }
54248
54249
  get isCalculatedMeasureInvalid() {
54249
- return this.env.model.getters.getMeasureCompiledFormula(this.props.measure).isBadExpression;
54250
+ return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
54250
54251
  }
54251
54252
  }
54252
54253
 
@@ -61258,11 +61259,11 @@ class HeaderSizePlugin extends CorePlugin {
61258
61259
  break;
61259
61260
  }
61260
61261
  case "ADD_COLUMNS_ROWS": {
61261
- const sizes = [...this.sizes[cmd.sheetId][cmd.dimension]];
61262
+ const sizes = this.sizes[cmd.sheetId][cmd.dimension];
61262
61263
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
61263
61264
  const baseSize = sizes[cmd.base];
61264
- sizes.splice(addIndex, 0, ...Array(cmd.quantity).fill(baseSize));
61265
- this.history.update("sizes", cmd.sheetId, cmd.dimension, sizes);
61265
+ const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
61266
+ this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
61266
61267
  break;
61267
61268
  }
61268
61269
  case "RESIZE_COLUMNS_ROWS":
@@ -61413,9 +61414,8 @@ class HeaderVisibilityPlugin extends CorePlugin {
61413
61414
  break;
61414
61415
  }
61415
61416
  case "ADD_COLUMNS_ROWS": {
61416
- const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
61417
61417
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
61418
- hiddenHeaders.splice(addIndex, 0, ...Array(cmd.quantity).fill(false));
61418
+ const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
61419
61419
  this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
61420
61420
  break;
61421
61421
  }
@@ -65450,12 +65450,12 @@ class SpreadsheetRTree {
65450
65450
  this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
65451
65451
  }
65452
65452
  rtreeItemComparer(left, right) {
65453
- return (left.data === right.data &&
65454
- left.boundingBox.sheetId === right.boundingBox.sheetId &&
65453
+ return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
65455
65454
  left.boundingBox?.zone.left === right.boundingBox.zone.left &&
65456
65455
  left.boundingBox?.zone.top === right.boundingBox.zone.top &&
65457
65456
  left.boundingBox?.zone.right === right.boundingBox.zone.right &&
65458
- left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
65457
+ left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
65458
+ deepEquals(left.data, right.data));
65459
65459
  }
65460
65460
  }
65461
65461
  /**
@@ -71657,7 +71657,10 @@ class SortPlugin extends UIPlugin {
71657
71657
  return "Success" /* CommandResult.Success */;
71658
71658
  }
71659
71659
  checkArrayFormulaInSortZone({ sheetId, zone }) {
71660
- const arrayFormulaInZone = positions(zone).some(({ col, row }) => this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row }));
71660
+ const arrayFormulaInZone = positions(zone).some(({ col, row }) => {
71661
+ const originPosition = this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row });
71662
+ return originPosition && !deepEquals(originPosition, { sheetId, col, row });
71663
+ });
71661
71664
  return arrayFormulaInZone ? "SortZoneWithArrayFormulas" /* CommandResult.SortZoneWithArrayFormulas */ : "Success" /* CommandResult.Success */;
71662
71665
  }
71663
71666
  /**
@@ -78692,6 +78695,9 @@ class SmallBottomBar extends owl.Component {
78692
78695
  ? this.composerFocusStore.focusMode
78693
78696
  : "inactive";
78694
78697
  }
78698
+ get showFxIcon() {
78699
+ return this.focus === "inactive" && !this.composerStore.currentContent;
78700
+ }
78695
78701
  get rect() {
78696
78702
  return this.composerRef.el
78697
78703
  ? getBoundingRectAsPOJO(this.composerRef.el)
@@ -78734,12 +78740,6 @@ class SmallBottomBar extends owl.Component {
78734
78740
  }
78735
78741
 
78736
78742
  const COMPOSER_MAX_HEIGHT = 100;
78737
- /* svg free of use from https://uxwing.com/formula-fx-icon/ */
78738
- const FX_SVG = /*xml*/ `
78739
- <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
78740
- <path d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='#BDBDBD'/>
78741
- </svg>
78742
- `;
78743
78743
  css /* scss */ `
78744
78744
  .o-topbar-composer-container {
78745
78745
  height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
@@ -78751,14 +78751,6 @@ css /* scss */ `
78751
78751
  margin-bottom: -1px;
78752
78752
  border: 1px solid;
78753
78753
  font-family: ${DEFAULT_FONT};
78754
-
78755
- /* In readonly we always show the fx icon if the composer is empty, not matter the focus */
78756
- .o-composer:empty:not(:focus):not(.active)::before,
78757
- &.o-topbar-composer-readonly .o-composer:empty::before {
78758
- content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
78759
- position: relative;
78760
- top: 20%;
78761
- }
78762
78754
  }
78763
78755
 
78764
78756
  .user-select-text {
@@ -78791,6 +78783,9 @@ class TopBarComposer extends owl.Component {
78791
78783
  ? this.composerFocusStore.focusMode
78792
78784
  : "inactive";
78793
78785
  }
78786
+ get showFxIcon() {
78787
+ return this.focus === "inactive" && !this.composerStore.currentContent;
78788
+ }
78794
78789
  get composerStyle() {
78795
78790
  const style = {
78796
78791
  padding: "5px 0px 5px 8px",
@@ -84856,6 +84851,6 @@ exports.tokenColors = tokenColors;
84856
84851
  exports.tokenize = tokenize;
84857
84852
 
84858
84853
 
84859
- __info__.version = "18.4.11";
84860
- __info__.date = "2025-09-19T07:25:39.033Z";
84861
- __info__.hash = "c7e71ac";
84854
+ __info__.version = "18.4.13";
84855
+ __info__.date = "2025-10-07T10:00:55.413Z";
84856
+ __info__.hash = "d4df70e";
@@ -12204,6 +12204,7 @@ declare class SmallBottomBar extends Component<Props$1, SpreadsheetChildEnv> {
12204
12204
  private menuState;
12205
12205
  setup(): void;
12206
12206
  get focus(): ComposerFocusType;
12207
+ get showFxIcon(): boolean;
12207
12208
  get rect(): Rect;
12208
12209
  get composerProps(): CellComposerProps;
12209
12210
  get symbols(): string[];
@@ -12256,6 +12257,7 @@ declare class TopBarComposer extends Component<any, SpreadsheetChildEnv> {
12256
12257
  private composerInterface;
12257
12258
  setup(): void;
12258
12259
  get focus(): ComposerFocusType;
12260
+ get showFxIcon(): boolean;
12259
12261
  get composerStyle(): string;
12260
12262
  get containerStyle(): string;
12261
12263
  onFocus(selection: ComposerSelection): void;
@@ -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 18.4.11
6
- * @date 2025-09-19T07:25:39.033Z
7
- * @hash c7e71ac
5
+ * @version 18.4.13
6
+ * @date 2025-10-07T10:00:55.413Z
7
+ * @hash d4df70e
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -904,9 +904,7 @@ function removeIndexesFromArray(array, indexes) {
904
904
  return newArray;
905
905
  }
906
906
  function insertItemsAtIndex(array, items, index) {
907
- const newArray = [...array];
908
- newArray.splice(index, 0, ...items);
909
- return newArray;
907
+ return array.slice(0, index).concat(items).concat(array.slice(index));
910
908
  }
911
909
  function replaceItemAtIndex(array, newItem, index) {
912
910
  const newArray = [...array];
@@ -4313,7 +4311,7 @@ function tokensToTextInternalFormat(tokens) {
4313
4311
  * Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
4314
4312
  *
4315
4313
  * As per OpenXML specification, in date formats if a date token "m" or "mm" is followed by a date token "s" or
4316
- * preceded by a data token "h", then it's not a month but an minute.
4314
+ * preceded by a data token "h", then it's not a month but a minute.
4317
4315
  */
4318
4316
  function convertTokensToMinutesInDateFormat(tokens) {
4319
4317
  const dateParts = tokens.filter((token) => token.type === "DATE_PART");
@@ -4356,6 +4354,9 @@ function internalFormatPartToFormat(internalFormat) {
4356
4354
  case "REPEATED_CHAR":
4357
4355
  format += "*" + token.value;
4358
4356
  break;
4357
+ case "DATE_PART":
4358
+ format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
4359
+ break;
4359
4360
  default:
4360
4361
  format += token.value;
4361
4362
  }
@@ -54244,7 +54245,7 @@ class PivotMeasureEditor extends Component {
54244
54245
  return undefined;
54245
54246
  }
54246
54247
  get isCalculatedMeasureInvalid() {
54247
- return this.env.model.getters.getMeasureCompiledFormula(this.props.measure).isBadExpression;
54248
+ return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
54248
54249
  }
54249
54250
  }
54250
54251
 
@@ -61256,11 +61257,11 @@ class HeaderSizePlugin extends CorePlugin {
61256
61257
  break;
61257
61258
  }
61258
61259
  case "ADD_COLUMNS_ROWS": {
61259
- const sizes = [...this.sizes[cmd.sheetId][cmd.dimension]];
61260
+ const sizes = this.sizes[cmd.sheetId][cmd.dimension];
61260
61261
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
61261
61262
  const baseSize = sizes[cmd.base];
61262
- sizes.splice(addIndex, 0, ...Array(cmd.quantity).fill(baseSize));
61263
- this.history.update("sizes", cmd.sheetId, cmd.dimension, sizes);
61263
+ const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
61264
+ this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
61264
61265
  break;
61265
61266
  }
61266
61267
  case "RESIZE_COLUMNS_ROWS":
@@ -61411,9 +61412,8 @@ class HeaderVisibilityPlugin extends CorePlugin {
61411
61412
  break;
61412
61413
  }
61413
61414
  case "ADD_COLUMNS_ROWS": {
61414
- const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
61415
61415
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
61416
- hiddenHeaders.splice(addIndex, 0, ...Array(cmd.quantity).fill(false));
61416
+ const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
61417
61417
  this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
61418
61418
  break;
61419
61419
  }
@@ -65448,12 +65448,12 @@ class SpreadsheetRTree {
65448
65448
  this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
65449
65449
  }
65450
65450
  rtreeItemComparer(left, right) {
65451
- return (left.data === right.data &&
65452
- left.boundingBox.sheetId === right.boundingBox.sheetId &&
65451
+ return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
65453
65452
  left.boundingBox?.zone.left === right.boundingBox.zone.left &&
65454
65453
  left.boundingBox?.zone.top === right.boundingBox.zone.top &&
65455
65454
  left.boundingBox?.zone.right === right.boundingBox.zone.right &&
65456
- left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
65455
+ left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
65456
+ deepEquals(left.data, right.data));
65457
65457
  }
65458
65458
  }
65459
65459
  /**
@@ -71655,7 +71655,10 @@ class SortPlugin extends UIPlugin {
71655
71655
  return "Success" /* CommandResult.Success */;
71656
71656
  }
71657
71657
  checkArrayFormulaInSortZone({ sheetId, zone }) {
71658
- const arrayFormulaInZone = positions(zone).some(({ col, row }) => this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row }));
71658
+ const arrayFormulaInZone = positions(zone).some(({ col, row }) => {
71659
+ const originPosition = this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row });
71660
+ return originPosition && !deepEquals(originPosition, { sheetId, col, row });
71661
+ });
71659
71662
  return arrayFormulaInZone ? "SortZoneWithArrayFormulas" /* CommandResult.SortZoneWithArrayFormulas */ : "Success" /* CommandResult.Success */;
71660
71663
  }
71661
71664
  /**
@@ -78690,6 +78693,9 @@ class SmallBottomBar extends Component {
78690
78693
  ? this.composerFocusStore.focusMode
78691
78694
  : "inactive";
78692
78695
  }
78696
+ get showFxIcon() {
78697
+ return this.focus === "inactive" && !this.composerStore.currentContent;
78698
+ }
78693
78699
  get rect() {
78694
78700
  return this.composerRef.el
78695
78701
  ? getBoundingRectAsPOJO(this.composerRef.el)
@@ -78732,12 +78738,6 @@ class SmallBottomBar extends Component {
78732
78738
  }
78733
78739
 
78734
78740
  const COMPOSER_MAX_HEIGHT = 100;
78735
- /* svg free of use from https://uxwing.com/formula-fx-icon/ */
78736
- const FX_SVG = /*xml*/ `
78737
- <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
78738
- <path d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='#BDBDBD'/>
78739
- </svg>
78740
- `;
78741
78741
  css /* scss */ `
78742
78742
  .o-topbar-composer-container {
78743
78743
  height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
@@ -78749,14 +78749,6 @@ css /* scss */ `
78749
78749
  margin-bottom: -1px;
78750
78750
  border: 1px solid;
78751
78751
  font-family: ${DEFAULT_FONT};
78752
-
78753
- /* In readonly we always show the fx icon if the composer is empty, not matter the focus */
78754
- .o-composer:empty:not(:focus):not(.active)::before,
78755
- &.o-topbar-composer-readonly .o-composer:empty::before {
78756
- content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
78757
- position: relative;
78758
- top: 20%;
78759
- }
78760
78752
  }
78761
78753
 
78762
78754
  .user-select-text {
@@ -78789,6 +78781,9 @@ class TopBarComposer extends Component {
78789
78781
  ? this.composerFocusStore.focusMode
78790
78782
  : "inactive";
78791
78783
  }
78784
+ get showFxIcon() {
78785
+ return this.focus === "inactive" && !this.composerStore.currentContent;
78786
+ }
78792
78787
  get composerStyle() {
78793
78788
  const style = {
78794
78789
  padding: "5px 0px 5px 8px",
@@ -84806,6 +84801,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
84806
84801
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
84807
84802
 
84808
84803
 
84809
- __info__.version = "18.4.11";
84810
- __info__.date = "2025-09-19T07:25:39.033Z";
84811
- __info__.hash = "c7e71ac";
84804
+ __info__.version = "18.4.13";
84805
+ __info__.date = "2025-10-07T10:00:55.413Z";
84806
+ __info__.hash = "d4df70e";
@@ -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 18.4.11
6
- * @date 2025-09-19T07:25:39.033Z
7
- * @hash c7e71ac
5
+ * @version 18.4.13
6
+ * @date 2025-10-07T10:00:55.413Z
7
+ * @hash d4df70e
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -905,9 +905,7 @@
905
905
  return newArray;
906
906
  }
907
907
  function insertItemsAtIndex(array, items, index) {
908
- const newArray = [...array];
909
- newArray.splice(index, 0, ...items);
910
- return newArray;
908
+ return array.slice(0, index).concat(items).concat(array.slice(index));
911
909
  }
912
910
  function replaceItemAtIndex(array, newItem, index) {
913
911
  const newArray = [...array];
@@ -4314,7 +4312,7 @@
4314
4312
  * Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
4315
4313
  *
4316
4314
  * As per OpenXML specification, in date formats if a date token "m" or "mm" is followed by a date token "s" or
4317
- * preceded by a data token "h", then it's not a month but an minute.
4315
+ * preceded by a data token "h", then it's not a month but a minute.
4318
4316
  */
4319
4317
  function convertTokensToMinutesInDateFormat(tokens) {
4320
4318
  const dateParts = tokens.filter((token) => token.type === "DATE_PART");
@@ -4357,6 +4355,9 @@
4357
4355
  case "REPEATED_CHAR":
4358
4356
  format += "*" + token.value;
4359
4357
  break;
4358
+ case "DATE_PART":
4359
+ format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
4360
+ break;
4360
4361
  default:
4361
4362
  format += token.value;
4362
4363
  }
@@ -54245,7 +54246,7 @@ stores.inject(MyMetaStore, storeInstance);
54245
54246
  return undefined;
54246
54247
  }
54247
54248
  get isCalculatedMeasureInvalid() {
54248
- return this.env.model.getters.getMeasureCompiledFormula(this.props.measure).isBadExpression;
54249
+ return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
54249
54250
  }
54250
54251
  }
54251
54252
 
@@ -61257,11 +61258,11 @@ stores.inject(MyMetaStore, storeInstance);
61257
61258
  break;
61258
61259
  }
61259
61260
  case "ADD_COLUMNS_ROWS": {
61260
- const sizes = [...this.sizes[cmd.sheetId][cmd.dimension]];
61261
+ const sizes = this.sizes[cmd.sheetId][cmd.dimension];
61261
61262
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
61262
61263
  const baseSize = sizes[cmd.base];
61263
- sizes.splice(addIndex, 0, ...Array(cmd.quantity).fill(baseSize));
61264
- this.history.update("sizes", cmd.sheetId, cmd.dimension, sizes);
61264
+ const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
61265
+ this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
61265
61266
  break;
61266
61267
  }
61267
61268
  case "RESIZE_COLUMNS_ROWS":
@@ -61412,9 +61413,8 @@ stores.inject(MyMetaStore, storeInstance);
61412
61413
  break;
61413
61414
  }
61414
61415
  case "ADD_COLUMNS_ROWS": {
61415
- const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
61416
61416
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
61417
- hiddenHeaders.splice(addIndex, 0, ...Array(cmd.quantity).fill(false));
61417
+ const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
61418
61418
  this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
61419
61419
  break;
61420
61420
  }
@@ -65449,12 +65449,12 @@ stores.inject(MyMetaStore, storeInstance);
65449
65449
  this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
65450
65450
  }
65451
65451
  rtreeItemComparer(left, right) {
65452
- return (left.data === right.data &&
65453
- left.boundingBox.sheetId === right.boundingBox.sheetId &&
65452
+ return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
65454
65453
  left.boundingBox?.zone.left === right.boundingBox.zone.left &&
65455
65454
  left.boundingBox?.zone.top === right.boundingBox.zone.top &&
65456
65455
  left.boundingBox?.zone.right === right.boundingBox.zone.right &&
65457
- left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
65456
+ left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
65457
+ deepEquals(left.data, right.data));
65458
65458
  }
65459
65459
  }
65460
65460
  /**
@@ -71656,7 +71656,10 @@ stores.inject(MyMetaStore, storeInstance);
71656
71656
  return "Success" /* CommandResult.Success */;
71657
71657
  }
71658
71658
  checkArrayFormulaInSortZone({ sheetId, zone }) {
71659
- const arrayFormulaInZone = positions(zone).some(({ col, row }) => this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row }));
71659
+ const arrayFormulaInZone = positions(zone).some(({ col, row }) => {
71660
+ const originPosition = this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row });
71661
+ return originPosition && !deepEquals(originPosition, { sheetId, col, row });
71662
+ });
71660
71663
  return arrayFormulaInZone ? "SortZoneWithArrayFormulas" /* CommandResult.SortZoneWithArrayFormulas */ : "Success" /* CommandResult.Success */;
71661
71664
  }
71662
71665
  /**
@@ -78691,6 +78694,9 @@ stores.inject(MyMetaStore, storeInstance);
78691
78694
  ? this.composerFocusStore.focusMode
78692
78695
  : "inactive";
78693
78696
  }
78697
+ get showFxIcon() {
78698
+ return this.focus === "inactive" && !this.composerStore.currentContent;
78699
+ }
78694
78700
  get rect() {
78695
78701
  return this.composerRef.el
78696
78702
  ? getBoundingRectAsPOJO(this.composerRef.el)
@@ -78733,12 +78739,6 @@ stores.inject(MyMetaStore, storeInstance);
78733
78739
  }
78734
78740
 
78735
78741
  const COMPOSER_MAX_HEIGHT = 100;
78736
- /* svg free of use from https://uxwing.com/formula-fx-icon/ */
78737
- const FX_SVG = /*xml*/ `
78738
- <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
78739
- <path d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='#BDBDBD'/>
78740
- </svg>
78741
- `;
78742
78742
  css /* scss */ `
78743
78743
  .o-topbar-composer-container {
78744
78744
  height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
@@ -78750,14 +78750,6 @@ stores.inject(MyMetaStore, storeInstance);
78750
78750
  margin-bottom: -1px;
78751
78751
  border: 1px solid;
78752
78752
  font-family: ${DEFAULT_FONT};
78753
-
78754
- /* In readonly we always show the fx icon if the composer is empty, not matter the focus */
78755
- .o-composer:empty:not(:focus):not(.active)::before,
78756
- &.o-topbar-composer-readonly .o-composer:empty::before {
78757
- content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
78758
- position: relative;
78759
- top: 20%;
78760
- }
78761
78753
  }
78762
78754
 
78763
78755
  .user-select-text {
@@ -78790,6 +78782,9 @@ stores.inject(MyMetaStore, storeInstance);
78790
78782
  ? this.composerFocusStore.focusMode
78791
78783
  : "inactive";
78792
78784
  }
78785
+ get showFxIcon() {
78786
+ return this.focus === "inactive" && !this.composerStore.currentContent;
78787
+ }
78793
78788
  get composerStyle() {
78794
78789
  const style = {
78795
78790
  padding: "5px 0px 5px 8px",
@@ -84855,9 +84850,9 @@ stores.inject(MyMetaStore, storeInstance);
84855
84850
  exports.tokenize = tokenize;
84856
84851
 
84857
84852
 
84858
- __info__.version = "18.4.11";
84859
- __info__.date = "2025-09-19T07:25:39.033Z";
84860
- __info__.hash = "c7e71ac";
84853
+ __info__.version = "18.4.13";
84854
+ __info__.date = "2025-10-07T10:00:55.413Z";
84855
+ __info__.hash = "d4df70e";
84861
84856
 
84862
84857
 
84863
84858
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);