@odoo/o-spreadsheet 19.1.0-alpha.4 → 19.1.0-alpha.5
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 +388 -153
- package/dist/o-spreadsheet.d.ts +30 -5
- package/dist/o-spreadsheet.esm.js +388 -153
- package/dist/o-spreadsheet.iife.js +388 -153
- package/dist/o-spreadsheet.iife.min.js +321 -321
- package/dist/o_spreadsheet.xml +31 -6
- 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.1.0-alpha.
|
|
6
|
-
* @date 2025-10-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.1.0-alpha.5
|
|
6
|
+
* @date 2025-10-16T06:39:55.925Z
|
|
7
|
+
* @hash 1a0e3d5
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -4452,7 +4452,17 @@ function toNumberMatrix(data, argName) {
|
|
|
4452
4452
|
return toMatrix(data).map((row) => {
|
|
4453
4453
|
return row.map((cell) => {
|
|
4454
4454
|
if (typeof cell.value !== "number") {
|
|
4455
|
-
|
|
4455
|
+
let message = "";
|
|
4456
|
+
if (typeof cell === "object") {
|
|
4457
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got an empty value.", argName);
|
|
4458
|
+
}
|
|
4459
|
+
else if (typeof cell === "string") {
|
|
4460
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a string.", argName);
|
|
4461
|
+
}
|
|
4462
|
+
else if (typeof cell === "boolean") {
|
|
4463
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a boolean.", argName);
|
|
4464
|
+
}
|
|
4465
|
+
throw new EvaluationError(message);
|
|
4456
4466
|
}
|
|
4457
4467
|
return cell.value;
|
|
4458
4468
|
});
|
|
@@ -6390,6 +6400,9 @@ function parseLiteral(content, locale) {
|
|
|
6390
6400
|
if (content.startsWith("=")) {
|
|
6391
6401
|
throw new Error(`Cannot parse "${content}" because it's not a literal value. It's a formula`);
|
|
6392
6402
|
}
|
|
6403
|
+
if (content.startsWith("'")) {
|
|
6404
|
+
return content.slice(1);
|
|
6405
|
+
}
|
|
6393
6406
|
if (content === "") {
|
|
6394
6407
|
return null;
|
|
6395
6408
|
}
|
|
@@ -9339,6 +9352,32 @@ function getCustomFieldWithParentField(definition, parentField, fields) {
|
|
|
9339
9352
|
groups: [],
|
|
9340
9353
|
});
|
|
9341
9354
|
}
|
|
9355
|
+
function togglePivotCollapse(position, env) {
|
|
9356
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
9357
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
9358
|
+
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
9359
|
+
return;
|
|
9360
|
+
}
|
|
9361
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
9362
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
9363
|
+
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
9364
|
+
: [];
|
|
9365
|
+
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
9366
|
+
if (index !== -1) {
|
|
9367
|
+
collapsedDomains.splice(index, 1);
|
|
9368
|
+
}
|
|
9369
|
+
else {
|
|
9370
|
+
collapsedDomains.push(pivotCell.domain);
|
|
9371
|
+
}
|
|
9372
|
+
const newDomains = definition.collapsedDomains
|
|
9373
|
+
? { ...definition.collapsedDomains }
|
|
9374
|
+
: { COL: [], ROW: [] };
|
|
9375
|
+
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
9376
|
+
env.model.dispatch("UPDATE_PIVOT", {
|
|
9377
|
+
pivotId,
|
|
9378
|
+
pivot: { ...definition, collapsedDomains: newDomains },
|
|
9379
|
+
});
|
|
9380
|
+
}
|
|
9342
9381
|
|
|
9343
9382
|
class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
9344
9383
|
isCutAllowed(data) {
|
|
@@ -9512,7 +9551,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
9512
9551
|
pasteCell(origin, target, clipboardOption) {
|
|
9513
9552
|
const { sheetId, col, row } = target;
|
|
9514
9553
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
9515
|
-
const originFormat = origin?.format
|
|
9554
|
+
const originFormat = origin?.format || origin.evaluatedCell.format;
|
|
9516
9555
|
if (clipboardOption?.pasteOption === "asValue") {
|
|
9517
9556
|
this.dispatch("UPDATE_CELL", {
|
|
9518
9557
|
...target,
|
|
@@ -13738,7 +13777,7 @@ const GROWTH = {
|
|
|
13738
13777
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
13739
13778
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
13740
13779
|
}
|
|
13741
|
-
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "
|
|
13780
|
+
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "known_data_y")), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b)));
|
|
13742
13781
|
},
|
|
13743
13782
|
};
|
|
13744
13783
|
// -----------------------------------------------------------------------------
|
|
@@ -13811,7 +13850,7 @@ const LINEST = {
|
|
|
13811
13850
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13812
13851
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13813
13852
|
}
|
|
13814
|
-
return fullLinearRegression(toNumberMatrix(dataX, "
|
|
13853
|
+
return fullLinearRegression(toNumberMatrix(dataX, "data_x"), toNumberMatrix(dataY, "data_y"), toBoolean(calculateB), toBoolean(verbose));
|
|
13815
13854
|
},
|
|
13816
13855
|
isExported: true,
|
|
13817
13856
|
};
|
|
@@ -13830,7 +13869,7 @@ const LOGEST = {
|
|
|
13830
13869
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13831
13870
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13832
13871
|
}
|
|
13833
|
-
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "
|
|
13872
|
+
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "data_x"), logM(toNumberMatrix(dataY, "data_y")), toBoolean(calculateB), toBoolean(verbose));
|
|
13834
13873
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13835
13874
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
13836
13875
|
}
|
|
@@ -14451,7 +14490,7 @@ const TREND = {
|
|
|
14451
14490
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
14452
14491
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
14453
14492
|
}
|
|
14454
|
-
return predictLinearValues(toNumberMatrix(knownDataY, "
|
|
14493
|
+
return predictLinearValues(toNumberMatrix(knownDataY, "known_data_y"), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b));
|
|
14455
14494
|
},
|
|
14456
14495
|
};
|
|
14457
14496
|
// -----------------------------------------------------------------------------
|
|
@@ -22972,6 +23011,10 @@ const chartShowValuesPlugin = {
|
|
|
22972
23011
|
}
|
|
22973
23012
|
const ctx = chart.ctx;
|
|
22974
23013
|
ctx.save();
|
|
23014
|
+
const { left, top, height, width } = chart.chartArea;
|
|
23015
|
+
ctx.beginPath();
|
|
23016
|
+
ctx.rect(left, top, width, height);
|
|
23017
|
+
ctx.clip();
|
|
22975
23018
|
ctx.textAlign = "center";
|
|
22976
23019
|
ctx.textBaseline = "middle";
|
|
22977
23020
|
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
@@ -24006,7 +24049,7 @@ class ChartJsComponent extends owl.Component {
|
|
|
24006
24049
|
this.chart.update();
|
|
24007
24050
|
}
|
|
24008
24051
|
hasChartDataChanged() {
|
|
24009
|
-
return !deepEquals(this.currentRuntime
|
|
24052
|
+
return !deepEquals(this.getChartDataInRuntime(this.currentRuntime), this.getChartDataInRuntime(this.chartRuntime));
|
|
24010
24053
|
}
|
|
24011
24054
|
enableAnimationInChartData(chartData) {
|
|
24012
24055
|
return {
|
|
@@ -24014,6 +24057,17 @@ class ChartJsComponent extends owl.Component {
|
|
|
24014
24057
|
options: { ...chartData.options, animation: { animateRotate: true } },
|
|
24015
24058
|
};
|
|
24016
24059
|
}
|
|
24060
|
+
getChartDataInRuntime(runtime) {
|
|
24061
|
+
const data = runtime.chartJsConfig.data;
|
|
24062
|
+
return {
|
|
24063
|
+
labels: data.labels,
|
|
24064
|
+
dataset: data.datasets.map((dataset) => ({
|
|
24065
|
+
data: dataset.data,
|
|
24066
|
+
label: dataset.label,
|
|
24067
|
+
tree: dataset.tree,
|
|
24068
|
+
})),
|
|
24069
|
+
};
|
|
24070
|
+
}
|
|
24017
24071
|
get animationChartId() {
|
|
24018
24072
|
return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
|
|
24019
24073
|
}
|
|
@@ -25437,6 +25491,7 @@ function getChartTimeOptions(labels, labelFormat, locale) {
|
|
|
25437
25491
|
parser: luxonFormat,
|
|
25438
25492
|
displayFormats,
|
|
25439
25493
|
unit: timeUnit ?? false,
|
|
25494
|
+
tooltipFormat: luxonFormat,
|
|
25440
25495
|
};
|
|
25441
25496
|
}
|
|
25442
25497
|
/**
|
|
@@ -26505,6 +26560,7 @@ function getLineChartScales(definition, args) {
|
|
|
26505
26560
|
};
|
|
26506
26561
|
Object.assign(scales.x, axis);
|
|
26507
26562
|
scales.x.ticks.maxTicksLimit = 15;
|
|
26563
|
+
delete scales?.x?.ticks?.callback;
|
|
26508
26564
|
}
|
|
26509
26565
|
else if (axisType === "linear") {
|
|
26510
26566
|
scales.x.type = "linear";
|
|
@@ -31583,7 +31639,8 @@ class Menu extends owl.Component {
|
|
|
31583
31639
|
const menuItemsAndSeparators = [];
|
|
31584
31640
|
for (let i = 0; i < this.props.menuItems.length; i++) {
|
|
31585
31641
|
const menuItem = this.props.menuItems[i];
|
|
31586
|
-
if (menuItem.isVisible(this.env)
|
|
31642
|
+
if (menuItem.isVisible(this.env) &&
|
|
31643
|
+
(!this.isRoot(menuItem) || this.hasVisibleChildren(menuItem))) {
|
|
31587
31644
|
menuItemsAndSeparators.push(menuItem);
|
|
31588
31645
|
}
|
|
31589
31646
|
if (menuItem.separator &&
|
|
@@ -31625,6 +31682,9 @@ class Menu extends owl.Component {
|
|
|
31625
31682
|
isRoot(menu) {
|
|
31626
31683
|
return !menu.execute;
|
|
31627
31684
|
}
|
|
31685
|
+
hasVisibleChildren(menu) {
|
|
31686
|
+
return menu.children(this.env).some((child) => child.isVisible(this.env));
|
|
31687
|
+
}
|
|
31628
31688
|
isEnabled(menu) {
|
|
31629
31689
|
if (menu.isEnabled(this.env)) {
|
|
31630
31690
|
return this.env.model.getters.isReadonly() ? menu.isReadonlyAllowed : true;
|
|
@@ -32183,7 +32243,7 @@ class ChartDashboardMenu extends owl.Component {
|
|
|
32183
32243
|
}
|
|
32184
32244
|
openContextMenu(ev) {
|
|
32185
32245
|
this.menuState.isOpen = true;
|
|
32186
|
-
this.menuState.anchorRect =
|
|
32246
|
+
this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
|
|
32187
32247
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32188
32248
|
this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
|
|
32189
32249
|
}
|
|
@@ -32215,6 +32275,7 @@ class CarouselFigure extends owl.Component {
|
|
|
32215
32275
|
onFigureDeleted: Function,
|
|
32216
32276
|
editFigureStyle: { type: Function, optional: true },
|
|
32217
32277
|
isFullScreen: { type: Boolean, optional: true },
|
|
32278
|
+
openContextMenu: { type: Function, optional: true },
|
|
32218
32279
|
};
|
|
32219
32280
|
static components = { ChartDashboardMenu, MenuPopover };
|
|
32220
32281
|
carouselTabsRef = owl.useRef("carouselTabs");
|
|
@@ -32348,6 +32409,12 @@ class CarouselFigure extends owl.Component {
|
|
|
32348
32409
|
get visibleCarouselItems() {
|
|
32349
32410
|
return this.carousel.items.filter((item) => item.type === "carouselDataView" && this.props.isFullScreen ? false : true);
|
|
32350
32411
|
}
|
|
32412
|
+
openContextMenu(event) {
|
|
32413
|
+
const target = event.currentTarget;
|
|
32414
|
+
if (target) {
|
|
32415
|
+
this.props.openContextMenu?.(getBoundingRectAsPOJO(target));
|
|
32416
|
+
}
|
|
32417
|
+
}
|
|
32351
32418
|
}
|
|
32352
32419
|
|
|
32353
32420
|
class ChartFigure extends owl.Component {
|
|
@@ -32357,6 +32424,7 @@ class ChartFigure extends owl.Component {
|
|
|
32357
32424
|
onFigureDeleted: Function,
|
|
32358
32425
|
editFigureStyle: { type: Function, optional: true },
|
|
32359
32426
|
isFullScreen: { type: Boolean, optional: true },
|
|
32427
|
+
openContextMenu: { type: Function, optional: true },
|
|
32360
32428
|
};
|
|
32361
32429
|
static components = { ChartDashboardMenu };
|
|
32362
32430
|
onDoubleClick() {
|
|
@@ -32389,6 +32457,7 @@ class ImageFigure extends owl.Component {
|
|
|
32389
32457
|
figureUI: Object,
|
|
32390
32458
|
onFigureDeleted: Function,
|
|
32391
32459
|
editFigureStyle: { type: Function, optional: true },
|
|
32460
|
+
openContextMenu: { type: Function, optional: true },
|
|
32392
32461
|
};
|
|
32393
32462
|
static components = {};
|
|
32394
32463
|
// ---------------------------------------------------------------------------
|
|
@@ -34191,8 +34260,11 @@ class Composer extends owl.Component {
|
|
|
34191
34260
|
}
|
|
34192
34261
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
34193
34262
|
this.props.composerStore.stopComposerRangeSelection();
|
|
34194
|
-
this.props.
|
|
34195
|
-
this.props.
|
|
34263
|
+
const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
|
|
34264
|
+
this.props.onComposerContentFocused(newSelection);
|
|
34265
|
+
if (!isCurrentlyInactive) {
|
|
34266
|
+
this.props.composerStore.changeComposerCursorSelection(newSelection.start, newSelection.end);
|
|
34267
|
+
}
|
|
34196
34268
|
this.processTokenAtCursor();
|
|
34197
34269
|
}
|
|
34198
34270
|
onDblClick() {
|
|
@@ -34687,13 +34759,6 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34687
34759
|
}
|
|
34688
34760
|
}
|
|
34689
34761
|
startEdition(text, selection) {
|
|
34690
|
-
if (selection) {
|
|
34691
|
-
const content = text || this.getComposerContent(this.getters.getActivePosition());
|
|
34692
|
-
const validSelection = this.isSelectionValid(content.length, selection.start, selection.end);
|
|
34693
|
-
if (!validSelection) {
|
|
34694
|
-
return;
|
|
34695
|
-
}
|
|
34696
|
-
}
|
|
34697
34762
|
const { col, row } = this.getters.getActivePosition();
|
|
34698
34763
|
this.model.dispatch("SELECT_FIGURE", { figureId: null });
|
|
34699
34764
|
this.model.dispatch("SCROLL_TO_CELL", { col, row });
|
|
@@ -34750,7 +34815,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34750
34815
|
// ---------------------------------------------------------------------------
|
|
34751
34816
|
get currentContent() {
|
|
34752
34817
|
if (this.editionMode === "inactive") {
|
|
34753
|
-
return this.getComposerContent(this.getters.getActivePosition());
|
|
34818
|
+
return this.getComposerContent(this.getters.getActivePosition()).text;
|
|
34754
34819
|
}
|
|
34755
34820
|
return this._currentContent;
|
|
34756
34821
|
}
|
|
@@ -34949,8 +35014,9 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34949
35014
|
this.sheetId = sheetId;
|
|
34950
35015
|
this.row = row;
|
|
34951
35016
|
this.editionMode = "editing";
|
|
34952
|
-
|
|
34953
|
-
this.
|
|
35017
|
+
const { text, adjustedSelection } = this.getComposerContent({ sheetId, col, row }, selection);
|
|
35018
|
+
this.initialContent = text;
|
|
35019
|
+
this.setContent(str || this.initialContent, adjustedSelection ?? selection);
|
|
34954
35020
|
this.colorIndexByRange = {};
|
|
34955
35021
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
34956
35022
|
this.captureSelection(zone, col, row);
|
|
@@ -35427,7 +35493,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35427
35493
|
constructor(get, args) {
|
|
35428
35494
|
super(get);
|
|
35429
35495
|
this.args = args;
|
|
35430
|
-
this._currentContent = this.getComposerContent();
|
|
35496
|
+
this._currentContent = this.getComposerContent().text;
|
|
35431
35497
|
}
|
|
35432
35498
|
getAutoCompleteProviders() {
|
|
35433
35499
|
const providersDefinitions = super.getAutoCompleteProviders();
|
|
@@ -35464,7 +35530,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35464
35530
|
})
|
|
35465
35531
|
.join("");
|
|
35466
35532
|
}
|
|
35467
|
-
return localizeContent(content, this.getters.getLocale());
|
|
35533
|
+
return { text: localizeContent(content, this.getters.getLocale()) };
|
|
35468
35534
|
}
|
|
35469
35535
|
stopEdition() {
|
|
35470
35536
|
this._stopEdition();
|
|
@@ -38684,6 +38750,74 @@ function getPath2D(svgPath) {
|
|
|
38684
38750
|
return path2D;
|
|
38685
38751
|
}
|
|
38686
38752
|
|
|
38753
|
+
/**
|
|
38754
|
+
* Get the relative path between two files
|
|
38755
|
+
*
|
|
38756
|
+
* Eg.:
|
|
38757
|
+
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
38758
|
+
*/
|
|
38759
|
+
function getRelativePath(from, to) {
|
|
38760
|
+
const fromPathParts = from.split("/");
|
|
38761
|
+
const toPathParts = to.split("/");
|
|
38762
|
+
let relPath = "";
|
|
38763
|
+
let startIndex = 0;
|
|
38764
|
+
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
38765
|
+
if (fromPathParts[i] === toPathParts[i]) {
|
|
38766
|
+
startIndex++;
|
|
38767
|
+
}
|
|
38768
|
+
else {
|
|
38769
|
+
relPath += "../";
|
|
38770
|
+
}
|
|
38771
|
+
}
|
|
38772
|
+
relPath += toPathParts.slice(startIndex).join("/");
|
|
38773
|
+
return relPath;
|
|
38774
|
+
}
|
|
38775
|
+
/**
|
|
38776
|
+
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
38777
|
+
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
38778
|
+
*
|
|
38779
|
+
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
38780
|
+
*/
|
|
38781
|
+
function arrayToObject(array, indexOffset = 0) {
|
|
38782
|
+
const obj = {};
|
|
38783
|
+
for (let i = 0; i < array.length; i++) {
|
|
38784
|
+
if (array[i]) {
|
|
38785
|
+
obj[i + indexOffset] = array[i];
|
|
38786
|
+
}
|
|
38787
|
+
}
|
|
38788
|
+
return obj;
|
|
38789
|
+
}
|
|
38790
|
+
/**
|
|
38791
|
+
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
38792
|
+
* Replace with characters understandable by JS
|
|
38793
|
+
*/
|
|
38794
|
+
function fixXlsxUnicode(str) {
|
|
38795
|
+
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
38796
|
+
return String.fromCharCode(parseInt(code, 16));
|
|
38797
|
+
});
|
|
38798
|
+
}
|
|
38799
|
+
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
38800
|
+
function getSheetDataHeader(sheetData, dimension, index) {
|
|
38801
|
+
if (dimension === "COL") {
|
|
38802
|
+
if (!sheetData.cols[index]) {
|
|
38803
|
+
sheetData.cols[index] = {};
|
|
38804
|
+
}
|
|
38805
|
+
return sheetData.cols[index];
|
|
38806
|
+
}
|
|
38807
|
+
if (!sheetData.rows[index]) {
|
|
38808
|
+
sheetData.rows[index] = {};
|
|
38809
|
+
}
|
|
38810
|
+
return sheetData.rows[index];
|
|
38811
|
+
}
|
|
38812
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
38813
|
+
function prefixFormulaWithEqual(formula) {
|
|
38814
|
+
if (formula[0] === "=") {
|
|
38815
|
+
return formula;
|
|
38816
|
+
}
|
|
38817
|
+
const tokens = tokenize(formula);
|
|
38818
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
38819
|
+
}
|
|
38820
|
+
|
|
38687
38821
|
/**
|
|
38688
38822
|
* Map of the different types of conversions warnings and their name in error messages
|
|
38689
38823
|
*/
|
|
@@ -39206,66 +39340,6 @@ function hexaToInt(hex) {
|
|
|
39206
39340
|
*/
|
|
39207
39341
|
const DEFAULT_SYSTEM_COLOR = "FF000000";
|
|
39208
39342
|
|
|
39209
|
-
/**
|
|
39210
|
-
* Get the relative path between two files
|
|
39211
|
-
*
|
|
39212
|
-
* Eg.:
|
|
39213
|
-
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
39214
|
-
*/
|
|
39215
|
-
function getRelativePath(from, to) {
|
|
39216
|
-
const fromPathParts = from.split("/");
|
|
39217
|
-
const toPathParts = to.split("/");
|
|
39218
|
-
let relPath = "";
|
|
39219
|
-
let startIndex = 0;
|
|
39220
|
-
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
39221
|
-
if (fromPathParts[i] === toPathParts[i]) {
|
|
39222
|
-
startIndex++;
|
|
39223
|
-
}
|
|
39224
|
-
else {
|
|
39225
|
-
relPath += "../";
|
|
39226
|
-
}
|
|
39227
|
-
}
|
|
39228
|
-
relPath += toPathParts.slice(startIndex).join("/");
|
|
39229
|
-
return relPath;
|
|
39230
|
-
}
|
|
39231
|
-
/**
|
|
39232
|
-
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
39233
|
-
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
39234
|
-
*
|
|
39235
|
-
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
39236
|
-
*/
|
|
39237
|
-
function arrayToObject(array, indexOffset = 0) {
|
|
39238
|
-
const obj = {};
|
|
39239
|
-
for (let i = 0; i < array.length; i++) {
|
|
39240
|
-
if (array[i]) {
|
|
39241
|
-
obj[i + indexOffset] = array[i];
|
|
39242
|
-
}
|
|
39243
|
-
}
|
|
39244
|
-
return obj;
|
|
39245
|
-
}
|
|
39246
|
-
/**
|
|
39247
|
-
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
39248
|
-
* Replace with characters understandable by JS
|
|
39249
|
-
*/
|
|
39250
|
-
function fixXlsxUnicode(str) {
|
|
39251
|
-
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
39252
|
-
return String.fromCharCode(parseInt(code, 16));
|
|
39253
|
-
});
|
|
39254
|
-
}
|
|
39255
|
-
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
39256
|
-
function getSheetDataHeader(sheetData, dimension, index) {
|
|
39257
|
-
if (dimension === "COL") {
|
|
39258
|
-
if (!sheetData.cols[index]) {
|
|
39259
|
-
sheetData.cols[index] = {};
|
|
39260
|
-
}
|
|
39261
|
-
return sheetData.cols[index];
|
|
39262
|
-
}
|
|
39263
|
-
if (!sheetData.rows[index]) {
|
|
39264
|
-
sheetData.rows[index] = {};
|
|
39265
|
-
}
|
|
39266
|
-
return sheetData.rows[index];
|
|
39267
|
-
}
|
|
39268
|
-
|
|
39269
39343
|
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;
|
|
39270
39344
|
/**
|
|
39271
39345
|
* Convert excel format to o_spreadsheet format
|
|
@@ -39480,9 +39554,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
39480
39554
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
39481
39555
|
continue;
|
|
39482
39556
|
operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
|
|
39483
|
-
values.push(
|
|
39557
|
+
values.push(prefixFormulaWithEqual(rule.formula[0]));
|
|
39484
39558
|
if (rule.formula.length === 2) {
|
|
39485
|
-
values.push(
|
|
39559
|
+
values.push(prefixFormulaWithEqual(rule.formula[1]));
|
|
39486
39560
|
}
|
|
39487
39561
|
break;
|
|
39488
39562
|
}
|
|
@@ -39640,11 +39714,6 @@ function convertIcons(xlsxIconSet, index) {
|
|
|
39640
39714
|
? ICON_SETS[iconSet].neutral
|
|
39641
39715
|
: ICON_SETS[iconSet].good;
|
|
39642
39716
|
}
|
|
39643
|
-
/** Prefix the string by "=" if the string looks like a formula */
|
|
39644
|
-
function prefixFormula(formula) {
|
|
39645
|
-
const tokens = tokenize(formula);
|
|
39646
|
-
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
39647
|
-
}
|
|
39648
39717
|
// ---------------------------------------------------------------------------
|
|
39649
39718
|
// Warnings
|
|
39650
39719
|
// ---------------------------------------------------------------------------
|
|
@@ -40120,7 +40189,7 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
40120
40189
|
dvRules.push(decimalRule);
|
|
40121
40190
|
break;
|
|
40122
40191
|
case "list":
|
|
40123
|
-
const listRule =
|
|
40192
|
+
const listRule = convertListRule(dvId++, dv);
|
|
40124
40193
|
dvRules.push(listRule);
|
|
40125
40194
|
break;
|
|
40126
40195
|
case "date":
|
|
@@ -40140,9 +40209,9 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
40140
40209
|
return dvRules;
|
|
40141
40210
|
}
|
|
40142
40211
|
function convertDecimalRule(id, dv) {
|
|
40143
|
-
const values = [dv.formula1.toString()];
|
|
40212
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
40144
40213
|
if (dv.formula2) {
|
|
40145
|
-
values.push(dv.formula2.toString());
|
|
40214
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
40146
40215
|
}
|
|
40147
40216
|
return {
|
|
40148
40217
|
id: id.toString(),
|
|
@@ -40154,7 +40223,7 @@ function convertDecimalRule(id, dv) {
|
|
|
40154
40223
|
},
|
|
40155
40224
|
};
|
|
40156
40225
|
}
|
|
40157
|
-
function
|
|
40226
|
+
function convertListRule(id, dv) {
|
|
40158
40227
|
const formula1 = dv.formula1.toString();
|
|
40159
40228
|
const isRangeRule = rangeReference.test(formula1);
|
|
40160
40229
|
return {
|
|
@@ -40170,9 +40239,9 @@ function convertListrule(id, dv) {
|
|
|
40170
40239
|
}
|
|
40171
40240
|
function convertDateRule(id, dv) {
|
|
40172
40241
|
let criterion;
|
|
40173
|
-
const values = [dv.formula1.toString()];
|
|
40242
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
40174
40243
|
if (dv.formula2) {
|
|
40175
|
-
values.push(dv.formula2.toString());
|
|
40244
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
40176
40245
|
criterion = {
|
|
40177
40246
|
type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
|
|
40178
40247
|
values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
|
|
@@ -40199,7 +40268,7 @@ function convertCustomRule(id, dv) {
|
|
|
40199
40268
|
isBlocking: dv.errorStyle !== "warning",
|
|
40200
40269
|
criterion: {
|
|
40201
40270
|
type: "customFormula",
|
|
40202
|
-
values: [
|
|
40271
|
+
values: [prefixFormulaWithEqual(dv.formula1.toString())],
|
|
40203
40272
|
},
|
|
40204
40273
|
};
|
|
40205
40274
|
}
|
|
@@ -45973,6 +46042,18 @@ class SpreadsheetPivotTable {
|
|
|
45973
46042
|
get numberOfCells() {
|
|
45974
46043
|
return this.rows.length * this.getNumberOfDataColumns();
|
|
45975
46044
|
}
|
|
46045
|
+
getColumnDomainsAtDepth(depth) {
|
|
46046
|
+
if (depth < 0 || depth >= this.columns.length - 1) {
|
|
46047
|
+
return [];
|
|
46048
|
+
}
|
|
46049
|
+
return this.columns[depth].map((col) => this.getDomain(col)).filter((d) => d.length);
|
|
46050
|
+
}
|
|
46051
|
+
getRowDomainsAtDepth(depth) {
|
|
46052
|
+
if (depth < 0 || depth > this.maxIndent) {
|
|
46053
|
+
return [];
|
|
46054
|
+
}
|
|
46055
|
+
return this.rows.filter((row) => row.indent === depth + 1).map((row) => this.getDomain(row));
|
|
46056
|
+
}
|
|
45976
46057
|
}
|
|
45977
46058
|
const EMPTY_PIVOT_CELL = { type: "EMPTY" };
|
|
45978
46059
|
|
|
@@ -46965,6 +47046,109 @@ const ungroupPivotHeadersAction = {
|
|
|
46965
47046
|
return areFieldValuesInGroups(definition, values, field, pivot.getFields());
|
|
46966
47047
|
},
|
|
46967
47048
|
};
|
|
47049
|
+
const toggleCollapsePivotGroupAction = {
|
|
47050
|
+
name: (env) => {
|
|
47051
|
+
const position = env.model.getters.getActivePosition();
|
|
47052
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47053
|
+
if (pivotCellState.isPivotGroup) {
|
|
47054
|
+
return pivotCellState.isCollapsed ? _t("Expand") : _t("Collapse");
|
|
47055
|
+
}
|
|
47056
|
+
return "";
|
|
47057
|
+
},
|
|
47058
|
+
execute(env) {
|
|
47059
|
+
const position = env.model.getters.getActivePosition();
|
|
47060
|
+
togglePivotCollapse(position, env);
|
|
47061
|
+
},
|
|
47062
|
+
isVisible: (env) => {
|
|
47063
|
+
const position = env.model.getters.getActivePosition();
|
|
47064
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47065
|
+
return pivotCellState.isPivotGroup;
|
|
47066
|
+
},
|
|
47067
|
+
};
|
|
47068
|
+
const collapseAllPivotGroupAction = {
|
|
47069
|
+
name: _t("Collapse all"),
|
|
47070
|
+
execute(env) {
|
|
47071
|
+
const position = env.model.getters.getActivePosition();
|
|
47072
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47073
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47074
|
+
return;
|
|
47075
|
+
}
|
|
47076
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47077
|
+
const definition = deepCopy(env.model.getters.getPivotCoreDefinition(pivotId));
|
|
47078
|
+
definition.collapsedDomains = definition.collapsedDomains || { COL: [], ROW: [] };
|
|
47079
|
+
const newCollapsed = [
|
|
47080
|
+
...(definition.collapsedDomains[pivotCell.dimension] || []),
|
|
47081
|
+
...siblingDomains,
|
|
47082
|
+
];
|
|
47083
|
+
const filteredCollapsed = newCollapsed.filter((domain, index) => index === newCollapsed.findIndex((d) => deepEquals(d, domain)));
|
|
47084
|
+
definition.collapsedDomains[pivotCell.dimension] = filteredCollapsed;
|
|
47085
|
+
env.model.dispatch("UPDATE_PIVOT", { pivotId, pivot: definition });
|
|
47086
|
+
},
|
|
47087
|
+
isVisible: (env) => {
|
|
47088
|
+
const position = env.model.getters.getActivePosition();
|
|
47089
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47090
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47091
|
+
return false;
|
|
47092
|
+
}
|
|
47093
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47094
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
47095
|
+
return !siblingDomains.every((domain) => (definition.collapsedDomains?.[pivotCell.dimension] || []).some((d) => deepEquals(d, domain)));
|
|
47096
|
+
},
|
|
47097
|
+
};
|
|
47098
|
+
const expandAllPivotGroupAction = {
|
|
47099
|
+
name: _t("Expand all"),
|
|
47100
|
+
execute(env) {
|
|
47101
|
+
const position = env.model.getters.getActivePosition();
|
|
47102
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47103
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47104
|
+
return;
|
|
47105
|
+
}
|
|
47106
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47107
|
+
const definition = deepCopy(env.model.getters.getPivotCoreDefinition(pivotId));
|
|
47108
|
+
definition.collapsedDomains = definition.collapsedDomains || { COL: [], ROW: [] };
|
|
47109
|
+
const domains = definition.collapsedDomains[pivotCell.dimension] || [];
|
|
47110
|
+
const filteredDomains = domains.filter((domain) => !siblingDomains.find((d) => deepEquals(d, domain)));
|
|
47111
|
+
definition.collapsedDomains[pivotCell.dimension] = filteredDomains;
|
|
47112
|
+
env.model.dispatch("UPDATE_PIVOT", { pivotId, pivot: definition });
|
|
47113
|
+
},
|
|
47114
|
+
isVisible: (env) => {
|
|
47115
|
+
const position = env.model.getters.getActivePosition();
|
|
47116
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47117
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47118
|
+
return false;
|
|
47119
|
+
}
|
|
47120
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47121
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
47122
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension] || [];
|
|
47123
|
+
return collapsedDomains.some((domain) => siblingDomains.some((d) => deepEquals(d, domain)));
|
|
47124
|
+
},
|
|
47125
|
+
};
|
|
47126
|
+
function getPivotCellCollapseState(getters, position) {
|
|
47127
|
+
if (!getters.isSpillPivotFormula(position)) {
|
|
47128
|
+
return { isPivotGroup: false };
|
|
47129
|
+
}
|
|
47130
|
+
const pivotCell = getters.getPivotCellFromPosition(position);
|
|
47131
|
+
const pivotId = getters.getPivotIdFromPosition(position);
|
|
47132
|
+
if (pivotCell.type !== "HEADER" || !pivotId || !pivotCell.domain.length) {
|
|
47133
|
+
return { isPivotGroup: false };
|
|
47134
|
+
}
|
|
47135
|
+
const definition = getters.getPivotCoreDefinition(pivotId);
|
|
47136
|
+
const isDashboard = getters.isDashboard();
|
|
47137
|
+
const fields = pivotCell.dimension === "COL" ? definition.columns : definition.rows;
|
|
47138
|
+
const hasIcon = !isDashboard && pivotCell.domain.length !== fields.length;
|
|
47139
|
+
if (!hasIcon) {
|
|
47140
|
+
return { isPivotGroup: false };
|
|
47141
|
+
}
|
|
47142
|
+
const domains = definition.collapsedDomains?.[pivotCell.dimension] ?? [];
|
|
47143
|
+
const isCollapsed = domains.some((domain) => deepEquals(domain, pivotCell.domain));
|
|
47144
|
+
const pivot = getters.getPivot(pivotId);
|
|
47145
|
+
const table = pivot.getExpandedTableStructure();
|
|
47146
|
+
const depth = pivotCell.domain.length - 1;
|
|
47147
|
+
const siblingDomains = pivotCell.dimension === "ROW"
|
|
47148
|
+
? table.getRowDomainsAtDepth(depth)
|
|
47149
|
+
: table.getColumnDomainsAtDepth(depth);
|
|
47150
|
+
return { isPivotGroup: true, isCollapsed, pivotCell, pivotId, siblingDomains };
|
|
47151
|
+
}
|
|
46968
47152
|
function canSortPivot(getters, position) {
|
|
46969
47153
|
const pivotId = getters.getPivotIdFromPosition(position);
|
|
46970
47154
|
if (!pivotId || !getters.isExistingPivot(pivotId) || !getters.isSpillPivotFormula(position)) {
|
|
@@ -47300,6 +47484,23 @@ cellMenuRegistry
|
|
|
47300
47484
|
sequence: 155,
|
|
47301
47485
|
icon: "o-spreadsheet-Icon.MINUS_IN_BOX",
|
|
47302
47486
|
...ungroupPivotHeadersAction,
|
|
47487
|
+
})
|
|
47488
|
+
.add("collapse_pivot", {
|
|
47489
|
+
sequence: 156,
|
|
47490
|
+
name: _t("Expand/Collapse"),
|
|
47491
|
+
icon: "o-spreadsheet-Icon.COLLAPSE",
|
|
47492
|
+
})
|
|
47493
|
+
.addChild("toggle_collapse_pivot_cell", ["collapse_pivot"], {
|
|
47494
|
+
sequence: 10,
|
|
47495
|
+
...toggleCollapsePivotGroupAction,
|
|
47496
|
+
})
|
|
47497
|
+
.addChild("collapse_all_pivot", ["collapse_pivot"], {
|
|
47498
|
+
sequence: 20,
|
|
47499
|
+
...collapseAllPivotGroupAction,
|
|
47500
|
+
})
|
|
47501
|
+
.addChild("expand_all_pivot", ["collapse_pivot"], {
|
|
47502
|
+
sequence: 30,
|
|
47503
|
+
...expandAllPivotGroupAction,
|
|
47303
47504
|
})
|
|
47304
47505
|
.add("pivot_sorting", {
|
|
47305
47506
|
name: _t("Sort pivot"),
|
|
@@ -47924,6 +48125,7 @@ function createHeaderGroupContainerContextMenu(sheetId, dimension) {
|
|
|
47924
48125
|
execute: (env) => {
|
|
47925
48126
|
env.model.dispatch("UNFOLD_ALL_HEADER_GROUPS", { sheetId, dimension });
|
|
47926
48127
|
},
|
|
48128
|
+
icon: "o-spreadsheet-Icon.EXPAND",
|
|
47927
48129
|
},
|
|
47928
48130
|
{
|
|
47929
48131
|
id: "fold_all",
|
|
@@ -47931,6 +48133,7 @@ function createHeaderGroupContainerContextMenu(sheetId, dimension) {
|
|
|
47931
48133
|
execute: (env) => {
|
|
47932
48134
|
env.model.dispatch("FOLD_ALL_HEADER_GROUPS", { sheetId, dimension });
|
|
47933
48135
|
},
|
|
48136
|
+
icon: "o-spreadsheet-Icon.COLLAPSE",
|
|
47934
48137
|
},
|
|
47935
48138
|
]);
|
|
47936
48139
|
}
|
|
@@ -47952,6 +48155,11 @@ function getHeaderGroupContextMenu(sheetId, dimension, start, end) {
|
|
|
47952
48155
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
47953
48156
|
interactiveToggleGroup(env, sheetId, dimension, start, end);
|
|
47954
48157
|
},
|
|
48158
|
+
icon: (env) => {
|
|
48159
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
48160
|
+
const groupIsFolded = env.model.getters.isGroupFolded(sheetId, dimension, start, end);
|
|
48161
|
+
return groupIsFolded ? "o-spreadsheet-Icon.EXPAND" : "o-spreadsheet-Icon.COLLAPSE";
|
|
48162
|
+
},
|
|
47955
48163
|
},
|
|
47956
48164
|
{
|
|
47957
48165
|
id: "remove_group",
|
|
@@ -47960,6 +48168,7 @@ function getHeaderGroupContextMenu(sheetId, dimension, start, end) {
|
|
|
47960
48168
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
47961
48169
|
env.model.dispatch("UNGROUP_HEADERS", { sheetId, dimension, start, end });
|
|
47962
48170
|
},
|
|
48171
|
+
icon: "o-spreadsheet-Icon.TRASH",
|
|
47963
48172
|
separator: true,
|
|
47964
48173
|
},
|
|
47965
48174
|
]);
|
|
@@ -48822,39 +49031,66 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
48822
49031
|
this.model.dispatch("AUTOFILL_TABLE_COLUMN", { ...this.currentEditedCell });
|
|
48823
49032
|
this.setContent("");
|
|
48824
49033
|
}
|
|
48825
|
-
getComposerContent(position) {
|
|
49034
|
+
getComposerContent(position, selection) {
|
|
48826
49035
|
const locale = this.getters.getLocale();
|
|
48827
49036
|
const cell = this.getters.getCell(position);
|
|
48828
49037
|
if (cell?.isFormula) {
|
|
48829
49038
|
const prettifiedContent = this.getPrettifiedFormula(cell);
|
|
48830
|
-
|
|
49039
|
+
// when a formula is prettified (multi lines, indented), adapt the cursor position
|
|
49040
|
+
// to take into account line breaks and tabs
|
|
49041
|
+
function adjustCursorIndex(targetIndex) {
|
|
49042
|
+
let adjustedIndex = 0;
|
|
49043
|
+
let originalIndex = 0;
|
|
49044
|
+
while (originalIndex < targetIndex) {
|
|
49045
|
+
adjustedIndex++;
|
|
49046
|
+
const char = prettifiedContent[adjustedIndex];
|
|
49047
|
+
if (char !== "\n" && char !== "\t") {
|
|
49048
|
+
originalIndex++;
|
|
49049
|
+
}
|
|
49050
|
+
}
|
|
49051
|
+
return adjustedIndex;
|
|
49052
|
+
}
|
|
49053
|
+
let adjustedSelection = selection;
|
|
49054
|
+
if (selection) {
|
|
49055
|
+
adjustedSelection = {
|
|
49056
|
+
start: adjustCursorIndex(selection.start),
|
|
49057
|
+
end: adjustCursorIndex(selection.end),
|
|
49058
|
+
};
|
|
49059
|
+
}
|
|
49060
|
+
return {
|
|
49061
|
+
text: localizeFormula(prettifiedContent, locale),
|
|
49062
|
+
adjustedSelection,
|
|
49063
|
+
};
|
|
48831
49064
|
}
|
|
48832
49065
|
const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
|
|
48833
49066
|
if (spreader) {
|
|
48834
|
-
return "";
|
|
49067
|
+
return { text: "" };
|
|
49068
|
+
}
|
|
49069
|
+
if (cell?.content.startsWith("'")) {
|
|
49070
|
+
return { text: cell.content };
|
|
48835
49071
|
}
|
|
48836
49072
|
const { format, value, type, formattedValue } = this.getters.getEvaluatedCell(position);
|
|
48837
49073
|
switch (type) {
|
|
48838
49074
|
case CellValueType.empty:
|
|
48839
|
-
return "";
|
|
49075
|
+
return { text: "" };
|
|
48840
49076
|
case CellValueType.text:
|
|
48841
49077
|
case CellValueType.error:
|
|
48842
|
-
return value;
|
|
49078
|
+
return { text: value };
|
|
48843
49079
|
case CellValueType.boolean:
|
|
48844
|
-
return formattedValue;
|
|
49080
|
+
return { text: formattedValue };
|
|
48845
49081
|
case CellValueType.number:
|
|
48846
49082
|
if (format && isDateTimeFormat(format)) {
|
|
48847
49083
|
if (parseDateTime(formattedValue, locale) !== null) {
|
|
48848
49084
|
// formatted string can be parsed again
|
|
48849
|
-
return formattedValue;
|
|
49085
|
+
return { text: formattedValue };
|
|
48850
49086
|
}
|
|
48851
49087
|
// display a simplified and parsable string otherwise
|
|
48852
49088
|
const timeFormat = Number.isInteger(value)
|
|
48853
49089
|
? locale.dateFormat
|
|
48854
49090
|
: getDateTimeFormat(locale);
|
|
48855
|
-
return formatValue(value, { locale, format: timeFormat });
|
|
49091
|
+
return { text: formatValue(value, { locale, format: timeFormat }) };
|
|
48856
49092
|
}
|
|
48857
|
-
return this.numberComposerContent(value, format, locale);
|
|
49093
|
+
return { text: this.numberComposerContent(value, format, locale) };
|
|
48858
49094
|
}
|
|
48859
49095
|
}
|
|
48860
49096
|
getPrettifiedFormula(cell) {
|
|
@@ -49001,8 +49237,9 @@ class GridComposer extends owl.Component {
|
|
|
49001
49237
|
},
|
|
49002
49238
|
focus: this.focus,
|
|
49003
49239
|
isDefaultFocus: true,
|
|
49004
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
49240
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
49005
49241
|
focusMode: "contentFocus",
|
|
49242
|
+
selection,
|
|
49006
49243
|
}),
|
|
49007
49244
|
onComposerCellFocused: (content) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
49008
49245
|
focusMode: "cellFocus",
|
|
@@ -55690,12 +55927,13 @@ class DataValidationEditor extends owl.Component {
|
|
|
55690
55927
|
onCloseSidePanel: { type: Function, optional: true },
|
|
55691
55928
|
};
|
|
55692
55929
|
state = owl.useState({ rule: this.defaultDataValidationRule, errors: [] });
|
|
55930
|
+
editingSheetId;
|
|
55693
55931
|
setup() {
|
|
55932
|
+
this.editingSheetId = this.env.model.getters.getActiveSheetId();
|
|
55694
55933
|
if (this.props.rule) {
|
|
55695
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
55696
55934
|
this.state.rule = {
|
|
55697
55935
|
...this.props.rule,
|
|
55698
|
-
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range,
|
|
55936
|
+
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
|
|
55699
55937
|
};
|
|
55700
55938
|
this.state.rule.criterion.type = this.props.rule.criterion.type;
|
|
55701
55939
|
}
|
|
@@ -55729,7 +55967,6 @@ class DataValidationEditor extends owl.Component {
|
|
|
55729
55967
|
const locale = this.env.model.getters.getLocale();
|
|
55730
55968
|
const criterion = rule.criterion;
|
|
55731
55969
|
const criterionEvaluator = criterionEvaluatorRegistry.get(criterion.type);
|
|
55732
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
55733
55970
|
const values = criterion.values
|
|
55734
55971
|
.slice(0, criterionEvaluator.numberOfValues(criterion))
|
|
55735
55972
|
.map((value) => value?.trim())
|
|
@@ -55737,8 +55974,8 @@ class DataValidationEditor extends owl.Component {
|
|
|
55737
55974
|
.map((value) => canonicalizeContent(value, locale));
|
|
55738
55975
|
rule.criterion = { ...criterion, values };
|
|
55739
55976
|
return {
|
|
55740
|
-
sheetId,
|
|
55741
|
-
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(
|
|
55977
|
+
sheetId: this.editingSheetId,
|
|
55978
|
+
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(this.editingSheetId, xc)),
|
|
55742
55979
|
rule,
|
|
55743
55980
|
};
|
|
55744
55981
|
}
|
|
@@ -60848,7 +61085,7 @@ class CellPlugin extends CorePlugin {
|
|
|
60848
61085
|
(typeof parsedValue === "number"
|
|
60849
61086
|
? detectDateFormat(content, locale) || detectNumberFormat(content)
|
|
60850
61087
|
: undefined);
|
|
60851
|
-
if (!isTextFormat(format) && !isEvaluationError(content)) {
|
|
61088
|
+
if (!isTextFormat(format) && !content.startsWith("'") && !isEvaluationError(content)) {
|
|
60852
61089
|
content = toString(parsedValue);
|
|
60853
61090
|
}
|
|
60854
61091
|
return {
|
|
@@ -66746,7 +66983,7 @@ class FormulaDependencyGraph {
|
|
|
66746
66983
|
* in the correct order they should be evaluated.
|
|
66747
66984
|
* This is called a topological ordering (excluding cycles)
|
|
66748
66985
|
*/
|
|
66749
|
-
getCellsDependingOn(ranges) {
|
|
66986
|
+
getCellsDependingOn(ranges, ignore) {
|
|
66750
66987
|
const visited = this.createEmptyPositionSet();
|
|
66751
66988
|
const queue = Array.from(ranges).reverse();
|
|
66752
66989
|
while (queue.length > 0) {
|
|
@@ -66761,7 +66998,7 @@ class FormulaDependencyGraph {
|
|
|
66761
66998
|
const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
|
|
66762
66999
|
const nextInQueue = {};
|
|
66763
67000
|
for (const position of impactedPositions) {
|
|
66764
|
-
if (!visited.has(position)) {
|
|
67001
|
+
if (!visited.has(position) && !ignore.has(position)) {
|
|
66765
67002
|
if (!nextInQueue[position.sheetId]) {
|
|
66766
67003
|
nextInQueue[position.sheetId] = [];
|
|
66767
67004
|
}
|
|
@@ -67319,7 +67556,7 @@ class Evaluator {
|
|
|
67319
67556
|
}
|
|
67320
67557
|
invalidatePositionsDependingOnSpread(sheetId, resultZone) {
|
|
67321
67558
|
// the result matrix is split in 2 zones to exclude the array formula position
|
|
67322
|
-
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
|
|
67559
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })), this.nextPositionsToUpdate);
|
|
67323
67560
|
invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
|
|
67324
67561
|
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
67325
67562
|
}
|
|
@@ -67437,7 +67674,7 @@ class Evaluator {
|
|
|
67437
67674
|
for (const sheetId in zonesBySheetIds) {
|
|
67438
67675
|
ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
|
|
67439
67676
|
}
|
|
67440
|
-
return this.formulaDependencies().getCellsDependingOn(ranges);
|
|
67677
|
+
return this.formulaDependencies().getCellsDependingOn(ranges, this.nextPositionsToUpdate);
|
|
67441
67678
|
}
|
|
67442
67679
|
}
|
|
67443
67680
|
function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
@@ -68704,32 +68941,6 @@ iconsOnCellRegistry.add("pivot_collapse", (getters, position) => {
|
|
|
68704
68941
|
}
|
|
68705
68942
|
return undefined;
|
|
68706
68943
|
});
|
|
68707
|
-
function togglePivotCollapse(position, env) {
|
|
68708
|
-
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
68709
|
-
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
68710
|
-
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
68711
|
-
return;
|
|
68712
|
-
}
|
|
68713
|
-
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
68714
|
-
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
68715
|
-
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
68716
|
-
: [];
|
|
68717
|
-
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
68718
|
-
if (index !== -1) {
|
|
68719
|
-
collapsedDomains.splice(index, 1);
|
|
68720
|
-
}
|
|
68721
|
-
else {
|
|
68722
|
-
collapsedDomains.push(pivotCell.domain);
|
|
68723
|
-
}
|
|
68724
|
-
const newDomains = definition.collapsedDomains
|
|
68725
|
-
? { ...definition.collapsedDomains }
|
|
68726
|
-
: { COL: [], ROW: [] };
|
|
68727
|
-
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
68728
|
-
env.model.dispatch("UPDATE_PIVOT", {
|
|
68729
|
-
pivotId,
|
|
68730
|
-
pivot: { ...definition, collapsedDomains: newDomains },
|
|
68731
|
-
});
|
|
68732
|
-
}
|
|
68733
68944
|
iconsOnCellRegistry.add("pivot_dashboard_sorting", (getters, position) => {
|
|
68734
68945
|
if (!getters.isDashboard()) {
|
|
68735
68946
|
return undefined;
|
|
@@ -68948,7 +69159,8 @@ class DynamicTablesPlugin extends CoreViewPlugin {
|
|
|
68948
69159
|
const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
|
|
68949
69160
|
const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
|
|
68950
69161
|
if (!parentSpreadingCell) {
|
|
68951
|
-
|
|
69162
|
+
const evaluatedCell = this.getters.getEvaluatedCell(topLeft);
|
|
69163
|
+
return (evaluatedCell.value === CellErrorType.SpilledBlocked && !evaluatedCell.errorOriginPosition);
|
|
68952
69164
|
}
|
|
68953
69165
|
else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
|
|
68954
69166
|
return true;
|
|
@@ -79814,6 +80026,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79814
80026
|
static components = { Menu };
|
|
79815
80027
|
rootItems = topbarMenuRegistry.getMenuItems();
|
|
79816
80028
|
menuRef = owl.useRef("menu");
|
|
80029
|
+
containerRef = owl.useRef("container");
|
|
79817
80030
|
state = owl.useState({
|
|
79818
80031
|
menuItems: this.rootItems,
|
|
79819
80032
|
title: _t("Menu Bar"),
|
|
@@ -79821,6 +80034,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79821
80034
|
});
|
|
79822
80035
|
setup() {
|
|
79823
80036
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
80037
|
+
owl.onMounted(this.updateShadows);
|
|
79824
80038
|
}
|
|
79825
80039
|
onExternalClick(ev) {
|
|
79826
80040
|
if (!this.menuRef.el?.contains(ev.target)) {
|
|
@@ -79833,6 +80047,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79833
80047
|
this.state.parentState = { ...this.state };
|
|
79834
80048
|
this.state.menuItems = children;
|
|
79835
80049
|
this.state.title = menu.name(this.env);
|
|
80050
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
79836
80051
|
}
|
|
79837
80052
|
else {
|
|
79838
80053
|
this.state.menuItems = this.rootItems;
|
|
@@ -79854,6 +80069,19 @@ class RibbonMenu extends owl.Component {
|
|
|
79854
80069
|
height: `${this.props.height}px`,
|
|
79855
80070
|
});
|
|
79856
80071
|
}
|
|
80072
|
+
updateShadows() {
|
|
80073
|
+
if (!this.containerRef.el) {
|
|
80074
|
+
return;
|
|
80075
|
+
}
|
|
80076
|
+
this.containerRef.el.classList.remove("scroll-top", "scroll-bottom");
|
|
80077
|
+
const maxScroll = this.containerRef.el.scrollHeight - this.containerRef.el.clientHeight || 0;
|
|
80078
|
+
if (this.containerRef.el.scrollTop < maxScroll - 1) {
|
|
80079
|
+
this.containerRef.el.classList.add("scroll-bottom");
|
|
80080
|
+
}
|
|
80081
|
+
if (this.containerRef.el.scrollTop > 0) {
|
|
80082
|
+
this.containerRef.el.classList.add("scroll-top");
|
|
80083
|
+
}
|
|
80084
|
+
}
|
|
79857
80085
|
onClickBack() {
|
|
79858
80086
|
if (!this.state.parentState) {
|
|
79859
80087
|
this.props.onClose();
|
|
@@ -79862,6 +80090,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79862
80090
|
this.state.menuItems = this.state.parentState.menuItems;
|
|
79863
80091
|
this.state.title = this.state.parentState.title;
|
|
79864
80092
|
this.state.parentState = this.state.parentState.parentState;
|
|
80093
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
79865
80094
|
}
|
|
79866
80095
|
get backTitle() {
|
|
79867
80096
|
return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
|
|
@@ -79913,7 +80142,9 @@ class SmallBottomBar extends owl.Component {
|
|
|
79913
80142
|
: "inactive";
|
|
79914
80143
|
}
|
|
79915
80144
|
get showFxIcon() {
|
|
79916
|
-
return this.focus === "inactive" &&
|
|
80145
|
+
return (this.focus === "inactive" &&
|
|
80146
|
+
!this.composerStore.currentContent &&
|
|
80147
|
+
!this.composerStore.placeholder);
|
|
79917
80148
|
}
|
|
79918
80149
|
get rect() {
|
|
79919
80150
|
return this.composerRef.el
|
|
@@ -79930,8 +80161,9 @@ class SmallBottomBar extends owl.Component {
|
|
|
79930
80161
|
},
|
|
79931
80162
|
focus: this.focus,
|
|
79932
80163
|
composerStore: this.composerStore,
|
|
79933
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
80164
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
79934
80165
|
focusMode: "contentFocus",
|
|
80166
|
+
selection,
|
|
79935
80167
|
}),
|
|
79936
80168
|
isDefaultFocus: false,
|
|
79937
80169
|
inputStyle: cssPropertiesToCss({
|
|
@@ -79939,6 +80171,7 @@ class SmallBottomBar extends owl.Component {
|
|
|
79939
80171
|
"max-height": `130px`,
|
|
79940
80172
|
}),
|
|
79941
80173
|
showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
|
|
80174
|
+
placeholder: this.composerStore.placeholder,
|
|
79942
80175
|
};
|
|
79943
80176
|
}
|
|
79944
80177
|
get symbols() {
|
|
@@ -79984,7 +80217,9 @@ class TopBarComposer extends owl.Component {
|
|
|
79984
80217
|
: "inactive";
|
|
79985
80218
|
}
|
|
79986
80219
|
get showFxIcon() {
|
|
79987
|
-
return this.focus === "inactive" &&
|
|
80220
|
+
return (this.focus === "inactive" &&
|
|
80221
|
+
!this.composerStore.currentContent &&
|
|
80222
|
+
!this.composerStore.placeholder);
|
|
79988
80223
|
}
|
|
79989
80224
|
get composerStyle() {
|
|
79990
80225
|
const style = {
|
|
@@ -85786,6 +86021,6 @@ exports.tokenColors = tokenColors;
|
|
|
85786
86021
|
exports.tokenize = tokenize;
|
|
85787
86022
|
|
|
85788
86023
|
|
|
85789
|
-
__info__.version = "19.1.0-alpha.
|
|
85790
|
-
__info__.date = "2025-10-
|
|
85791
|
-
__info__.hash = "
|
|
86024
|
+
__info__.version = "19.1.0-alpha.5";
|
|
86025
|
+
__info__.date = "2025-10-16T06:39:55.925Z";
|
|
86026
|
+
__info__.hash = "1a0e3d5";
|