@odoo/o-spreadsheet 17.1.21 → 17.1.23

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.21
6
- * @date 2024-07-02T10:35:57.801Z
7
- * @hash ec4c09b
5
+ * @version 17.1.23
6
+ * @date 2024-07-11T06:37:01.931Z
7
+ * @hash 31e8450
8
8
  */
9
9
 
10
10
  'use strict';
@@ -546,7 +546,7 @@ function getAddHeaderStartIndex(position, base) {
546
546
  /**
547
547
  * Compares two objects.
548
548
  */
549
- function deepEquals(o1, o2, ignoreFunctions) {
549
+ function deepEquals(o1, o2) {
550
550
  if (o1 === o2)
551
551
  return true;
552
552
  if ((o1 && !o2) || (o2 && !o1))
@@ -562,17 +562,13 @@ function deepEquals(o1, o2, ignoreFunctions) {
562
562
  }
563
563
  }
564
564
  for (const key in o1) {
565
- const typeOfO1Key = typeof o1[key];
566
- if (typeOfO1Key !== typeof o2[key])
565
+ if (typeof o1[key] !== typeof o2[key])
567
566
  return false;
568
- if (typeOfO1Key === "object") {
569
- if (!deepEquals(o1[key], o2[key], ignoreFunctions))
567
+ if (typeof o1[key] === "object") {
568
+ if (!deepEquals(o1[key], o2[key]))
570
569
  return false;
571
570
  }
572
571
  else {
573
- if (ignoreFunctions && typeOfO1Key === "function") {
574
- continue;
575
- }
576
572
  if (o1[key] !== o2[key])
577
573
  return false;
578
574
  }
@@ -643,11 +639,9 @@ class JetSet extends Set {
643
639
  return this;
644
640
  }
645
641
  deleteMany(iterable) {
646
- let wasDeleted = false;
647
642
  for (const element of iterable) {
648
- wasDeleted ||= super.delete(element);
643
+ super.delete(element);
649
644
  }
650
- return wasDeleted;
651
645
  }
652
646
  }
653
647
  /**
@@ -1704,7 +1698,7 @@ const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSepa
1704
1698
  });
1705
1699
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1706
1700
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
1707
- const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
1701
+ const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
1708
1702
  const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1709
1703
  const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1710
1704
  const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
@@ -1731,7 +1725,7 @@ function isNumber(value, locale) {
1731
1725
  return getNumberRegex(locale).test(value.trim());
1732
1726
  }
1733
1727
  const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
1734
- return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
1728
+ return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
1735
1729
  });
1736
1730
  /**
1737
1731
  * Convert a string into a number. It assumes that the string actually represents
@@ -2595,6 +2589,9 @@ function getPredicate(descr, isQuery, locale) {
2595
2589
  return result;
2596
2590
  }
2597
2591
  function operandToRegExp(operand) {
2592
+ if (operand === "*") {
2593
+ return /.+/;
2594
+ }
2598
2595
  let exp = "";
2599
2596
  let predecessor = "";
2600
2597
  for (let char of operand) {
@@ -2618,9 +2615,9 @@ function operandToRegExp(operand) {
2618
2615
  }
2619
2616
  return new RegExp("^" + exp + "$", "i");
2620
2617
  }
2621
- function evaluatePredicate(value, criterion) {
2618
+ function evaluatePredicate(value = "", criterion) {
2622
2619
  const { operator, operand } = criterion;
2623
- if (value === undefined || operand === undefined || value === null || operand === null) {
2620
+ if (operand === undefined || value === null || operand === null) {
2624
2621
  return false;
2625
2622
  }
2626
2623
  if (typeof operand === "number" && operator === "=") {
@@ -4854,7 +4851,6 @@ class ChartJsComponent extends owl.Component {
4854
4851
  };
4855
4852
  canvas = owl.useRef("graphContainer");
4856
4853
  chart;
4857
- currentRuntime;
4858
4854
  get background() {
4859
4855
  return this.chartRuntime.background;
4860
4856
  }
@@ -4871,18 +4867,11 @@ class ChartJsComponent extends owl.Component {
4871
4867
  setup() {
4872
4868
  owl.onMounted(() => {
4873
4869
  const runtime = this.chartRuntime;
4874
- this.currentRuntime = runtime;
4875
4870
  // Note: chartJS modify the runtime in place, so it's important to give it a copy
4876
4871
  this.createChart(deepCopy(runtime.chartJsConfig));
4877
4872
  });
4878
4873
  owl.onWillUnmount(() => this.chart?.destroy());
4879
- owl.useEffect(() => {
4880
- const runtime = this.chartRuntime;
4881
- if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
4882
- this.currentRuntime = runtime;
4883
- this.updateChartJs(deepCopy(runtime));
4884
- }
4885
- });
4874
+ owl.useEffect(() => this.updateChartJs(deepCopy(this.chartRuntime)), () => [this.chartRuntime]);
4886
4875
  }
4887
4876
  createChart(chartData) {
4888
4877
  const canvas = this.canvas.el;
@@ -7718,19 +7707,22 @@ class TokenizingChars {
7718
7707
  }
7719
7708
 
7720
7709
  function isValidLocale(locale) {
7721
- if (!(locale &&
7722
- typeof locale === "object" &&
7723
- typeof locale.name === "string" &&
7724
- typeof locale.code === "string" &&
7725
- typeof locale.thousandsSeparator === "string" &&
7726
- typeof locale.decimalSeparator === "string" &&
7727
- typeof locale.dateFormat === "string" &&
7728
- typeof locale.timeFormat === "string" &&
7729
- typeof locale.formulaArgSeparator === "string")) {
7710
+ if (!locale ||
7711
+ typeof locale !== "object" ||
7712
+ !(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
7730
7713
  return false;
7731
7714
  }
7732
- if (!Object.values(locale).every((v) => v)) {
7733
- return false;
7715
+ for (const property of [
7716
+ "code",
7717
+ "name",
7718
+ "decimalSeparator",
7719
+ "dateFormat",
7720
+ "timeFormat",
7721
+ "formulaArgSeparator",
7722
+ ]) {
7723
+ if (!locale[property] || typeof locale[property] !== "string") {
7724
+ return false;
7725
+ }
7734
7726
  }
7735
7727
  if (locale.formulaArgSeparator === locale.decimalSeparator) {
7736
7728
  return false;
@@ -7828,7 +7820,10 @@ function canonicalizeNumberLiteral(content, locale) {
7828
7820
  if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
7829
7821
  return content;
7830
7822
  }
7831
- return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
7823
+ if (locale.thousandsSeparator) {
7824
+ content = content.replaceAll(locale.thousandsSeparator, "");
7825
+ }
7826
+ return content.replace(locale.decimalSeparator, ".");
7832
7827
  }
7833
7828
  /**
7834
7829
  * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
@@ -8474,7 +8469,7 @@ function truncateLabel(label) {
8474
8469
  /**
8475
8470
  * Get a default chart js configuration
8476
8471
  */
8477
- function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
8472
+ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
8478
8473
  const options = {
8479
8474
  // https://www.chartjs.org/docs/latest/general/responsive.html
8480
8475
  responsive: true,
@@ -9507,15 +9502,6 @@ function createLineChartRuntime(chart, getters) {
9507
9502
  }
9508
9503
  const colors = new ChartColors();
9509
9504
  for (let [index, { label, data }] of dataSetsValues.entries()) {
9510
- if (["linear", "time"].includes(axisType)) {
9511
- // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
9512
- data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
9513
- }
9514
- const color = colors.next();
9515
- let backgroundRGBA = colorToRGBA(color);
9516
- if (chart.stacked) {
9517
- backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
9518
- }
9519
9505
  if (chart.cumulative) {
9520
9506
  let accumulator = 0;
9521
9507
  data = data.map((value) => {
@@ -9526,6 +9512,15 @@ function createLineChartRuntime(chart, getters) {
9526
9512
  return value;
9527
9513
  });
9528
9514
  }
9515
+ if (["linear", "time"].includes(axisType)) {
9516
+ // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
9517
+ data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
9518
+ }
9519
+ const color = colors.next();
9520
+ let backgroundRGBA = colorToRGBA(color);
9521
+ if (chart.stacked) {
9522
+ backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
9523
+ }
9529
9524
  const backgroundColor = rgbaToHex(backgroundRGBA);
9530
9525
  const dataset = {
9531
9526
  label,
@@ -24781,7 +24776,13 @@ class SettingsPanel extends owl.Component {
24781
24776
  }
24782
24777
  async loadLocales() {
24783
24778
  this.loadedLocales = (await this.env.loadLocales())
24784
- .filter(isValidLocale)
24779
+ .filter((locale) => {
24780
+ const isValid = isValidLocale(locale);
24781
+ if (!isValid) {
24782
+ console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
24783
+ }
24784
+ return isValid;
24785
+ })
24785
24786
  .sort((a, b) => a.name.localeCompare(b.name));
24786
24787
  }
24787
24788
  get numberFormatPreview() {
@@ -30537,6 +30538,7 @@ class Grid extends owl.Component {
30537
30538
  return;
30538
30539
  }
30539
30540
  if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
30541
+ ev.preventDefault();
30540
30542
  const content = clipboardData.getData(ClipboardMIMEType.PlainText);
30541
30543
  const target = this.env.model.getters.getSelectedZones();
30542
30544
  const clipboardString = this.env.model.getters.getClipboardTextContent();
@@ -35134,6 +35136,21 @@ class BordersPlugin extends CorePlugin {
35134
35136
  return [];
35135
35137
  return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
35136
35138
  }
35139
+ /**
35140
+ * Get all the rows which contains at least a border
35141
+ */
35142
+ getRowsWithBorders(sheetId) {
35143
+ const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
35144
+ if (!sheetBorders)
35145
+ return [];
35146
+ const rowsWithBorders = new Set();
35147
+ for (const rowBorders of sheetBorders) {
35148
+ for (const rowBorder in rowBorders) {
35149
+ rowsWithBorders.add(parseInt(rowBorder, 10));
35150
+ }
35151
+ }
35152
+ return Array.from(rowsWithBorders);
35153
+ }
35137
35154
  /**
35138
35155
  * Get the range of all the rows in the sheet
35139
35156
  */
@@ -35183,7 +35200,7 @@ class BordersPlugin extends CorePlugin {
35183
35200
  destructive: false,
35184
35201
  });
35185
35202
  }
35186
- this.getRowsRange(sheetId)
35203
+ this.getRowsWithBorders(sheetId)
35187
35204
  .filter((row) => row >= start)
35188
35205
  .sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
35189
35206
  .forEach((row) => {
@@ -35638,7 +35655,7 @@ function parseExpression(tokens, parent_priority = 0) {
35638
35655
  * Parse an expression (as a string) into an AST.
35639
35656
  */
35640
35657
  function parse(str) {
35641
- return parseTokens(tokenize(str));
35658
+ return parseTokens(rangeTokenize(str));
35642
35659
  }
35643
35660
  function parseTokens(tokens) {
35644
35661
  tokens = tokens.filter((x) => x.type !== "SPACE");
@@ -42132,6 +42149,7 @@ class Evaluator {
42132
42149
  }
42133
42150
  finally {
42134
42151
  this.cellsBeingComputed.delete(cellId);
42152
+ this.nextPositionsToUpdate.delete(positionId);
42135
42153
  }
42136
42154
  }
42137
42155
  computeAndSave(position) {
@@ -42160,11 +42178,36 @@ class Evaluator {
42160
42178
  forEachSpreadPositionInMatrix(nbColumns, nbRows,
42161
42179
  // thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
42162
42180
  this.spreadValues(formulaPosition, formulaReturn));
42181
+ this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
42163
42182
  return createEvaluatedCell(formulaReturn[0][0].value, {
42164
42183
  format: cellData.format || formulaReturn[0][0]?.format,
42165
42184
  locale: this.getters.getLocale(),
42166
42185
  }, formulaReturn[0][0].message);
42167
42186
  }
42187
+ invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
42188
+ // the result matrix is split in 2 zones to exclude the array formula position
42189
+ const top = arrayFormulaPosition.row;
42190
+ const left = arrayFormulaPosition.col;
42191
+ const bottom = top + nbRows - 1;
42192
+ const leftColumnZone = {
42193
+ top: top + 1,
42194
+ bottom,
42195
+ left,
42196
+ right: left,
42197
+ };
42198
+ const rightPartZone = {
42199
+ top,
42200
+ bottom,
42201
+ left: left + 1,
42202
+ right: left + nbColumns - 1,
42203
+ };
42204
+ const sheetId = arrayFormulaPosition.sheetId;
42205
+ const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
42206
+ { sheetId, zone: rightPartZone },
42207
+ { sheetId, zone: leftColumnZone },
42208
+ ]);
42209
+ this.nextPositionsToUpdate.addMany(invalidatedPositions);
42210
+ }
42168
42211
  assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
42169
42212
  const numberOfCols = this.getters.getNumberCols(sheetId);
42170
42213
  const numberOfRows = this.getters.getNumberRows(sheetId);
@@ -42213,9 +42256,6 @@ class Evaluator {
42213
42256
  }, matrixResult[i][j].message);
42214
42257
  const positionId = this.encoder.encode(position);
42215
42258
  this.setEvaluatedCell(positionId, evaluatedCell);
42216
- // check if formula dependencies present in the spread zone
42217
- // if so, they need to be recomputed
42218
- this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
42219
42259
  };
42220
42260
  }
42221
42261
  invalidateSpreading(positionId) {
@@ -57839,6 +57879,6 @@ exports.setTranslationMethod = setTranslationMethod;
57839
57879
  exports.tokenize = tokenize;
57840
57880
 
57841
57881
 
57842
- __info__.version = "17.1.21";
57843
- __info__.date = "2024-07-02T10:35:57.801Z";
57844
- __info__.hash = "ec4c09b";
57882
+ __info__.version = "17.1.23";
57883
+ __info__.date = "2024-07-11T06:37:01.931Z";
57884
+ __info__.hash = "31e8450";
@@ -985,7 +985,7 @@ declare function lazy<T>(fn: (() => T) | T): Lazy<T>;
985
985
  /**
986
986
  * Compares two objects.
987
987
  */
988
- declare function deepEquals(o1: any, o2: any, ignoreFunctions?: "ignoreFunctions"): boolean;
988
+ declare function deepEquals(o1: any, o2: any): boolean;
989
989
 
990
990
  interface ConstructorArgs {
991
991
  readonly zone: Readonly<Zone | UnboundedZone>;
@@ -2736,7 +2736,7 @@ type LocaleCode = string & Alias;
2736
2736
  interface Locale {
2737
2737
  name: string;
2738
2738
  code: LocaleCode;
2739
- thousandsSeparator: string;
2739
+ thousandsSeparator?: string;
2740
2740
  decimalSeparator: string;
2741
2741
  dateFormat: string;
2742
2742
  timeFormat: string;
@@ -3189,6 +3189,10 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
3189
3189
  * Get all the columns which contains at least a border
3190
3190
  */
3191
3191
  private getColumnsWithBorders;
3192
+ /**
3193
+ * Get all the rows which contains at least a border
3194
+ */
3195
+ private getRowsWithBorders;
3192
3196
  /**
3193
3197
  * Get the range of all the rows in the sheet
3194
3198
  */
@@ -6253,7 +6257,6 @@ declare class ChartJsComponent extends Component<Props$B, SpreadsheetChildEnv> {
6253
6257
  };
6254
6258
  private canvas;
6255
6259
  private chart?;
6256
- private currentRuntime;
6257
6260
  get background(): string;
6258
6261
  get canvasStyle(): string;
6259
6262
  get chartRuntime(): ChartJSRuntime;