@odoo/o-spreadsheet 17.2.5 → 17.2.7

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.5
7
- * @date 2024-04-26T07:41:13.193Z
8
- * @hash a730f5c
6
+ * @version 17.2.7
7
+ * @date 2024-05-15T09:20:44.429Z
8
+ * @hash 57e89fa
9
9
  */
10
10
 
11
11
  (function (exports, owl) {
@@ -553,7 +553,7 @@
553
553
  /**
554
554
  * Compares two objects.
555
555
  */
556
- function deepEquals(o1, o2) {
556
+ function deepEquals(o1, o2, ignoreFunctions) {
557
557
  if (o1 === o2)
558
558
  return true;
559
559
  if ((o1 && !o2) || (o2 && !o1))
@@ -569,13 +569,16 @@
569
569
  }
570
570
  }
571
571
  for (const key in o1) {
572
- if (typeof o1[key] !== typeof o2[key])
572
+ const typeOfO1Key = typeof o1[key];
573
+ if (typeOfO1Key !== typeof o2[key])
573
574
  return false;
574
- if (typeof o1[key] === "object") {
575
- if (!deepEquals(o1[key], o2[key]))
575
+ if (typeOfO1Key === "object") {
576
+ if (!deepEquals(o1[key], o2[key], ignoreFunctions))
576
577
  return false;
577
578
  }
578
579
  else {
580
+ if (ignoreFunctions && typeOfO1Key === "function")
581
+ return true;
579
582
  if (o1[key] !== o2[key])
580
583
  return false;
581
584
  }
@@ -3683,21 +3686,22 @@
3683
3686
  xc = xc.split("!").at(-1);
3684
3687
  }
3685
3688
  if (xc.includes("$")) {
3686
- xc = xc.replace(/\$/g, "");
3689
+ xc = xc.replaceAll("$", "");
3687
3690
  }
3688
- let ranges;
3691
+ let firstRangePart = "";
3692
+ let secondRangePart;
3689
3693
  if (xc.includes(":")) {
3690
- ranges = xc.split(":").map((x) => x.trim());
3694
+ [firstRangePart, secondRangePart] = xc.split(":");
3695
+ firstRangePart = firstRangePart.trim();
3696
+ secondRangePart = secondRangePart.trim();
3691
3697
  }
3692
3698
  else {
3693
- ranges = [xc.trim()];
3699
+ firstRangePart = xc.trim();
3694
3700
  }
3695
3701
  let top, bottom, left, right;
3696
3702
  let fullCol = false;
3697
3703
  let fullRow = false;
3698
3704
  let hasHeader = false;
3699
- const firstRangePart = ranges[0];
3700
- const secondRangePart = ranges[1] && ranges[1];
3701
3705
  if (isColReference(firstRangePart)) {
3702
3706
  left = right = lettersToNumber(firstRangePart);
3703
3707
  top = bottom = 0;
@@ -3714,7 +3718,7 @@
3714
3718
  top = bottom = c.row;
3715
3719
  hasHeader = true;
3716
3720
  }
3717
- if (ranges.length === 2) {
3721
+ if (secondRangePart) {
3718
3722
  if (isColReference(secondRangePart)) {
3719
3723
  right = lettersToNumber(secondRangePart);
3720
3724
  fullCol = true;
@@ -5198,7 +5202,7 @@
5198
5202
  }
5199
5203
  return null;
5200
5204
  }
5201
- const separatorRegexp = /^[\w\.!\$]+/;
5205
+ const SYMBOL_CHARS = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.!$");
5202
5206
  /**
5203
5207
  * A "Symbol" is just basically any word-like element that can appear in a
5204
5208
  * formula, which is not a string. So:
@@ -5238,11 +5242,8 @@
5238
5242
  };
5239
5243
  }
5240
5244
  }
5241
- const match = chars.remaining().match(separatorRegexp);
5242
- if (match) {
5243
- const value = match[0];
5244
- result += value;
5245
- chars.advanceBy(value.length);
5245
+ while (chars.current && SYMBOL_CHARS.has(chars.current)) {
5246
+ result += chars.shift();
5246
5247
  }
5247
5248
  if (result.length) {
5248
5249
  const value = result;
@@ -6794,7 +6795,7 @@
6794
6795
  function matchReference(tokens) {
6795
6796
  let head = 0;
6796
6797
  let transitions = machine[State.LeftRef];
6797
- const matchedTokens = [];
6798
+ let matchedTokens = "";
6798
6799
  while (transitions !== undefined) {
6799
6800
  const token = tokens[head++];
6800
6801
  if (!token) {
@@ -6806,15 +6807,15 @@
6806
6807
  case undefined:
6807
6808
  return null;
6808
6809
  case State.Found:
6809
- matchedTokens.push(token);
6810
+ matchedTokens += token.value;
6810
6811
  tokens.splice(0, head);
6811
6812
  return {
6812
6813
  type: "REFERENCE",
6813
- value: concat(matchedTokens.map((token) => token.value)),
6814
+ value: matchedTokens,
6814
6815
  };
6815
6816
  default:
6816
6817
  transitions = machine[nextState];
6817
- matchedTokens.push(token);
6818
+ matchedTokens += token.value;
6818
6819
  break;
6819
6820
  }
6820
6821
  }
@@ -8905,8 +8906,7 @@ stores.inject(MyMetaStore, storeInstance);
8905
8906
  const exactMatch = proposals?.find((p) => p.text === tokenAtCursor.value);
8906
8907
  // remove tokens that are likely to be other parts of the formula that slipped in the token if it's a string
8907
8908
  const searchTerm = tokenAtCursor.value.replace(/[ ,\(\)]/g, "");
8908
- const initialContent = this.initialContent;
8909
- if (exactMatch && exactMatch.text !== initialContent) {
8909
+ if (exactMatch && this._currentContent !== this.initialContent) {
8910
8910
  // this means the user has chosen a proposal
8911
8911
  return;
8912
8912
  }
@@ -8914,7 +8914,7 @@ stores.inject(MyMetaStore, storeInstance);
8914
8914
  proposals &&
8915
8915
  !["ARG_SEPARATOR", "LEFT_PAREN"].includes(tokenAtCursor.type)) {
8916
8916
  const filteredProposals = fuzzyLookup(searchTerm, proposals, (p) => p.fuzzySearchKey || p.text);
8917
- if (!exactMatch) {
8917
+ if (!exactMatch || filteredProposals.length > 1) {
8918
8918
  proposals = filteredProposals;
8919
8919
  }
8920
8920
  }
@@ -9049,6 +9049,7 @@ stores.inject(MyMetaStore, storeInstance);
9049
9049
  };
9050
9050
  canvas = owl.useRef("graphContainer");
9051
9051
  chart;
9052
+ currentRuntime;
9052
9053
  get background() {
9053
9054
  return this.chartRuntime.background;
9054
9055
  }
@@ -9065,9 +9066,18 @@ stores.inject(MyMetaStore, storeInstance);
9065
9066
  setup() {
9066
9067
  owl.onMounted(() => {
9067
9068
  const runtime = this.chartRuntime;
9068
- this.createChart(runtime.chartJsConfig);
9069
+ this.currentRuntime = runtime;
9070
+ // Note: chartJS modify the runtime in place, so it's important to give it a copy
9071
+ this.createChart(deepCopy(runtime.chartJsConfig));
9072
+ });
9073
+ owl.onWillUnmount(() => this.chart?.destroy());
9074
+ owl.useEffect(() => {
9075
+ const runtime = this.chartRuntime;
9076
+ if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
9077
+ this.currentRuntime = runtime;
9078
+ this.updateChartJs(deepCopy(runtime));
9079
+ }
9069
9080
  });
9070
- owl.useEffect(() => this.updateChartJs(this.chartRuntime), () => [this.chartRuntime]);
9071
9081
  }
9072
9082
  createChart(chartData) {
9073
9083
  const canvas = this.canvas.el;
@@ -9089,8 +9099,7 @@ stores.inject(MyMetaStore, storeInstance);
9089
9099
  this.chart.config.options.plugins.tooltip = chartData.options.plugins.tooltip;
9090
9100
  this.chart.config.options.plugins.legend = chartData.options.plugins.legend;
9091
9101
  this.chart.config.options.scales = chartData.options?.scales;
9092
- // ?
9093
- this.chart.update("active");
9102
+ this.chart.update();
9094
9103
  }
9095
9104
  }
9096
9105
 
@@ -19453,7 +19462,7 @@ stores.inject(MyMetaStore, storeInstance);
19453
19462
  /**
19454
19463
  * Get a default chart js configuration
19455
19464
  */
19456
- function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale }) {
19465
+ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
19457
19466
  const options = {
19458
19467
  // https://www.chartjs.org/docs/latest/general/responsive.html
19459
19468
  responsive: true,
@@ -19500,7 +19509,7 @@ stores.inject(MyMetaStore, storeInstance);
19500
19509
  type: chart.type,
19501
19510
  options,
19502
19511
  data: {
19503
- labels: labels.map(truncateLabel),
19512
+ labels: truncateLabels ? labels.map(truncateLabel) : labels,
19504
19513
  datasets: [],
19505
19514
  },
19506
19515
  platform: undefined,
@@ -20266,9 +20275,9 @@ stores.inject(MyMetaStore, storeInstance);
20266
20275
  }
20267
20276
  return isInstalled;
20268
20277
  }
20269
- function getLineOrScatterConfiguration(chart, labels, localeFormat) {
20278
+ function getLineOrScatterConfiguration(chart, labels, options) {
20270
20279
  const fontColor = chartFontColor(chart.background);
20271
- const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
20280
+ const config = getDefaultChartJsRuntime(chart, labels, fontColor, options);
20272
20281
  const legend = {
20273
20282
  labels: {
20274
20283
  color: fontColor,
@@ -20311,7 +20320,7 @@ stores.inject(MyMetaStore, storeInstance);
20311
20320
  value = Number(value);
20312
20321
  if (isNaN(value))
20313
20322
  return value;
20314
- const { locale, format } = localeFormat;
20323
+ const { locale, format } = options;
20315
20324
  return formatValue(value, {
20316
20325
  locale,
20317
20326
  format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
@@ -20344,9 +20353,10 @@ stores.inject(MyMetaStore, storeInstance);
20344
20353
  ({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
20345
20354
  }
20346
20355
  const locale = getters.getLocale();
20356
+ const truncateLabels = axisType === "category";
20347
20357
  const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
20348
- const localeFormat = { format: dataSetFormat, locale };
20349
- const config = getLineOrScatterConfiguration(chart, labels, localeFormat);
20358
+ const options = { format: dataSetFormat, locale, truncateLabels };
20359
+ const config = getLineOrScatterConfiguration(chart, labels, options);
20350
20360
  const labelFormat = getChartLabelFormat(getters, chart.labelRange);
20351
20361
  if (axisType === "time") {
20352
20362
  const axis = {
@@ -32900,7 +32910,8 @@ stores.inject(MyMetaStore, storeInstance);
32900
32910
  get checkBoxCellPositions() {
32901
32911
  return this.env.model.getters
32902
32912
  .getVisibleCellPositions()
32903
- .filter(this.env.model.getters.isCellValidCheckbox);
32913
+ .filter((position) => this.env.model.getters.isCellValidCheckbox(position) &&
32914
+ !this.env.model.getters.isFilterHeader(position));
32904
32915
  }
32905
32916
  get listIconsCellPositions() {
32906
32917
  if (this.env.model.getters.isReadonly()) {
@@ -32908,7 +32919,8 @@ stores.inject(MyMetaStore, storeInstance);
32908
32919
  }
32909
32920
  return this.env.model.getters
32910
32921
  .getVisibleCellPositions()
32911
- .filter(this.env.model.getters.cellHasListDataValidationIcon);
32922
+ .filter((position) => this.env.model.getters.cellHasListDataValidationIcon(position) &&
32923
+ !this.env.model.getters.isFilterHeader(position));
32912
32924
  }
32913
32925
  }
32914
32926
 
@@ -47421,9 +47433,10 @@ stores.inject(MyMetaStore, storeInstance);
47421
47433
  }
47422
47434
  if (!content) {
47423
47435
  // The previous content could have blocked some array formulas
47424
- impactedPositions.addMany(this.getArrayFormulasBlockedBy(position));
47436
+ impactedPositions.add(position);
47425
47437
  }
47426
47438
  }
47439
+ impactedPositions.addMany(this.getArrayFormulasBlockedBy(impactedPositions));
47427
47440
  return impactedPositions;
47428
47441
  }
47429
47442
  buildDependencyGraph() {
@@ -47465,23 +47478,25 @@ stores.inject(MyMetaStore, storeInstance);
47465
47478
  return positions;
47466
47479
  }
47467
47480
  /**
47468
- * Return the position of formulas blocked by the given position
47481
+ * Return the position of formulas blocked by the given positions
47469
47482
  * as well as all their dependencies.
47470
47483
  */
47471
- getArrayFormulasBlockedBy(position) {
47472
- if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
47473
- return [];
47474
- }
47475
- const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
47476
- const positions = this.createEmptyPositionSet();
47477
- positions.addMany(arrayFormulas);
47478
- const arrayFormulaPosition = this.getArrayFormulaSpreadingOn(position);
47479
- if (arrayFormulaPosition) {
47480
- // ignore the formula spreading on the position. Keep only the blocked ones
47481
- positions.delete(arrayFormulaPosition);
47484
+ getArrayFormulasBlockedBy(positions) {
47485
+ const arrayFormulaPositions = this.createEmptyPositionSet();
47486
+ for (const position of positions) {
47487
+ if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
47488
+ continue;
47489
+ }
47490
+ const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
47491
+ arrayFormulaPositions.addMany(arrayFormulas);
47492
+ const arrayFormulaPosition = this.getArrayFormulaSpreadingOn(position);
47493
+ if (arrayFormulaPosition) {
47494
+ // ignore the formula spreading on the position. Keep only the blocked ones
47495
+ arrayFormulaPositions.delete(arrayFormulaPosition);
47496
+ }
47482
47497
  }
47483
- positions.addMany(this.getCellsDependingOn(positions));
47484
- return positions;
47498
+ arrayFormulaPositions.addMany(this.getCellsDependingOn(arrayFormulaPositions));
47499
+ return arrayFormulaPositions;
47485
47500
  }
47486
47501
  nextPositionsToUpdate = new PositionSet({});
47487
47502
  cellsBeingComputed = new Set();
@@ -47611,6 +47626,7 @@ stores.inject(MyMetaStore, storeInstance);
47611
47626
  if (!this.spreadingRelations.isArrayFormula(position)) {
47612
47627
  return;
47613
47628
  }
47629
+ const invalidated = this.createEmptyPositionSet();
47614
47630
  for (const child of this.spreadingRelations.getArrayResultPositions(position)) {
47615
47631
  const content = this.getters.getCell(child)?.content;
47616
47632
  if (content) {
@@ -47618,10 +47634,11 @@ stores.inject(MyMetaStore, storeInstance);
47618
47634
  // there's still a collision
47619
47635
  continue;
47620
47636
  }
47637
+ invalidated.add(child);
47621
47638
  this.evaluatedCells.delete(child);
47622
- this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
47623
- this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedBy(child));
47624
47639
  }
47640
+ this.nextPositionsToUpdate.addMany(this.getCellsDependingOn(invalidated));
47641
+ this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedBy(invalidated));
47625
47642
  this.spreadingRelations.removeNode(position);
47626
47643
  }
47627
47644
  // ----------------------------------------------------------
@@ -47928,7 +47945,7 @@ stores.inject(MyMetaStore, storeInstance);
47928
47945
  ? getItemId(newFormat, data.formats)
47929
47946
  : exportedCellData.format;
47930
47947
  let content;
47931
- if (isFormula && formulaCell instanceof FormulaCellWithDependencies) {
47948
+ if (isExported && isFormula && formulaCell instanceof FormulaCellWithDependencies) {
47932
47949
  content = formulaCell.contentWithFixedReferences;
47933
47950
  }
47934
47951
  else {
@@ -60599,9 +60616,9 @@ stores.inject(MyMetaStore, storeInstance);
60599
60616
  exports.tokenize = tokenize;
60600
60617
 
60601
60618
 
60602
- __info__.version = "17.2.5";
60603
- __info__.date = "2024-04-26T07:41:13.193Z";
60604
- __info__.hash = "a730f5c";
60619
+ __info__.version = "17.2.7";
60620
+ __info__.date = "2024-05-15T09:20:44.429Z";
60621
+ __info__.hash = "57e89fa";
60605
60622
 
60606
60623
 
60607
60624
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);