@odoo/o-spreadsheet 19.0.5 → 19.0.6
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 +211 -125
- package/dist/o-spreadsheet.d.ts +19 -5
- package/dist/o-spreadsheet.esm.js +211 -125
- package/dist/o-spreadsheet.iife.js +211 -125
- package/dist/o-spreadsheet.iife.min.js +101 -100
- package/dist/o_spreadsheet.xml +13 -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 19.0.
|
|
6
|
-
* @date 2025-10-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.0.6
|
|
6
|
+
* @date 2025-10-16T06:39:36.282Z
|
|
7
|
+
* @hash 0d4315a
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -4515,7 +4515,17 @@ function toNumberMatrix(data, argName) {
|
|
|
4515
4515
|
return toMatrix(data).map((row) => {
|
|
4516
4516
|
return row.map((cell) => {
|
|
4517
4517
|
if (typeof cell.value !== "number") {
|
|
4518
|
-
|
|
4518
|
+
let message = "";
|
|
4519
|
+
if (typeof cell === "object") {
|
|
4520
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got an empty value.", argName);
|
|
4521
|
+
}
|
|
4522
|
+
else if (typeof cell === "string") {
|
|
4523
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a string.", argName);
|
|
4524
|
+
}
|
|
4525
|
+
else if (typeof cell === "boolean") {
|
|
4526
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a boolean.", argName);
|
|
4527
|
+
}
|
|
4528
|
+
throw new EvaluationError(message);
|
|
4519
4529
|
}
|
|
4520
4530
|
return cell.value;
|
|
4521
4531
|
});
|
|
@@ -9530,7 +9540,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
9530
9540
|
pasteCell(origin, target, clipboardOption) {
|
|
9531
9541
|
const { sheetId, col, row } = target;
|
|
9532
9542
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
9533
|
-
const originFormat = origin?.format
|
|
9543
|
+
const originFormat = origin?.format || origin.evaluatedCell.format;
|
|
9534
9544
|
if (clipboardOption?.pasteOption === "asValue") {
|
|
9535
9545
|
this.dispatch("UPDATE_CELL", {
|
|
9536
9546
|
...target,
|
|
@@ -13903,7 +13913,7 @@ const GROWTH = {
|
|
|
13903
13913
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
13904
13914
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
13905
13915
|
}
|
|
13906
|
-
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "
|
|
13916
|
+
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "known_data_y")), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b)));
|
|
13907
13917
|
},
|
|
13908
13918
|
};
|
|
13909
13919
|
// -----------------------------------------------------------------------------
|
|
@@ -13976,7 +13986,7 @@ const LINEST = {
|
|
|
13976
13986
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13977
13987
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13978
13988
|
}
|
|
13979
|
-
return fullLinearRegression(toNumberMatrix(dataX, "
|
|
13989
|
+
return fullLinearRegression(toNumberMatrix(dataX, "data_x"), toNumberMatrix(dataY, "data_y"), toBoolean(calculateB), toBoolean(verbose));
|
|
13980
13990
|
},
|
|
13981
13991
|
isExported: true,
|
|
13982
13992
|
};
|
|
@@ -13995,7 +14005,7 @@ const LOGEST = {
|
|
|
13995
14005
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13996
14006
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13997
14007
|
}
|
|
13998
|
-
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "
|
|
14008
|
+
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "data_x"), logM(toNumberMatrix(dataY, "data_y")), toBoolean(calculateB), toBoolean(verbose));
|
|
13999
14009
|
for (let i = 0; i < coeffs.length; i++) {
|
|
14000
14010
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
14001
14011
|
}
|
|
@@ -14616,7 +14626,7 @@ const TREND = {
|
|
|
14616
14626
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
14617
14627
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
14618
14628
|
}
|
|
14619
|
-
return predictLinearValues(toNumberMatrix(knownDataY, "
|
|
14629
|
+
return predictLinearValues(toNumberMatrix(knownDataY, "known_data_y"), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b));
|
|
14620
14630
|
},
|
|
14621
14631
|
};
|
|
14622
14632
|
// -----------------------------------------------------------------------------
|
|
@@ -23137,6 +23147,10 @@ const chartShowValuesPlugin = {
|
|
|
23137
23147
|
}
|
|
23138
23148
|
const ctx = chart.ctx;
|
|
23139
23149
|
ctx.save();
|
|
23150
|
+
const { left, top, height, width } = chart.chartArea;
|
|
23151
|
+
ctx.beginPath();
|
|
23152
|
+
ctx.rect(left, top, width, height);
|
|
23153
|
+
ctx.clip();
|
|
23140
23154
|
ctx.textAlign = "center";
|
|
23141
23155
|
ctx.textBaseline = "middle";
|
|
23142
23156
|
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
@@ -24180,7 +24194,7 @@ class ChartJsComponent extends owl.Component {
|
|
|
24180
24194
|
this.chart.update();
|
|
24181
24195
|
}
|
|
24182
24196
|
hasChartDataChanged() {
|
|
24183
|
-
return !deepEquals(this.currentRuntime
|
|
24197
|
+
return !deepEquals(this.getChartDataInRuntime(this.currentRuntime), this.getChartDataInRuntime(this.chartRuntime));
|
|
24184
24198
|
}
|
|
24185
24199
|
enableAnimationInChartData(chartData) {
|
|
24186
24200
|
return {
|
|
@@ -24188,6 +24202,17 @@ class ChartJsComponent extends owl.Component {
|
|
|
24188
24202
|
options: { ...chartData.options, animation: { animateRotate: true } },
|
|
24189
24203
|
};
|
|
24190
24204
|
}
|
|
24205
|
+
getChartDataInRuntime(runtime) {
|
|
24206
|
+
const data = runtime.chartJsConfig.data;
|
|
24207
|
+
return {
|
|
24208
|
+
labels: data.labels,
|
|
24209
|
+
dataset: data.datasets.map((dataset) => ({
|
|
24210
|
+
data: dataset.data,
|
|
24211
|
+
label: dataset.label,
|
|
24212
|
+
tree: dataset.tree,
|
|
24213
|
+
})),
|
|
24214
|
+
};
|
|
24215
|
+
}
|
|
24191
24216
|
get animationChartId() {
|
|
24192
24217
|
return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
|
|
24193
24218
|
}
|
|
@@ -25611,6 +25636,7 @@ function getChartTimeOptions(labels, labelFormat, locale) {
|
|
|
25611
25636
|
parser: luxonFormat,
|
|
25612
25637
|
displayFormats,
|
|
25613
25638
|
unit: timeUnit ?? false,
|
|
25639
|
+
tooltipFormat: luxonFormat,
|
|
25614
25640
|
};
|
|
25615
25641
|
}
|
|
25616
25642
|
/**
|
|
@@ -26679,6 +26705,7 @@ function getLineChartScales(definition, args) {
|
|
|
26679
26705
|
};
|
|
26680
26706
|
Object.assign(scales.x, axis);
|
|
26681
26707
|
scales.x.ticks.maxTicksLimit = 15;
|
|
26708
|
+
delete scales?.x?.ticks?.callback;
|
|
26682
26709
|
}
|
|
26683
26710
|
else if (axisType === "linear") {
|
|
26684
26711
|
scales.x.type = "linear";
|
|
@@ -32364,7 +32391,7 @@ class ChartDashboardMenu extends owl.Component {
|
|
|
32364
32391
|
}
|
|
32365
32392
|
openContextMenu(ev) {
|
|
32366
32393
|
this.menuState.isOpen = true;
|
|
32367
|
-
this.menuState.anchorRect =
|
|
32394
|
+
this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
|
|
32368
32395
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32369
32396
|
this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
|
|
32370
32397
|
}
|
|
@@ -32396,6 +32423,7 @@ class CarouselFigure extends owl.Component {
|
|
|
32396
32423
|
onFigureDeleted: Function,
|
|
32397
32424
|
editFigureStyle: { type: Function, optional: true },
|
|
32398
32425
|
isFullScreen: { type: Boolean, optional: true },
|
|
32426
|
+
openContextMenu: { type: Function, optional: true },
|
|
32399
32427
|
};
|
|
32400
32428
|
static components = { ChartDashboardMenu, MenuPopover };
|
|
32401
32429
|
carouselTabsRef = owl.useRef("carouselTabs");
|
|
@@ -32529,6 +32557,12 @@ class CarouselFigure extends owl.Component {
|
|
|
32529
32557
|
get visibleCarouselItems() {
|
|
32530
32558
|
return this.carousel.items.filter((item) => item.type === "carouselDataView" && this.props.isFullScreen ? false : true);
|
|
32531
32559
|
}
|
|
32560
|
+
openContextMenu(event) {
|
|
32561
|
+
const target = event.currentTarget;
|
|
32562
|
+
if (target) {
|
|
32563
|
+
this.props.openContextMenu?.(getBoundingRectAsPOJO(target));
|
|
32564
|
+
}
|
|
32565
|
+
}
|
|
32532
32566
|
}
|
|
32533
32567
|
|
|
32534
32568
|
class ChartFigure extends owl.Component {
|
|
@@ -32538,6 +32572,7 @@ class ChartFigure extends owl.Component {
|
|
|
32538
32572
|
onFigureDeleted: Function,
|
|
32539
32573
|
editFigureStyle: { type: Function, optional: true },
|
|
32540
32574
|
isFullScreen: { type: Boolean, optional: true },
|
|
32575
|
+
openContextMenu: { type: Function, optional: true },
|
|
32541
32576
|
};
|
|
32542
32577
|
static components = { ChartDashboardMenu };
|
|
32543
32578
|
onDoubleClick() {
|
|
@@ -32570,6 +32605,7 @@ class ImageFigure extends owl.Component {
|
|
|
32570
32605
|
figureUI: Object,
|
|
32571
32606
|
onFigureDeleted: Function,
|
|
32572
32607
|
editFigureStyle: { type: Function, optional: true },
|
|
32608
|
+
openContextMenu: { type: Function, optional: true },
|
|
32573
32609
|
};
|
|
32574
32610
|
static components = {};
|
|
32575
32611
|
// ---------------------------------------------------------------------------
|
|
@@ -34621,8 +34657,11 @@ class Composer extends owl.Component {
|
|
|
34621
34657
|
}
|
|
34622
34658
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
34623
34659
|
this.props.composerStore.stopComposerRangeSelection();
|
|
34624
|
-
this.props.
|
|
34625
|
-
this.props.
|
|
34660
|
+
const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
|
|
34661
|
+
this.props.onComposerContentFocused(newSelection);
|
|
34662
|
+
if (!isCurrentlyInactive) {
|
|
34663
|
+
this.props.composerStore.changeComposerCursorSelection(newSelection.start, newSelection.end);
|
|
34664
|
+
}
|
|
34626
34665
|
this.processTokenAtCursor();
|
|
34627
34666
|
}
|
|
34628
34667
|
onDblClick() {
|
|
@@ -35117,13 +35156,6 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
35117
35156
|
}
|
|
35118
35157
|
}
|
|
35119
35158
|
startEdition(text, selection) {
|
|
35120
|
-
if (selection) {
|
|
35121
|
-
const content = text || this.getComposerContent(this.getters.getActivePosition());
|
|
35122
|
-
const validSelection = this.isSelectionValid(content.length, selection.start, selection.end);
|
|
35123
|
-
if (!validSelection) {
|
|
35124
|
-
return;
|
|
35125
|
-
}
|
|
35126
|
-
}
|
|
35127
35159
|
const { col, row } = this.getters.getActivePosition();
|
|
35128
35160
|
this.model.dispatch("SELECT_FIGURE", { figureId: null });
|
|
35129
35161
|
this.model.dispatch("SCROLL_TO_CELL", { col, row });
|
|
@@ -35180,7 +35212,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
35180
35212
|
// ---------------------------------------------------------------------------
|
|
35181
35213
|
get currentContent() {
|
|
35182
35214
|
if (this.editionMode === "inactive") {
|
|
35183
|
-
return this.getComposerContent(this.getters.getActivePosition());
|
|
35215
|
+
return this.getComposerContent(this.getters.getActivePosition()).text;
|
|
35184
35216
|
}
|
|
35185
35217
|
return this._currentContent;
|
|
35186
35218
|
}
|
|
@@ -35379,8 +35411,9 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
35379
35411
|
this.sheetId = sheetId;
|
|
35380
35412
|
this.row = row;
|
|
35381
35413
|
this.editionMode = "editing";
|
|
35382
|
-
|
|
35383
|
-
this.
|
|
35414
|
+
const { text, adjustedSelection } = this.getComposerContent({ sheetId, col, row }, selection);
|
|
35415
|
+
this.initialContent = text;
|
|
35416
|
+
this.setContent(str || this.initialContent, adjustedSelection ?? selection);
|
|
35384
35417
|
this.colorIndexByRange = {};
|
|
35385
35418
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
35386
35419
|
this.captureSelection(zone, col, row);
|
|
@@ -35857,7 +35890,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35857
35890
|
constructor(get, args) {
|
|
35858
35891
|
super(get);
|
|
35859
35892
|
this.args = args;
|
|
35860
|
-
this._currentContent = this.getComposerContent();
|
|
35893
|
+
this._currentContent = this.getComposerContent().text;
|
|
35861
35894
|
}
|
|
35862
35895
|
getAutoCompleteProviders() {
|
|
35863
35896
|
const providersDefinitions = super.getAutoCompleteProviders();
|
|
@@ -35894,7 +35927,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35894
35927
|
})
|
|
35895
35928
|
.join("");
|
|
35896
35929
|
}
|
|
35897
|
-
return localizeContent(content, this.getters.getLocale());
|
|
35930
|
+
return { text: localizeContent(content, this.getters.getLocale()) };
|
|
35898
35931
|
}
|
|
35899
35932
|
stopEdition() {
|
|
35900
35933
|
this._stopEdition();
|
|
@@ -39572,6 +39605,74 @@ function getPath2D(svgPath) {
|
|
|
39572
39605
|
return path2D;
|
|
39573
39606
|
}
|
|
39574
39607
|
|
|
39608
|
+
/**
|
|
39609
|
+
* Get the relative path between two files
|
|
39610
|
+
*
|
|
39611
|
+
* Eg.:
|
|
39612
|
+
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
39613
|
+
*/
|
|
39614
|
+
function getRelativePath(from, to) {
|
|
39615
|
+
const fromPathParts = from.split("/");
|
|
39616
|
+
const toPathParts = to.split("/");
|
|
39617
|
+
let relPath = "";
|
|
39618
|
+
let startIndex = 0;
|
|
39619
|
+
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
39620
|
+
if (fromPathParts[i] === toPathParts[i]) {
|
|
39621
|
+
startIndex++;
|
|
39622
|
+
}
|
|
39623
|
+
else {
|
|
39624
|
+
relPath += "../";
|
|
39625
|
+
}
|
|
39626
|
+
}
|
|
39627
|
+
relPath += toPathParts.slice(startIndex).join("/");
|
|
39628
|
+
return relPath;
|
|
39629
|
+
}
|
|
39630
|
+
/**
|
|
39631
|
+
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
39632
|
+
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
39633
|
+
*
|
|
39634
|
+
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
39635
|
+
*/
|
|
39636
|
+
function arrayToObject(array, indexOffset = 0) {
|
|
39637
|
+
const obj = {};
|
|
39638
|
+
for (let i = 0; i < array.length; i++) {
|
|
39639
|
+
if (array[i]) {
|
|
39640
|
+
obj[i + indexOffset] = array[i];
|
|
39641
|
+
}
|
|
39642
|
+
}
|
|
39643
|
+
return obj;
|
|
39644
|
+
}
|
|
39645
|
+
/**
|
|
39646
|
+
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
39647
|
+
* Replace with characters understandable by JS
|
|
39648
|
+
*/
|
|
39649
|
+
function fixXlsxUnicode(str) {
|
|
39650
|
+
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
39651
|
+
return String.fromCharCode(parseInt(code, 16));
|
|
39652
|
+
});
|
|
39653
|
+
}
|
|
39654
|
+
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
39655
|
+
function getSheetDataHeader(sheetData, dimension, index) {
|
|
39656
|
+
if (dimension === "COL") {
|
|
39657
|
+
if (!sheetData.cols[index]) {
|
|
39658
|
+
sheetData.cols[index] = {};
|
|
39659
|
+
}
|
|
39660
|
+
return sheetData.cols[index];
|
|
39661
|
+
}
|
|
39662
|
+
if (!sheetData.rows[index]) {
|
|
39663
|
+
sheetData.rows[index] = {};
|
|
39664
|
+
}
|
|
39665
|
+
return sheetData.rows[index];
|
|
39666
|
+
}
|
|
39667
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
39668
|
+
function prefixFormulaWithEqual(formula) {
|
|
39669
|
+
if (formula[0] === "=") {
|
|
39670
|
+
return formula;
|
|
39671
|
+
}
|
|
39672
|
+
const tokens = tokenize(formula);
|
|
39673
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
39674
|
+
}
|
|
39675
|
+
|
|
39575
39676
|
/**
|
|
39576
39677
|
* Map of the different types of conversions warnings and their name in error messages
|
|
39577
39678
|
*/
|
|
@@ -40094,66 +40195,6 @@ function hexaToInt(hex) {
|
|
|
40094
40195
|
*/
|
|
40095
40196
|
const DEFAULT_SYSTEM_COLOR = "FF000000";
|
|
40096
40197
|
|
|
40097
|
-
/**
|
|
40098
|
-
* Get the relative path between two files
|
|
40099
|
-
*
|
|
40100
|
-
* Eg.:
|
|
40101
|
-
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
40102
|
-
*/
|
|
40103
|
-
function getRelativePath(from, to) {
|
|
40104
|
-
const fromPathParts = from.split("/");
|
|
40105
|
-
const toPathParts = to.split("/");
|
|
40106
|
-
let relPath = "";
|
|
40107
|
-
let startIndex = 0;
|
|
40108
|
-
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
40109
|
-
if (fromPathParts[i] === toPathParts[i]) {
|
|
40110
|
-
startIndex++;
|
|
40111
|
-
}
|
|
40112
|
-
else {
|
|
40113
|
-
relPath += "../";
|
|
40114
|
-
}
|
|
40115
|
-
}
|
|
40116
|
-
relPath += toPathParts.slice(startIndex).join("/");
|
|
40117
|
-
return relPath;
|
|
40118
|
-
}
|
|
40119
|
-
/**
|
|
40120
|
-
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
40121
|
-
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
40122
|
-
*
|
|
40123
|
-
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
40124
|
-
*/
|
|
40125
|
-
function arrayToObject(array, indexOffset = 0) {
|
|
40126
|
-
const obj = {};
|
|
40127
|
-
for (let i = 0; i < array.length; i++) {
|
|
40128
|
-
if (array[i]) {
|
|
40129
|
-
obj[i + indexOffset] = array[i];
|
|
40130
|
-
}
|
|
40131
|
-
}
|
|
40132
|
-
return obj;
|
|
40133
|
-
}
|
|
40134
|
-
/**
|
|
40135
|
-
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
40136
|
-
* Replace with characters understandable by JS
|
|
40137
|
-
*/
|
|
40138
|
-
function fixXlsxUnicode(str) {
|
|
40139
|
-
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
40140
|
-
return String.fromCharCode(parseInt(code, 16));
|
|
40141
|
-
});
|
|
40142
|
-
}
|
|
40143
|
-
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
40144
|
-
function getSheetDataHeader(sheetData, dimension, index) {
|
|
40145
|
-
if (dimension === "COL") {
|
|
40146
|
-
if (!sheetData.cols[index]) {
|
|
40147
|
-
sheetData.cols[index] = {};
|
|
40148
|
-
}
|
|
40149
|
-
return sheetData.cols[index];
|
|
40150
|
-
}
|
|
40151
|
-
if (!sheetData.rows[index]) {
|
|
40152
|
-
sheetData.rows[index] = {};
|
|
40153
|
-
}
|
|
40154
|
-
return sheetData.rows[index];
|
|
40155
|
-
}
|
|
40156
|
-
|
|
40157
40198
|
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;
|
|
40158
40199
|
/**
|
|
40159
40200
|
* Convert excel format to o_spreadsheet format
|
|
@@ -40368,9 +40409,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
40368
40409
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
40369
40410
|
continue;
|
|
40370
40411
|
operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
|
|
40371
|
-
values.push(
|
|
40412
|
+
values.push(prefixFormulaWithEqual(rule.formula[0]));
|
|
40372
40413
|
if (rule.formula.length === 2) {
|
|
40373
|
-
values.push(
|
|
40414
|
+
values.push(prefixFormulaWithEqual(rule.formula[1]));
|
|
40374
40415
|
}
|
|
40375
40416
|
break;
|
|
40376
40417
|
}
|
|
@@ -40528,11 +40569,6 @@ function convertIcons(xlsxIconSet, index) {
|
|
|
40528
40569
|
? ICON_SETS[iconSet].neutral
|
|
40529
40570
|
: ICON_SETS[iconSet].good;
|
|
40530
40571
|
}
|
|
40531
|
-
/** Prefix the string by "=" if the string looks like a formula */
|
|
40532
|
-
function prefixFormula(formula) {
|
|
40533
|
-
const tokens = tokenize(formula);
|
|
40534
|
-
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
40535
|
-
}
|
|
40536
40572
|
// ---------------------------------------------------------------------------
|
|
40537
40573
|
// Warnings
|
|
40538
40574
|
// ---------------------------------------------------------------------------
|
|
@@ -41008,7 +41044,7 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
41008
41044
|
dvRules.push(decimalRule);
|
|
41009
41045
|
break;
|
|
41010
41046
|
case "list":
|
|
41011
|
-
const listRule =
|
|
41047
|
+
const listRule = convertListRule(dvId++, dv);
|
|
41012
41048
|
dvRules.push(listRule);
|
|
41013
41049
|
break;
|
|
41014
41050
|
case "date":
|
|
@@ -41028,9 +41064,9 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
41028
41064
|
return dvRules;
|
|
41029
41065
|
}
|
|
41030
41066
|
function convertDecimalRule(id, dv) {
|
|
41031
|
-
const values = [dv.formula1.toString()];
|
|
41067
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
41032
41068
|
if (dv.formula2) {
|
|
41033
|
-
values.push(dv.formula2.toString());
|
|
41069
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
41034
41070
|
}
|
|
41035
41071
|
return {
|
|
41036
41072
|
id: id.toString(),
|
|
@@ -41042,7 +41078,7 @@ function convertDecimalRule(id, dv) {
|
|
|
41042
41078
|
},
|
|
41043
41079
|
};
|
|
41044
41080
|
}
|
|
41045
|
-
function
|
|
41081
|
+
function convertListRule(id, dv) {
|
|
41046
41082
|
const formula1 = dv.formula1.toString();
|
|
41047
41083
|
const isRangeRule = rangeReference.test(formula1);
|
|
41048
41084
|
return {
|
|
@@ -41058,9 +41094,9 @@ function convertListrule(id, dv) {
|
|
|
41058
41094
|
}
|
|
41059
41095
|
function convertDateRule(id, dv) {
|
|
41060
41096
|
let criterion;
|
|
41061
|
-
const values = [dv.formula1.toString()];
|
|
41097
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
41062
41098
|
if (dv.formula2) {
|
|
41063
|
-
values.push(dv.formula2.toString());
|
|
41099
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
41064
41100
|
criterion = {
|
|
41065
41101
|
type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
|
|
41066
41102
|
values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
|
|
@@ -41087,7 +41123,7 @@ function convertCustomRule(id, dv) {
|
|
|
41087
41123
|
isBlocking: dv.errorStyle !== "warning",
|
|
41088
41124
|
criterion: {
|
|
41089
41125
|
type: "customFormula",
|
|
41090
|
-
values: [
|
|
41126
|
+
values: [prefixFormulaWithEqual(dv.formula1.toString())],
|
|
41091
41127
|
},
|
|
41092
41128
|
};
|
|
41093
41129
|
}
|
|
@@ -49751,39 +49787,63 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
49751
49787
|
this.model.dispatch("AUTOFILL_TABLE_COLUMN", { ...this.currentEditedCell });
|
|
49752
49788
|
this.setContent("");
|
|
49753
49789
|
}
|
|
49754
|
-
getComposerContent(position) {
|
|
49790
|
+
getComposerContent(position, selection) {
|
|
49755
49791
|
const locale = this.getters.getLocale();
|
|
49756
49792
|
const cell = this.getters.getCell(position);
|
|
49757
49793
|
if (cell?.isFormula) {
|
|
49758
49794
|
const prettifiedContent = this.getPrettifiedFormula(cell);
|
|
49759
|
-
|
|
49795
|
+
// when a formula is prettified (multi lines, indented), adapt the cursor position
|
|
49796
|
+
// to take into account line breaks and tabs
|
|
49797
|
+
function adjustCursorIndex(targetIndex) {
|
|
49798
|
+
let adjustedIndex = 0;
|
|
49799
|
+
let originalIndex = 0;
|
|
49800
|
+
while (originalIndex < targetIndex) {
|
|
49801
|
+
adjustedIndex++;
|
|
49802
|
+
const char = prettifiedContent[adjustedIndex];
|
|
49803
|
+
if (char !== "\n" && char !== "\t") {
|
|
49804
|
+
originalIndex++;
|
|
49805
|
+
}
|
|
49806
|
+
}
|
|
49807
|
+
return adjustedIndex;
|
|
49808
|
+
}
|
|
49809
|
+
let adjustedSelection = selection;
|
|
49810
|
+
if (selection) {
|
|
49811
|
+
adjustedSelection = {
|
|
49812
|
+
start: adjustCursorIndex(selection.start),
|
|
49813
|
+
end: adjustCursorIndex(selection.end),
|
|
49814
|
+
};
|
|
49815
|
+
}
|
|
49816
|
+
return {
|
|
49817
|
+
text: localizeFormula(prettifiedContent, locale),
|
|
49818
|
+
adjustedSelection,
|
|
49819
|
+
};
|
|
49760
49820
|
}
|
|
49761
49821
|
const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
|
|
49762
49822
|
if (spreader) {
|
|
49763
|
-
return "";
|
|
49823
|
+
return { text: "" };
|
|
49764
49824
|
}
|
|
49765
49825
|
const { format, value, type, formattedValue } = this.getters.getEvaluatedCell(position);
|
|
49766
49826
|
switch (type) {
|
|
49767
49827
|
case CellValueType.empty:
|
|
49768
|
-
return "";
|
|
49828
|
+
return { text: "" };
|
|
49769
49829
|
case CellValueType.text:
|
|
49770
49830
|
case CellValueType.error:
|
|
49771
|
-
return value;
|
|
49831
|
+
return { text: value };
|
|
49772
49832
|
case CellValueType.boolean:
|
|
49773
|
-
return formattedValue;
|
|
49833
|
+
return { text: formattedValue };
|
|
49774
49834
|
case CellValueType.number:
|
|
49775
49835
|
if (format && isDateTimeFormat(format)) {
|
|
49776
49836
|
if (parseDateTime(formattedValue, locale) !== null) {
|
|
49777
49837
|
// formatted string can be parsed again
|
|
49778
|
-
return formattedValue;
|
|
49838
|
+
return { text: formattedValue };
|
|
49779
49839
|
}
|
|
49780
49840
|
// display a simplified and parsable string otherwise
|
|
49781
49841
|
const timeFormat = Number.isInteger(value)
|
|
49782
49842
|
? locale.dateFormat
|
|
49783
49843
|
: getDateTimeFormat(locale);
|
|
49784
|
-
return formatValue(value, { locale, format: timeFormat });
|
|
49844
|
+
return { text: formatValue(value, { locale, format: timeFormat }) };
|
|
49785
49845
|
}
|
|
49786
|
-
return this.numberComposerContent(value, format, locale);
|
|
49846
|
+
return { text: this.numberComposerContent(value, format, locale) };
|
|
49787
49847
|
}
|
|
49788
49848
|
}
|
|
49789
49849
|
getPrettifiedFormula(cell) {
|
|
@@ -49952,8 +50012,9 @@ class GridComposer extends owl.Component {
|
|
|
49952
50012
|
},
|
|
49953
50013
|
focus: this.focus,
|
|
49954
50014
|
isDefaultFocus: true,
|
|
49955
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
50015
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
49956
50016
|
focusMode: "contentFocus",
|
|
50017
|
+
selection,
|
|
49957
50018
|
}),
|
|
49958
50019
|
onComposerCellFocused: (content) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
49959
50020
|
focusMode: "cellFocus",
|
|
@@ -57359,12 +57420,13 @@ class DataValidationEditor extends owl.Component {
|
|
|
57359
57420
|
onCloseSidePanel: { type: Function, optional: true },
|
|
57360
57421
|
};
|
|
57361
57422
|
state = owl.useState({ rule: this.defaultDataValidationRule, errors: [] });
|
|
57423
|
+
editingSheetId;
|
|
57362
57424
|
setup() {
|
|
57425
|
+
this.editingSheetId = this.env.model.getters.getActiveSheetId();
|
|
57363
57426
|
if (this.props.rule) {
|
|
57364
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
57365
57427
|
this.state.rule = {
|
|
57366
57428
|
...this.props.rule,
|
|
57367
|
-
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range,
|
|
57429
|
+
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
|
|
57368
57430
|
};
|
|
57369
57431
|
this.state.rule.criterion.type = this.props.rule.criterion.type;
|
|
57370
57432
|
}
|
|
@@ -57398,7 +57460,6 @@ class DataValidationEditor extends owl.Component {
|
|
|
57398
57460
|
const locale = this.env.model.getters.getLocale();
|
|
57399
57461
|
const criterion = rule.criterion;
|
|
57400
57462
|
const criterionEvaluator = criterionEvaluatorRegistry.get(criterion.type);
|
|
57401
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
57402
57463
|
const values = criterion.values
|
|
57403
57464
|
.slice(0, criterionEvaluator.numberOfValues(criterion))
|
|
57404
57465
|
.map((value) => value?.trim())
|
|
@@ -57406,8 +57467,8 @@ class DataValidationEditor extends owl.Component {
|
|
|
57406
57467
|
.map((value) => canonicalizeContent(value, locale));
|
|
57407
57468
|
rule.criterion = { ...criterion, values };
|
|
57408
57469
|
return {
|
|
57409
|
-
sheetId,
|
|
57410
|
-
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(
|
|
57470
|
+
sheetId: this.editingSheetId,
|
|
57471
|
+
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(this.editingSheetId, xc)),
|
|
57411
57472
|
rule,
|
|
57412
57473
|
};
|
|
57413
57474
|
}
|
|
@@ -57934,6 +57995,7 @@ css /* scss */ `
|
|
|
57934
57995
|
.o-button {
|
|
57935
57996
|
height: 19px;
|
|
57936
57997
|
width: 19px;
|
|
57998
|
+
box-sizing: content-box;
|
|
57937
57999
|
.o-icon {
|
|
57938
58000
|
height: 14px;
|
|
57939
58001
|
width: 14px;
|
|
@@ -68756,7 +68818,7 @@ class FormulaDependencyGraph {
|
|
|
68756
68818
|
* in the correct order they should be evaluated.
|
|
68757
68819
|
* This is called a topological ordering (excluding cycles)
|
|
68758
68820
|
*/
|
|
68759
|
-
getCellsDependingOn(ranges) {
|
|
68821
|
+
getCellsDependingOn(ranges, ignore) {
|
|
68760
68822
|
const visited = this.createEmptyPositionSet();
|
|
68761
68823
|
const queue = Array.from(ranges).reverse();
|
|
68762
68824
|
while (queue.length > 0) {
|
|
@@ -68771,7 +68833,7 @@ class FormulaDependencyGraph {
|
|
|
68771
68833
|
const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
|
|
68772
68834
|
const nextInQueue = {};
|
|
68773
68835
|
for (const position of impactedPositions) {
|
|
68774
|
-
if (!visited.has(position)) {
|
|
68836
|
+
if (!visited.has(position) && !ignore.has(position)) {
|
|
68775
68837
|
if (!nextInQueue[position.sheetId]) {
|
|
68776
68838
|
nextInQueue[position.sheetId] = [];
|
|
68777
68839
|
}
|
|
@@ -69329,7 +69391,7 @@ class Evaluator {
|
|
|
69329
69391
|
}
|
|
69330
69392
|
invalidatePositionsDependingOnSpread(sheetId, resultZone) {
|
|
69331
69393
|
// the result matrix is split in 2 zones to exclude the array formula position
|
|
69332
|
-
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
|
|
69394
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })), this.nextPositionsToUpdate);
|
|
69333
69395
|
invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
|
|
69334
69396
|
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
69335
69397
|
}
|
|
@@ -69447,7 +69509,7 @@ class Evaluator {
|
|
|
69447
69509
|
for (const sheetId in zonesBySheetIds) {
|
|
69448
69510
|
ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
|
|
69449
69511
|
}
|
|
69450
|
-
return this.formulaDependencies().getCellsDependingOn(ranges);
|
|
69512
|
+
return this.formulaDependencies().getCellsDependingOn(ranges, this.nextPositionsToUpdate);
|
|
69451
69513
|
}
|
|
69452
69514
|
}
|
|
69453
69515
|
function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
@@ -70958,7 +71020,8 @@ class DynamicTablesPlugin extends CoreViewPlugin {
|
|
|
70958
71020
|
const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
|
|
70959
71021
|
const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
|
|
70960
71022
|
if (!parentSpreadingCell) {
|
|
70961
|
-
|
|
71023
|
+
const evaluatedCell = this.getters.getEvaluatedCell(topLeft);
|
|
71024
|
+
return (evaluatedCell.value === CellErrorType.SpilledBlocked && !evaluatedCell.errorOriginPosition);
|
|
70962
71025
|
}
|
|
70963
71026
|
else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
|
|
70964
71027
|
return true;
|
|
@@ -82130,6 +82193,7 @@ class RibbonMenu extends owl.Component {
|
|
|
82130
82193
|
static components = { Menu };
|
|
82131
82194
|
rootItems = topbarMenuRegistry.getMenuItems();
|
|
82132
82195
|
menuRef = owl.useRef("menu");
|
|
82196
|
+
containerRef = owl.useRef("container");
|
|
82133
82197
|
state = owl.useState({
|
|
82134
82198
|
menuItems: this.rootItems,
|
|
82135
82199
|
title: _t("Menu Bar"),
|
|
@@ -82137,6 +82201,7 @@ class RibbonMenu extends owl.Component {
|
|
|
82137
82201
|
});
|
|
82138
82202
|
setup() {
|
|
82139
82203
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
82204
|
+
owl.onMounted(this.updateShadows);
|
|
82140
82205
|
}
|
|
82141
82206
|
onExternalClick(ev) {
|
|
82142
82207
|
if (!this.menuRef.el?.contains(ev.target)) {
|
|
@@ -82149,6 +82214,7 @@ class RibbonMenu extends owl.Component {
|
|
|
82149
82214
|
this.state.parentState = { ...this.state };
|
|
82150
82215
|
this.state.menuItems = children;
|
|
82151
82216
|
this.state.title = menu.name(this.env);
|
|
82217
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
82152
82218
|
}
|
|
82153
82219
|
else {
|
|
82154
82220
|
this.state.menuItems = this.rootItems;
|
|
@@ -82170,6 +82236,19 @@ class RibbonMenu extends owl.Component {
|
|
|
82170
82236
|
height: `${this.props.height}px`,
|
|
82171
82237
|
});
|
|
82172
82238
|
}
|
|
82239
|
+
updateShadows() {
|
|
82240
|
+
if (!this.containerRef.el) {
|
|
82241
|
+
return;
|
|
82242
|
+
}
|
|
82243
|
+
this.containerRef.el.classList.remove("scroll-top", "scroll-bottom");
|
|
82244
|
+
const maxScroll = this.containerRef.el.scrollHeight - this.containerRef.el.clientHeight || 0;
|
|
82245
|
+
if (this.containerRef.el.scrollTop < maxScroll - 1) {
|
|
82246
|
+
this.containerRef.el.classList.add("scroll-bottom");
|
|
82247
|
+
}
|
|
82248
|
+
if (this.containerRef.el.scrollTop > 0) {
|
|
82249
|
+
this.containerRef.el.classList.add("scroll-top");
|
|
82250
|
+
}
|
|
82251
|
+
}
|
|
82173
82252
|
onClickBack() {
|
|
82174
82253
|
if (!this.state.parentState) {
|
|
82175
82254
|
this.props.onClose();
|
|
@@ -82178,6 +82257,7 @@ class RibbonMenu extends owl.Component {
|
|
|
82178
82257
|
this.state.menuItems = this.state.parentState.menuItems;
|
|
82179
82258
|
this.state.title = this.state.parentState.title;
|
|
82180
82259
|
this.state.parentState = this.state.parentState.parentState;
|
|
82260
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
82181
82261
|
}
|
|
82182
82262
|
get backTitle() {
|
|
82183
82263
|
return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
|
|
@@ -82234,7 +82314,9 @@ class SmallBottomBar extends owl.Component {
|
|
|
82234
82314
|
: "inactive";
|
|
82235
82315
|
}
|
|
82236
82316
|
get showFxIcon() {
|
|
82237
|
-
return this.focus === "inactive" &&
|
|
82317
|
+
return (this.focus === "inactive" &&
|
|
82318
|
+
!this.composerStore.currentContent &&
|
|
82319
|
+
!this.composerStore.placeholder);
|
|
82238
82320
|
}
|
|
82239
82321
|
get rect() {
|
|
82240
82322
|
return this.composerRef.el
|
|
@@ -82251,8 +82333,9 @@ class SmallBottomBar extends owl.Component {
|
|
|
82251
82333
|
},
|
|
82252
82334
|
focus: this.focus,
|
|
82253
82335
|
composerStore: this.composerStore,
|
|
82254
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
82336
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
82255
82337
|
focusMode: "contentFocus",
|
|
82338
|
+
selection,
|
|
82256
82339
|
}),
|
|
82257
82340
|
isDefaultFocus: false,
|
|
82258
82341
|
inputStyle: cssPropertiesToCss({
|
|
@@ -82260,6 +82343,7 @@ class SmallBottomBar extends owl.Component {
|
|
|
82260
82343
|
"max-height": `130px`,
|
|
82261
82344
|
}),
|
|
82262
82345
|
showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
|
|
82346
|
+
placeholder: this.composerStore.placeholder,
|
|
82263
82347
|
};
|
|
82264
82348
|
}
|
|
82265
82349
|
get symbols() {
|
|
@@ -82322,7 +82406,9 @@ class TopBarComposer extends owl.Component {
|
|
|
82322
82406
|
: "inactive";
|
|
82323
82407
|
}
|
|
82324
82408
|
get showFxIcon() {
|
|
82325
|
-
return this.focus === "inactive" &&
|
|
82409
|
+
return (this.focus === "inactive" &&
|
|
82410
|
+
!this.composerStore.currentContent &&
|
|
82411
|
+
!this.composerStore.placeholder);
|
|
82326
82412
|
}
|
|
82327
82413
|
get composerStyle() {
|
|
82328
82414
|
const style = {
|
|
@@ -88538,6 +88624,6 @@ exports.tokenColors = tokenColors;
|
|
|
88538
88624
|
exports.tokenize = tokenize;
|
|
88539
88625
|
|
|
88540
88626
|
|
|
88541
|
-
__info__.version = "19.0.
|
|
88542
|
-
__info__.date = "2025-10-
|
|
88543
|
-
__info__.hash = "
|
|
88627
|
+
__info__.version = "19.0.6";
|
|
88628
|
+
__info__.date = "2025-10-16T06:39:36.282Z";
|
|
88629
|
+
__info__.hash = "0d4315a";
|