@odoo/o-spreadsheet 18.1.0-alpha.0 → 18.1.0-alpha.1
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 +571 -358
- package/dist/o-spreadsheet.d.ts +40 -18
- package/dist/o-spreadsheet.esm.js +571 -358
- package/dist/o-spreadsheet.iife.js +571 -358
- package/dist/o-spreadsheet.iife.min.js +517 -519
- package/dist/o_spreadsheet.xml +154 -9
- package/package.json +12 -12
|
@@ -2,13 +2,119 @@
|
|
|
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.1.0-alpha.
|
|
6
|
-
* @date 2024-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.1.0-alpha.1
|
|
6
|
+
* @date 2024-10-14T07:53:17.717Z
|
|
7
|
+
* @hash e9ce3aa
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
11
11
|
|
|
12
|
+
function createActions(menuItems) {
|
|
13
|
+
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
14
|
+
}
|
|
15
|
+
let nextItemId = 1;
|
|
16
|
+
function createAction(item) {
|
|
17
|
+
const name = item.name;
|
|
18
|
+
const children = item.children;
|
|
19
|
+
const description = item.description;
|
|
20
|
+
const icon = item.icon;
|
|
21
|
+
const secondaryIcon = item.secondaryIcon;
|
|
22
|
+
const itemId = item.id || nextItemId++;
|
|
23
|
+
return {
|
|
24
|
+
id: itemId.toString(),
|
|
25
|
+
name: typeof name === "function" ? name : () => name,
|
|
26
|
+
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
27
|
+
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
28
|
+
isActive: item.isActive,
|
|
29
|
+
execute: item.execute,
|
|
30
|
+
children: children
|
|
31
|
+
? (env) => {
|
|
32
|
+
return children
|
|
33
|
+
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
34
|
+
.flat()
|
|
35
|
+
.map(createAction);
|
|
36
|
+
}
|
|
37
|
+
: () => [],
|
|
38
|
+
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
39
|
+
separator: item.separator || false,
|
|
40
|
+
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
41
|
+
iconColor: item.iconColor,
|
|
42
|
+
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
43
|
+
description: typeof description === "function" ? description : () => description || "",
|
|
44
|
+
textColor: item.textColor,
|
|
45
|
+
sequence: item.sequence || 0,
|
|
46
|
+
onStartHover: item.onStartHover,
|
|
47
|
+
onStopHover: item.onStopHover,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Registry
|
|
53
|
+
*
|
|
54
|
+
* The Registry class is basically just a mapping from a string key to an object.
|
|
55
|
+
* It is really not much more than an object. It is however useful for the
|
|
56
|
+
* following reasons:
|
|
57
|
+
*
|
|
58
|
+
* 1. it let us react and execute code when someone add something to the registry
|
|
59
|
+
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
60
|
+
* 2. it throws an error when the get operation fails
|
|
61
|
+
* 3. it provides a chained API to add items to the registry.
|
|
62
|
+
*/
|
|
63
|
+
class Registry {
|
|
64
|
+
content = {};
|
|
65
|
+
/**
|
|
66
|
+
* Add an item to the registry
|
|
67
|
+
*
|
|
68
|
+
* Note that this also returns the registry, so another add method call can
|
|
69
|
+
* be chained
|
|
70
|
+
*/
|
|
71
|
+
add(key, value) {
|
|
72
|
+
this.content[key] = value;
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get an item from the registry
|
|
77
|
+
*/
|
|
78
|
+
get(key) {
|
|
79
|
+
/**
|
|
80
|
+
* Note: key in {} is ~12 times slower than {}[key].
|
|
81
|
+
* So, we check the absence of key only when the direct access returns
|
|
82
|
+
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
83
|
+
*/
|
|
84
|
+
const content = this.content[key];
|
|
85
|
+
if (!content) {
|
|
86
|
+
if (!(key in this.content)) {
|
|
87
|
+
throw new Error(`Cannot find ${key} in this registry!`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return content;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if the key is already in the registry
|
|
94
|
+
*/
|
|
95
|
+
contains(key) {
|
|
96
|
+
return key in this.content;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get a list of all elements in the registry
|
|
100
|
+
*/
|
|
101
|
+
getAll() {
|
|
102
|
+
return Object.values(this.content);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get a list of all keys in the registry
|
|
106
|
+
*/
|
|
107
|
+
getKeys() {
|
|
108
|
+
return Object.keys(this.content);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Remove an item from the registry
|
|
112
|
+
*/
|
|
113
|
+
remove(key) {
|
|
114
|
+
delete this.content[key];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
12
118
|
const CANVAS_SHIFT = 0.5;
|
|
13
119
|
// Colors
|
|
14
120
|
const HIGHLIGHT_COLOR = "#37A850";
|
|
@@ -5968,18 +6074,9 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
|
|
|
5968
6074
|
* https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
5969
6075
|
* */
|
|
5970
6076
|
class UuidGenerator {
|
|
5971
|
-
isFastIdStrategy = false;
|
|
5972
|
-
fastIdStart = 0;
|
|
5973
|
-
setIsFastStrategy(isFast) {
|
|
5974
|
-
this.isFastIdStrategy = isFast;
|
|
5975
|
-
}
|
|
5976
6077
|
uuidv4() {
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
return String(this.fastIdStart);
|
|
5980
|
-
//@ts-ignore
|
|
5981
|
-
}
|
|
5982
|
-
else if (window.crypto && window.crypto.getRandomValues) {
|
|
6078
|
+
//@ts-ignore
|
|
6079
|
+
if (window.crypto && window.crypto.getRandomValues) {
|
|
5983
6080
|
//@ts-ignore
|
|
5984
6081
|
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
|
|
5985
6082
|
}
|
|
@@ -5993,111 +6090,6 @@ class UuidGenerator {
|
|
|
5993
6090
|
}
|
|
5994
6091
|
}
|
|
5995
6092
|
|
|
5996
|
-
function createActions(menuItems) {
|
|
5997
|
-
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
5998
|
-
}
|
|
5999
|
-
const uuidGenerator$1 = new UuidGenerator();
|
|
6000
|
-
function createAction(item) {
|
|
6001
|
-
const name = item.name;
|
|
6002
|
-
const children = item.children;
|
|
6003
|
-
const description = item.description;
|
|
6004
|
-
const icon = item.icon;
|
|
6005
|
-
const secondaryIcon = item.secondaryIcon;
|
|
6006
|
-
return {
|
|
6007
|
-
id: item.id || uuidGenerator$1.uuidv4(),
|
|
6008
|
-
name: typeof name === "function" ? name : () => name,
|
|
6009
|
-
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
6010
|
-
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
6011
|
-
isActive: item.isActive,
|
|
6012
|
-
execute: item.execute,
|
|
6013
|
-
children: children
|
|
6014
|
-
? (env) => {
|
|
6015
|
-
return children
|
|
6016
|
-
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
6017
|
-
.flat()
|
|
6018
|
-
.map(createAction);
|
|
6019
|
-
}
|
|
6020
|
-
: () => [],
|
|
6021
|
-
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
6022
|
-
separator: item.separator || false,
|
|
6023
|
-
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
6024
|
-
iconColor: item.iconColor,
|
|
6025
|
-
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
6026
|
-
description: typeof description === "function" ? description : () => description || "",
|
|
6027
|
-
textColor: item.textColor,
|
|
6028
|
-
sequence: item.sequence || 0,
|
|
6029
|
-
onStartHover: item.onStartHover,
|
|
6030
|
-
onStopHover: item.onStopHover,
|
|
6031
|
-
};
|
|
6032
|
-
}
|
|
6033
|
-
|
|
6034
|
-
/**
|
|
6035
|
-
* Registry
|
|
6036
|
-
*
|
|
6037
|
-
* The Registry class is basically just a mapping from a string key to an object.
|
|
6038
|
-
* It is really not much more than an object. It is however useful for the
|
|
6039
|
-
* following reasons:
|
|
6040
|
-
*
|
|
6041
|
-
* 1. it let us react and execute code when someone add something to the registry
|
|
6042
|
-
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
6043
|
-
* 2. it throws an error when the get operation fails
|
|
6044
|
-
* 3. it provides a chained API to add items to the registry.
|
|
6045
|
-
*/
|
|
6046
|
-
class Registry {
|
|
6047
|
-
content = {};
|
|
6048
|
-
/**
|
|
6049
|
-
* Add an item to the registry
|
|
6050
|
-
*
|
|
6051
|
-
* Note that this also returns the registry, so another add method call can
|
|
6052
|
-
* be chained
|
|
6053
|
-
*/
|
|
6054
|
-
add(key, value) {
|
|
6055
|
-
this.content[key] = value;
|
|
6056
|
-
return this;
|
|
6057
|
-
}
|
|
6058
|
-
/**
|
|
6059
|
-
* Get an item from the registry
|
|
6060
|
-
*/
|
|
6061
|
-
get(key) {
|
|
6062
|
-
/**
|
|
6063
|
-
* Note: key in {} is ~12 times slower than {}[key].
|
|
6064
|
-
* So, we check the absence of key only when the direct access returns
|
|
6065
|
-
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
6066
|
-
*/
|
|
6067
|
-
const content = this.content[key];
|
|
6068
|
-
if (!content) {
|
|
6069
|
-
if (!(key in this.content)) {
|
|
6070
|
-
throw new Error(`Cannot find ${key} in this registry!`);
|
|
6071
|
-
}
|
|
6072
|
-
}
|
|
6073
|
-
return content;
|
|
6074
|
-
}
|
|
6075
|
-
/**
|
|
6076
|
-
* Check if the key is already in the registry
|
|
6077
|
-
*/
|
|
6078
|
-
contains(key) {
|
|
6079
|
-
return key in this.content;
|
|
6080
|
-
}
|
|
6081
|
-
/**
|
|
6082
|
-
* Get a list of all elements in the registry
|
|
6083
|
-
*/
|
|
6084
|
-
getAll() {
|
|
6085
|
-
return Object.values(this.content);
|
|
6086
|
-
}
|
|
6087
|
-
/**
|
|
6088
|
-
* Get a list of all keys in the registry
|
|
6089
|
-
*/
|
|
6090
|
-
getKeys() {
|
|
6091
|
-
return Object.keys(this.content);
|
|
6092
|
-
}
|
|
6093
|
-
/**
|
|
6094
|
-
* Remove an item from the registry
|
|
6095
|
-
*/
|
|
6096
|
-
remove(key) {
|
|
6097
|
-
delete this.content[key];
|
|
6098
|
-
}
|
|
6099
|
-
}
|
|
6100
|
-
|
|
6101
6093
|
function getClipboardDataPositions(sheetId, zones) {
|
|
6102
6094
|
const lefts = new Set(zones.map((z) => z.left));
|
|
6103
6095
|
const rights = new Set(zones.map((z) => z.right));
|
|
@@ -8452,31 +8444,34 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8452
8444
|
for (let col of columnsIndexes) {
|
|
8453
8445
|
const position = { col, row, sheetId };
|
|
8454
8446
|
const table = this.getters.getTable(position);
|
|
8455
|
-
if (!table
|
|
8447
|
+
if (!table) {
|
|
8456
8448
|
tableCellsInRow.push({});
|
|
8457
8449
|
continue;
|
|
8458
8450
|
}
|
|
8459
8451
|
const coreTable = this.getters.getCoreTable(position);
|
|
8460
8452
|
const tableZone = coreTable?.range.zone;
|
|
8453
|
+
let copiedTable = undefined;
|
|
8461
8454
|
// Copy whole table
|
|
8462
|
-
if (
|
|
8463
|
-
|
|
8455
|
+
if (!copiedTablesIds.has(table.id) &&
|
|
8456
|
+
coreTable &&
|
|
8457
|
+
tableZone &&
|
|
8458
|
+
zones.some((z) => isZoneInside(tableZone, z))) {
|
|
8459
|
+
copiedTablesIds.add(table.id);
|
|
8464
8460
|
const values = [];
|
|
8465
8461
|
for (const col of range(tableZone.left, tableZone.right + 1)) {
|
|
8466
8462
|
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
|
|
8467
8463
|
}
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
},
|
|
8474
|
-
});
|
|
8475
|
-
}
|
|
8476
|
-
// Copy only style of cell
|
|
8477
|
-
else if (table) {
|
|
8478
|
-
tableCellsInRow.push({ style: this.getTableStyleToCopy(position) });
|
|
8464
|
+
copiedTable = {
|
|
8465
|
+
range: coreTable.range.rangeData,
|
|
8466
|
+
config: coreTable.config,
|
|
8467
|
+
type: coreTable.type,
|
|
8468
|
+
};
|
|
8479
8469
|
}
|
|
8470
|
+
tableCellsInRow.push({
|
|
8471
|
+
table: copiedTable,
|
|
8472
|
+
style: this.getTableStyleToCopy(position),
|
|
8473
|
+
isWholeTableCopied: copiedTablesIds.has(table.id),
|
|
8474
|
+
});
|
|
8480
8475
|
}
|
|
8481
8476
|
}
|
|
8482
8477
|
return {
|
|
@@ -8557,11 +8552,14 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8557
8552
|
tableType: tableCell.table.type,
|
|
8558
8553
|
});
|
|
8559
8554
|
}
|
|
8560
|
-
// Do not paste table style if we're inside another table
|
|
8561
8555
|
// We cannot check for dynamic tables, because at this point the paste can have changed the evaluation, and the
|
|
8562
8556
|
// dynamic tables are not yet computed
|
|
8563
|
-
if (
|
|
8564
|
-
|
|
8557
|
+
if (this.getters.getCoreTable(position) || options?.pasteOption === "asValue") {
|
|
8558
|
+
return;
|
|
8559
|
+
}
|
|
8560
|
+
if ((!options?.pasteOption && !tableCell.isWholeTableCopied) ||
|
|
8561
|
+
options?.pasteOption === "onlyFormat") {
|
|
8562
|
+
if (tableCell.style?.style) {
|
|
8565
8563
|
this.dispatch("UPDATE_CELL", { ...position, style: tableCell.style.style });
|
|
8566
8564
|
}
|
|
8567
8565
|
if (tableCell.style?.border) {
|
|
@@ -9281,6 +9279,49 @@ function getDefinedAxis(definition) {
|
|
|
9281
9279
|
useLeftAxis ||= !useRightAxis;
|
|
9282
9280
|
return { useLeftAxis, useRightAxis };
|
|
9283
9281
|
}
|
|
9282
|
+
function getChartAxis(definition, position, type, options) {
|
|
9283
|
+
const { useLeftAxis, useRightAxis } = getDefinedAxis(definition);
|
|
9284
|
+
if ((position === "left" && !useLeftAxis) || (position === "right" && !useRightAxis)) {
|
|
9285
|
+
return undefined;
|
|
9286
|
+
}
|
|
9287
|
+
const fontColor = chartFontColor(definition.background);
|
|
9288
|
+
let design;
|
|
9289
|
+
if (position === "bottom") {
|
|
9290
|
+
design = definition.axesDesign?.x;
|
|
9291
|
+
}
|
|
9292
|
+
else if (position === "left") {
|
|
9293
|
+
design = definition.axesDesign?.y;
|
|
9294
|
+
}
|
|
9295
|
+
else {
|
|
9296
|
+
design = definition.axesDesign?.y1;
|
|
9297
|
+
}
|
|
9298
|
+
if (type === "values") {
|
|
9299
|
+
const displayGridLines = position === "left" || (position === "right" && !useLeftAxis);
|
|
9300
|
+
return {
|
|
9301
|
+
position: position,
|
|
9302
|
+
title: getChartAxisTitleRuntime(design),
|
|
9303
|
+
grid: {
|
|
9304
|
+
display: displayGridLines,
|
|
9305
|
+
},
|
|
9306
|
+
beginAtZero: true,
|
|
9307
|
+
stacked: options?.stacked,
|
|
9308
|
+
ticks: {
|
|
9309
|
+
color: fontColor,
|
|
9310
|
+
callback: formatTickValue(options),
|
|
9311
|
+
},
|
|
9312
|
+
};
|
|
9313
|
+
}
|
|
9314
|
+
else {
|
|
9315
|
+
return {
|
|
9316
|
+
ticks: {
|
|
9317
|
+
padding: 5,
|
|
9318
|
+
color: fontColor,
|
|
9319
|
+
},
|
|
9320
|
+
stacked: options?.stacked,
|
|
9321
|
+
title: getChartAxisTitleRuntime(design),
|
|
9322
|
+
};
|
|
9323
|
+
}
|
|
9324
|
+
}
|
|
9284
9325
|
function computeChartPadding({ displayTitle, displayLegend, }) {
|
|
9285
9326
|
let top = 25;
|
|
9286
9327
|
if (displayTitle) {
|
|
@@ -9367,6 +9408,12 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
9367
9408
|
return [];
|
|
9368
9409
|
}
|
|
9369
9410
|
}
|
|
9411
|
+
function formatChartDatasetValue(axisFormats, locale) {
|
|
9412
|
+
return (value, axisId) => {
|
|
9413
|
+
const format = axisId ? axisFormats?.[axisId] : undefined;
|
|
9414
|
+
return formatTickValue({ format, locale })(value);
|
|
9415
|
+
};
|
|
9416
|
+
}
|
|
9370
9417
|
function formatTickValue(localeFormat) {
|
|
9371
9418
|
return (value) => {
|
|
9372
9419
|
value = Number(value);
|
|
@@ -9429,10 +9476,12 @@ const chartShowValuesPlugin = {
|
|
|
9429
9476
|
case "bar":
|
|
9430
9477
|
case "line": {
|
|
9431
9478
|
const yOffset = dataset.type === "bar" && !options.horizontal ? 0 : 3;
|
|
9479
|
+
const horizontalChart = dataset.type === "bar" && options.horizontal;
|
|
9480
|
+
const axisId = horizontalChart ? dataset.xAxisID : dataset.yAxisID;
|
|
9432
9481
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9433
9482
|
const point = dataset.data[i];
|
|
9434
9483
|
const value = options.horizontal ? dataset._parsed[i].x : dataset._parsed[i].y;
|
|
9435
|
-
const displayedValue = options.callback(value - 0);
|
|
9484
|
+
const displayedValue = options.callback(value - 0, axisId);
|
|
9436
9485
|
let xPosition = 0, yPosition = 0;
|
|
9437
9486
|
if (options.horizontal) {
|
|
9438
9487
|
yPosition = point.y;
|
|
@@ -17841,7 +17890,7 @@ function assertDomainLength(domain) {
|
|
|
17841
17890
|
throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
|
|
17842
17891
|
}
|
|
17843
17892
|
}
|
|
17844
|
-
function addPivotDependencies(evalContext, coreDefinition) {
|
|
17893
|
+
function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
|
|
17845
17894
|
//TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
|
|
17846
17895
|
const dependencies = [];
|
|
17847
17896
|
if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
|
|
@@ -17853,7 +17902,7 @@ function addPivotDependencies(evalContext, coreDefinition) {
|
|
|
17853
17902
|
}
|
|
17854
17903
|
dependencies.push(range);
|
|
17855
17904
|
}
|
|
17856
|
-
for (const measure of
|
|
17905
|
+
for (const measure of forMeasures) {
|
|
17857
17906
|
if (measure.computedBy) {
|
|
17858
17907
|
const formula = evalContext.getters.getMeasureCompiledFormula(measure);
|
|
17859
17908
|
dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
@@ -18286,7 +18335,7 @@ const PIVOT_VALUE = {
|
|
|
18286
18335
|
assertDomainLength(domainArgs);
|
|
18287
18336
|
const pivot = this.getters.getPivot(pivotId);
|
|
18288
18337
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18289
|
-
addPivotDependencies(this, coreDefinition);
|
|
18338
|
+
addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
|
|
18290
18339
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18291
18340
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
18292
18341
|
if (error) {
|
|
@@ -18316,7 +18365,7 @@ const PIVOT_HEADER = {
|
|
|
18316
18365
|
assertDomainLength(domainArgs);
|
|
18317
18366
|
const pivot = this.getters.getPivot(_pivotId);
|
|
18318
18367
|
const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
|
|
18319
|
-
addPivotDependencies(this, coreDefinition);
|
|
18368
|
+
addPivotDependencies(this, coreDefinition, []);
|
|
18320
18369
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18321
18370
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
18322
18371
|
if (error) {
|
|
@@ -18367,7 +18416,7 @@ const PIVOT = {
|
|
|
18367
18416
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18368
18417
|
const pivot = this.getters.getPivot(pivotId);
|
|
18369
18418
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18370
|
-
addPivotDependencies(this, coreDefinition);
|
|
18419
|
+
addPivotDependencies(this, coreDefinition, coreDefinition.measures);
|
|
18371
18420
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18372
18421
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
18373
18422
|
if (error) {
|
|
@@ -20163,7 +20212,7 @@ class ContentEditableHelper {
|
|
|
20163
20212
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
20164
20213
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
20165
20214
|
range.setStart(startNode.node, startNode.offset);
|
|
20166
|
-
|
|
20215
|
+
range.setEnd(endNode.node, endNode.offset);
|
|
20167
20216
|
}
|
|
20168
20217
|
}
|
|
20169
20218
|
/**
|
|
@@ -20661,7 +20710,7 @@ class Composer extends Component {
|
|
|
20661
20710
|
"Alt+Enter": this.processNewLineEvent,
|
|
20662
20711
|
"Ctrl+Enter": this.processNewLineEvent,
|
|
20663
20712
|
Escape: this.processEscapeKey,
|
|
20664
|
-
F2: () =>
|
|
20713
|
+
F2: (ev) => this.toggleEditionMode(ev),
|
|
20665
20714
|
F4: (ev) => this.processF4Key(ev),
|
|
20666
20715
|
Tab: (ev) => this.processTabKey(ev, "right"),
|
|
20667
20716
|
"Shift+Tab": (ev) => this.processTabKey(ev, "left"),
|
|
@@ -20780,6 +20829,11 @@ class Composer extends Component {
|
|
|
20780
20829
|
this.props.composerStore.cycleReferences();
|
|
20781
20830
|
this.processContent();
|
|
20782
20831
|
}
|
|
20832
|
+
toggleEditionMode(ev) {
|
|
20833
|
+
ev.stopPropagation();
|
|
20834
|
+
this.props.composerStore.toggleEditionMode();
|
|
20835
|
+
this.processContent();
|
|
20836
|
+
}
|
|
20783
20837
|
processNumpadDecimal(ev) {
|
|
20784
20838
|
ev.stopPropagation();
|
|
20785
20839
|
ev.preventDefault();
|
|
@@ -21005,7 +21059,13 @@ class Composer extends Component {
|
|
|
21005
21059
|
break;
|
|
21006
21060
|
case "REFERENCE":
|
|
21007
21061
|
const { xc, sheetName } = splitReference(token.value);
|
|
21008
|
-
result.push({
|
|
21062
|
+
result.push({
|
|
21063
|
+
value: token.value,
|
|
21064
|
+
color: this.rangeColor(xc, sheetName) || "#000",
|
|
21065
|
+
class: tokenAtCursor === token && this.props.composerStore.editionMode === "selecting"
|
|
21066
|
+
? "text-decoration-underline"
|
|
21067
|
+
: undefined,
|
|
21068
|
+
});
|
|
21009
21069
|
break;
|
|
21010
21070
|
case "SYMBOL":
|
|
21011
21071
|
const value = token.value;
|
|
@@ -21576,6 +21636,7 @@ function insertTokenAfterArgSeparator(tokenAtCursor, value) {
|
|
|
21576
21636
|
// replace the whole token
|
|
21577
21637
|
start = tokenAtCursor.start;
|
|
21578
21638
|
}
|
|
21639
|
+
this.composer.stopComposerRangeSelection();
|
|
21579
21640
|
this.composer.changeComposerCursorSelection(start, end);
|
|
21580
21641
|
this.composer.replaceComposerCursorSelection(value);
|
|
21581
21642
|
}
|
|
@@ -21593,6 +21654,7 @@ function insertTokenAfterLeftParenthesis(tokenAtCursor, value) {
|
|
|
21593
21654
|
// replace the whole token
|
|
21594
21655
|
start = tokenAtCursor.start;
|
|
21595
21656
|
}
|
|
21657
|
+
this.composer.stopComposerRangeSelection();
|
|
21596
21658
|
this.composer.changeComposerCursorSelection(start, end);
|
|
21597
21659
|
this.composer.replaceComposerCursorSelection(value);
|
|
21598
21660
|
}
|
|
@@ -22185,6 +22247,27 @@ autofillModifiersRegistry
|
|
|
22185
22247
|
tooltip: content ? { props: { content: tooltipValue } } : undefined,
|
|
22186
22248
|
};
|
|
22187
22249
|
},
|
|
22250
|
+
})
|
|
22251
|
+
.add("DATE_INCREMENT_MODIFIER", {
|
|
22252
|
+
apply: (rule, data, getters) => {
|
|
22253
|
+
const date = toJsDate(rule.current, getters.getLocale());
|
|
22254
|
+
date.setFullYear(date.getFullYear() + rule.increment.years || 0);
|
|
22255
|
+
date.setMonth(date.getMonth() + rule.increment.months || 0);
|
|
22256
|
+
date.setDate(date.getDate() + rule.increment.days || 0);
|
|
22257
|
+
const value = jsDateToNumber(date);
|
|
22258
|
+
rule.current = value;
|
|
22259
|
+
const locale = getters.getLocale();
|
|
22260
|
+
const tooltipValue = formatValue(value, { format: data.cell?.format, locale });
|
|
22261
|
+
return {
|
|
22262
|
+
cellData: {
|
|
22263
|
+
border: data.border,
|
|
22264
|
+
style: data.cell && data.cell.style,
|
|
22265
|
+
format: data.cell && data.cell.format,
|
|
22266
|
+
content: value.toString(),
|
|
22267
|
+
},
|
|
22268
|
+
tooltip: value ? { props: { content: tooltipValue } } : undefined,
|
|
22269
|
+
};
|
|
22270
|
+
},
|
|
22188
22271
|
})
|
|
22189
22272
|
.add("COPY_MODIFIER", {
|
|
22190
22273
|
apply: (rule, data, getters) => {
|
|
@@ -22265,7 +22348,9 @@ function getGroup(cell, cells, filter) {
|
|
|
22265
22348
|
if (x === cell) {
|
|
22266
22349
|
found = true;
|
|
22267
22350
|
}
|
|
22268
|
-
const cellValue = x === undefined || x.isFormula
|
|
22351
|
+
const cellValue = x === undefined || x.isFormula
|
|
22352
|
+
? undefined
|
|
22353
|
+
: evaluateLiteral(x, { locale: DEFAULT_LOCALE, format: x.format });
|
|
22269
22354
|
if (cellValue && filter(cellValue)) {
|
|
22270
22355
|
group.push(cellValue);
|
|
22271
22356
|
}
|
|
@@ -22301,6 +22386,72 @@ function calculateIncrementBasedOnGroup(group) {
|
|
|
22301
22386
|
}
|
|
22302
22387
|
return increment;
|
|
22303
22388
|
}
|
|
22389
|
+
/**
|
|
22390
|
+
* Iterates on a list of date intervals.
|
|
22391
|
+
* if every interval is the same, return the interval
|
|
22392
|
+
* Otherwise return undefined
|
|
22393
|
+
*
|
|
22394
|
+
*/
|
|
22395
|
+
function getEqualInterval(intervals) {
|
|
22396
|
+
if (intervals.length < 2) {
|
|
22397
|
+
return intervals[0] || { years: 0, months: 0, days: 0 };
|
|
22398
|
+
}
|
|
22399
|
+
const equal = intervals.every((interval) => interval.years === intervals[0].years &&
|
|
22400
|
+
interval.months === intervals[0].months &&
|
|
22401
|
+
interval.days === intervals[0].days);
|
|
22402
|
+
return equal ? intervals[0] : undefined;
|
|
22403
|
+
}
|
|
22404
|
+
/**
|
|
22405
|
+
* Based on a group of dates, calculate the increment that should be applied
|
|
22406
|
+
* to the next date.
|
|
22407
|
+
*
|
|
22408
|
+
* This will compute the date difference in calendar terms (years, months, days)
|
|
22409
|
+
* In order to make abstraction of leap years and months with different number of days.
|
|
22410
|
+
*
|
|
22411
|
+
* In case the dates are not equidistant in calendar terms, no rule can be extrapolated
|
|
22412
|
+
* In case of equidistant dates, we either have in that order:
|
|
22413
|
+
* - exact date interval (e.g. +n year OR +n month OR +n day) in which case we increment by the same interval
|
|
22414
|
+
* - exact day interval (e.g. +n days) in which case we increment by the same day interval
|
|
22415
|
+
* - equidistant dates but not the same interval, in which case we return increment of the same interval
|
|
22416
|
+
*
|
|
22417
|
+
* */
|
|
22418
|
+
function calculateDateIncrementBasedOnGroup(group) {
|
|
22419
|
+
if (group.length < 2) {
|
|
22420
|
+
return 1;
|
|
22421
|
+
}
|
|
22422
|
+
const jsDates = group.map((date) => toJsDate(date, DEFAULT_LOCALE));
|
|
22423
|
+
const datesIntervals = getDateIntervals(jsDates);
|
|
22424
|
+
const datesEquidistantInterval = getEqualInterval(datesIntervals);
|
|
22425
|
+
if (datesEquidistantInterval === undefined) {
|
|
22426
|
+
// dates are not equidistant in terms of years, months or days, thus no rule can be extrapolated
|
|
22427
|
+
return undefined;
|
|
22428
|
+
}
|
|
22429
|
+
// The dates are apart by an exact interval of years, months or days
|
|
22430
|
+
// but not a combination of them
|
|
22431
|
+
const exactDateInterval = Object.values(datesEquidistantInterval).filter((value) => value !== 0).length === 1;
|
|
22432
|
+
const isSameDay = Object.values(datesEquidistantInterval).every((el) => el === 0); // handles time values (strict decimals)
|
|
22433
|
+
if (!exactDateInterval || isSameDay) {
|
|
22434
|
+
const timeIntervals = jsDates
|
|
22435
|
+
.map((date, index) => {
|
|
22436
|
+
if (index === 0) {
|
|
22437
|
+
return 0;
|
|
22438
|
+
}
|
|
22439
|
+
const previous = jsDates[index - 1];
|
|
22440
|
+
const days = Math.floor(date.getTime()) - Math.floor(previous.getTime());
|
|
22441
|
+
return days;
|
|
22442
|
+
})
|
|
22443
|
+
.slice(1);
|
|
22444
|
+
const equidistantDates = timeIntervals.every((interval) => interval === timeIntervals[0]);
|
|
22445
|
+
if (equidistantDates) {
|
|
22446
|
+
return group.length * (group[1] - group[0]);
|
|
22447
|
+
}
|
|
22448
|
+
}
|
|
22449
|
+
return {
|
|
22450
|
+
years: datesEquidistantInterval.years * group.length,
|
|
22451
|
+
months: datesEquidistantInterval.months * group.length,
|
|
22452
|
+
days: datesEquidistantInterval.days * group.length,
|
|
22453
|
+
};
|
|
22454
|
+
}
|
|
22304
22455
|
autofillRulesRegistry
|
|
22305
22456
|
.add("simple_value_copy", {
|
|
22306
22457
|
condition: (cell, cells) => {
|
|
@@ -22348,12 +22499,47 @@ autofillRulesRegistry
|
|
|
22348
22499
|
return { type: "FORMULA_MODIFIER", increment: cells.length, current: 0 };
|
|
22349
22500
|
},
|
|
22350
22501
|
sequence: 30,
|
|
22502
|
+
})
|
|
22503
|
+
.add("increment_dates", {
|
|
22504
|
+
condition: (cell, cells) => {
|
|
22505
|
+
return (!cell.isFormula &&
|
|
22506
|
+
evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.number &&
|
|
22507
|
+
!!cell.format &&
|
|
22508
|
+
isDateTimeFormat(cell.format));
|
|
22509
|
+
},
|
|
22510
|
+
generateRule: (cell, cells) => {
|
|
22511
|
+
const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number &&
|
|
22512
|
+
!!evaluatedCell.format &&
|
|
22513
|
+
isDateTimeFormat(evaluatedCell.format)).map((cell) => Number(cell.value));
|
|
22514
|
+
const increment = calculateDateIncrementBasedOnGroup(group);
|
|
22515
|
+
if (increment === undefined) {
|
|
22516
|
+
return { type: "COPY_MODIFIER" };
|
|
22517
|
+
}
|
|
22518
|
+
/** requires to detect the current date (requires to be an integer value with the right format)
|
|
22519
|
+
* detect if year or if month or if day then extrapolate increment required (+1 month, +1 year + 1 day)
|
|
22520
|
+
*/
|
|
22521
|
+
const evaluation = evaluateLiteral(cell, { locale: DEFAULT_LOCALE });
|
|
22522
|
+
if (typeof increment === "object") {
|
|
22523
|
+
return {
|
|
22524
|
+
type: "DATE_INCREMENT_MODIFIER",
|
|
22525
|
+
increment,
|
|
22526
|
+
current: evaluation.type === CellValueType.number ? evaluation.value : 0,
|
|
22527
|
+
};
|
|
22528
|
+
}
|
|
22529
|
+
return {
|
|
22530
|
+
type: "INCREMENT_MODIFIER",
|
|
22531
|
+
increment,
|
|
22532
|
+
current: evaluation.type === CellValueType.number ? evaluation.value : 0,
|
|
22533
|
+
};
|
|
22534
|
+
},
|
|
22535
|
+
sequence: 25,
|
|
22351
22536
|
})
|
|
22352
22537
|
.add("increment_number", {
|
|
22353
22538
|
condition: (cell) => !cell.isFormula &&
|
|
22354
22539
|
evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.number,
|
|
22355
22540
|
generateRule: (cell, cells) => {
|
|
22356
|
-
const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number
|
|
22541
|
+
const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number &&
|
|
22542
|
+
!isDateTimeFormat(evaluatedCell.format || "")).map((cell) => Number(cell.value));
|
|
22357
22543
|
const increment = calculateIncrementBasedOnGroup(group);
|
|
22358
22544
|
const evaluation = evaluateLiteral(cell, { locale: DEFAULT_LOCALE });
|
|
22359
22545
|
return {
|
|
@@ -22364,6 +22550,37 @@ autofillRulesRegistry
|
|
|
22364
22550
|
},
|
|
22365
22551
|
sequence: 40,
|
|
22366
22552
|
});
|
|
22553
|
+
/**
|
|
22554
|
+
* Returns the date intervals between consecutive dates of an array
|
|
22555
|
+
* in the format of { years: number, months: number, days: number }
|
|
22556
|
+
*
|
|
22557
|
+
* The split is necessary to make abstraction of leap years and
|
|
22558
|
+
* months with different number of days.
|
|
22559
|
+
*
|
|
22560
|
+
* @param dates
|
|
22561
|
+
*/
|
|
22562
|
+
function getDateIntervals(dates) {
|
|
22563
|
+
if (dates.length < 2) {
|
|
22564
|
+
return [{ years: 0, months: 0, days: 0 }];
|
|
22565
|
+
}
|
|
22566
|
+
const res = dates.map((date, index) => {
|
|
22567
|
+
if (index === 0) {
|
|
22568
|
+
return { years: 0, months: 0, days: 0 };
|
|
22569
|
+
}
|
|
22570
|
+
const previous = DateTime.fromTimestamp(dates[index - 1].getTime());
|
|
22571
|
+
const years = getTimeDifferenceInWholeYears(previous, date);
|
|
22572
|
+
const months = getTimeDifferenceInWholeMonths(previous, date) % 12;
|
|
22573
|
+
previous.setFullYear(previous.getFullYear() + years);
|
|
22574
|
+
previous.setMonth(previous.getMonth() + months);
|
|
22575
|
+
const days = getTimeDifferenceInWholeDays(previous, date);
|
|
22576
|
+
return {
|
|
22577
|
+
years,
|
|
22578
|
+
months,
|
|
22579
|
+
days,
|
|
22580
|
+
};
|
|
22581
|
+
});
|
|
22582
|
+
return res.slice(1);
|
|
22583
|
+
}
|
|
22367
22584
|
|
|
22368
22585
|
const cellPopoverRegistry = new Registry();
|
|
22369
22586
|
|
|
@@ -27874,9 +28091,9 @@ function truncateLabel(label) {
|
|
|
27874
28091
|
/**
|
|
27875
28092
|
* Get a default chart js configuration
|
|
27876
28093
|
*/
|
|
27877
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, {
|
|
28094
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { axisFormats, locale, truncateLabels = true, horizontalChart }) {
|
|
27878
28095
|
const chartTitle = chart.title.text ? chart.title : { ...chart.title, content: "" };
|
|
27879
|
-
const
|
|
28096
|
+
const chartOptions = {
|
|
27880
28097
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
27881
28098
|
responsive: true, // will resize when its container is resized
|
|
27882
28099
|
maintainAspectRatio: false, // doesn't maintain the aspect ration (width/height =2 by default) so the user has the choice of the exact layout
|
|
@@ -27923,8 +28140,10 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
|
|
|
27923
28140
|
if (!yLabel) {
|
|
27924
28141
|
yLabel = tooltipItem.parsed;
|
|
27925
28142
|
}
|
|
27926
|
-
const
|
|
27927
|
-
|
|
28143
|
+
const axisId = horizontalChart
|
|
28144
|
+
? tooltipItem.dataset.xAxisID
|
|
28145
|
+
: tooltipItem.dataset.yAxisID;
|
|
28146
|
+
const yLabelStr = formatChartDatasetValue(axisFormats, locale)(yLabel, axisId);
|
|
27928
28147
|
return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
|
|
27929
28148
|
},
|
|
27930
28149
|
},
|
|
@@ -27933,7 +28152,7 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
|
|
|
27933
28152
|
};
|
|
27934
28153
|
return {
|
|
27935
28154
|
type: chart.type,
|
|
27936
|
-
options,
|
|
28155
|
+
options: chartOptions,
|
|
27937
28156
|
data: {
|
|
27938
28157
|
labels: truncateLabels ? labels.map(truncateLabel) : labels,
|
|
27939
28158
|
datasets: [],
|
|
@@ -27992,7 +28211,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
|
|
|
27992
28211
|
* Get the format to apply to the the dataset values. This format is defined as the first format
|
|
27993
28212
|
* found in the dataset ranges that isn't a date format.
|
|
27994
28213
|
*/
|
|
27995
|
-
function getChartDatasetFormat(getters,
|
|
28214
|
+
function getChartDatasetFormat(getters, allDataSets, axis) {
|
|
28215
|
+
const dataSets = allDataSets.filter((ds) => (axis === "right") === !!ds.rightYAxis);
|
|
27996
28216
|
for (const ds of dataSets) {
|
|
27997
28217
|
const formatsInDataset = getters.getRangeFormats(ds.dataRange);
|
|
27998
28218
|
const format = formatsInDataset.find((f) => f !== undefined && !isDateTimeFormat(f));
|
|
@@ -28246,12 +28466,16 @@ function createBarChartRuntime(chart, getters) {
|
|
|
28246
28466
|
if (chart.aggregated) {
|
|
28247
28467
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
28248
28468
|
}
|
|
28249
|
-
const
|
|
28469
|
+
const leftAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
28470
|
+
const rightAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
28250
28471
|
const locale = getters.getLocale();
|
|
28251
|
-
const localeFormat = { format: dataSetFormat, locale };
|
|
28252
28472
|
const fontColor = chartFontColor(chart.background);
|
|
28473
|
+
const axisFormats = chart.horizontal
|
|
28474
|
+
? { x: leftAxisFormat || rightAxisFormat }
|
|
28475
|
+
: { y: leftAxisFormat, y1: rightAxisFormat };
|
|
28253
28476
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, {
|
|
28254
|
-
|
|
28477
|
+
locale,
|
|
28478
|
+
axisFormats,
|
|
28255
28479
|
horizontalChart: chart.horizontal,
|
|
28256
28480
|
});
|
|
28257
28481
|
const legend = {
|
|
@@ -28272,51 +28496,27 @@ function createBarChartRuntime(chart, getters) {
|
|
|
28272
28496
|
};
|
|
28273
28497
|
config.options.indexAxis = chart.horizontal ? "y" : "x";
|
|
28274
28498
|
config.options.scales = {};
|
|
28275
|
-
const
|
|
28276
|
-
const
|
|
28277
|
-
|
|
28278
|
-
|
|
28279
|
-
|
|
28280
|
-
|
|
28281
|
-
},
|
|
28282
|
-
};
|
|
28283
|
-
const xAxis = chart.horizontal ? valuesAxis : labelsAxis;
|
|
28284
|
-
const yAxis = chart.horizontal ? labelsAxis : valuesAxis;
|
|
28285
|
-
const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition());
|
|
28286
|
-
config.options.scales.x = { ...xAxis, title: getChartAxisTitleRuntime(chart.axesDesign?.x) };
|
|
28287
|
-
if (useLeftAxis) {
|
|
28288
|
-
config.options.scales.y = {
|
|
28289
|
-
...yAxis,
|
|
28290
|
-
position: "left",
|
|
28291
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
28292
|
-
};
|
|
28293
|
-
}
|
|
28294
|
-
if (useRightAxis) {
|
|
28295
|
-
config.options.scales.y1 = {
|
|
28296
|
-
...yAxis,
|
|
28297
|
-
position: "right",
|
|
28298
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
28299
|
-
};
|
|
28499
|
+
const definition = chart.getDefinition();
|
|
28500
|
+
const options = { stacked: chart.stacked, locale };
|
|
28501
|
+
if (chart.horizontal) {
|
|
28502
|
+
const format = leftAxisFormat || rightAxisFormat;
|
|
28503
|
+
config.options.scales.x = getChartAxis(definition, "bottom", "values", { ...options, format });
|
|
28504
|
+
config.options.scales.y = getChartAxis(definition, "left", "labels", options);
|
|
28300
28505
|
}
|
|
28301
|
-
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
|
|
28306
|
-
|
|
28307
|
-
}
|
|
28308
|
-
if (useRightAxis) {
|
|
28309
|
-
// @ts-ignore chart.js type is broken
|
|
28310
|
-
config.options.scales.y1.stacked = true;
|
|
28311
|
-
}
|
|
28506
|
+
else {
|
|
28507
|
+
config.options.scales.x = getChartAxis(definition, "bottom", "labels", options);
|
|
28508
|
+
const leftAxisOptions = { ...options, format: leftAxisFormat };
|
|
28509
|
+
config.options.scales.y = getChartAxis(definition, "left", "values", leftAxisOptions);
|
|
28510
|
+
const rightAxisOptions = { ...options, format: rightAxisFormat };
|
|
28511
|
+
config.options.scales.y1 = getChartAxis(definition, "right", "values", rightAxisOptions);
|
|
28312
28512
|
}
|
|
28513
|
+
config.options.scales = removeFalsyAttributes(config.options.scales);
|
|
28313
28514
|
config.options.plugins.chartShowValuesPlugin = {
|
|
28314
28515
|
showValues: chart.showValues,
|
|
28315
28516
|
background: chart.background,
|
|
28316
28517
|
horizontal: chart.horizontal,
|
|
28317
|
-
callback:
|
|
28518
|
+
callback: formatChartDatasetValue(axisFormats, locale),
|
|
28318
28519
|
};
|
|
28319
|
-
const definition = chart.getDefinition();
|
|
28320
28520
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28321
28521
|
const trendDatasets = [];
|
|
28322
28522
|
for (const index in dataSetsValues) {
|
|
@@ -28334,9 +28534,8 @@ function createBarChartRuntime(chart, getters) {
|
|
|
28334
28534
|
const label = definition.dataSets[index].label;
|
|
28335
28535
|
dataset.label = label;
|
|
28336
28536
|
}
|
|
28337
|
-
|
|
28338
|
-
|
|
28339
|
-
}
|
|
28537
|
+
dataset.yAxisID = chart.horizontal ? "y" : definition.dataSets[index].yAxisId || "y";
|
|
28538
|
+
dataset.xAxisID = "x";
|
|
28340
28539
|
const trend = definition.dataSets?.[index].trend;
|
|
28341
28540
|
if (!trend?.display || chart.horizontal) {
|
|
28342
28541
|
continue;
|
|
@@ -28352,7 +28551,7 @@ function createBarChartRuntime(chart, getters) {
|
|
|
28352
28551
|
*/
|
|
28353
28552
|
const maxLength = Math.max(...trendDatasets.map((trendDataset) => trendDataset.data.length));
|
|
28354
28553
|
config.options.scales[TREND_LINE_XAXIS_ID] = {
|
|
28355
|
-
...
|
|
28554
|
+
...config.options.scales.x,
|
|
28356
28555
|
labels: Array(maxLength).fill(""),
|
|
28357
28556
|
offset: false,
|
|
28358
28557
|
display: false,
|
|
@@ -28642,8 +28841,10 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28642
28841
|
}
|
|
28643
28842
|
const locale = getters.getLocale();
|
|
28644
28843
|
const truncateLabels = axisType === "category";
|
|
28645
|
-
const
|
|
28646
|
-
const
|
|
28844
|
+
const leftAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
28845
|
+
const rightAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
28846
|
+
const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat };
|
|
28847
|
+
const options = { locale, truncateLabels, axisFormats };
|
|
28647
28848
|
const fontColor = chartFontColor(chart.background);
|
|
28648
28849
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, options);
|
|
28649
28850
|
const legend = {
|
|
@@ -28673,52 +28874,18 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28673
28874
|
displayLegend: chart.legendPosition === "top",
|
|
28674
28875
|
}),
|
|
28675
28876
|
};
|
|
28676
|
-
const
|
|
28677
|
-
|
|
28678
|
-
padding: 5,
|
|
28679
|
-
color: fontColor,
|
|
28680
|
-
},
|
|
28681
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
28682
|
-
};
|
|
28877
|
+
const definition = chart.getDefinition();
|
|
28878
|
+
const stacked = "stacked" in chart && chart.stacked;
|
|
28683
28879
|
config.options.scales = {
|
|
28684
|
-
x:
|
|
28685
|
-
|
|
28686
|
-
|
|
28687
|
-
beginAtZero: true, // the origin of the y axis is always zero
|
|
28688
|
-
ticks: {
|
|
28689
|
-
color: fontColor,
|
|
28690
|
-
callback: formatTickValue(options),
|
|
28691
|
-
},
|
|
28880
|
+
x: getChartAxis(definition, "bottom", "labels", { locale }),
|
|
28881
|
+
y: getChartAxis(definition, "left", "values", { locale, stacked, format: leftAxisFormat }),
|
|
28882
|
+
y1: getChartAxis(definition, "right", "values", { locale, stacked, format: rightAxisFormat }),
|
|
28692
28883
|
};
|
|
28693
|
-
|
|
28694
|
-
if (useLeftAxis) {
|
|
28695
|
-
config.options.scales.y = {
|
|
28696
|
-
...yAxis,
|
|
28697
|
-
position: "left",
|
|
28698
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
28699
|
-
};
|
|
28700
|
-
}
|
|
28701
|
-
if (useRightAxis) {
|
|
28702
|
-
config.options.scales.y1 = {
|
|
28703
|
-
...yAxis,
|
|
28704
|
-
position: "right",
|
|
28705
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
28706
|
-
};
|
|
28707
|
-
}
|
|
28708
|
-
if ("stacked" in chart && chart.stacked) {
|
|
28709
|
-
if (useLeftAxis) {
|
|
28710
|
-
// @ts-ignore chart.js type is broken
|
|
28711
|
-
config.options.scales.y.stacked = true;
|
|
28712
|
-
}
|
|
28713
|
-
if (useRightAxis) {
|
|
28714
|
-
// @ts-ignore chart.js type is broken
|
|
28715
|
-
config.options.scales.y1.stacked = true;
|
|
28716
|
-
}
|
|
28717
|
-
}
|
|
28884
|
+
config.options.scales = removeFalsyAttributes(config.options.scales);
|
|
28718
28885
|
config.options.plugins.chartShowValuesPlugin = {
|
|
28719
28886
|
showValues: chart.showValues,
|
|
28720
28887
|
background: chart.background,
|
|
28721
|
-
callback:
|
|
28888
|
+
callback: formatChartDatasetValue(axisFormats, locale),
|
|
28722
28889
|
};
|
|
28723
28890
|
if (chart.dataSetsHaveTitle &&
|
|
28724
28891
|
dataSetsValues[0] &&
|
|
@@ -28745,7 +28912,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28745
28912
|
label = toNumber(label, locale);
|
|
28746
28913
|
}
|
|
28747
28914
|
const formattedX = formatValue(label, { locale, format: labelFormat });
|
|
28748
|
-
const formattedY = formatValue(dataSetPoint, { locale, format:
|
|
28915
|
+
const formattedY = formatValue(dataSetPoint, { locale, format: leftAxisFormat });
|
|
28749
28916
|
const dataSetTitle = tooltipItem.dataset.label;
|
|
28750
28917
|
return formattedX
|
|
28751
28918
|
? `${dataSetTitle}: (${formattedX}, ${formattedY})`
|
|
@@ -28755,7 +28922,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28755
28922
|
const areaChart = "fillArea" in chart ? chart.fillArea : false;
|
|
28756
28923
|
const stackedChart = "stacked" in chart ? chart.stacked : false;
|
|
28757
28924
|
const cumulative = "cumulative" in chart ? chart.cumulative : false;
|
|
28758
|
-
const definition = chart.getDefinition();
|
|
28759
28925
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28760
28926
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
28761
28927
|
const color = colors.next();
|
|
@@ -28796,9 +28962,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28796
28962
|
const label = definition.dataSets[index].label;
|
|
28797
28963
|
dataset.label = label;
|
|
28798
28964
|
}
|
|
28799
|
-
|
|
28800
|
-
dataset["yAxisID"] = definition.dataSets[index].yAxisId;
|
|
28801
|
-
}
|
|
28965
|
+
dataset["yAxisID"] = definition.dataSets[index].yAxisId || "y";
|
|
28802
28966
|
const trend = definition.dataSets?.[index].trend;
|
|
28803
28967
|
if (!trend?.display) {
|
|
28804
28968
|
continue;
|
|
@@ -28815,7 +28979,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28815
28979
|
* set so that the second axis points match the classical x axis
|
|
28816
28980
|
*/
|
|
28817
28981
|
config.options.scales[TREND_LINE_XAXIS_ID] = {
|
|
28818
|
-
...
|
|
28982
|
+
...config.options.scales.x,
|
|
28819
28983
|
type: "category",
|
|
28820
28984
|
labels: range(0, maxLength).map((x) => x.toString()),
|
|
28821
28985
|
offset: false,
|
|
@@ -28837,10 +29001,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28837
29001
|
return {
|
|
28838
29002
|
chartJsConfig: config,
|
|
28839
29003
|
background: chart.background || BACKGROUND_CHART_COLOR,
|
|
28840
|
-
dataSetsValues,
|
|
28841
|
-
labelValues,
|
|
28842
|
-
dataSetFormat,
|
|
28843
|
-
labelFormat,
|
|
28844
29004
|
};
|
|
28845
29005
|
}
|
|
28846
29006
|
|
|
@@ -28898,6 +29058,7 @@ class ComboChart extends AbstractChart {
|
|
|
28898
29058
|
ranges.push({
|
|
28899
29059
|
...this.dataSetDesign?.[i],
|
|
28900
29060
|
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
29061
|
+
type: this.dataSetDesign?.[i]?.type ?? (i ? "line" : "bar"),
|
|
28901
29062
|
});
|
|
28902
29063
|
}
|
|
28903
29064
|
return {
|
|
@@ -28943,9 +29104,13 @@ class ComboChart extends AbstractChart {
|
|
|
28943
29104
|
return new ComboChart(definition, this.sheetId, this.getters);
|
|
28944
29105
|
}
|
|
28945
29106
|
static getDefinitionFromContextCreation(context) {
|
|
29107
|
+
const dataSets = (context.range ?? []).map((ds, index) => ({
|
|
29108
|
+
...ds,
|
|
29109
|
+
type: index ? "line" : "bar",
|
|
29110
|
+
}));
|
|
28946
29111
|
return {
|
|
28947
29112
|
background: context.background,
|
|
28948
|
-
dataSets
|
|
29113
|
+
dataSets,
|
|
28949
29114
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
28950
29115
|
aggregated: context.aggregated,
|
|
28951
29116
|
legendPosition: context.legendPosition ?? "top",
|
|
@@ -28968,10 +29133,8 @@ class ComboChart extends AbstractChart {
|
|
|
28968
29133
|
}
|
|
28969
29134
|
}
|
|
28970
29135
|
function createComboChartRuntime(chart, getters) {
|
|
28971
|
-
const mainDataSetFormat = chart.dataSets
|
|
28972
|
-
|
|
28973
|
-
: undefined;
|
|
28974
|
-
const lineDataSetsFormat = getChartDatasetFormat(getters, chart.dataSets.slice(1));
|
|
29136
|
+
const mainDataSetFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
29137
|
+
const lineDataSetsFormat = getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
28975
29138
|
const locale = getters.getLocale();
|
|
28976
29139
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
28977
29140
|
let labels = labelValues.formattedValues;
|
|
@@ -28985,12 +29148,11 @@ function createComboChartRuntime(chart, getters) {
|
|
|
28985
29148
|
if (chart.aggregated) {
|
|
28986
29149
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
28987
29150
|
}
|
|
28988
|
-
const localeFormat = { format: mainDataSetFormat, locale };
|
|
28989
29151
|
const fontColor = chartFontColor(chart.background);
|
|
28990
|
-
const
|
|
29152
|
+
const axisFormats = { y: mainDataSetFormat, y1: lineDataSetsFormat };
|
|
29153
|
+
const config = getDefaultChartJsRuntime(chart, labels, fontColor, { locale, axisFormats });
|
|
28991
29154
|
const legend = {
|
|
28992
29155
|
labels: { color: fontColor },
|
|
28993
|
-
reverse: true,
|
|
28994
29156
|
};
|
|
28995
29157
|
if (chart.legendPosition === "none") {
|
|
28996
29158
|
legend.display = false;
|
|
@@ -29005,52 +29167,17 @@ function createComboChartRuntime(chart, getters) {
|
|
|
29005
29167
|
displayLegend: chart.legendPosition === "top",
|
|
29006
29168
|
}),
|
|
29007
29169
|
};
|
|
29170
|
+
const definition = chart.getDefinition();
|
|
29008
29171
|
config.options.scales = {
|
|
29009
|
-
x: {
|
|
29010
|
-
|
|
29011
|
-
|
|
29012
|
-
color: fontColor,
|
|
29013
|
-
},
|
|
29014
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
29015
|
-
},
|
|
29172
|
+
x: getChartAxis(definition, "bottom", "labels", { locale }),
|
|
29173
|
+
y: getChartAxis(definition, "left", "values", { locale, format: mainDataSetFormat }),
|
|
29174
|
+
y1: getChartAxis(definition, "right", "values", { locale, format: lineDataSetsFormat }),
|
|
29016
29175
|
};
|
|
29017
|
-
|
|
29018
|
-
beginAtZero: true, // the origin of the y axis is always zero
|
|
29019
|
-
ticks: {
|
|
29020
|
-
color: fontColor,
|
|
29021
|
-
callback: formatTickValue({ format: mainDataSetFormat, locale }),
|
|
29022
|
-
},
|
|
29023
|
-
};
|
|
29024
|
-
const rightVerticalAxis = {
|
|
29025
|
-
beginAtZero: true, // the origin of the y axis is always zero
|
|
29026
|
-
ticks: {
|
|
29027
|
-
color: fontColor,
|
|
29028
|
-
callback: formatTickValue({ format: lineDataSetsFormat, locale }),
|
|
29029
|
-
},
|
|
29030
|
-
};
|
|
29031
|
-
const definition = chart.getDefinition();
|
|
29032
|
-
const { useLeftAxis, useRightAxis } = getDefinedAxis(definition);
|
|
29033
|
-
if (useLeftAxis) {
|
|
29034
|
-
config.options.scales.y = {
|
|
29035
|
-
...leftVerticalAxis,
|
|
29036
|
-
position: "left",
|
|
29037
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
29038
|
-
};
|
|
29039
|
-
}
|
|
29040
|
-
if (useRightAxis) {
|
|
29041
|
-
config.options.scales.y1 = {
|
|
29042
|
-
...rightVerticalAxis,
|
|
29043
|
-
position: "right",
|
|
29044
|
-
grid: {
|
|
29045
|
-
display: false,
|
|
29046
|
-
},
|
|
29047
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
29048
|
-
};
|
|
29049
|
-
}
|
|
29176
|
+
config.options.scales = removeFalsyAttributes(config.options.scales);
|
|
29050
29177
|
config.options.plugins.chartShowValuesPlugin = {
|
|
29051
29178
|
showValues: chart.showValues,
|
|
29052
29179
|
background: chart.background,
|
|
29053
|
-
callback:
|
|
29180
|
+
callback: formatChartDatasetValue(axisFormats, locale),
|
|
29054
29181
|
};
|
|
29055
29182
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
29056
29183
|
let maxLength = 0;
|
|
@@ -29058,14 +29185,15 @@ function createComboChartRuntime(chart, getters) {
|
|
|
29058
29185
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
29059
29186
|
const design = definition.dataSets[index];
|
|
29060
29187
|
const color = colors.next();
|
|
29188
|
+
const type = design?.type ?? "line";
|
|
29061
29189
|
const dataset = {
|
|
29062
29190
|
label: design?.label ?? label,
|
|
29063
29191
|
data,
|
|
29064
29192
|
borderColor: color,
|
|
29065
29193
|
backgroundColor: color,
|
|
29066
29194
|
yAxisID: design?.yAxisId ?? "y",
|
|
29067
|
-
type
|
|
29068
|
-
order:
|
|
29195
|
+
type,
|
|
29196
|
+
order: type === "bar" ? dataSetsValues.length + index : index,
|
|
29069
29197
|
};
|
|
29070
29198
|
config.data.datasets.push(dataset);
|
|
29071
29199
|
const trend = definition.dataSets?.[index].trend;
|
|
@@ -29678,7 +29806,7 @@ function createPieChartRuntime(chart, getters) {
|
|
|
29678
29806
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
29679
29807
|
}
|
|
29680
29808
|
({ dataSetsValues, labels } = filterNegativeValues(labels, dataSetsValues));
|
|
29681
|
-
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
29809
|
+
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
29682
29810
|
const locale = getters.getLocale();
|
|
29683
29811
|
const config = getPieConfiguration(chart, labels, { format: dataSetFormat, locale });
|
|
29684
29812
|
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
|
|
@@ -29833,7 +29961,7 @@ function createPyramidChartRuntime(chart, getters) {
|
|
|
29833
29961
|
return tooltipLabelCallback(tooltipItem);
|
|
29834
29962
|
};
|
|
29835
29963
|
const callback = config.options.plugins.chartShowValuesPlugin.callback;
|
|
29836
|
-
config.options.plugins.chartShowValuesPlugin.callback = (x) => callback(Math.abs(x));
|
|
29964
|
+
config.options.plugins.chartShowValuesPlugin.callback = (x, axisId) => callback(Math.abs(x), axisId);
|
|
29837
29965
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
29838
29966
|
}
|
|
29839
29967
|
|
|
@@ -30224,7 +30352,8 @@ function createWaterfallChartRuntime(chart, getters) {
|
|
|
30224
30352
|
if (chart.showSubTotals) {
|
|
30225
30353
|
labels.push(_t("Subtotal"));
|
|
30226
30354
|
}
|
|
30227
|
-
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets)
|
|
30355
|
+
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets, "left") ||
|
|
30356
|
+
getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
30228
30357
|
const locale = getters.getLocale();
|
|
30229
30358
|
const dataSeriesLabels = dataSetsValues.map((dataSet) => dataSet.label);
|
|
30230
30359
|
const config = getWaterfallConfiguration(chart, labels, dataSeriesLabels, {
|
|
@@ -35294,6 +35423,7 @@ const CHECK_SVG = /*xml*/ `
|
|
|
35294
35423
|
<path fill='none' stroke='#FFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
|
|
35295
35424
|
</svg>
|
|
35296
35425
|
`;
|
|
35426
|
+
const CHECKBOX_WIDTH = 14;
|
|
35297
35427
|
css /* scss */ `
|
|
35298
35428
|
label.o-checkbox {
|
|
35299
35429
|
input {
|
|
@@ -35301,8 +35431,8 @@ css /* scss */ `
|
|
|
35301
35431
|
-webkit-appearance: none;
|
|
35302
35432
|
-moz-appearance: none;
|
|
35303
35433
|
border-radius: 0;
|
|
35304
|
-
width:
|
|
35305
|
-
height:
|
|
35434
|
+
width: ${CHECKBOX_WIDTH}px;
|
|
35435
|
+
height: ${CHECKBOX_WIDTH}px;
|
|
35306
35436
|
vertical-align: top;
|
|
35307
35437
|
box-sizing: border-box;
|
|
35308
35438
|
outline: none;
|
|
@@ -37212,6 +37342,32 @@ class ChartWithAxisDesignPanel extends Component {
|
|
|
37212
37342
|
}
|
|
37213
37343
|
}
|
|
37214
37344
|
|
|
37345
|
+
class ComboChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
37346
|
+
static template = "o-spreadsheet-ComboChartDesignPanel";
|
|
37347
|
+
seriesTypeChoices = [
|
|
37348
|
+
{ value: "bar", label: _t("Bar") },
|
|
37349
|
+
{ value: "line", label: _t("Line") },
|
|
37350
|
+
];
|
|
37351
|
+
updateDataSeriesType(type) {
|
|
37352
|
+
const dataSets = [...this.props.definition.dataSets];
|
|
37353
|
+
if (!dataSets?.[this.state.index]) {
|
|
37354
|
+
return;
|
|
37355
|
+
}
|
|
37356
|
+
dataSets[this.state.index] = {
|
|
37357
|
+
...dataSets[this.state.index],
|
|
37358
|
+
type,
|
|
37359
|
+
};
|
|
37360
|
+
this.props.updateChart(this.props.figureId, { dataSets });
|
|
37361
|
+
}
|
|
37362
|
+
getDataSeriesType() {
|
|
37363
|
+
const dataSets = this.props.definition.dataSets;
|
|
37364
|
+
if (!dataSets?.[this.state.index]) {
|
|
37365
|
+
return "bar";
|
|
37366
|
+
}
|
|
37367
|
+
return dataSets[this.state.index].type ?? "line";
|
|
37368
|
+
}
|
|
37369
|
+
}
|
|
37370
|
+
|
|
37215
37371
|
class GaugeChartConfigPanel extends Component {
|
|
37216
37372
|
static template = "o-spreadsheet-GaugeChartConfigPanel";
|
|
37217
37373
|
static components = { ChartErrorSection, ChartDataSeries };
|
|
@@ -37638,7 +37794,7 @@ chartSidePanelComponentRegistry
|
|
|
37638
37794
|
})
|
|
37639
37795
|
.add("combo", {
|
|
37640
37796
|
configuration: GenericChartConfigPanel,
|
|
37641
|
-
design:
|
|
37797
|
+
design: ComboChartDesignPanel,
|
|
37642
37798
|
})
|
|
37643
37799
|
.add("pie", {
|
|
37644
37800
|
configuration: GenericChartConfigPanel,
|
|
@@ -37924,6 +38080,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
37924
38080
|
"stopComposerRangeSelection",
|
|
37925
38081
|
"cancelEdition",
|
|
37926
38082
|
"cycleReferences",
|
|
38083
|
+
"toggleEditionMode",
|
|
37927
38084
|
"changeComposerCursorSelection",
|
|
37928
38085
|
"replaceComposerCursorSelection",
|
|
37929
38086
|
];
|
|
@@ -38079,6 +38236,42 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
38079
38236
|
}
|
|
38080
38237
|
this.setCurrentContent(updated.content, updated.selection);
|
|
38081
38238
|
}
|
|
38239
|
+
toggleEditionMode() {
|
|
38240
|
+
if (this.editionMode === "inactive")
|
|
38241
|
+
return;
|
|
38242
|
+
const start = Math.min(this.selectionStart, this.selectionEnd);
|
|
38243
|
+
const end = Math.max(this.selectionStart, this.selectionEnd);
|
|
38244
|
+
const refToken = [...this.currentTokens]
|
|
38245
|
+
.reverse()
|
|
38246
|
+
.find((tk) => tk.end >= start && end >= tk.start && tk.type === "REFERENCE");
|
|
38247
|
+
if (this.editionMode === "editing" && refToken) {
|
|
38248
|
+
const currentSheetId = this.getters.getActiveSheetId();
|
|
38249
|
+
const { sheetName, xc } = splitReference(refToken.value);
|
|
38250
|
+
const sheetId = this.getters.getSheetIdByName(sheetName);
|
|
38251
|
+
if (sheetId && sheetId !== currentSheetId) {
|
|
38252
|
+
this.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: currentSheetId, sheetIdTo: sheetId });
|
|
38253
|
+
}
|
|
38254
|
+
// move cursor to the right part of the token
|
|
38255
|
+
this.selectionStart = this.selectionEnd = refToken.end;
|
|
38256
|
+
const zone = this.getters.getRangeFromSheetXC(this.sheetId, xc).zone;
|
|
38257
|
+
this.captureSelection(zone);
|
|
38258
|
+
this.editionMode = "selecting";
|
|
38259
|
+
}
|
|
38260
|
+
else {
|
|
38261
|
+
this.editionMode = "editing";
|
|
38262
|
+
}
|
|
38263
|
+
}
|
|
38264
|
+
captureSelection(zone, col, row) {
|
|
38265
|
+
this.model.selection.capture(this, {
|
|
38266
|
+
cell: { col: col || zone.left, row: row || zone.right },
|
|
38267
|
+
zone,
|
|
38268
|
+
}, {
|
|
38269
|
+
handleEvent: this.handleEvent.bind(this),
|
|
38270
|
+
release: () => {
|
|
38271
|
+
this._stopEdition();
|
|
38272
|
+
},
|
|
38273
|
+
});
|
|
38274
|
+
}
|
|
38082
38275
|
isSelectionValid(length, start, end) {
|
|
38083
38276
|
return start >= 0 && start <= length && end >= 0 && end <= length;
|
|
38084
38277
|
}
|
|
@@ -38117,12 +38310,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
38117
38310
|
this.setContent(str || this.initialContent, selection);
|
|
38118
38311
|
this.colorIndexByRange = {};
|
|
38119
38312
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
38120
|
-
this.
|
|
38121
|
-
handleEvent: this.handleEvent.bind(this),
|
|
38122
|
-
release: () => {
|
|
38123
|
-
this._stopEdition();
|
|
38124
|
-
},
|
|
38125
|
-
});
|
|
38313
|
+
this.captureSelection(zone, col, row);
|
|
38126
38314
|
}
|
|
38127
38315
|
_stopEdition() {
|
|
38128
38316
|
if (this.editionMode !== "inactive") {
|
|
@@ -42817,8 +43005,9 @@ const EMPTY_PIVOT_CELL = { type: "EMPTY" };
|
|
|
42817
43005
|
* This function converts a list of data entry into a spreadsheet pivot table.
|
|
42818
43006
|
*/
|
|
42819
43007
|
function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
43008
|
+
const measureIds = definition.measures.filter((measure) => !measure.isHidden).map((m) => m.id);
|
|
42820
43009
|
const columnsTree = dataEntriesToColumnsTree(dataEntries, definition.columns, 0);
|
|
42821
|
-
computeWidthOfColumnsNodes(columnsTree,
|
|
43010
|
+
computeWidthOfColumnsNodes(columnsTree, measureIds.length);
|
|
42822
43011
|
const cols = columnsTreeToColumns(columnsTree, definition);
|
|
42823
43012
|
const rows = dataEntriesToRows(dataEntries, 0, definition.rows, [], []);
|
|
42824
43013
|
// Add the total row
|
|
@@ -42827,7 +43016,6 @@ function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
|
42827
43016
|
values: [],
|
|
42828
43017
|
indent: 0,
|
|
42829
43018
|
});
|
|
42830
|
-
const measureIds = definition.measures.filter((measure) => !measure.isHidden).map((m) => m.id);
|
|
42831
43019
|
const fieldsType = {};
|
|
42832
43020
|
for (const columns of definition.columns) {
|
|
42833
43021
|
fieldsType[columns.fieldName] = columns.type;
|
|
@@ -43588,7 +43776,7 @@ pivotRegistry.add("SPREADSHEET", {
|
|
|
43588
43776
|
onIterationEndEvaluation: (pivot) => pivot.markAsDirtyForEvaluation(),
|
|
43589
43777
|
dateGranularities: [...dateGranularities],
|
|
43590
43778
|
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
|
|
43591
|
-
isMeasureCandidate: (field) => !["
|
|
43779
|
+
isMeasureCandidate: (field) => !["datetime", "boolean"].includes(field.type),
|
|
43592
43780
|
isGroupable: () => true,
|
|
43593
43781
|
});
|
|
43594
43782
|
|
|
@@ -46117,13 +46305,10 @@ class GridCellIcon extends Component {
|
|
|
46117
46305
|
}
|
|
46118
46306
|
}
|
|
46119
46307
|
|
|
46120
|
-
const CHECKBOX_WIDTH = 15;
|
|
46121
46308
|
const MARGIN = (GRID_ICON_EDGE_LENGTH - CHECKBOX_WIDTH) / 2;
|
|
46122
46309
|
css /* scss */ `
|
|
46123
46310
|
.o-dv-checkbox {
|
|
46124
46311
|
box-sizing: border-box !important;
|
|
46125
|
-
width: ${CHECKBOX_WIDTH}px;
|
|
46126
|
-
height: ${CHECKBOX_WIDTH}px;
|
|
46127
46312
|
accent-color: #808080;
|
|
46128
46313
|
margin: ${MARGIN}px;
|
|
46129
46314
|
/** required to prevent the checkbox position to be sensible to the font-size (affects Firefox) */
|
|
@@ -46132,13 +46317,15 @@ css /* scss */ `
|
|
|
46132
46317
|
`;
|
|
46133
46318
|
class DataValidationCheckbox extends Component {
|
|
46134
46319
|
static template = "o-spreadsheet-DataValidationCheckbox";
|
|
46320
|
+
static components = {
|
|
46321
|
+
Checkbox,
|
|
46322
|
+
};
|
|
46135
46323
|
static props = {
|
|
46136
46324
|
cellPosition: Object,
|
|
46137
46325
|
};
|
|
46138
|
-
onCheckboxChange(
|
|
46139
|
-
const newValue = ev.target.checked;
|
|
46326
|
+
onCheckboxChange(value) {
|
|
46140
46327
|
const { sheetId, col, row } = this.props.cellPosition;
|
|
46141
|
-
const cellContent =
|
|
46328
|
+
const cellContent = value ? "TRUE" : "FALSE";
|
|
46142
46329
|
this.env.model.dispatch("UPDATE_CELL", { sheetId, col, row, content: cellContent });
|
|
46143
46330
|
}
|
|
46144
46331
|
get checkBoxValue() {
|
|
@@ -46952,7 +47139,11 @@ class GridAddRowsFooter extends Component {
|
|
|
46952
47139
|
class PaintFormatStore extends SpreadsheetStore {
|
|
46953
47140
|
mutators = ["activate", "cancel", "pasteFormat"];
|
|
46954
47141
|
highlightStore = this.get(HighlightStore);
|
|
46955
|
-
|
|
47142
|
+
clipboardHandlers = [
|
|
47143
|
+
new CellClipboardHandler(this.getters, this.model.dispatch),
|
|
47144
|
+
new BorderClipboardHandler(this.getters, this.model.dispatch),
|
|
47145
|
+
new TableClipboardHandler(this.getters, this.model.dispatch),
|
|
47146
|
+
];
|
|
46956
47147
|
status = "inactive";
|
|
46957
47148
|
copiedData;
|
|
46958
47149
|
constructor(get) {
|
|
@@ -46973,10 +47164,12 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
46973
47164
|
pasteFormat(target) {
|
|
46974
47165
|
if (this.copiedData) {
|
|
46975
47166
|
const sheetId = this.getters.getActiveSheetId();
|
|
46976
|
-
|
|
46977
|
-
|
|
46978
|
-
|
|
46979
|
-
|
|
47167
|
+
for (const handler of this.clipboardHandlers) {
|
|
47168
|
+
handler.paste({ zones: target, sheetId }, this.copiedData, {
|
|
47169
|
+
isCutOperation: false,
|
|
47170
|
+
pasteOption: "onlyFormat",
|
|
47171
|
+
});
|
|
47172
|
+
}
|
|
46980
47173
|
}
|
|
46981
47174
|
if (this.status === "oneOff") {
|
|
46982
47175
|
this.cancel();
|
|
@@ -46988,7 +47181,11 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
46988
47181
|
copyFormats() {
|
|
46989
47182
|
const sheetId = this.getters.getActiveSheetId();
|
|
46990
47183
|
const zones = this.getters.getSelectedZones();
|
|
46991
|
-
|
|
47184
|
+
const copiedData = {};
|
|
47185
|
+
for (const handler of this.clipboardHandlers) {
|
|
47186
|
+
Object.assign(copiedData, handler.copy(getClipboardDataPositions(sheetId, zones)));
|
|
47187
|
+
}
|
|
47188
|
+
return copiedData;
|
|
46992
47189
|
}
|
|
46993
47190
|
get highlights() {
|
|
46994
47191
|
const data = this.copiedData;
|
|
@@ -49796,12 +49993,10 @@ class BasePlugin {
|
|
|
49796
49993
|
*/
|
|
49797
49994
|
class CorePlugin extends BasePlugin {
|
|
49798
49995
|
getters;
|
|
49799
|
-
|
|
49800
|
-
constructor({ getters, stateObserver, range, dispatch, canDispatch, uuidGenerator, }) {
|
|
49996
|
+
constructor({ getters, stateObserver, range, dispatch, canDispatch }) {
|
|
49801
49997
|
super(stateObserver, dispatch, canDispatch);
|
|
49802
49998
|
range.addRangeProvider(this.adaptRanges.bind(this));
|
|
49803
49999
|
this.getters = getters;
|
|
49804
|
-
this.uuidGenerator = uuidGenerator;
|
|
49805
50000
|
}
|
|
49806
50001
|
// ---------------------------------------------------------------------------
|
|
49807
50002
|
// Import/Export
|
|
@@ -54299,6 +54494,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
54299
54494
|
}
|
|
54300
54495
|
}
|
|
54301
54496
|
|
|
54497
|
+
let nextTableId = 1;
|
|
54302
54498
|
class TablePlugin extends CorePlugin {
|
|
54303
54499
|
static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
|
|
54304
54500
|
tables = {};
|
|
@@ -54366,7 +54562,7 @@ class TablePlugin extends CorePlugin {
|
|
|
54366
54562
|
const union = this.getters.getRangesUnion(ranges);
|
|
54367
54563
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
54368
54564
|
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
54369
|
-
const id =
|
|
54565
|
+
const id = `${nextTableId++}`;
|
|
54370
54566
|
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
54371
54567
|
const newTable = cmd.tableType === "dynamic"
|
|
54372
54568
|
? this.createDynamicTable(id, union, config)
|
|
@@ -54519,7 +54715,7 @@ class TablePlugin extends CorePlugin {
|
|
|
54519
54715
|
filters = [];
|
|
54520
54716
|
for (const i of range(zone.left, zone.right + 1)) {
|
|
54521
54717
|
const filterZone = { ...zone, left: i, right: i };
|
|
54522
|
-
const uid =
|
|
54718
|
+
const uid = `${nextTableId++}`;
|
|
54523
54719
|
filters.push(this.createFilterFromZone(uid, tableRange.sheetId, filterZone, config));
|
|
54524
54720
|
}
|
|
54525
54721
|
}
|
|
@@ -54584,7 +54780,7 @@ class TablePlugin extends CorePlugin {
|
|
|
54584
54780
|
? table.filters.find((f) => f.col === i)
|
|
54585
54781
|
: undefined;
|
|
54586
54782
|
const filterZone = { ...tableZone, left: i, right: i };
|
|
54587
|
-
const filterId = oldFilter?.id ||
|
|
54783
|
+
const filterId = oldFilter?.id || `${nextTableId++}`;
|
|
54588
54784
|
filters.push(this.createFilterFromZone(filterId, tableRange.sheetId, filterZone, config));
|
|
54589
54785
|
}
|
|
54590
54786
|
}
|
|
@@ -54685,7 +54881,7 @@ class TablePlugin extends CorePlugin {
|
|
|
54685
54881
|
if (filters.length < zoneToDimension(tableZone).numberOfCols) {
|
|
54686
54882
|
for (let col = tableZone.left; col <= tableZone.right; col++) {
|
|
54687
54883
|
if (!filters.find((filter) => filter.col === col)) {
|
|
54688
|
-
const uid =
|
|
54884
|
+
const uid = `${nextTableId++}`;
|
|
54689
54885
|
const filterZone = { ...tableZone, left: col, right: col };
|
|
54690
54886
|
filters.push(this.createFilterFromZone(uid, sheetId, filterZone, table.config));
|
|
54691
54887
|
}
|
|
@@ -54701,7 +54897,7 @@ class TablePlugin extends CorePlugin {
|
|
|
54701
54897
|
import(data) {
|
|
54702
54898
|
for (const sheet of data.sheets) {
|
|
54703
54899
|
for (const tableData of sheet.tables || []) {
|
|
54704
|
-
const uuid =
|
|
54900
|
+
const uuid = `${nextTableId++}`;
|
|
54705
54901
|
const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
|
|
54706
54902
|
const range = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
|
|
54707
54903
|
const tableType = tableData.type || "static";
|
|
@@ -59050,7 +59246,7 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
59050
59246
|
const ranking = {};
|
|
59051
59247
|
const mainDimension = getFieldDimensionType(this, fieldNameWithGranularity);
|
|
59052
59248
|
const secondaryDimension = mainDimension === "row" ? "column" : "row";
|
|
59053
|
-
let pivotCells = this.getPivotValueCells();
|
|
59249
|
+
let pivotCells = this.getPivotValueCells(measure.id);
|
|
59054
59250
|
if (mainDimension === "column") {
|
|
59055
59251
|
// Transpose the pivot cells so we can do the same operations on the columns as on the rows
|
|
59056
59252
|
// This means that we need to transpose back the ranking at the end
|
|
@@ -59094,7 +59290,7 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
59094
59290
|
const cellsRunningTotals = {};
|
|
59095
59291
|
const mainDimension = getFieldDimensionType(this, fieldNameWithGranularity);
|
|
59096
59292
|
const secondaryDimension = mainDimension === "row" ? "column" : "row";
|
|
59097
|
-
let pivotCells = this.getPivotValueCells();
|
|
59293
|
+
let pivotCells = this.getPivotValueCells(measure.id);
|
|
59098
59294
|
if (mainDimension === "column") {
|
|
59099
59295
|
// Transpose the pivot cells so we can do the same operations on the columns as on the rows
|
|
59100
59296
|
// This means that we need to transpose back the totals at the end
|
|
@@ -59173,10 +59369,10 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
59173
59369
|
const comparedValueNumber = this.strictMeasureValueToNumber(comparedValue);
|
|
59174
59370
|
return comparedValueNumber;
|
|
59175
59371
|
}
|
|
59176
|
-
getPivotValueCells() {
|
|
59372
|
+
getPivotValueCells(measureId) {
|
|
59177
59373
|
return this.getTableStructure()
|
|
59178
59374
|
.getPivotCells()
|
|
59179
|
-
.map((col) => col.filter((cell) => cell.type === "VALUE"))
|
|
59375
|
+
.map((col) => col.filter((cell) => cell.type === "VALUE" && cell.measure === measureId))
|
|
59180
59376
|
.filter((col) => col.length > 0);
|
|
59181
59377
|
}
|
|
59182
59378
|
measureValueToNumber(result) {
|
|
@@ -60944,6 +61140,7 @@ class Session extends EventBus {
|
|
|
60944
61140
|
case "REMOTE_REVISION":
|
|
60945
61141
|
case "REVISION_REDONE":
|
|
60946
61142
|
case "REVISION_UNDONE":
|
|
61143
|
+
case "SNAPSHOT_CREATED":
|
|
60947
61144
|
return this.processedRevisions.has(message.nextRevisionId);
|
|
60948
61145
|
default:
|
|
60949
61146
|
return false;
|
|
@@ -61506,7 +61703,7 @@ class InsertPivotPlugin extends UIPlugin {
|
|
|
61506
61703
|
const position = this.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
61507
61704
|
const formulaId = this.getters.getPivotFormulaId(newPivotId);
|
|
61508
61705
|
const newPivotName = this.getters.getPivotName(newPivotId);
|
|
61509
|
-
this.dispatch("CREATE_SHEET", {
|
|
61706
|
+
const result = this.dispatch("CREATE_SHEET", {
|
|
61510
61707
|
sheetId: newSheetId,
|
|
61511
61708
|
name: this.getPivotDuplicateSheetName(_t("%(newPivotName)s (Pivot #%(formulaId)s)", {
|
|
61512
61709
|
newPivotName,
|
|
@@ -61514,20 +61711,19 @@ class InsertPivotPlugin extends UIPlugin {
|
|
|
61514
61711
|
})),
|
|
61515
61712
|
position,
|
|
61516
61713
|
});
|
|
61517
|
-
|
|
61518
|
-
|
|
61519
|
-
|
|
61520
|
-
|
|
61521
|
-
|
|
61522
|
-
content: `=PIVOT(${formulaId})`,
|
|
61523
|
-
});
|
|
61714
|
+
if (result.isSuccessful) {
|
|
61715
|
+
this.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: newSheetId });
|
|
61716
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
61717
|
+
this.insertPivotWithTable(newSheetId, 0, 0, newPivotId, pivot.getTableStructure().export(), "dynamic");
|
|
61718
|
+
}
|
|
61524
61719
|
}
|
|
61525
61720
|
getPivotDuplicateSheetName(pivotName) {
|
|
61526
61721
|
let i = 1;
|
|
61527
61722
|
const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
|
|
61528
|
-
|
|
61723
|
+
const sanitizedName = pivotName.replace(new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g"), " ");
|
|
61724
|
+
let name = sanitizedName;
|
|
61529
61725
|
while (names.includes(name)) {
|
|
61530
|
-
name = `${
|
|
61726
|
+
name = `${sanitizedName} (${i})`;
|
|
61531
61727
|
i++;
|
|
61532
61728
|
}
|
|
61533
61729
|
return name;
|
|
@@ -70880,6 +71076,15 @@ function addTableColumns(table, sheetData) {
|
|
|
70880
71076
|
["id", i + 1], // id cannot be 0
|
|
70881
71077
|
["name", colName],
|
|
70882
71078
|
];
|
|
71079
|
+
if (table.config.totalRow) {
|
|
71080
|
+
// Note: To be 100% complete, we could also add a `totalsRowLabel` attribute for total strings, and a tag
|
|
71081
|
+
// `<totalsRowFormula>` for the formula of the total. But those doesn't seem to be mandatory for Excel.
|
|
71082
|
+
const colTotalXc = toXC(tableZone.left + i, tableZone.bottom);
|
|
71083
|
+
const colTotalContent = sheetData.cells[colTotalXc]?.content;
|
|
71084
|
+
if (colTotalContent?.startsWith("=")) {
|
|
71085
|
+
colAttributes.push(["totalsRowFunction", "custom"]);
|
|
71086
|
+
}
|
|
71087
|
+
}
|
|
70883
71088
|
columns.push(escapeXml /*xml*/ `<tableColumn ${formatAttributes(colAttributes)}/>`);
|
|
70884
71089
|
}
|
|
70885
71090
|
return escapeXml /*xml*/ `
|
|
@@ -70974,8 +71179,9 @@ function addRows(construct, data, sheet) {
|
|
|
70974
71179
|
}
|
|
70975
71180
|
else if (cell.content && cell.content !== "") {
|
|
70976
71181
|
const isTableHeader = isCellTableHeader(c, r, sheet);
|
|
71182
|
+
const isTableTotal = isCellTableTotal(c, r, sheet);
|
|
70977
71183
|
const isPlainText = !!(cell.format && isTextFormat(data.formats[cell.format]));
|
|
70978
|
-
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isPlainText));
|
|
71184
|
+
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isTableTotal || isPlainText));
|
|
70979
71185
|
}
|
|
70980
71186
|
attributes.push(...additionalAttrs);
|
|
70981
71187
|
// prettier-ignore
|
|
@@ -71009,6 +71215,16 @@ function isCellTableHeader(col, row, sheet) {
|
|
|
71009
71215
|
return isInside(col, row, headerZone);
|
|
71010
71216
|
});
|
|
71011
71217
|
}
|
|
71218
|
+
function isCellTableTotal(col, row, sheet) {
|
|
71219
|
+
return sheet.tables.some((table) => {
|
|
71220
|
+
if (!table.config.totalRow) {
|
|
71221
|
+
return false;
|
|
71222
|
+
}
|
|
71223
|
+
const zone = toZone(table.range);
|
|
71224
|
+
const totalZone = { ...zone, top: zone.bottom };
|
|
71225
|
+
return isInside(col, row, totalZone);
|
|
71226
|
+
});
|
|
71227
|
+
}
|
|
71012
71228
|
function addHyperlinks(construct, data, sheetIndex) {
|
|
71013
71229
|
const sheet = data.sheets[sheetIndex];
|
|
71014
71230
|
const cells = sheet.cells;
|
|
@@ -71499,7 +71715,6 @@ class Model extends EventBus {
|
|
|
71499
71715
|
isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
|
|
71500
71716
|
isDashboard: () => this.config.mode === "dashboard",
|
|
71501
71717
|
};
|
|
71502
|
-
this.uuidGenerator.setIsFastStrategy(true);
|
|
71503
71718
|
// Initiate stream processor
|
|
71504
71719
|
this.selection = new SelectionStreamProcessorImpl(this.getters);
|
|
71505
71720
|
this.coreHandlers.push(this.range);
|
|
@@ -71531,7 +71746,6 @@ class Model extends EventBus {
|
|
|
71531
71746
|
this.handlers.push(plugin);
|
|
71532
71747
|
this.uiHandlers.push(plugin);
|
|
71533
71748
|
}
|
|
71534
|
-
this.uuidGenerator.setIsFastStrategy(false);
|
|
71535
71749
|
// starting plugins
|
|
71536
71750
|
this.dispatch("START");
|
|
71537
71751
|
// Model should be the last permanent subscriber in the list since he should render
|
|
@@ -71679,7 +71893,6 @@ class Model extends EventBus {
|
|
|
71679
71893
|
range: this.range,
|
|
71680
71894
|
dispatch: this.dispatchFromCorePlugin,
|
|
71681
71895
|
canDispatch: this.canDispatch,
|
|
71682
|
-
uuidGenerator: this.uuidGenerator,
|
|
71683
71896
|
custom: this.config.custom,
|
|
71684
71897
|
external: this.config.external,
|
|
71685
71898
|
};
|
|
@@ -72130,6 +72343,6 @@ const constants = {
|
|
|
72130
72343
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
72131
72344
|
|
|
72132
72345
|
|
|
72133
|
-
__info__.version = "18.1.0-alpha.
|
|
72134
|
-
__info__.date = "2024-
|
|
72135
|
-
__info__.hash = "
|
|
72346
|
+
__info__.version = "18.1.0-alpha.1";
|
|
72347
|
+
__info__.date = "2024-10-14T07:53:17.717Z";
|
|
72348
|
+
__info__.hash = "e9ce3aa";
|