@odoo/o-spreadsheet 17.0.27 → 17.0.29

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.0.27
6
- * @date 2024-07-02T09:01:48.383Z
7
- * @hash c1c2d01
5
+ * @version 17.0.29
6
+ * @date 2024-07-08T05:40:27.608Z
7
+ * @hash 2d467e3
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -658,7 +658,7 @@
658
658
  /**
659
659
  * Compares two objects.
660
660
  */
661
- function deepEquals(o1, o2, ignoreFunctions) {
661
+ function deepEquals(o1, o2) {
662
662
  if (o1 === o2)
663
663
  return true;
664
664
  if ((o1 && !o2) || (o2 && !o1))
@@ -674,17 +674,13 @@
674
674
  }
675
675
  }
676
676
  for (const key in o1) {
677
- const typeOfO1Key = typeof o1[key];
678
- if (typeOfO1Key !== typeof o2[key])
677
+ if (typeof o1[key] !== typeof o2[key])
679
678
  return false;
680
- if (typeOfO1Key === "object") {
681
- if (!deepEquals(o1[key], o2[key], ignoreFunctions))
679
+ if (typeof o1[key] === "object") {
680
+ if (!deepEquals(o1[key], o2[key]))
682
681
  return false;
683
682
  }
684
683
  else {
685
- if (ignoreFunctions && typeOfO1Key === "function") {
686
- continue;
687
- }
688
684
  if (o1[key] !== o2[key])
689
685
  return false;
690
686
  }
@@ -755,11 +751,9 @@
755
751
  return this;
756
752
  }
757
753
  deleteMany(iterable) {
758
- let wasDeleted = false;
759
754
  for (const element of iterable) {
760
- wasDeleted ||= super.delete(element);
755
+ super.delete(element);
761
756
  }
762
- return wasDeleted;
763
757
  }
764
758
  }
765
759
  /**
@@ -1816,7 +1810,7 @@
1816
1810
  });
1817
1811
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1818
1812
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
1819
- const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
1813
+ const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
1820
1814
  const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1821
1815
  const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1822
1816
  const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
@@ -1843,7 +1837,7 @@
1843
1837
  return getNumberRegex(locale).test(value.trim());
1844
1838
  }
1845
1839
  const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
1846
- return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
1840
+ return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
1847
1841
  });
1848
1842
  /**
1849
1843
  * Convert a string into a number. It assumes that the string actually represents
@@ -2545,6 +2539,9 @@
2545
2539
  return result;
2546
2540
  }
2547
2541
  function operandToRegExp(operand) {
2542
+ if (operand === "*") {
2543
+ return /.+/;
2544
+ }
2548
2545
  let exp = "";
2549
2546
  let predecessor = "";
2550
2547
  for (let char of operand) {
@@ -2568,9 +2565,9 @@
2568
2565
  }
2569
2566
  return new RegExp("^" + exp + "$", "i");
2570
2567
  }
2571
- function evaluatePredicate(value, criterion) {
2568
+ function evaluatePredicate(value = "", criterion) {
2572
2569
  const { operator, operand } = criterion;
2573
- if (value === undefined || operand === undefined || value === null || operand === null) {
2570
+ if (operand === undefined || value === null || operand === null) {
2574
2571
  return false;
2575
2572
  }
2576
2573
  if (typeof operand === "number" && operator === "=") {
@@ -4783,7 +4780,6 @@
4783
4780
  static template = "o-spreadsheet-ChartJsComponent";
4784
4781
  canvas = owl.useRef("graphContainer");
4785
4782
  chart;
4786
- currentRuntime;
4787
4783
  get background() {
4788
4784
  return this.chartRuntime.background;
4789
4785
  }
@@ -4800,17 +4796,10 @@
4800
4796
  setup() {
4801
4797
  owl.onMounted(() => {
4802
4798
  const runtime = this.chartRuntime;
4803
- this.currentRuntime = runtime;
4804
4799
  // Note: chartJS modify the runtime in place, so it's important to give it a copy
4805
4800
  this.createChart(deepCopy(runtime.chartJsConfig));
4806
4801
  });
4807
- owl.useEffect(() => {
4808
- const runtime = this.chartRuntime;
4809
- if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
4810
- this.currentRuntime = runtime;
4811
- this.updateChartJs(deepCopy(runtime));
4812
- }
4813
- });
4802
+ owl.useEffect(() => this.updateChartJs(deepCopy(this.chartRuntime)), () => [this.chartRuntime]);
4814
4803
  }
4815
4804
  createChart(chartData) {
4816
4805
  const canvas = this.canvas.el;
@@ -7678,19 +7667,22 @@
7678
7667
  }
7679
7668
 
7680
7669
  function isValidLocale(locale) {
7681
- if (!(locale &&
7682
- typeof locale === "object" &&
7683
- typeof locale.name === "string" &&
7684
- typeof locale.code === "string" &&
7685
- typeof locale.thousandsSeparator === "string" &&
7686
- typeof locale.decimalSeparator === "string" &&
7687
- typeof locale.dateFormat === "string" &&
7688
- typeof locale.timeFormat === "string" &&
7689
- typeof locale.formulaArgSeparator === "string")) {
7670
+ if (!locale ||
7671
+ typeof locale !== "object" ||
7672
+ !(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
7690
7673
  return false;
7691
7674
  }
7692
- if (!Object.values(locale).every((v) => v)) {
7693
- return false;
7675
+ for (const property of [
7676
+ "code",
7677
+ "name",
7678
+ "decimalSeparator",
7679
+ "dateFormat",
7680
+ "timeFormat",
7681
+ "formulaArgSeparator",
7682
+ ]) {
7683
+ if (!locale[property] || typeof locale[property] !== "string") {
7684
+ return false;
7685
+ }
7694
7686
  }
7695
7687
  if (locale.formulaArgSeparator === locale.decimalSeparator) {
7696
7688
  return false;
@@ -7788,7 +7780,10 @@
7788
7780
  if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
7789
7781
  return content;
7790
7782
  }
7791
- return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
7783
+ if (locale.thousandsSeparator) {
7784
+ content = content.replaceAll(locale.thousandsSeparator, "");
7785
+ }
7786
+ return content.replace(locale.decimalSeparator, ".");
7792
7787
  }
7793
7788
  /**
7794
7789
  * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
@@ -9466,15 +9461,6 @@
9466
9461
  }
9467
9462
  const colors = new ChartColors();
9468
9463
  for (let [index, { label, data }] of dataSetsValues.entries()) {
9469
- if (["linear", "time"].includes(axisType)) {
9470
- // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
9471
- data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
9472
- }
9473
- const color = colors.next();
9474
- let backgroundRGBA = colorToRGBA(color);
9475
- if (chart.stacked) {
9476
- backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
9477
- }
9478
9464
  if (chart.cumulative) {
9479
9465
  let accumulator = 0;
9480
9466
  data = data.map((value) => {
@@ -9485,6 +9471,15 @@
9485
9471
  return value;
9486
9472
  });
9487
9473
  }
9474
+ if (["linear", "time"].includes(axisType)) {
9475
+ // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
9476
+ data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
9477
+ }
9478
+ const color = colors.next();
9479
+ let backgroundRGBA = colorToRGBA(color);
9480
+ if (chart.stacked) {
9481
+ backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
9482
+ }
9488
9483
  const backgroundColor = rgbaToHex(backgroundRGBA);
9489
9484
  const dataset = {
9490
9485
  label,
@@ -24282,7 +24277,13 @@
24282
24277
  }
24283
24278
  async loadLocales() {
24284
24279
  this.loadedLocales = (await this.env.loadLocales())
24285
- .filter(isValidLocale)
24280
+ .filter((locale) => {
24281
+ const isValid = isValidLocale(locale);
24282
+ if (!isValid) {
24283
+ console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
24284
+ }
24285
+ return isValid;
24286
+ })
24286
24287
  .sort((a, b) => a.name.localeCompare(b.name));
24287
24288
  }
24288
24289
  get numberFormatPreview() {
@@ -30065,6 +30066,7 @@
30065
30066
  return;
30066
30067
  }
30067
30068
  if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
30069
+ ev.preventDefault();
30068
30070
  const content = clipboardData.getData(ClipboardMIMEType.PlainText);
30069
30071
  const target = this.env.model.getters.getSelectedZones();
30070
30072
  const clipboardString = this.env.model.getters.getClipboardTextContent();
@@ -30327,6 +30329,8 @@
30327
30329
  "BITOR",
30328
30330
  "BITRSHIFT",
30329
30331
  "BITXOR",
30332
+ "BYCOL",
30333
+ "BYROW",
30330
30334
  "CEILING.MATH",
30331
30335
  "CEILING.PRECISE",
30332
30336
  "CHISQ.DIST",
@@ -30334,6 +30338,8 @@
30334
30338
  "CHISQ.INV",
30335
30339
  "CHISQ.INV.RT",
30336
30340
  "CHISQ.TEST",
30341
+ "CHOOSECOLS",
30342
+ "CHOOSEROWS",
30337
30343
  "COMBINA",
30338
30344
  "CONCAT",
30339
30345
  "CONFIDENCE.NORM",
@@ -30346,14 +30352,17 @@
30346
30352
  "CSCH",
30347
30353
  "DAYS",
30348
30354
  "DECIMAL",
30355
+ "DROP",
30349
30356
  "ERF.PRECISE",
30350
30357
  "ERFC.PRECISE",
30358
+ "EXPAND",
30351
30359
  "EXPON.DIST",
30352
30360
  "F.DIST",
30353
30361
  "F.DIST.RT",
30354
30362
  "F.INV",
30355
30363
  "F.INV.RT",
30356
30364
  "F.TEST",
30365
+ "FIELDVALUE",
30357
30366
  "FILTERXML",
30358
30367
  "FLOOR.MATH",
30359
30368
  "FLOOR.PRECISE",
@@ -30368,6 +30377,7 @@
30368
30377
  "GAMMA.INV",
30369
30378
  "GAMMALN.PRECISE",
30370
30379
  "GAUSS",
30380
+ "HSTACK",
30371
30381
  "HYPGEOM.DIST",
30372
30382
  "IFNA",
30373
30383
  "IFS",
@@ -30380,9 +30390,14 @@
30380
30390
  "IMSINH",
30381
30391
  "IMTAN",
30382
30392
  "ISFORMULA",
30393
+ "ISOMITTED",
30383
30394
  "ISOWEEKNUM",
30395
+ "LAMBDA",
30396
+ "LET",
30384
30397
  "LOGNORM.DIST",
30385
30398
  "LOGNORM.INV",
30399
+ "MAKEARRAY",
30400
+ "MAP",
30386
30401
  "MAXIFS",
30387
30402
  "MINIFS",
30388
30403
  "MODE.MULT",
@@ -30402,17 +30417,26 @@
30402
30417
  "PERMUTATIONA",
30403
30418
  "PHI",
30404
30419
  "POISSON.DIST",
30420
+ "PQSOURCE",
30421
+ "PYTHON_STR",
30422
+ "PYTHON_TYPE",
30423
+ "PYTHON_TYPENAME",
30405
30424
  "QUARTILE.EXC",
30406
30425
  "QUARTILE.INC",
30407
30426
  "QUERYSTRING",
30427
+ "RANDARRAY",
30408
30428
  "RANK.AVG",
30409
30429
  "RANK.EQ",
30430
+ "REDUCE",
30410
30431
  "RRI",
30432
+ "SCAN",
30411
30433
  "SEC",
30412
30434
  "SECH",
30435
+ "SEQUENCE",
30413
30436
  "SHEET",
30414
30437
  "SHEETS",
30415
30438
  "SKEW.P",
30439
+ "SORTBY",
30416
30440
  "STDEV.P",
30417
30441
  "STDEV.S",
30418
30442
  "SWITCH",
@@ -30422,13 +30446,24 @@
30422
30446
  "T.INV",
30423
30447
  "T.INV.2T",
30424
30448
  "T.TEST",
30449
+ "TAKE",
30450
+ "TEXTAFTER",
30451
+ "TEXTBEFORE",
30425
30452
  "TEXTJOIN",
30453
+ "TEXTSPLIT",
30454
+ "TOCOL",
30455
+ "TOROW",
30426
30456
  "UNICHAR",
30427
30457
  "UNICODE",
30458
+ "UNIQUE",
30428
30459
  "VAR.P",
30429
30460
  "VAR.S",
30461
+ "VSTACK",
30430
30462
  "WEBSERVICE",
30431
30463
  "WEIBULL.DIST",
30464
+ "WRAPCOLS",
30465
+ "WRAPROWS",
30466
+ "XLOOKUP",
30432
30467
  "XOR",
30433
30468
  "Z.TEST",
30434
30469
  ];
@@ -34607,6 +34642,21 @@
34607
34642
  return [];
34608
34643
  return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
34609
34644
  }
34645
+ /**
34646
+ * Get all the rows which contains at least a border
34647
+ */
34648
+ getRowsWithBorders(sheetId) {
34649
+ const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
34650
+ if (!sheetBorders)
34651
+ return [];
34652
+ const rowsWithBorders = new Set();
34653
+ for (const rowBorders of sheetBorders) {
34654
+ for (const rowBorder in rowBorders) {
34655
+ rowsWithBorders.add(parseInt(rowBorder, 10));
34656
+ }
34657
+ }
34658
+ return Array.from(rowsWithBorders);
34659
+ }
34610
34660
  /**
34611
34661
  * Get the range of all the rows in the sheet
34612
34662
  */
@@ -34656,7 +34706,7 @@
34656
34706
  destructive: false,
34657
34707
  });
34658
34708
  }
34659
- this.getRowsRange(sheetId)
34709
+ this.getRowsWithBorders(sheetId)
34660
34710
  .filter((row) => row >= start)
34661
34711
  .sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
34662
34712
  .forEach((row) => {
@@ -35120,7 +35170,7 @@
35120
35170
  * Parse an expression (as a string) into an AST.
35121
35171
  */
35122
35172
  function parse(str) {
35123
- return parseTokens(tokenize(str));
35173
+ return parseTokens(rangeTokenize(str));
35124
35174
  }
35125
35175
  function parseTokens(tokens) {
35126
35176
  tokens = tokens.filter((x) => x.type !== "SPACE");
@@ -41638,6 +41688,7 @@
41638
41688
  }
41639
41689
  finally {
41640
41690
  this.cellsBeingComputed.delete(cellId);
41691
+ this.nextPositionsToUpdate.delete(positionId);
41641
41692
  }
41642
41693
  }
41643
41694
  computeAndSave(position) {
@@ -41679,11 +41730,36 @@
41679
41730
  forEachSpreadPositionInMatrix(nbColumns, nbRows,
41680
41731
  // thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
41681
41732
  this.spreadValues(formulaPosition, formulaReturn));
41733
+ this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
41682
41734
  return createEvaluatedCell(formulaReturn[0][0].value, {
41683
41735
  format: cellData.format || formulaReturn[0][0]?.format,
41684
41736
  locale: this.getters.getLocale(),
41685
41737
  });
41686
41738
  }
41739
+ invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
41740
+ // the result matrix is split in 2 zones to exclude the array formula position
41741
+ const top = arrayFormulaPosition.row;
41742
+ const left = arrayFormulaPosition.col;
41743
+ const bottom = top + nbRows - 1;
41744
+ const leftColumnZone = {
41745
+ top: top + 1,
41746
+ bottom,
41747
+ left,
41748
+ right: left,
41749
+ };
41750
+ const rightPartZone = {
41751
+ top,
41752
+ bottom,
41753
+ left: left + 1,
41754
+ right: left + nbColumns - 1,
41755
+ };
41756
+ const sheetId = arrayFormulaPosition.sheetId;
41757
+ const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
41758
+ { sheetId, zone: rightPartZone },
41759
+ { sheetId, zone: leftColumnZone },
41760
+ ]);
41761
+ this.nextPositionsToUpdate.addMany(invalidatedPositions);
41762
+ }
41687
41763
  assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
41688
41764
  const numberOfCols = this.getters.getNumberCols(sheetId);
41689
41765
  const numberOfRows = this.getters.getNumberRows(sheetId);
@@ -41732,9 +41808,6 @@
41732
41808
  });
41733
41809
  const positionId = this.encoder.encode(position);
41734
41810
  this.setEvaluatedCell(positionId, evaluatedCell);
41735
- // check if formula dependencies present in the spread zone
41736
- // if so, they need to be recomputed
41737
- this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
41738
41811
  };
41739
41812
  }
41740
41813
  invalidateSpreading(positionId) {
@@ -57504,9 +57577,9 @@
57504
57577
  exports.tokenize = tokenize;
57505
57578
 
57506
57579
 
57507
- __info__.version = "17.0.27";
57508
- __info__.date = "2024-07-02T09:01:48.383Z";
57509
- __info__.hash = "c1c2d01";
57580
+ __info__.version = "17.0.29";
57581
+ __info__.date = "2024-07-08T05:40:27.608Z";
57582
+ __info__.hash = "2d467e3";
57510
57583
 
57511
57584
 
57512
57585
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);