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