@odoo/o-spreadsheet 17.0.28 → 17.0.30
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.
- package/dist/o-spreadsheet.cjs.js +98 -58
- package/dist/o-spreadsheet.d.ts +6 -3
- package/dist/o-spreadsheet.esm.js +98 -58
- package/dist/o-spreadsheet.iife.js +98 -58
- package/dist/o-spreadsheet.iife.min.js +168 -168
- package/dist/o_spreadsheet.xml +4 -4
- package/package.json +1 -1
|
@@ -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.
|
|
6
|
-
* @date 2024-07-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.30
|
|
6
|
+
* @date 2024-07-11T06:34:04.932Z
|
|
7
|
+
* @hash a8eacf4
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
|
|
@@ -657,7 +657,7 @@ function getAddHeaderStartIndex(position, base) {
|
|
|
657
657
|
/**
|
|
658
658
|
* Compares two objects.
|
|
659
659
|
*/
|
|
660
|
-
function deepEquals(o1, o2
|
|
660
|
+
function deepEquals(o1, o2) {
|
|
661
661
|
if (o1 === o2)
|
|
662
662
|
return true;
|
|
663
663
|
if ((o1 && !o2) || (o2 && !o1))
|
|
@@ -673,17 +673,13 @@ function deepEquals(o1, o2, ignoreFunctions) {
|
|
|
673
673
|
}
|
|
674
674
|
}
|
|
675
675
|
for (const key in o1) {
|
|
676
|
-
|
|
677
|
-
if (typeOfO1Key !== typeof o2[key])
|
|
676
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
678
677
|
return false;
|
|
679
|
-
if (
|
|
680
|
-
if (!deepEquals(o1[key], o2[key]
|
|
678
|
+
if (typeof o1[key] === "object") {
|
|
679
|
+
if (!deepEquals(o1[key], o2[key]))
|
|
681
680
|
return false;
|
|
682
681
|
}
|
|
683
682
|
else {
|
|
684
|
-
if (ignoreFunctions && typeOfO1Key === "function") {
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
683
|
if (o1[key] !== o2[key])
|
|
688
684
|
return false;
|
|
689
685
|
}
|
|
@@ -754,11 +750,9 @@ class JetSet extends Set {
|
|
|
754
750
|
return this;
|
|
755
751
|
}
|
|
756
752
|
deleteMany(iterable) {
|
|
757
|
-
let wasDeleted = false;
|
|
758
753
|
for (const element of iterable) {
|
|
759
|
-
|
|
754
|
+
super.delete(element);
|
|
760
755
|
}
|
|
761
|
-
return wasDeleted;
|
|
762
756
|
}
|
|
763
757
|
}
|
|
764
758
|
/**
|
|
@@ -1815,7 +1809,7 @@ const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSepa
|
|
|
1815
1809
|
});
|
|
1816
1810
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
1817
1811
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
1818
|
-
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
|
|
1812
|
+
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
|
|
1819
1813
|
const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
|
|
1820
1814
|
const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
|
|
1821
1815
|
const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -1842,7 +1836,7 @@ function isNumber(value, locale) {
|
|
|
1842
1836
|
return getNumberRegex(locale).test(value.trim());
|
|
1843
1837
|
}
|
|
1844
1838
|
const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
|
|
1845
|
-
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
|
|
1839
|
+
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
|
|
1846
1840
|
});
|
|
1847
1841
|
/**
|
|
1848
1842
|
* Convert a string into a number. It assumes that the string actually represents
|
|
@@ -2544,6 +2538,9 @@ function getPredicate(descr, isQuery, locale) {
|
|
|
2544
2538
|
return result;
|
|
2545
2539
|
}
|
|
2546
2540
|
function operandToRegExp(operand) {
|
|
2541
|
+
if (operand === "*") {
|
|
2542
|
+
return /.+/;
|
|
2543
|
+
}
|
|
2547
2544
|
let exp = "";
|
|
2548
2545
|
let predecessor = "";
|
|
2549
2546
|
for (let char of operand) {
|
|
@@ -2567,9 +2564,9 @@ function operandToRegExp(operand) {
|
|
|
2567
2564
|
}
|
|
2568
2565
|
return new RegExp("^" + exp + "$", "i");
|
|
2569
2566
|
}
|
|
2570
|
-
function evaluatePredicate(value, criterion) {
|
|
2567
|
+
function evaluatePredicate(value = "", criterion) {
|
|
2571
2568
|
const { operator, operand } = criterion;
|
|
2572
|
-
if (
|
|
2569
|
+
if (operand === undefined || value === null || operand === null) {
|
|
2573
2570
|
return false;
|
|
2574
2571
|
}
|
|
2575
2572
|
if (typeof operand === "number" && operator === "=") {
|
|
@@ -4782,7 +4779,6 @@ class ChartJsComponent extends Component {
|
|
|
4782
4779
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
4783
4780
|
canvas = useRef("graphContainer");
|
|
4784
4781
|
chart;
|
|
4785
|
-
currentRuntime;
|
|
4786
4782
|
get background() {
|
|
4787
4783
|
return this.chartRuntime.background;
|
|
4788
4784
|
}
|
|
@@ -4799,17 +4795,10 @@ class ChartJsComponent extends Component {
|
|
|
4799
4795
|
setup() {
|
|
4800
4796
|
onMounted(() => {
|
|
4801
4797
|
const runtime = this.chartRuntime;
|
|
4802
|
-
this.currentRuntime = runtime;
|
|
4803
4798
|
// Note: chartJS modify the runtime in place, so it's important to give it a copy
|
|
4804
4799
|
this.createChart(deepCopy(runtime.chartJsConfig));
|
|
4805
4800
|
});
|
|
4806
|
-
useEffect(() =>
|
|
4807
|
-
const runtime = this.chartRuntime;
|
|
4808
|
-
if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
|
|
4809
|
-
this.currentRuntime = runtime;
|
|
4810
|
-
this.updateChartJs(deepCopy(runtime));
|
|
4811
|
-
}
|
|
4812
|
-
});
|
|
4801
|
+
useEffect(() => this.updateChartJs(deepCopy(this.chartRuntime)), () => [this.chartRuntime]);
|
|
4813
4802
|
}
|
|
4814
4803
|
createChart(chartData) {
|
|
4815
4804
|
const canvas = this.canvas.el;
|
|
@@ -7677,19 +7666,22 @@ class TokenizingChars {
|
|
|
7677
7666
|
}
|
|
7678
7667
|
|
|
7679
7668
|
function isValidLocale(locale) {
|
|
7680
|
-
if (!
|
|
7681
|
-
typeof locale
|
|
7682
|
-
typeof locale.
|
|
7683
|
-
typeof locale.code === "string" &&
|
|
7684
|
-
typeof locale.thousandsSeparator === "string" &&
|
|
7685
|
-
typeof locale.decimalSeparator === "string" &&
|
|
7686
|
-
typeof locale.dateFormat === "string" &&
|
|
7687
|
-
typeof locale.timeFormat === "string" &&
|
|
7688
|
-
typeof locale.formulaArgSeparator === "string")) {
|
|
7669
|
+
if (!locale ||
|
|
7670
|
+
typeof locale !== "object" ||
|
|
7671
|
+
!(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
|
|
7689
7672
|
return false;
|
|
7690
7673
|
}
|
|
7691
|
-
|
|
7692
|
-
|
|
7674
|
+
for (const property of [
|
|
7675
|
+
"code",
|
|
7676
|
+
"name",
|
|
7677
|
+
"decimalSeparator",
|
|
7678
|
+
"dateFormat",
|
|
7679
|
+
"timeFormat",
|
|
7680
|
+
"formulaArgSeparator",
|
|
7681
|
+
]) {
|
|
7682
|
+
if (!locale[property] || typeof locale[property] !== "string") {
|
|
7683
|
+
return false;
|
|
7684
|
+
}
|
|
7693
7685
|
}
|
|
7694
7686
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
7695
7687
|
return false;
|
|
@@ -7787,7 +7779,10 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
7787
7779
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
7788
7780
|
return content;
|
|
7789
7781
|
}
|
|
7790
|
-
|
|
7782
|
+
if (locale.thousandsSeparator) {
|
|
7783
|
+
content = content.replaceAll(locale.thousandsSeparator, "");
|
|
7784
|
+
}
|
|
7785
|
+
return content.replace(locale.decimalSeparator, ".");
|
|
7791
7786
|
}
|
|
7792
7787
|
/**
|
|
7793
7788
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -8433,7 +8428,7 @@ function truncateLabel(label) {
|
|
|
8433
8428
|
/**
|
|
8434
8429
|
* Get a default chart js configuration
|
|
8435
8430
|
*/
|
|
8436
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
|
|
8431
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
|
|
8437
8432
|
const options = {
|
|
8438
8433
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
8439
8434
|
responsive: true,
|
|
@@ -9465,15 +9460,6 @@ function createLineChartRuntime(chart, getters) {
|
|
|
9465
9460
|
}
|
|
9466
9461
|
const colors = new ChartColors();
|
|
9467
9462
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
9468
|
-
if (["linear", "time"].includes(axisType)) {
|
|
9469
|
-
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
9470
|
-
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
9471
|
-
}
|
|
9472
|
-
const color = colors.next();
|
|
9473
|
-
let backgroundRGBA = colorToRGBA(color);
|
|
9474
|
-
if (chart.stacked) {
|
|
9475
|
-
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
|
|
9476
|
-
}
|
|
9477
9463
|
if (chart.cumulative) {
|
|
9478
9464
|
let accumulator = 0;
|
|
9479
9465
|
data = data.map((value) => {
|
|
@@ -9484,6 +9470,15 @@ function createLineChartRuntime(chart, getters) {
|
|
|
9484
9470
|
return value;
|
|
9485
9471
|
});
|
|
9486
9472
|
}
|
|
9473
|
+
if (["linear", "time"].includes(axisType)) {
|
|
9474
|
+
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
9475
|
+
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
9476
|
+
}
|
|
9477
|
+
const color = colors.next();
|
|
9478
|
+
let backgroundRGBA = colorToRGBA(color);
|
|
9479
|
+
if (chart.stacked) {
|
|
9480
|
+
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
|
|
9481
|
+
}
|
|
9487
9482
|
const backgroundColor = rgbaToHex(backgroundRGBA);
|
|
9488
9483
|
const dataset = {
|
|
9489
9484
|
label,
|
|
@@ -24281,7 +24276,13 @@ class SettingsPanel extends Component {
|
|
|
24281
24276
|
}
|
|
24282
24277
|
async loadLocales() {
|
|
24283
24278
|
this.loadedLocales = (await this.env.loadLocales())
|
|
24284
|
-
.filter(
|
|
24279
|
+
.filter((locale) => {
|
|
24280
|
+
const isValid = isValidLocale(locale);
|
|
24281
|
+
if (!isValid) {
|
|
24282
|
+
console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
|
|
24283
|
+
}
|
|
24284
|
+
return isValid;
|
|
24285
|
+
})
|
|
24285
24286
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
24286
24287
|
}
|
|
24287
24288
|
get numberFormatPreview() {
|
|
@@ -30064,6 +30065,7 @@ class Grid extends Component {
|
|
|
30064
30065
|
return;
|
|
30065
30066
|
}
|
|
30066
30067
|
if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
|
|
30068
|
+
ev.preventDefault();
|
|
30067
30069
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
30068
30070
|
const target = this.env.model.getters.getSelectedZones();
|
|
30069
30071
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
@@ -34639,6 +34641,21 @@ class BordersPlugin extends CorePlugin {
|
|
|
34639
34641
|
return [];
|
|
34640
34642
|
return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
|
|
34641
34643
|
}
|
|
34644
|
+
/**
|
|
34645
|
+
* Get all the rows which contains at least a border
|
|
34646
|
+
*/
|
|
34647
|
+
getRowsWithBorders(sheetId) {
|
|
34648
|
+
const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
|
|
34649
|
+
if (!sheetBorders)
|
|
34650
|
+
return [];
|
|
34651
|
+
const rowsWithBorders = new Set();
|
|
34652
|
+
for (const rowBorders of sheetBorders) {
|
|
34653
|
+
for (const rowBorder in rowBorders) {
|
|
34654
|
+
rowsWithBorders.add(parseInt(rowBorder, 10));
|
|
34655
|
+
}
|
|
34656
|
+
}
|
|
34657
|
+
return Array.from(rowsWithBorders);
|
|
34658
|
+
}
|
|
34642
34659
|
/**
|
|
34643
34660
|
* Get the range of all the rows in the sheet
|
|
34644
34661
|
*/
|
|
@@ -34688,7 +34705,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
34688
34705
|
destructive: false,
|
|
34689
34706
|
});
|
|
34690
34707
|
}
|
|
34691
|
-
this.
|
|
34708
|
+
this.getRowsWithBorders(sheetId)
|
|
34692
34709
|
.filter((row) => row >= start)
|
|
34693
34710
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
34694
34711
|
.forEach((row) => {
|
|
@@ -35152,7 +35169,7 @@ function parseExpression(tokens, parent_priority = 0) {
|
|
|
35152
35169
|
* Parse an expression (as a string) into an AST.
|
|
35153
35170
|
*/
|
|
35154
35171
|
function parse(str) {
|
|
35155
|
-
return parseTokens(
|
|
35172
|
+
return parseTokens(rangeTokenize(str));
|
|
35156
35173
|
}
|
|
35157
35174
|
function parseTokens(tokens) {
|
|
35158
35175
|
tokens = tokens.filter((x) => x.type !== "SPACE");
|
|
@@ -41670,6 +41687,7 @@ class Evaluator {
|
|
|
41670
41687
|
}
|
|
41671
41688
|
finally {
|
|
41672
41689
|
this.cellsBeingComputed.delete(cellId);
|
|
41690
|
+
this.nextPositionsToUpdate.delete(positionId);
|
|
41673
41691
|
}
|
|
41674
41692
|
}
|
|
41675
41693
|
computeAndSave(position) {
|
|
@@ -41711,11 +41729,36 @@ class Evaluator {
|
|
|
41711
41729
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
41712
41730
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
41713
41731
|
this.spreadValues(formulaPosition, formulaReturn));
|
|
41732
|
+
this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
|
|
41714
41733
|
return createEvaluatedCell(formulaReturn[0][0].value, {
|
|
41715
41734
|
format: cellData.format || formulaReturn[0][0]?.format,
|
|
41716
41735
|
locale: this.getters.getLocale(),
|
|
41717
41736
|
});
|
|
41718
41737
|
}
|
|
41738
|
+
invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
|
|
41739
|
+
// the result matrix is split in 2 zones to exclude the array formula position
|
|
41740
|
+
const top = arrayFormulaPosition.row;
|
|
41741
|
+
const left = arrayFormulaPosition.col;
|
|
41742
|
+
const bottom = top + nbRows - 1;
|
|
41743
|
+
const leftColumnZone = {
|
|
41744
|
+
top: top + 1,
|
|
41745
|
+
bottom,
|
|
41746
|
+
left,
|
|
41747
|
+
right: left,
|
|
41748
|
+
};
|
|
41749
|
+
const rightPartZone = {
|
|
41750
|
+
top,
|
|
41751
|
+
bottom,
|
|
41752
|
+
left: left + 1,
|
|
41753
|
+
right: left + nbColumns - 1,
|
|
41754
|
+
};
|
|
41755
|
+
const sheetId = arrayFormulaPosition.sheetId;
|
|
41756
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
|
|
41757
|
+
{ sheetId, zone: rightPartZone },
|
|
41758
|
+
{ sheetId, zone: leftColumnZone },
|
|
41759
|
+
]);
|
|
41760
|
+
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
41761
|
+
}
|
|
41719
41762
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
41720
41763
|
const numberOfCols = this.getters.getNumberCols(sheetId);
|
|
41721
41764
|
const numberOfRows = this.getters.getNumberRows(sheetId);
|
|
@@ -41764,9 +41807,6 @@ class Evaluator {
|
|
|
41764
41807
|
});
|
|
41765
41808
|
const positionId = this.encoder.encode(position);
|
|
41766
41809
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
41767
|
-
// check if formula dependencies present in the spread zone
|
|
41768
|
-
// if so, they need to be recomputed
|
|
41769
|
-
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
41770
41810
|
};
|
|
41771
41811
|
}
|
|
41772
41812
|
invalidateSpreading(positionId) {
|
|
@@ -57501,6 +57541,6 @@ const constants = {
|
|
|
57501
57541
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
57502
57542
|
|
|
57503
57543
|
|
|
57504
|
-
__info__.version = "17.0.
|
|
57505
|
-
__info__.date = "2024-07-
|
|
57506
|
-
__info__.hash = "
|
|
57544
|
+
__info__.version = "17.0.30";
|
|
57545
|
+
__info__.date = "2024-07-11T06:34:04.932Z";
|
|
57546
|
+
__info__.hash = "a8eacf4";
|
|
@@ -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.
|
|
6
|
-
* @date 2024-07-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.30
|
|
6
|
+
* @date 2024-07-11T06:34:04.932Z
|
|
7
|
+
* @hash a8eacf4
|
|
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
|
|
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
|
-
|
|
678
|
-
if (typeOfO1Key !== typeof o2[key])
|
|
677
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
679
678
|
return false;
|
|
680
|
-
if (
|
|
681
|
-
if (!deepEquals(o1[key], o2[key]
|
|
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
|
-
|
|
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 (
|
|
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 (!
|
|
7682
|
-
typeof locale
|
|
7683
|
-
typeof locale.
|
|
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
|
-
|
|
7693
|
-
|
|
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
|
-
|
|
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.
|
|
@@ -8434,7 +8429,7 @@
|
|
|
8434
8429
|
/**
|
|
8435
8430
|
* Get a default chart js configuration
|
|
8436
8431
|
*/
|
|
8437
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
|
|
8432
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
|
|
8438
8433
|
const options = {
|
|
8439
8434
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
8440
8435
|
responsive: true,
|
|
@@ -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(
|
|
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();
|
|
@@ -34640,6 +34642,21 @@
|
|
|
34640
34642
|
return [];
|
|
34641
34643
|
return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
|
|
34642
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
|
+
}
|
|
34643
34660
|
/**
|
|
34644
34661
|
* Get the range of all the rows in the sheet
|
|
34645
34662
|
*/
|
|
@@ -34689,7 +34706,7 @@
|
|
|
34689
34706
|
destructive: false,
|
|
34690
34707
|
});
|
|
34691
34708
|
}
|
|
34692
|
-
this.
|
|
34709
|
+
this.getRowsWithBorders(sheetId)
|
|
34693
34710
|
.filter((row) => row >= start)
|
|
34694
34711
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
34695
34712
|
.forEach((row) => {
|
|
@@ -35153,7 +35170,7 @@
|
|
|
35153
35170
|
* Parse an expression (as a string) into an AST.
|
|
35154
35171
|
*/
|
|
35155
35172
|
function parse(str) {
|
|
35156
|
-
return parseTokens(
|
|
35173
|
+
return parseTokens(rangeTokenize(str));
|
|
35157
35174
|
}
|
|
35158
35175
|
function parseTokens(tokens) {
|
|
35159
35176
|
tokens = tokens.filter((x) => x.type !== "SPACE");
|
|
@@ -41671,6 +41688,7 @@
|
|
|
41671
41688
|
}
|
|
41672
41689
|
finally {
|
|
41673
41690
|
this.cellsBeingComputed.delete(cellId);
|
|
41691
|
+
this.nextPositionsToUpdate.delete(positionId);
|
|
41674
41692
|
}
|
|
41675
41693
|
}
|
|
41676
41694
|
computeAndSave(position) {
|
|
@@ -41712,11 +41730,36 @@
|
|
|
41712
41730
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
41713
41731
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
41714
41732
|
this.spreadValues(formulaPosition, formulaReturn));
|
|
41733
|
+
this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
|
|
41715
41734
|
return createEvaluatedCell(formulaReturn[0][0].value, {
|
|
41716
41735
|
format: cellData.format || formulaReturn[0][0]?.format,
|
|
41717
41736
|
locale: this.getters.getLocale(),
|
|
41718
41737
|
});
|
|
41719
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
|
+
}
|
|
41720
41763
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
41721
41764
|
const numberOfCols = this.getters.getNumberCols(sheetId);
|
|
41722
41765
|
const numberOfRows = this.getters.getNumberRows(sheetId);
|
|
@@ -41765,9 +41808,6 @@
|
|
|
41765
41808
|
});
|
|
41766
41809
|
const positionId = this.encoder.encode(position);
|
|
41767
41810
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
41768
|
-
// check if formula dependencies present in the spread zone
|
|
41769
|
-
// if so, they need to be recomputed
|
|
41770
|
-
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
41771
41811
|
};
|
|
41772
41812
|
}
|
|
41773
41813
|
invalidateSpreading(positionId) {
|
|
@@ -57537,9 +57577,9 @@
|
|
|
57537
57577
|
exports.tokenize = tokenize;
|
|
57538
57578
|
|
|
57539
57579
|
|
|
57540
|
-
__info__.version = "17.0.
|
|
57541
|
-
__info__.date = "2024-07-
|
|
57542
|
-
__info__.hash = "
|
|
57580
|
+
__info__.version = "17.0.30";
|
|
57581
|
+
__info__.date = "2024-07-11T06:34:04.932Z";
|
|
57582
|
+
__info__.hash = "a8eacf4";
|
|
57543
57583
|
|
|
57544
57584
|
|
|
57545
57585
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|