@odoo/o-spreadsheet 18.4.12 → 18.4.14
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 +171 -125
- package/dist/o-spreadsheet.d.ts +5 -0
- package/dist/o-spreadsheet.esm.js +171 -125
- package/dist/o-spreadsheet.iife.js +171 -125
- package/dist/o-spreadsheet.iife.min.js +17 -24
- package/dist/o_spreadsheet.xml +25 -5
- 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 18.4.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.4.14
|
|
6
|
+
* @date 2025-10-16T06:39:40.249Z
|
|
7
|
+
* @hash bc55c40
|
|
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
|
-
|
|
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];
|
|
@@ -3195,7 +3193,17 @@
|
|
|
3195
3193
|
return toMatrix(data).map((row) => {
|
|
3196
3194
|
return row.map((cell) => {
|
|
3197
3195
|
if (typeof cell.value !== "number") {
|
|
3198
|
-
|
|
3196
|
+
let message = "";
|
|
3197
|
+
if (typeof cell === "object") {
|
|
3198
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got an empty value.", argName);
|
|
3199
|
+
}
|
|
3200
|
+
else if (typeof cell === "string") {
|
|
3201
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a string.", argName);
|
|
3202
|
+
}
|
|
3203
|
+
else if (typeof cell === "boolean") {
|
|
3204
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a boolean.", argName);
|
|
3205
|
+
}
|
|
3206
|
+
throw new EvaluationError(message);
|
|
3199
3207
|
}
|
|
3200
3208
|
return cell.value;
|
|
3201
3209
|
});
|
|
@@ -4314,7 +4322,7 @@
|
|
|
4314
4322
|
* Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
|
|
4315
4323
|
*
|
|
4316
4324
|
* 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
|
|
4325
|
+
* preceded by a data token "h", then it's not a month but a minute.
|
|
4318
4326
|
*/
|
|
4319
4327
|
function convertTokensToMinutesInDateFormat(tokens) {
|
|
4320
4328
|
const dateParts = tokens.filter((token) => token.type === "DATE_PART");
|
|
@@ -4357,6 +4365,9 @@
|
|
|
4357
4365
|
case "REPEATED_CHAR":
|
|
4358
4366
|
format += "*" + token.value;
|
|
4359
4367
|
break;
|
|
4368
|
+
case "DATE_PART":
|
|
4369
|
+
format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
|
|
4370
|
+
break;
|
|
4360
4371
|
default:
|
|
4361
4372
|
format += token.value;
|
|
4362
4373
|
}
|
|
@@ -9080,7 +9091,7 @@
|
|
|
9080
9091
|
pasteCell(origin, target, clipboardOption) {
|
|
9081
9092
|
const { sheetId, col, row } = target;
|
|
9082
9093
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
9083
|
-
const originFormat = origin?.format
|
|
9094
|
+
const originFormat = origin?.format || origin.evaluatedCell.format;
|
|
9084
9095
|
if (clipboardOption?.pasteOption === "asValue") {
|
|
9085
9096
|
this.dispatch("UPDATE_CELL", {
|
|
9086
9097
|
...target,
|
|
@@ -13177,7 +13188,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13177
13188
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
13178
13189
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
13179
13190
|
}
|
|
13180
|
-
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "
|
|
13191
|
+
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "known_data_y")), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b)));
|
|
13181
13192
|
},
|
|
13182
13193
|
};
|
|
13183
13194
|
// -----------------------------------------------------------------------------
|
|
@@ -13250,7 +13261,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13250
13261
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13251
13262
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13252
13263
|
}
|
|
13253
|
-
return fullLinearRegression(toNumberMatrix(dataX, "
|
|
13264
|
+
return fullLinearRegression(toNumberMatrix(dataX, "data_x"), toNumberMatrix(dataY, "data_y"), toBoolean(calculateB), toBoolean(verbose));
|
|
13254
13265
|
},
|
|
13255
13266
|
isExported: true,
|
|
13256
13267
|
};
|
|
@@ -13269,7 +13280,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13269
13280
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13270
13281
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13271
13282
|
}
|
|
13272
|
-
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "
|
|
13283
|
+
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "data_x"), logM(toNumberMatrix(dataY, "data_y")), toBoolean(calculateB), toBoolean(verbose));
|
|
13273
13284
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13274
13285
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
13275
13286
|
}
|
|
@@ -13883,7 +13894,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13883
13894
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
13884
13895
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
13885
13896
|
}
|
|
13886
|
-
return predictLinearValues(toNumberMatrix(knownDataY, "
|
|
13897
|
+
return predictLinearValues(toNumberMatrix(knownDataY, "known_data_y"), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b));
|
|
13887
13898
|
},
|
|
13888
13899
|
};
|
|
13889
13900
|
// -----------------------------------------------------------------------------
|
|
@@ -21877,6 +21888,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21877
21888
|
}
|
|
21878
21889
|
const ctx = chart.ctx;
|
|
21879
21890
|
ctx.save();
|
|
21891
|
+
const { left, top, height, width } = chart.chartArea;
|
|
21892
|
+
ctx.beginPath();
|
|
21893
|
+
ctx.rect(left, top, width, height);
|
|
21894
|
+
ctx.clip();
|
|
21880
21895
|
ctx.textAlign = "center";
|
|
21881
21896
|
ctx.textBaseline = "middle";
|
|
21882
21897
|
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
@@ -22912,7 +22927,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22912
22927
|
this.chart.update();
|
|
22913
22928
|
}
|
|
22914
22929
|
hasChartDataChanged() {
|
|
22915
|
-
return !deepEquals(this.currentRuntime
|
|
22930
|
+
return !deepEquals(this.getChartDataInRuntime(this.currentRuntime), this.getChartDataInRuntime(this.chartRuntime));
|
|
22931
|
+
}
|
|
22932
|
+
getChartDataInRuntime(runtime) {
|
|
22933
|
+
const data = runtime.chartJsConfig.data;
|
|
22934
|
+
return {
|
|
22935
|
+
labels: data.labels,
|
|
22936
|
+
dataset: data.datasets.map((dataset) => ({
|
|
22937
|
+
data: dataset.data,
|
|
22938
|
+
label: dataset.label,
|
|
22939
|
+
tree: dataset.tree,
|
|
22940
|
+
})),
|
|
22941
|
+
};
|
|
22916
22942
|
}
|
|
22917
22943
|
enableAnimationInChartData(chartData) {
|
|
22918
22944
|
return {
|
|
@@ -24534,6 +24560,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24534
24560
|
parser: luxonFormat,
|
|
24535
24561
|
displayFormats,
|
|
24536
24562
|
unit: timeUnit ?? false,
|
|
24563
|
+
tooltipFormat: luxonFormat,
|
|
24537
24564
|
};
|
|
24538
24565
|
}
|
|
24539
24566
|
/**
|
|
@@ -25614,6 +25641,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
25614
25641
|
};
|
|
25615
25642
|
Object.assign(scales.x, axis);
|
|
25616
25643
|
scales.x.ticks.maxTicksLimit = 15;
|
|
25644
|
+
delete scales?.x?.ticks?.callback;
|
|
25617
25645
|
}
|
|
25618
25646
|
else if (axisType === "linear") {
|
|
25619
25647
|
scales.x.type = "linear";
|
|
@@ -30662,7 +30690,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30662
30690
|
}
|
|
30663
30691
|
openContextMenu(ev) {
|
|
30664
30692
|
this.menuState.isOpen = true;
|
|
30665
|
-
this.menuState.anchorRect =
|
|
30693
|
+
this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
|
|
30666
30694
|
this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, () => { }, this.env);
|
|
30667
30695
|
}
|
|
30668
30696
|
get fullScreenMenuItem() {
|
|
@@ -37464,6 +37492,74 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37464
37492
|
return path2D;
|
|
37465
37493
|
}
|
|
37466
37494
|
|
|
37495
|
+
/**
|
|
37496
|
+
* Get the relative path between two files
|
|
37497
|
+
*
|
|
37498
|
+
* Eg.:
|
|
37499
|
+
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
37500
|
+
*/
|
|
37501
|
+
function getRelativePath(from, to) {
|
|
37502
|
+
const fromPathParts = from.split("/");
|
|
37503
|
+
const toPathParts = to.split("/");
|
|
37504
|
+
let relPath = "";
|
|
37505
|
+
let startIndex = 0;
|
|
37506
|
+
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
37507
|
+
if (fromPathParts[i] === toPathParts[i]) {
|
|
37508
|
+
startIndex++;
|
|
37509
|
+
}
|
|
37510
|
+
else {
|
|
37511
|
+
relPath += "../";
|
|
37512
|
+
}
|
|
37513
|
+
}
|
|
37514
|
+
relPath += toPathParts.slice(startIndex).join("/");
|
|
37515
|
+
return relPath;
|
|
37516
|
+
}
|
|
37517
|
+
/**
|
|
37518
|
+
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
37519
|
+
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
37520
|
+
*
|
|
37521
|
+
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
37522
|
+
*/
|
|
37523
|
+
function arrayToObject(array, indexOffset = 0) {
|
|
37524
|
+
const obj = {};
|
|
37525
|
+
for (let i = 0; i < array.length; i++) {
|
|
37526
|
+
if (array[i]) {
|
|
37527
|
+
obj[i + indexOffset] = array[i];
|
|
37528
|
+
}
|
|
37529
|
+
}
|
|
37530
|
+
return obj;
|
|
37531
|
+
}
|
|
37532
|
+
/**
|
|
37533
|
+
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
37534
|
+
* Replace with characters understandable by JS
|
|
37535
|
+
*/
|
|
37536
|
+
function fixXlsxUnicode(str) {
|
|
37537
|
+
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
37538
|
+
return String.fromCharCode(parseInt(code, 16));
|
|
37539
|
+
});
|
|
37540
|
+
}
|
|
37541
|
+
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
37542
|
+
function getSheetDataHeader(sheetData, dimension, index) {
|
|
37543
|
+
if (dimension === "COL") {
|
|
37544
|
+
if (!sheetData.cols[index]) {
|
|
37545
|
+
sheetData.cols[index] = {};
|
|
37546
|
+
}
|
|
37547
|
+
return sheetData.cols[index];
|
|
37548
|
+
}
|
|
37549
|
+
if (!sheetData.rows[index]) {
|
|
37550
|
+
sheetData.rows[index] = {};
|
|
37551
|
+
}
|
|
37552
|
+
return sheetData.rows[index];
|
|
37553
|
+
}
|
|
37554
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
37555
|
+
function prefixFormulaWithEqual(formula) {
|
|
37556
|
+
if (formula[0] === "=") {
|
|
37557
|
+
return formula;
|
|
37558
|
+
}
|
|
37559
|
+
const tokens = tokenize(formula);
|
|
37560
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
37561
|
+
}
|
|
37562
|
+
|
|
37467
37563
|
/**
|
|
37468
37564
|
* Map of the different types of conversions warnings and their name in error messages
|
|
37469
37565
|
*/
|
|
@@ -37986,66 +38082,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37986
38082
|
*/
|
|
37987
38083
|
const DEFAULT_SYSTEM_COLOR = "FF000000";
|
|
37988
38084
|
|
|
37989
|
-
/**
|
|
37990
|
-
* Get the relative path between two files
|
|
37991
|
-
*
|
|
37992
|
-
* Eg.:
|
|
37993
|
-
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
37994
|
-
*/
|
|
37995
|
-
function getRelativePath(from, to) {
|
|
37996
|
-
const fromPathParts = from.split("/");
|
|
37997
|
-
const toPathParts = to.split("/");
|
|
37998
|
-
let relPath = "";
|
|
37999
|
-
let startIndex = 0;
|
|
38000
|
-
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
38001
|
-
if (fromPathParts[i] === toPathParts[i]) {
|
|
38002
|
-
startIndex++;
|
|
38003
|
-
}
|
|
38004
|
-
else {
|
|
38005
|
-
relPath += "../";
|
|
38006
|
-
}
|
|
38007
|
-
}
|
|
38008
|
-
relPath += toPathParts.slice(startIndex).join("/");
|
|
38009
|
-
return relPath;
|
|
38010
|
-
}
|
|
38011
|
-
/**
|
|
38012
|
-
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
38013
|
-
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
38014
|
-
*
|
|
38015
|
-
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
38016
|
-
*/
|
|
38017
|
-
function arrayToObject(array, indexOffset = 0) {
|
|
38018
|
-
const obj = {};
|
|
38019
|
-
for (let i = 0; i < array.length; i++) {
|
|
38020
|
-
if (array[i]) {
|
|
38021
|
-
obj[i + indexOffset] = array[i];
|
|
38022
|
-
}
|
|
38023
|
-
}
|
|
38024
|
-
return obj;
|
|
38025
|
-
}
|
|
38026
|
-
/**
|
|
38027
|
-
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
38028
|
-
* Replace with characters understandable by JS
|
|
38029
|
-
*/
|
|
38030
|
-
function fixXlsxUnicode(str) {
|
|
38031
|
-
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
38032
|
-
return String.fromCharCode(parseInt(code, 16));
|
|
38033
|
-
});
|
|
38034
|
-
}
|
|
38035
|
-
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
38036
|
-
function getSheetDataHeader(sheetData, dimension, index) {
|
|
38037
|
-
if (dimension === "COL") {
|
|
38038
|
-
if (!sheetData.cols[index]) {
|
|
38039
|
-
sheetData.cols[index] = {};
|
|
38040
|
-
}
|
|
38041
|
-
return sheetData.cols[index];
|
|
38042
|
-
}
|
|
38043
|
-
if (!sheetData.rows[index]) {
|
|
38044
|
-
sheetData.rows[index] = {};
|
|
38045
|
-
}
|
|
38046
|
-
return sheetData.rows[index];
|
|
38047
|
-
}
|
|
38048
|
-
|
|
38049
38085
|
const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
|
|
38050
38086
|
/**
|
|
38051
38087
|
* Convert excel format to o_spreadsheet format
|
|
@@ -38255,9 +38291,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38255
38291
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
38256
38292
|
continue;
|
|
38257
38293
|
operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
|
|
38258
|
-
values.push(
|
|
38294
|
+
values.push(prefixFormulaWithEqual(rule.formula[0]));
|
|
38259
38295
|
if (rule.formula.length === 2) {
|
|
38260
|
-
values.push(
|
|
38296
|
+
values.push(prefixFormulaWithEqual(rule.formula[1]));
|
|
38261
38297
|
}
|
|
38262
38298
|
break;
|
|
38263
38299
|
}
|
|
@@ -38415,11 +38451,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38415
38451
|
? ICON_SETS[iconSet].neutral
|
|
38416
38452
|
: ICON_SETS[iconSet].good;
|
|
38417
38453
|
}
|
|
38418
|
-
/** Prefix the string by "=" if the string looks like a formula */
|
|
38419
|
-
function prefixFormula(formula) {
|
|
38420
|
-
const tokens = tokenize(formula);
|
|
38421
|
-
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
38422
|
-
}
|
|
38423
38454
|
// ---------------------------------------------------------------------------
|
|
38424
38455
|
// Warnings
|
|
38425
38456
|
// ---------------------------------------------------------------------------
|
|
@@ -38891,7 +38922,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38891
38922
|
dvRules.push(decimalRule);
|
|
38892
38923
|
break;
|
|
38893
38924
|
case "list":
|
|
38894
|
-
const listRule =
|
|
38925
|
+
const listRule = convertListRule(dvId++, dv);
|
|
38895
38926
|
dvRules.push(listRule);
|
|
38896
38927
|
break;
|
|
38897
38928
|
case "date":
|
|
@@ -38911,9 +38942,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38911
38942
|
return dvRules;
|
|
38912
38943
|
}
|
|
38913
38944
|
function convertDecimalRule(id, dv) {
|
|
38914
|
-
const values = [dv.formula1.toString()];
|
|
38945
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
38915
38946
|
if (dv.formula2) {
|
|
38916
|
-
values.push(dv.formula2.toString());
|
|
38947
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
38917
38948
|
}
|
|
38918
38949
|
return {
|
|
38919
38950
|
id: id.toString(),
|
|
@@ -38925,7 +38956,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38925
38956
|
},
|
|
38926
38957
|
};
|
|
38927
38958
|
}
|
|
38928
|
-
function
|
|
38959
|
+
function convertListRule(id, dv) {
|
|
38929
38960
|
const formula1 = dv.formula1.toString();
|
|
38930
38961
|
const isRangeRule = rangeReference.test(formula1);
|
|
38931
38962
|
return {
|
|
@@ -38941,9 +38972,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38941
38972
|
}
|
|
38942
38973
|
function convertDateRule(id, dv) {
|
|
38943
38974
|
let criterion;
|
|
38944
|
-
const values = [dv.formula1.toString()];
|
|
38975
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
38945
38976
|
if (dv.formula2) {
|
|
38946
|
-
values.push(dv.formula2.toString());
|
|
38977
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
38947
38978
|
criterion = {
|
|
38948
38979
|
type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
|
|
38949
38980
|
values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
|
|
@@ -38970,7 +39001,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38970
39001
|
isBlocking: dv.errorStyle !== "warning",
|
|
38971
39002
|
criterion: {
|
|
38972
39003
|
type: "customFormula",
|
|
38973
|
-
values: [
|
|
39004
|
+
values: [prefixFormulaWithEqual(dv.formula1.toString())],
|
|
38974
39005
|
},
|
|
38975
39006
|
};
|
|
38976
39007
|
}
|
|
@@ -52861,12 +52892,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52861
52892
|
onCloseSidePanel: { type: Function, optional: true },
|
|
52862
52893
|
};
|
|
52863
52894
|
state = owl.useState({ rule: this.defaultDataValidationRule, errors: [] });
|
|
52895
|
+
editingSheetId;
|
|
52864
52896
|
setup() {
|
|
52897
|
+
this.editingSheetId = this.env.model.getters.getActiveSheetId();
|
|
52865
52898
|
if (this.props.rule) {
|
|
52866
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
52867
52899
|
this.state.rule = {
|
|
52868
52900
|
...this.props.rule,
|
|
52869
|
-
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range,
|
|
52901
|
+
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
|
|
52870
52902
|
};
|
|
52871
52903
|
this.state.rule.criterion.type = this.props.rule.criterion.type;
|
|
52872
52904
|
}
|
|
@@ -52900,7 +52932,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52900
52932
|
const locale = this.env.model.getters.getLocale();
|
|
52901
52933
|
const criterion = rule.criterion;
|
|
52902
52934
|
const criterionEvaluator = criterionEvaluatorRegistry.get(criterion.type);
|
|
52903
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
52904
52935
|
const values = criterion.values
|
|
52905
52936
|
.slice(0, criterionEvaluator.numberOfValues(criterion))
|
|
52906
52937
|
.map((value) => value?.trim())
|
|
@@ -52908,8 +52939,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52908
52939
|
.map((value) => canonicalizeContent(value, locale));
|
|
52909
52940
|
rule.criterion = { ...criterion, values };
|
|
52910
52941
|
return {
|
|
52911
|
-
sheetId,
|
|
52912
|
-
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(
|
|
52942
|
+
sheetId: this.editingSheetId,
|
|
52943
|
+
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(this.editingSheetId, xc)),
|
|
52913
52944
|
rule,
|
|
52914
52945
|
};
|
|
52915
52946
|
}
|
|
@@ -53436,6 +53467,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53436
53467
|
.o-button {
|
|
53437
53468
|
height: 19px;
|
|
53438
53469
|
width: 19px;
|
|
53470
|
+
box-sizing: content-box;
|
|
53439
53471
|
.o-icon {
|
|
53440
53472
|
height: 14px;
|
|
53441
53473
|
width: 14px;
|
|
@@ -54245,7 +54277,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54245
54277
|
return undefined;
|
|
54246
54278
|
}
|
|
54247
54279
|
get isCalculatedMeasureInvalid() {
|
|
54248
|
-
return
|
|
54280
|
+
return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
|
|
54249
54281
|
}
|
|
54250
54282
|
}
|
|
54251
54283
|
|
|
@@ -61257,11 +61289,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61257
61289
|
break;
|
|
61258
61290
|
}
|
|
61259
61291
|
case "ADD_COLUMNS_ROWS": {
|
|
61260
|
-
const sizes =
|
|
61292
|
+
const sizes = this.sizes[cmd.sheetId][cmd.dimension];
|
|
61261
61293
|
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
61262
61294
|
const baseSize = sizes[cmd.base];
|
|
61263
|
-
sizes
|
|
61264
|
-
this.history.update("sizes", cmd.sheetId, cmd.dimension,
|
|
61295
|
+
const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
|
|
61296
|
+
this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
|
|
61265
61297
|
break;
|
|
61266
61298
|
}
|
|
61267
61299
|
case "RESIZE_COLUMNS_ROWS":
|
|
@@ -61412,9 +61444,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61412
61444
|
break;
|
|
61413
61445
|
}
|
|
61414
61446
|
case "ADD_COLUMNS_ROWS": {
|
|
61415
|
-
const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
|
|
61416
61447
|
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
61417
|
-
hiddenHeaders.
|
|
61448
|
+
const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
|
|
61418
61449
|
this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
|
|
61419
61450
|
break;
|
|
61420
61451
|
}
|
|
@@ -65449,12 +65480,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65449
65480
|
this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
|
|
65450
65481
|
}
|
|
65451
65482
|
rtreeItemComparer(left, right) {
|
|
65452
|
-
return (left.
|
|
65453
|
-
left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
65483
|
+
return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
65454
65484
|
left.boundingBox?.zone.left === right.boundingBox.zone.left &&
|
|
65455
65485
|
left.boundingBox?.zone.top === right.boundingBox.zone.top &&
|
|
65456
65486
|
left.boundingBox?.zone.right === right.boundingBox.zone.right &&
|
|
65457
|
-
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom
|
|
65487
|
+
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
|
|
65488
|
+
deepEquals(left.data, right.data));
|
|
65458
65489
|
}
|
|
65459
65490
|
}
|
|
65460
65491
|
/**
|
|
@@ -65527,7 +65558,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65527
65558
|
* in the correct order they should be evaluated.
|
|
65528
65559
|
* This is called a topological ordering (excluding cycles)
|
|
65529
65560
|
*/
|
|
65530
|
-
getCellsDependingOn(ranges) {
|
|
65561
|
+
getCellsDependingOn(ranges, ignore) {
|
|
65531
65562
|
const visited = this.createEmptyPositionSet();
|
|
65532
65563
|
const queue = Array.from(ranges).reverse();
|
|
65533
65564
|
while (queue.length > 0) {
|
|
@@ -65542,7 +65573,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65542
65573
|
const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
|
|
65543
65574
|
const nextInQueue = {};
|
|
65544
65575
|
for (const position of impactedPositions) {
|
|
65545
|
-
if (!visited.has(position)) {
|
|
65576
|
+
if (!visited.has(position) && !ignore.has(position)) {
|
|
65546
65577
|
if (!nextInQueue[position.sheetId]) {
|
|
65547
65578
|
nextInQueue[position.sheetId] = [];
|
|
65548
65579
|
}
|
|
@@ -66099,7 +66130,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66099
66130
|
}
|
|
66100
66131
|
invalidatePositionsDependingOnSpread(sheetId, resultZone) {
|
|
66101
66132
|
// the result matrix is split in 2 zones to exclude the array formula position
|
|
66102
|
-
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
|
|
66133
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })), this.nextPositionsToUpdate);
|
|
66103
66134
|
invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
|
|
66104
66135
|
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
66105
66136
|
}
|
|
@@ -66217,7 +66248,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66217
66248
|
for (const sheetId in zonesBySheetIds) {
|
|
66218
66249
|
ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
|
|
66219
66250
|
}
|
|
66220
|
-
return this.formulaDependencies().getCellsDependingOn(ranges);
|
|
66251
|
+
return this.formulaDependencies().getCellsDependingOn(ranges, this.nextPositionsToUpdate);
|
|
66221
66252
|
}
|
|
66222
66253
|
}
|
|
66223
66254
|
function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
@@ -67690,7 +67721,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67690
67721
|
const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
|
|
67691
67722
|
const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
|
|
67692
67723
|
if (!parentSpreadingCell) {
|
|
67693
|
-
|
|
67724
|
+
const evaluatedCell = this.getters.getEvaluatedCell(topLeft);
|
|
67725
|
+
return (evaluatedCell.value === CellErrorType.SpilledBlocked && !evaluatedCell.errorOriginPosition);
|
|
67694
67726
|
}
|
|
67695
67727
|
else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
|
|
67696
67728
|
return true;
|
|
@@ -78591,6 +78623,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78591
78623
|
static components = { Menu };
|
|
78592
78624
|
rootItems = topbarMenuRegistry.getMenuItems();
|
|
78593
78625
|
menuRef = owl.useRef("menu");
|
|
78626
|
+
containerRef = owl.useRef("container");
|
|
78594
78627
|
state = owl.useState({
|
|
78595
78628
|
menuItems: this.rootItems,
|
|
78596
78629
|
title: _t("Menu Bar"),
|
|
@@ -78598,6 +78631,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78598
78631
|
});
|
|
78599
78632
|
setup() {
|
|
78600
78633
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
78634
|
+
owl.onMounted(this.updateShadows);
|
|
78601
78635
|
}
|
|
78602
78636
|
onExternalClick(ev) {
|
|
78603
78637
|
if (!this.menuRef.el?.contains(ev.target)) {
|
|
@@ -78610,6 +78644,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78610
78644
|
this.state.parentState = { ...this.state };
|
|
78611
78645
|
this.state.menuItems = children;
|
|
78612
78646
|
this.state.title = menu.name(this.env);
|
|
78647
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
78613
78648
|
}
|
|
78614
78649
|
else {
|
|
78615
78650
|
this.state.menuItems = this.rootItems;
|
|
@@ -78631,6 +78666,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78631
78666
|
height: `${this.props.height}px`,
|
|
78632
78667
|
});
|
|
78633
78668
|
}
|
|
78669
|
+
updateShadows() {
|
|
78670
|
+
if (!this.containerRef.el) {
|
|
78671
|
+
return;
|
|
78672
|
+
}
|
|
78673
|
+
this.containerRef.el.classList.remove("scroll-top", "scroll-bottom");
|
|
78674
|
+
const maxScroll = this.containerRef.el.scrollHeight - this.containerRef.el.clientHeight || 0;
|
|
78675
|
+
if (this.containerRef.el.scrollTop < maxScroll - 1) {
|
|
78676
|
+
this.containerRef.el.classList.add("scroll-bottom");
|
|
78677
|
+
}
|
|
78678
|
+
if (this.containerRef.el.scrollTop > 0) {
|
|
78679
|
+
this.containerRef.el.classList.add("scroll-top");
|
|
78680
|
+
}
|
|
78681
|
+
}
|
|
78634
78682
|
onClickBack() {
|
|
78635
78683
|
if (!this.state.parentState) {
|
|
78636
78684
|
this.props.onClose();
|
|
@@ -78639,6 +78687,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78639
78687
|
this.state.menuItems = this.state.parentState.menuItems;
|
|
78640
78688
|
this.state.title = this.state.parentState.title;
|
|
78641
78689
|
this.state.parentState = this.state.parentState.parentState;
|
|
78690
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
78642
78691
|
}
|
|
78643
78692
|
get backTitle() {
|
|
78644
78693
|
return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
|
|
@@ -78694,6 +78743,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78694
78743
|
? this.composerFocusStore.focusMode
|
|
78695
78744
|
: "inactive";
|
|
78696
78745
|
}
|
|
78746
|
+
get showFxIcon() {
|
|
78747
|
+
return (this.focus === "inactive" &&
|
|
78748
|
+
!this.composerStore.currentContent &&
|
|
78749
|
+
!this.composerStore.placeholder);
|
|
78750
|
+
}
|
|
78697
78751
|
get rect() {
|
|
78698
78752
|
return this.composerRef.el
|
|
78699
78753
|
? getBoundingRectAsPOJO(this.composerRef.el)
|
|
@@ -78718,6 +78772,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78718
78772
|
"max-height": `130px`,
|
|
78719
78773
|
}),
|
|
78720
78774
|
showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
|
|
78775
|
+
placeholder: this.composerStore.placeholder,
|
|
78721
78776
|
};
|
|
78722
78777
|
}
|
|
78723
78778
|
get symbols() {
|
|
@@ -78736,12 +78791,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78736
78791
|
}
|
|
78737
78792
|
|
|
78738
78793
|
const COMPOSER_MAX_HEIGHT = 100;
|
|
78739
|
-
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
78740
|
-
const FX_SVG = /*xml*/ `
|
|
78741
|
-
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
|
|
78742
|
-
<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'/>
|
|
78743
|
-
</svg>
|
|
78744
|
-
`;
|
|
78745
78794
|
css /* scss */ `
|
|
78746
78795
|
.o-topbar-composer-container {
|
|
78747
78796
|
height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
@@ -78753,14 +78802,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78753
78802
|
margin-bottom: -1px;
|
|
78754
78803
|
border: 1px solid;
|
|
78755
78804
|
font-family: ${DEFAULT_FONT};
|
|
78756
|
-
|
|
78757
|
-
/* In readonly we always show the fx icon if the composer is empty, not matter the focus */
|
|
78758
|
-
.o-composer:empty:not(:focus):not(.active)::before,
|
|
78759
|
-
&.o-topbar-composer-readonly .o-composer:empty::before {
|
|
78760
|
-
content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
|
|
78761
|
-
position: relative;
|
|
78762
|
-
top: 20%;
|
|
78763
|
-
}
|
|
78764
78805
|
}
|
|
78765
78806
|
|
|
78766
78807
|
.user-select-text {
|
|
@@ -78793,6 +78834,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78793
78834
|
? this.composerFocusStore.focusMode
|
|
78794
78835
|
: "inactive";
|
|
78795
78836
|
}
|
|
78837
|
+
get showFxIcon() {
|
|
78838
|
+
return (this.focus === "inactive" &&
|
|
78839
|
+
!this.composerStore.currentContent &&
|
|
78840
|
+
!this.composerStore.placeholder);
|
|
78841
|
+
}
|
|
78796
78842
|
get composerStyle() {
|
|
78797
78843
|
const style = {
|
|
78798
78844
|
padding: "5px 0px 5px 8px",
|
|
@@ -84858,9 +84904,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84858
84904
|
exports.tokenize = tokenize;
|
|
84859
84905
|
|
|
84860
84906
|
|
|
84861
|
-
__info__.version = "18.4.
|
|
84862
|
-
__info__.date = "2025-
|
|
84863
|
-
__info__.hash = "
|
|
84907
|
+
__info__.version = "18.4.14";
|
|
84908
|
+
__info__.date = "2025-10-16T06:39:40.249Z";
|
|
84909
|
+
__info__.hash = "bc55c40";
|
|
84864
84910
|
|
|
84865
84911
|
|
|
84866
84912
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|