@odoo/o-spreadsheet 19.1.0-alpha.3 → 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 +544 -261
- package/dist/o-spreadsheet.d.ts +245 -157
- package/dist/o-spreadsheet.esm.js +544 -261
- package/dist/o-spreadsheet.iife.js +544 -261
- package/dist/o-spreadsheet.iife.min.js +317 -317
- package/dist/o_spreadsheet.xml +87 -18
- package/package.json +5 -2
|
@@ -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-
|
|
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
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -591,7 +591,6 @@ const BACKGROUND_HEADER_COLOR = "#F8F9FA";
|
|
|
591
591
|
const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
|
|
592
592
|
const BACKGROUND_HEADER_ACTIVE_COLOR = "#595959";
|
|
593
593
|
const TEXT_HEADER_COLOR = "#666666";
|
|
594
|
-
const FIGURE_BORDER_COLOR = "#c9ccd2";
|
|
595
594
|
const SELECTION_BORDER_COLOR = "#3266ca";
|
|
596
595
|
const HEADER_BORDER_COLOR = "#C0C0C0";
|
|
597
596
|
const CELL_BORDER_COLOR = "#E2E3E3";
|
|
@@ -599,7 +598,6 @@ const BACKGROUND_CHART_COLOR = "#FFFFFF";
|
|
|
599
598
|
const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
|
|
600
599
|
const LINK_COLOR = HIGHLIGHT_COLOR;
|
|
601
600
|
const FILTERS_COLOR = "#188038";
|
|
602
|
-
const HEADER_GROUPING_BORDER_COLOR = "#999";
|
|
603
601
|
const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
|
|
604
602
|
const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
|
|
605
603
|
const COMPOSER_ASSISTANT_COLOR = "#9B359B";
|
|
@@ -842,22 +840,6 @@ const DRAG_THRESHOLD = 5; // in pixels, to avoid unwanted drag when clicking
|
|
|
842
840
|
// Miscellaneous
|
|
843
841
|
//------------------------------------------------------------------------------
|
|
844
842
|
const sanitizeSheetNameRegex = new RegExp(FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX, "g");
|
|
845
|
-
/**
|
|
846
|
-
* Remove quotes from a quoted string
|
|
847
|
-
* ```js
|
|
848
|
-
* removeStringQuotes('"Hello"')
|
|
849
|
-
* > 'Hello'
|
|
850
|
-
* ```
|
|
851
|
-
*/
|
|
852
|
-
function removeStringQuotes(str) {
|
|
853
|
-
if (str[0] === '"') {
|
|
854
|
-
str = str.slice(1);
|
|
855
|
-
}
|
|
856
|
-
if (str[str.length - 1] === '"' && str[str.length - 2] !== "\\") {
|
|
857
|
-
return str.slice(0, str.length - 1);
|
|
858
|
-
}
|
|
859
|
-
return str;
|
|
860
|
-
}
|
|
861
843
|
function isCloneable(obj) {
|
|
862
844
|
return "clone" in obj && obj.clone instanceof Function;
|
|
863
845
|
}
|
|
@@ -926,6 +908,13 @@ function isPlainObject(obj) {
|
|
|
926
908
|
function getUnquotedSheetName(sheetName) {
|
|
927
909
|
return unquote(sheetName, "'");
|
|
928
910
|
}
|
|
911
|
+
/**
|
|
912
|
+
* Remove quotes from a quoted string
|
|
913
|
+
* ```js
|
|
914
|
+
* unquote('"Hello"')
|
|
915
|
+
* > 'Hello'
|
|
916
|
+
* ```
|
|
917
|
+
*/
|
|
929
918
|
function unquote(string, quoteChar = '"') {
|
|
930
919
|
if (string.startsWith(quoteChar)) {
|
|
931
920
|
string = string.slice(1);
|
|
@@ -1330,9 +1319,7 @@ function removeIndexesFromArray(array, indexes) {
|
|
|
1330
1319
|
return newArray;
|
|
1331
1320
|
}
|
|
1332
1321
|
function insertItemsAtIndex(array, items, index) {
|
|
1333
|
-
|
|
1334
|
-
newArray.splice(index, 0, ...items);
|
|
1335
|
-
return newArray;
|
|
1322
|
+
return array.slice(0, index).concat(items).concat(array.slice(index));
|
|
1336
1323
|
}
|
|
1337
1324
|
function replaceItemAtIndex(array, newItem, index) {
|
|
1338
1325
|
const newArray = [...array];
|
|
@@ -4463,7 +4450,17 @@ function toNumberMatrix(data, argName) {
|
|
|
4463
4450
|
return toMatrix(data).map((row) => {
|
|
4464
4451
|
return row.map((cell) => {
|
|
4465
4452
|
if (typeof cell.value !== "number") {
|
|
4466
|
-
|
|
4453
|
+
let message = "";
|
|
4454
|
+
if (typeof cell === "object") {
|
|
4455
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got an empty value.", argName);
|
|
4456
|
+
}
|
|
4457
|
+
else if (typeof cell === "string") {
|
|
4458
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a string.", argName);
|
|
4459
|
+
}
|
|
4460
|
+
else if (typeof cell === "boolean") {
|
|
4461
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a boolean.", argName);
|
|
4462
|
+
}
|
|
4463
|
+
throw new EvaluationError(message);
|
|
4467
4464
|
}
|
|
4468
4465
|
return cell.value;
|
|
4469
4466
|
});
|
|
@@ -5582,7 +5579,7 @@ function tokensToTextInternalFormat(tokens) {
|
|
|
5582
5579
|
* Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
|
|
5583
5580
|
*
|
|
5584
5581
|
* As per OpenXML specification, in date formats if a date token "m" or "mm" is followed by a date token "s" or
|
|
5585
|
-
* preceded by a data token "h", then it's not a month but
|
|
5582
|
+
* preceded by a data token "h", then it's not a month but a minute.
|
|
5586
5583
|
*/
|
|
5587
5584
|
function convertTokensToMinutesInDateFormat(tokens) {
|
|
5588
5585
|
const dateParts = tokens.filter((token) => token.type === "DATE_PART");
|
|
@@ -5625,6 +5622,9 @@ function internalFormatPartToFormat(internalFormat) {
|
|
|
5625
5622
|
case "REPEATED_CHAR":
|
|
5626
5623
|
format += "*" + token.value;
|
|
5627
5624
|
break;
|
|
5625
|
+
case "DATE_PART":
|
|
5626
|
+
format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
|
|
5627
|
+
break;
|
|
5628
5628
|
default:
|
|
5629
5629
|
format += token.value;
|
|
5630
5630
|
}
|
|
@@ -5698,7 +5698,7 @@ function formatValue(value, { format, locale, formatWidth }) {
|
|
|
5698
5698
|
return value;
|
|
5699
5699
|
}
|
|
5700
5700
|
const internalFormat = parseFormat(format);
|
|
5701
|
-
const formatToApply =
|
|
5701
|
+
const formatToApply = getFormatToApply(value, internalFormat).format;
|
|
5702
5702
|
if (!formatToApply || formatToApply.type !== "text") {
|
|
5703
5703
|
return value;
|
|
5704
5704
|
}
|
|
@@ -5709,16 +5709,15 @@ function formatValue(value, { format, locale, formatWidth }) {
|
|
|
5709
5709
|
format = createDefaultFormat(value);
|
|
5710
5710
|
}
|
|
5711
5711
|
const internalFormat = parseFormat(format);
|
|
5712
|
-
|
|
5713
|
-
|
|
5712
|
+
const { format: formatToApply, isNegativeFormat } = getFormatToApply(value, internalFormat);
|
|
5713
|
+
if (!formatToApply) {
|
|
5714
|
+
return value.toString();
|
|
5714
5715
|
}
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
formatToApply = internalFormat.negative;
|
|
5718
|
-
value = -value;
|
|
5716
|
+
if (formatToApply.type === "text") {
|
|
5717
|
+
return applyTextInternalFormat(value.toString(), formatToApply, formatWidth);
|
|
5719
5718
|
}
|
|
5720
|
-
|
|
5721
|
-
|
|
5719
|
+
if (isNegativeFormat) {
|
|
5720
|
+
value = Math.abs(value);
|
|
5722
5721
|
}
|
|
5723
5722
|
if (formatToApply.type === "date") {
|
|
5724
5723
|
return repeatCharToFitWidth(applyDateTimeFormat(value, formatToApply), formatWidth);
|
|
@@ -5730,6 +5729,31 @@ function formatValue(value, { format, locale, formatWidth }) {
|
|
|
5730
5729
|
return "";
|
|
5731
5730
|
}
|
|
5732
5731
|
}
|
|
5732
|
+
function getFormatToApply(value, internalFormat) {
|
|
5733
|
+
let formatToApply = undefined;
|
|
5734
|
+
let isNegativeFormat = false;
|
|
5735
|
+
switch (typeof value) {
|
|
5736
|
+
case "number":
|
|
5737
|
+
if (value < 0 && internalFormat.negative) {
|
|
5738
|
+
formatToApply = internalFormat.negative;
|
|
5739
|
+
isNegativeFormat = true;
|
|
5740
|
+
}
|
|
5741
|
+
else if (value === 0 && internalFormat.zero) {
|
|
5742
|
+
formatToApply = internalFormat.zero;
|
|
5743
|
+
}
|
|
5744
|
+
else {
|
|
5745
|
+
formatToApply = internalFormat.positive;
|
|
5746
|
+
}
|
|
5747
|
+
break;
|
|
5748
|
+
case "string":
|
|
5749
|
+
const format = internalFormat.text || internalFormat.positive;
|
|
5750
|
+
if (format.type === "text") {
|
|
5751
|
+
formatToApply = format;
|
|
5752
|
+
}
|
|
5753
|
+
break;
|
|
5754
|
+
}
|
|
5755
|
+
return { format: formatToApply, isNegativeFormat };
|
|
5756
|
+
}
|
|
5733
5757
|
function applyTextInternalFormat(value, internalFormat, formatWidth) {
|
|
5734
5758
|
let formattedValue = "";
|
|
5735
5759
|
for (const token of internalFormat.tokens) {
|
|
@@ -6341,6 +6365,27 @@ function isTextFormat(format) {
|
|
|
6341
6365
|
return false;
|
|
6342
6366
|
}
|
|
6343
6367
|
}
|
|
6368
|
+
function formatHasRepeatedChar(value, format) {
|
|
6369
|
+
if (!format) {
|
|
6370
|
+
return false;
|
|
6371
|
+
}
|
|
6372
|
+
try {
|
|
6373
|
+
const internalFormat = parseFormat(format);
|
|
6374
|
+
const { format: formatToApply } = getFormatToApply(value, internalFormat);
|
|
6375
|
+
if (formatToApply?.type === "text" || formatToApply?.type === "date") {
|
|
6376
|
+
const tokens = formatToApply.tokens;
|
|
6377
|
+
return tokens.some((token) => token.type === "REPEATED_CHAR");
|
|
6378
|
+
}
|
|
6379
|
+
else if (formatToApply?.type === "number") {
|
|
6380
|
+
return (formatToApply.integerPart.some((token) => token.type === "REPEATED_CHAR") ||
|
|
6381
|
+
(formatToApply.decimalPart
|
|
6382
|
+
? formatToApply.decimalPart.some((token) => token.type === "REPEATED_CHAR")
|
|
6383
|
+
: false));
|
|
6384
|
+
}
|
|
6385
|
+
}
|
|
6386
|
+
catch { }
|
|
6387
|
+
return false;
|
|
6388
|
+
}
|
|
6344
6389
|
|
|
6345
6390
|
function evaluateLiteral(literalCell, localeFormat, position) {
|
|
6346
6391
|
const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
|
|
@@ -6353,6 +6398,9 @@ function parseLiteral(content, locale) {
|
|
|
6353
6398
|
if (content.startsWith("=")) {
|
|
6354
6399
|
throw new Error(`Cannot parse "${content}" because it's not a literal value. It's a formula`);
|
|
6355
6400
|
}
|
|
6401
|
+
if (content.startsWith("'")) {
|
|
6402
|
+
return content.slice(1);
|
|
6403
|
+
}
|
|
6356
6404
|
if (content === "") {
|
|
6357
6405
|
return null;
|
|
6358
6406
|
}
|
|
@@ -9302,6 +9350,32 @@ function getCustomFieldWithParentField(definition, parentField, fields) {
|
|
|
9302
9350
|
groups: [],
|
|
9303
9351
|
});
|
|
9304
9352
|
}
|
|
9353
|
+
function togglePivotCollapse(position, env) {
|
|
9354
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
9355
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
9356
|
+
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
9357
|
+
return;
|
|
9358
|
+
}
|
|
9359
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
9360
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
9361
|
+
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
9362
|
+
: [];
|
|
9363
|
+
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
9364
|
+
if (index !== -1) {
|
|
9365
|
+
collapsedDomains.splice(index, 1);
|
|
9366
|
+
}
|
|
9367
|
+
else {
|
|
9368
|
+
collapsedDomains.push(pivotCell.domain);
|
|
9369
|
+
}
|
|
9370
|
+
const newDomains = definition.collapsedDomains
|
|
9371
|
+
? { ...definition.collapsedDomains }
|
|
9372
|
+
: { COL: [], ROW: [] };
|
|
9373
|
+
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
9374
|
+
env.model.dispatch("UPDATE_PIVOT", {
|
|
9375
|
+
pivotId,
|
|
9376
|
+
pivot: { ...definition, collapsedDomains: newDomains },
|
|
9377
|
+
});
|
|
9378
|
+
}
|
|
9305
9379
|
|
|
9306
9380
|
class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
9307
9381
|
isCutAllowed(data) {
|
|
@@ -9475,7 +9549,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
9475
9549
|
pasteCell(origin, target, clipboardOption) {
|
|
9476
9550
|
const { sheetId, col, row } = target;
|
|
9477
9551
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
9478
|
-
const originFormat = origin?.format
|
|
9552
|
+
const originFormat = origin?.format || origin.evaluatedCell.format;
|
|
9479
9553
|
if (clipboardOption?.pasteOption === "asValue") {
|
|
9480
9554
|
this.dispatch("UPDATE_CELL", {
|
|
9481
9555
|
...target,
|
|
@@ -13701,7 +13775,7 @@ const GROWTH = {
|
|
|
13701
13775
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
13702
13776
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
13703
13777
|
}
|
|
13704
|
-
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "
|
|
13778
|
+
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "known_data_y")), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b)));
|
|
13705
13779
|
},
|
|
13706
13780
|
};
|
|
13707
13781
|
// -----------------------------------------------------------------------------
|
|
@@ -13774,7 +13848,7 @@ const LINEST = {
|
|
|
13774
13848
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13775
13849
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13776
13850
|
}
|
|
13777
|
-
return fullLinearRegression(toNumberMatrix(dataX, "
|
|
13851
|
+
return fullLinearRegression(toNumberMatrix(dataX, "data_x"), toNumberMatrix(dataY, "data_y"), toBoolean(calculateB), toBoolean(verbose));
|
|
13778
13852
|
},
|
|
13779
13853
|
isExported: true,
|
|
13780
13854
|
};
|
|
@@ -13793,7 +13867,7 @@ const LOGEST = {
|
|
|
13793
13867
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13794
13868
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13795
13869
|
}
|
|
13796
|
-
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "
|
|
13870
|
+
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "data_x"), logM(toNumberMatrix(dataY, "data_y")), toBoolean(calculateB), toBoolean(verbose));
|
|
13797
13871
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13798
13872
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
13799
13873
|
}
|
|
@@ -14414,7 +14488,7 @@ const TREND = {
|
|
|
14414
14488
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
14415
14489
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
14416
14490
|
}
|
|
14417
|
-
return predictLinearValues(toNumberMatrix(knownDataY, "
|
|
14491
|
+
return predictLinearValues(toNumberMatrix(knownDataY, "known_data_y"), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b));
|
|
14418
14492
|
},
|
|
14419
14493
|
};
|
|
14420
14494
|
// -----------------------------------------------------------------------------
|
|
@@ -18635,7 +18709,7 @@ function parseOperand(tokens) {
|
|
|
18635
18709
|
case "STRING":
|
|
18636
18710
|
return {
|
|
18637
18711
|
type: "STRING",
|
|
18638
|
-
value:
|
|
18712
|
+
value: unquote(current.value),
|
|
18639
18713
|
tokenStartIndex: current.tokenIndex,
|
|
18640
18714
|
tokenEndIndex: current.tokenIndex,
|
|
18641
18715
|
};
|
|
@@ -22392,7 +22466,7 @@ function formulaArguments(tokens) {
|
|
|
22392
22466
|
dependencies.push(token.value);
|
|
22393
22467
|
break;
|
|
22394
22468
|
case "STRING":
|
|
22395
|
-
const value =
|
|
22469
|
+
const value = unquote(token.value);
|
|
22396
22470
|
literalValues.strings.push({ value });
|
|
22397
22471
|
break;
|
|
22398
22472
|
case "NUMBER": {
|
|
@@ -22935,6 +23009,10 @@ const chartShowValuesPlugin = {
|
|
|
22935
23009
|
}
|
|
22936
23010
|
const ctx = chart.ctx;
|
|
22937
23011
|
ctx.save();
|
|
23012
|
+
const { left, top, height, width } = chart.chartArea;
|
|
23013
|
+
ctx.beginPath();
|
|
23014
|
+
ctx.rect(left, top, width, height);
|
|
23015
|
+
ctx.clip();
|
|
22938
23016
|
ctx.textAlign = "center";
|
|
22939
23017
|
ctx.textBaseline = "middle";
|
|
22940
23018
|
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
@@ -23969,7 +24047,7 @@ class ChartJsComponent extends Component {
|
|
|
23969
24047
|
this.chart.update();
|
|
23970
24048
|
}
|
|
23971
24049
|
hasChartDataChanged() {
|
|
23972
|
-
return !deepEquals(this.currentRuntime
|
|
24050
|
+
return !deepEquals(this.getChartDataInRuntime(this.currentRuntime), this.getChartDataInRuntime(this.chartRuntime));
|
|
23973
24051
|
}
|
|
23974
24052
|
enableAnimationInChartData(chartData) {
|
|
23975
24053
|
return {
|
|
@@ -23977,6 +24055,17 @@ class ChartJsComponent extends Component {
|
|
|
23977
24055
|
options: { ...chartData.options, animation: { animateRotate: true } },
|
|
23978
24056
|
};
|
|
23979
24057
|
}
|
|
24058
|
+
getChartDataInRuntime(runtime) {
|
|
24059
|
+
const data = runtime.chartJsConfig.data;
|
|
24060
|
+
return {
|
|
24061
|
+
labels: data.labels,
|
|
24062
|
+
dataset: data.datasets.map((dataset) => ({
|
|
24063
|
+
data: dataset.data,
|
|
24064
|
+
label: dataset.label,
|
|
24065
|
+
tree: dataset.tree,
|
|
24066
|
+
})),
|
|
24067
|
+
};
|
|
24068
|
+
}
|
|
23980
24069
|
get animationChartId() {
|
|
23981
24070
|
return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
|
|
23982
24071
|
}
|
|
@@ -24644,6 +24733,7 @@ class ScorecardChart extends Component {
|
|
|
24644
24733
|
static template = "o-spreadsheet-ScorecardChart";
|
|
24645
24734
|
static props = {
|
|
24646
24735
|
chartId: String,
|
|
24736
|
+
isFullScreen: { type: Boolean, optional: true },
|
|
24647
24737
|
};
|
|
24648
24738
|
canvas = useRef("chartContainer");
|
|
24649
24739
|
get runtime() {
|
|
@@ -25399,6 +25489,7 @@ function getChartTimeOptions(labels, labelFormat, locale) {
|
|
|
25399
25489
|
parser: luxonFormat,
|
|
25400
25490
|
displayFormats,
|
|
25401
25491
|
unit: timeUnit ?? false,
|
|
25492
|
+
tooltipFormat: luxonFormat,
|
|
25402
25493
|
};
|
|
25403
25494
|
}
|
|
25404
25495
|
/**
|
|
@@ -26467,6 +26558,7 @@ function getLineChartScales(definition, args) {
|
|
|
26467
26558
|
};
|
|
26468
26559
|
Object.assign(scales.x, axis);
|
|
26469
26560
|
scales.x.ticks.maxTicksLimit = 15;
|
|
26561
|
+
delete scales?.x?.ticks?.callback;
|
|
26470
26562
|
}
|
|
26471
26563
|
else if (axisType === "linear") {
|
|
26472
26564
|
scales.x.type = "linear";
|
|
@@ -27407,26 +27499,6 @@ function createBarChartRuntime(chart, getters) {
|
|
|
27407
27499
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
27408
27500
|
}
|
|
27409
27501
|
|
|
27410
|
-
class FullScreenChartStore extends SpreadsheetStore {
|
|
27411
|
-
mutators = ["toggleFullScreenChart"];
|
|
27412
|
-
fullScreenFigure = undefined;
|
|
27413
|
-
toggleFullScreenChart(figureId) {
|
|
27414
|
-
if (this.fullScreenFigure?.id === figureId) {
|
|
27415
|
-
this.fullScreenFigure = undefined;
|
|
27416
|
-
}
|
|
27417
|
-
else {
|
|
27418
|
-
this.makeFullScreen(figureId);
|
|
27419
|
-
}
|
|
27420
|
-
}
|
|
27421
|
-
makeFullScreen(figureId) {
|
|
27422
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
27423
|
-
const figure = this.getters.getFigure(sheetId, figureId);
|
|
27424
|
-
if (figure) {
|
|
27425
|
-
this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
|
|
27426
|
-
}
|
|
27427
|
-
}
|
|
27428
|
-
}
|
|
27429
|
-
|
|
27430
27502
|
const TREND_LINE_AXES_IDS = [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID];
|
|
27431
27503
|
const ZOOMABLE_AXIS_IDS = ["x", ...TREND_LINE_AXES_IDS];
|
|
27432
27504
|
class ZoomableChartStore extends SpreadsheetStore {
|
|
@@ -27591,7 +27663,6 @@ chartJsExtensionRegistry.add("zoomWindowPlugin", {
|
|
|
27591
27663
|
class ZoomableChartJsComponent extends ChartJsComponent {
|
|
27592
27664
|
static template = "o-spreadsheet-ZoomableChartJsComponent";
|
|
27593
27665
|
store;
|
|
27594
|
-
fullScreenChartStore;
|
|
27595
27666
|
masterChartCanvas = useRef("masterChartCanvas");
|
|
27596
27667
|
masterChart;
|
|
27597
27668
|
mode;
|
|
@@ -27602,7 +27673,6 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27602
27673
|
removeEventListeners = () => { };
|
|
27603
27674
|
setup() {
|
|
27604
27675
|
this.store = useStore(ZoomableChartStore);
|
|
27605
|
-
this.fullScreenChartStore = useStore(FullScreenChartStore);
|
|
27606
27676
|
super.setup();
|
|
27607
27677
|
}
|
|
27608
27678
|
unmount() {
|
|
@@ -27617,12 +27687,8 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27617
27687
|
`;
|
|
27618
27688
|
}
|
|
27619
27689
|
get sliceable() {
|
|
27620
|
-
if (this.
|
|
27621
|
-
|
|
27622
|
-
const chartFigureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
27623
|
-
if (fullScreenFigureId === chartFigureId) {
|
|
27624
|
-
return true;
|
|
27625
|
-
}
|
|
27690
|
+
if (this.props.isFullScreen) {
|
|
27691
|
+
return true;
|
|
27626
27692
|
}
|
|
27627
27693
|
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
27628
27694
|
return ("zoomable" in definition && definition?.zoomable) ?? false;
|
|
@@ -27685,9 +27751,6 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27685
27751
|
const xMax = Math.max(...xValues);
|
|
27686
27752
|
return { xMin, xMax };
|
|
27687
27753
|
}
|
|
27688
|
-
get shouldAnimate() {
|
|
27689
|
-
return this.env.model.getters.isDashboard() && !this.sliceable;
|
|
27690
|
-
}
|
|
27691
27754
|
createChart(chartRuntime) {
|
|
27692
27755
|
const chartData = chartRuntime.chartJsConfig;
|
|
27693
27756
|
this.isBarChart = chartData.type === "bar";
|
|
@@ -27706,6 +27769,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27706
27769
|
const masterChartCtx = this.masterChartCanvas.el.getContext("2d");
|
|
27707
27770
|
this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
|
|
27708
27771
|
this.resetAxesLimits();
|
|
27772
|
+
if (this.chart?.options) {
|
|
27773
|
+
this.chart.options.animation = false;
|
|
27774
|
+
}
|
|
27709
27775
|
}
|
|
27710
27776
|
updateChartJs(chartRuntime) {
|
|
27711
27777
|
const chartData = chartRuntime.chartJsConfig;
|
|
@@ -27739,6 +27805,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27739
27805
|
}
|
|
27740
27806
|
}
|
|
27741
27807
|
this.resetAxesLimits();
|
|
27808
|
+
if (this.chart?.options) {
|
|
27809
|
+
this.chart.options.animation = false;
|
|
27810
|
+
}
|
|
27742
27811
|
}
|
|
27743
27812
|
resetAxesLimits() {
|
|
27744
27813
|
if (!this.chart) {
|
|
@@ -27836,7 +27905,7 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27836
27905
|
onPointerDownInMasterChart(ev) {
|
|
27837
27906
|
this.removeEventListeners();
|
|
27838
27907
|
const position = ev.offsetX;
|
|
27839
|
-
if (!this.masterChart?.chartArea || !this.chart?.scales
|
|
27908
|
+
if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
|
|
27840
27909
|
return;
|
|
27841
27910
|
}
|
|
27842
27911
|
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
@@ -31394,6 +31463,26 @@ function getCarouselItemTitle(getters, item) {
|
|
|
31394
31463
|
return matchedChart.displayName;
|
|
31395
31464
|
}
|
|
31396
31465
|
|
|
31466
|
+
class FullScreenFigureStore extends SpreadsheetStore {
|
|
31467
|
+
mutators = ["toggleFullScreenFigure"];
|
|
31468
|
+
fullScreenFigure = undefined;
|
|
31469
|
+
toggleFullScreenFigure(figureId) {
|
|
31470
|
+
if (this.fullScreenFigure?.id === figureId) {
|
|
31471
|
+
this.fullScreenFigure = undefined;
|
|
31472
|
+
}
|
|
31473
|
+
else {
|
|
31474
|
+
this.makeFullScreen(figureId);
|
|
31475
|
+
}
|
|
31476
|
+
}
|
|
31477
|
+
makeFullScreen(figureId) {
|
|
31478
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
31479
|
+
const figure = this.getters.getFigure(sheetId, figureId);
|
|
31480
|
+
if (figure) {
|
|
31481
|
+
this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
|
|
31482
|
+
}
|
|
31483
|
+
}
|
|
31484
|
+
}
|
|
31485
|
+
|
|
31397
31486
|
/**
|
|
31398
31487
|
* This file is largely inspired by owl 1.
|
|
31399
31488
|
* `css` tag has been removed from owl 2 without workaround to manage css.
|
|
@@ -31548,7 +31637,8 @@ class Menu extends Component {
|
|
|
31548
31637
|
const menuItemsAndSeparators = [];
|
|
31549
31638
|
for (let i = 0; i < this.props.menuItems.length; i++) {
|
|
31550
31639
|
const menuItem = this.props.menuItems[i];
|
|
31551
|
-
if (menuItem.isVisible(this.env)
|
|
31640
|
+
if (menuItem.isVisible(this.env) &&
|
|
31641
|
+
(!this.isRoot(menuItem) || this.hasVisibleChildren(menuItem))) {
|
|
31552
31642
|
menuItemsAndSeparators.push(menuItem);
|
|
31553
31643
|
}
|
|
31554
31644
|
if (menuItem.separator &&
|
|
@@ -31590,6 +31680,9 @@ class Menu extends Component {
|
|
|
31590
31680
|
isRoot(menu) {
|
|
31591
31681
|
return !menu.execute;
|
|
31592
31682
|
}
|
|
31683
|
+
hasVisibleChildren(menu) {
|
|
31684
|
+
return menu.children(this.env).some((child) => child.isVisible(this.env));
|
|
31685
|
+
}
|
|
31593
31686
|
isEnabled(menu) {
|
|
31594
31687
|
if (menu.isEnabled(this.env)) {
|
|
31595
31688
|
return this.env.model.getters.isReadonly() ? menu.isReadonlyAllowed : true;
|
|
@@ -32131,12 +32224,13 @@ class MenuPopover extends Component {
|
|
|
32131
32224
|
class ChartDashboardMenu extends Component {
|
|
32132
32225
|
static template = "o-spreadsheet-ChartDashboardMenu";
|
|
32133
32226
|
static components = { MenuPopover };
|
|
32134
|
-
static props = { chartId: String };
|
|
32227
|
+
static props = { chartId: String, hasFullScreenButton: { type: Boolean, optional: true } };
|
|
32228
|
+
static defaultProps = { hasFullScreenButton: true };
|
|
32135
32229
|
fullScreenFigureStore;
|
|
32136
32230
|
menuState = useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
32137
32231
|
setup() {
|
|
32138
32232
|
super.setup();
|
|
32139
|
-
this.fullScreenFigureStore = useStore(
|
|
32233
|
+
this.fullScreenFigureStore = useStore(FullScreenFigureStore);
|
|
32140
32234
|
}
|
|
32141
32235
|
getMenuItems() {
|
|
32142
32236
|
return [this.fullScreenMenuItem].filter(isDefined);
|
|
@@ -32147,11 +32241,14 @@ class ChartDashboardMenu extends Component {
|
|
|
32147
32241
|
}
|
|
32148
32242
|
openContextMenu(ev) {
|
|
32149
32243
|
this.menuState.isOpen = true;
|
|
32150
|
-
this.menuState.anchorRect =
|
|
32244
|
+
this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
|
|
32151
32245
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32152
32246
|
this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
|
|
32153
32247
|
}
|
|
32154
32248
|
get fullScreenMenuItem() {
|
|
32249
|
+
if (!this.props.hasFullScreenButton) {
|
|
32250
|
+
return undefined;
|
|
32251
|
+
}
|
|
32155
32252
|
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
32156
32253
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32157
32254
|
if (definition.type === "scorecard") {
|
|
@@ -32163,7 +32260,7 @@ class ChartDashboardMenu extends Component {
|
|
|
32163
32260
|
label: isFullScreen ? _t("Exit Full Screen") : _t("Full Screen"),
|
|
32164
32261
|
class: `text-muted fa ${isFullScreen ? "fa-compress" : "fa-expand"}`,
|
|
32165
32262
|
onClick: () => {
|
|
32166
|
-
this.fullScreenFigureStore.
|
|
32263
|
+
this.fullScreenFigureStore.toggleFullScreenFigure(figureId);
|
|
32167
32264
|
},
|
|
32168
32265
|
};
|
|
32169
32266
|
}
|
|
@@ -32175,6 +32272,8 @@ class CarouselFigure extends Component {
|
|
|
32175
32272
|
figureUI: Object,
|
|
32176
32273
|
onFigureDeleted: Function,
|
|
32177
32274
|
editFigureStyle: { type: Function, optional: true },
|
|
32275
|
+
isFullScreen: { type: Boolean, optional: true },
|
|
32276
|
+
openContextMenu: { type: Function, optional: true },
|
|
32178
32277
|
};
|
|
32179
32278
|
static components = { ChartDashboardMenu, MenuPopover };
|
|
32180
32279
|
carouselTabsRef = useRef("carouselTabs");
|
|
@@ -32182,8 +32281,10 @@ class CarouselFigure extends Component {
|
|
|
32182
32281
|
menuState = useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
32183
32282
|
hiddenItems = [];
|
|
32184
32283
|
animationStore;
|
|
32284
|
+
fullScreenFigureStore;
|
|
32185
32285
|
setup() {
|
|
32186
32286
|
this.animationStore = useStore(ChartAnimationStore);
|
|
32287
|
+
this.fullScreenFigureStore = useStore(FullScreenFigureStore);
|
|
32187
32288
|
useEffect(() => {
|
|
32188
32289
|
if (this.selectedCarouselItem?.type === "carouselDataView") {
|
|
32189
32290
|
this.props.editFigureStyle?.({ "pointer-events": "none" });
|
|
@@ -32230,7 +32331,8 @@ class CarouselFigure extends Component {
|
|
|
32230
32331
|
item,
|
|
32231
32332
|
});
|
|
32232
32333
|
if (item.type === "chart") {
|
|
32233
|
-
|
|
32334
|
+
const animationChartId = item.chartId + (this.props.isFullScreen ? "-fullscreen" : "");
|
|
32335
|
+
this.animationStore?.enableAnimationForChart(animationChartId);
|
|
32234
32336
|
}
|
|
32235
32337
|
}
|
|
32236
32338
|
get headerStyle() {
|
|
@@ -32294,6 +32396,23 @@ class CarouselFigure extends Component {
|
|
|
32294
32396
|
this.menuState.anchorRect = rect;
|
|
32295
32397
|
this.menuState.menuItems = createActions(menuItems);
|
|
32296
32398
|
}
|
|
32399
|
+
toggleFullScreen() {
|
|
32400
|
+
if (this.selectedCarouselItem?.type === "chart") {
|
|
32401
|
+
this.fullScreenFigureStore.toggleFullScreenFigure(this.props.figureUI.id);
|
|
32402
|
+
}
|
|
32403
|
+
}
|
|
32404
|
+
get fullScreenButtonTitle() {
|
|
32405
|
+
return this.props.isFullScreen ? _t("Exit Full Screen") : _t("Full Screen");
|
|
32406
|
+
}
|
|
32407
|
+
get visibleCarouselItems() {
|
|
32408
|
+
return this.carousel.items.filter((item) => item.type === "carouselDataView" && this.props.isFullScreen ? false : true);
|
|
32409
|
+
}
|
|
32410
|
+
openContextMenu(event) {
|
|
32411
|
+
const target = event.currentTarget;
|
|
32412
|
+
if (target) {
|
|
32413
|
+
this.props.openContextMenu?.(getBoundingRectAsPOJO(target));
|
|
32414
|
+
}
|
|
32415
|
+
}
|
|
32297
32416
|
}
|
|
32298
32417
|
|
|
32299
32418
|
class ChartFigure extends Component {
|
|
@@ -32302,6 +32421,8 @@ class ChartFigure extends Component {
|
|
|
32302
32421
|
figureUI: Object,
|
|
32303
32422
|
onFigureDeleted: Function,
|
|
32304
32423
|
editFigureStyle: { type: Function, optional: true },
|
|
32424
|
+
isFullScreen: { type: Boolean, optional: true },
|
|
32425
|
+
openContextMenu: { type: Function, optional: true },
|
|
32305
32426
|
};
|
|
32306
32427
|
static components = { ChartDashboardMenu };
|
|
32307
32428
|
onDoubleClick() {
|
|
@@ -32334,6 +32455,7 @@ class ImageFigure extends Component {
|
|
|
32334
32455
|
figureUI: Object,
|
|
32335
32456
|
onFigureDeleted: Function,
|
|
32336
32457
|
editFigureStyle: { type: Function, optional: true },
|
|
32458
|
+
openContextMenu: { type: Function, optional: true },
|
|
32337
32459
|
};
|
|
32338
32460
|
static components = {};
|
|
32339
32461
|
// ---------------------------------------------------------------------------
|
|
@@ -32404,9 +32526,7 @@ class FigureComponent extends Component {
|
|
|
32404
32526
|
return this.isSelected ? ACTIVE_BORDER_WIDTH : this.borderWidth;
|
|
32405
32527
|
}
|
|
32406
32528
|
getBorderStyle(position) {
|
|
32407
|
-
|
|
32408
|
-
const borderColor = this.isSelected ? SELECTION_BORDER_COLOR : FIGURE_BORDER_COLOR;
|
|
32409
|
-
return `border-${position}: ${borderWidth}px solid ${borderColor};`;
|
|
32529
|
+
return `border-${position}-width: ${this.getBorderWidth()}px;`;
|
|
32410
32530
|
}
|
|
32411
32531
|
get wrapperStyle() {
|
|
32412
32532
|
const { x, y, width, height } = this.props.figureUI;
|
|
@@ -34138,8 +34258,11 @@ class Composer extends Component {
|
|
|
34138
34258
|
}
|
|
34139
34259
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
34140
34260
|
this.props.composerStore.stopComposerRangeSelection();
|
|
34141
|
-
this.props.
|
|
34142
|
-
this.props.
|
|
34261
|
+
const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
|
|
34262
|
+
this.props.onComposerContentFocused(newSelection);
|
|
34263
|
+
if (!isCurrentlyInactive) {
|
|
34264
|
+
this.props.composerStore.changeComposerCursorSelection(newSelection.start, newSelection.end);
|
|
34265
|
+
}
|
|
34143
34266
|
this.processTokenAtCursor();
|
|
34144
34267
|
}
|
|
34145
34268
|
onDblClick() {
|
|
@@ -34634,13 +34757,6 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34634
34757
|
}
|
|
34635
34758
|
}
|
|
34636
34759
|
startEdition(text, selection) {
|
|
34637
|
-
if (selection) {
|
|
34638
|
-
const content = text || this.getComposerContent(this.getters.getActivePosition());
|
|
34639
|
-
const validSelection = this.isSelectionValid(content.length, selection.start, selection.end);
|
|
34640
|
-
if (!validSelection) {
|
|
34641
|
-
return;
|
|
34642
|
-
}
|
|
34643
|
-
}
|
|
34644
34760
|
const { col, row } = this.getters.getActivePosition();
|
|
34645
34761
|
this.model.dispatch("SELECT_FIGURE", { figureId: null });
|
|
34646
34762
|
this.model.dispatch("SCROLL_TO_CELL", { col, row });
|
|
@@ -34697,7 +34813,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34697
34813
|
// ---------------------------------------------------------------------------
|
|
34698
34814
|
get currentContent() {
|
|
34699
34815
|
if (this.editionMode === "inactive") {
|
|
34700
|
-
return this.getComposerContent(this.getters.getActivePosition());
|
|
34816
|
+
return this.getComposerContent(this.getters.getActivePosition()).text;
|
|
34701
34817
|
}
|
|
34702
34818
|
return this._currentContent;
|
|
34703
34819
|
}
|
|
@@ -34896,8 +35012,9 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34896
35012
|
this.sheetId = sheetId;
|
|
34897
35013
|
this.row = row;
|
|
34898
35014
|
this.editionMode = "editing";
|
|
34899
|
-
|
|
34900
|
-
this.
|
|
35015
|
+
const { text, adjustedSelection } = this.getComposerContent({ sheetId, col, row }, selection);
|
|
35016
|
+
this.initialContent = text;
|
|
35017
|
+
this.setContent(str || this.initialContent, adjustedSelection ?? selection);
|
|
34901
35018
|
this.colorIndexByRange = {};
|
|
34902
35019
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
34903
35020
|
this.captureSelection(zone, col, row);
|
|
@@ -35374,7 +35491,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35374
35491
|
constructor(get, args) {
|
|
35375
35492
|
super(get);
|
|
35376
35493
|
this.args = args;
|
|
35377
|
-
this._currentContent = this.getComposerContent();
|
|
35494
|
+
this._currentContent = this.getComposerContent().text;
|
|
35378
35495
|
}
|
|
35379
35496
|
getAutoCompleteProviders() {
|
|
35380
35497
|
const providersDefinitions = super.getAutoCompleteProviders();
|
|
@@ -35411,7 +35528,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35411
35528
|
})
|
|
35412
35529
|
.join("");
|
|
35413
35530
|
}
|
|
35414
|
-
return localizeContent(content, this.getters.getLocale());
|
|
35531
|
+
return { text: localizeContent(content, this.getters.getLocale()) };
|
|
35415
35532
|
}
|
|
35416
35533
|
stopEdition() {
|
|
35417
35534
|
this._stopEdition();
|
|
@@ -38631,6 +38748,74 @@ function getPath2D(svgPath) {
|
|
|
38631
38748
|
return path2D;
|
|
38632
38749
|
}
|
|
38633
38750
|
|
|
38751
|
+
/**
|
|
38752
|
+
* Get the relative path between two files
|
|
38753
|
+
*
|
|
38754
|
+
* Eg.:
|
|
38755
|
+
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
38756
|
+
*/
|
|
38757
|
+
function getRelativePath(from, to) {
|
|
38758
|
+
const fromPathParts = from.split("/");
|
|
38759
|
+
const toPathParts = to.split("/");
|
|
38760
|
+
let relPath = "";
|
|
38761
|
+
let startIndex = 0;
|
|
38762
|
+
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
38763
|
+
if (fromPathParts[i] === toPathParts[i]) {
|
|
38764
|
+
startIndex++;
|
|
38765
|
+
}
|
|
38766
|
+
else {
|
|
38767
|
+
relPath += "../";
|
|
38768
|
+
}
|
|
38769
|
+
}
|
|
38770
|
+
relPath += toPathParts.slice(startIndex).join("/");
|
|
38771
|
+
return relPath;
|
|
38772
|
+
}
|
|
38773
|
+
/**
|
|
38774
|
+
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
38775
|
+
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
38776
|
+
*
|
|
38777
|
+
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
38778
|
+
*/
|
|
38779
|
+
function arrayToObject(array, indexOffset = 0) {
|
|
38780
|
+
const obj = {};
|
|
38781
|
+
for (let i = 0; i < array.length; i++) {
|
|
38782
|
+
if (array[i]) {
|
|
38783
|
+
obj[i + indexOffset] = array[i];
|
|
38784
|
+
}
|
|
38785
|
+
}
|
|
38786
|
+
return obj;
|
|
38787
|
+
}
|
|
38788
|
+
/**
|
|
38789
|
+
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
38790
|
+
* Replace with characters understandable by JS
|
|
38791
|
+
*/
|
|
38792
|
+
function fixXlsxUnicode(str) {
|
|
38793
|
+
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
38794
|
+
return String.fromCharCode(parseInt(code, 16));
|
|
38795
|
+
});
|
|
38796
|
+
}
|
|
38797
|
+
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
38798
|
+
function getSheetDataHeader(sheetData, dimension, index) {
|
|
38799
|
+
if (dimension === "COL") {
|
|
38800
|
+
if (!sheetData.cols[index]) {
|
|
38801
|
+
sheetData.cols[index] = {};
|
|
38802
|
+
}
|
|
38803
|
+
return sheetData.cols[index];
|
|
38804
|
+
}
|
|
38805
|
+
if (!sheetData.rows[index]) {
|
|
38806
|
+
sheetData.rows[index] = {};
|
|
38807
|
+
}
|
|
38808
|
+
return sheetData.rows[index];
|
|
38809
|
+
}
|
|
38810
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
38811
|
+
function prefixFormulaWithEqual(formula) {
|
|
38812
|
+
if (formula[0] === "=") {
|
|
38813
|
+
return formula;
|
|
38814
|
+
}
|
|
38815
|
+
const tokens = tokenize(formula);
|
|
38816
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
38817
|
+
}
|
|
38818
|
+
|
|
38634
38819
|
/**
|
|
38635
38820
|
* Map of the different types of conversions warnings and their name in error messages
|
|
38636
38821
|
*/
|
|
@@ -39153,66 +39338,6 @@ function hexaToInt(hex) {
|
|
|
39153
39338
|
*/
|
|
39154
39339
|
const DEFAULT_SYSTEM_COLOR = "FF000000";
|
|
39155
39340
|
|
|
39156
|
-
/**
|
|
39157
|
-
* Get the relative path between two files
|
|
39158
|
-
*
|
|
39159
|
-
* Eg.:
|
|
39160
|
-
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
39161
|
-
*/
|
|
39162
|
-
function getRelativePath(from, to) {
|
|
39163
|
-
const fromPathParts = from.split("/");
|
|
39164
|
-
const toPathParts = to.split("/");
|
|
39165
|
-
let relPath = "";
|
|
39166
|
-
let startIndex = 0;
|
|
39167
|
-
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
39168
|
-
if (fromPathParts[i] === toPathParts[i]) {
|
|
39169
|
-
startIndex++;
|
|
39170
|
-
}
|
|
39171
|
-
else {
|
|
39172
|
-
relPath += "../";
|
|
39173
|
-
}
|
|
39174
|
-
}
|
|
39175
|
-
relPath += toPathParts.slice(startIndex).join("/");
|
|
39176
|
-
return relPath;
|
|
39177
|
-
}
|
|
39178
|
-
/**
|
|
39179
|
-
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
39180
|
-
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
39181
|
-
*
|
|
39182
|
-
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
39183
|
-
*/
|
|
39184
|
-
function arrayToObject(array, indexOffset = 0) {
|
|
39185
|
-
const obj = {};
|
|
39186
|
-
for (let i = 0; i < array.length; i++) {
|
|
39187
|
-
if (array[i]) {
|
|
39188
|
-
obj[i + indexOffset] = array[i];
|
|
39189
|
-
}
|
|
39190
|
-
}
|
|
39191
|
-
return obj;
|
|
39192
|
-
}
|
|
39193
|
-
/**
|
|
39194
|
-
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
39195
|
-
* Replace with characters understandable by JS
|
|
39196
|
-
*/
|
|
39197
|
-
function fixXlsxUnicode(str) {
|
|
39198
|
-
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
39199
|
-
return String.fromCharCode(parseInt(code, 16));
|
|
39200
|
-
});
|
|
39201
|
-
}
|
|
39202
|
-
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
39203
|
-
function getSheetDataHeader(sheetData, dimension, index) {
|
|
39204
|
-
if (dimension === "COL") {
|
|
39205
|
-
if (!sheetData.cols[index]) {
|
|
39206
|
-
sheetData.cols[index] = {};
|
|
39207
|
-
}
|
|
39208
|
-
return sheetData.cols[index];
|
|
39209
|
-
}
|
|
39210
|
-
if (!sheetData.rows[index]) {
|
|
39211
|
-
sheetData.rows[index] = {};
|
|
39212
|
-
}
|
|
39213
|
-
return sheetData.rows[index];
|
|
39214
|
-
}
|
|
39215
|
-
|
|
39216
39341
|
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;
|
|
39217
39342
|
/**
|
|
39218
39343
|
* Convert excel format to o_spreadsheet format
|
|
@@ -39427,9 +39552,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
39427
39552
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
39428
39553
|
continue;
|
|
39429
39554
|
operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
|
|
39430
|
-
values.push(
|
|
39555
|
+
values.push(prefixFormulaWithEqual(rule.formula[0]));
|
|
39431
39556
|
if (rule.formula.length === 2) {
|
|
39432
|
-
values.push(
|
|
39557
|
+
values.push(prefixFormulaWithEqual(rule.formula[1]));
|
|
39433
39558
|
}
|
|
39434
39559
|
break;
|
|
39435
39560
|
}
|
|
@@ -39587,11 +39712,6 @@ function convertIcons(xlsxIconSet, index) {
|
|
|
39587
39712
|
? ICON_SETS[iconSet].neutral
|
|
39588
39713
|
: ICON_SETS[iconSet].good;
|
|
39589
39714
|
}
|
|
39590
|
-
/** Prefix the string by "=" if the string looks like a formula */
|
|
39591
|
-
function prefixFormula(formula) {
|
|
39592
|
-
const tokens = tokenize(formula);
|
|
39593
|
-
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
39594
|
-
}
|
|
39595
39715
|
// ---------------------------------------------------------------------------
|
|
39596
39716
|
// Warnings
|
|
39597
39717
|
// ---------------------------------------------------------------------------
|
|
@@ -40067,7 +40187,7 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
40067
40187
|
dvRules.push(decimalRule);
|
|
40068
40188
|
break;
|
|
40069
40189
|
case "list":
|
|
40070
|
-
const listRule =
|
|
40190
|
+
const listRule = convertListRule(dvId++, dv);
|
|
40071
40191
|
dvRules.push(listRule);
|
|
40072
40192
|
break;
|
|
40073
40193
|
case "date":
|
|
@@ -40087,9 +40207,9 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
40087
40207
|
return dvRules;
|
|
40088
40208
|
}
|
|
40089
40209
|
function convertDecimalRule(id, dv) {
|
|
40090
|
-
const values = [dv.formula1.toString()];
|
|
40210
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
40091
40211
|
if (dv.formula2) {
|
|
40092
|
-
values.push(dv.formula2.toString());
|
|
40212
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
40093
40213
|
}
|
|
40094
40214
|
return {
|
|
40095
40215
|
id: id.toString(),
|
|
@@ -40101,7 +40221,7 @@ function convertDecimalRule(id, dv) {
|
|
|
40101
40221
|
},
|
|
40102
40222
|
};
|
|
40103
40223
|
}
|
|
40104
|
-
function
|
|
40224
|
+
function convertListRule(id, dv) {
|
|
40105
40225
|
const formula1 = dv.formula1.toString();
|
|
40106
40226
|
const isRangeRule = rangeReference.test(formula1);
|
|
40107
40227
|
return {
|
|
@@ -40117,9 +40237,9 @@ function convertListrule(id, dv) {
|
|
|
40117
40237
|
}
|
|
40118
40238
|
function convertDateRule(id, dv) {
|
|
40119
40239
|
let criterion;
|
|
40120
|
-
const values = [dv.formula1.toString()];
|
|
40240
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
40121
40241
|
if (dv.formula2) {
|
|
40122
|
-
values.push(dv.formula2.toString());
|
|
40242
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
40123
40243
|
criterion = {
|
|
40124
40244
|
type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
|
|
40125
40245
|
values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
|
|
@@ -40146,7 +40266,7 @@ function convertCustomRule(id, dv) {
|
|
|
40146
40266
|
isBlocking: dv.errorStyle !== "warning",
|
|
40147
40267
|
criterion: {
|
|
40148
40268
|
type: "customFormula",
|
|
40149
|
-
values: [
|
|
40269
|
+
values: [prefixFormulaWithEqual(dv.formula1.toString())],
|
|
40150
40270
|
},
|
|
40151
40271
|
};
|
|
40152
40272
|
}
|
|
@@ -45920,6 +46040,18 @@ class SpreadsheetPivotTable {
|
|
|
45920
46040
|
get numberOfCells() {
|
|
45921
46041
|
return this.rows.length * this.getNumberOfDataColumns();
|
|
45922
46042
|
}
|
|
46043
|
+
getColumnDomainsAtDepth(depth) {
|
|
46044
|
+
if (depth < 0 || depth >= this.columns.length - 1) {
|
|
46045
|
+
return [];
|
|
46046
|
+
}
|
|
46047
|
+
return this.columns[depth].map((col) => this.getDomain(col)).filter((d) => d.length);
|
|
46048
|
+
}
|
|
46049
|
+
getRowDomainsAtDepth(depth) {
|
|
46050
|
+
if (depth < 0 || depth > this.maxIndent) {
|
|
46051
|
+
return [];
|
|
46052
|
+
}
|
|
46053
|
+
return this.rows.filter((row) => row.indent === depth + 1).map((row) => this.getDomain(row));
|
|
46054
|
+
}
|
|
45923
46055
|
}
|
|
45924
46056
|
const EMPTY_PIVOT_CELL = { type: "EMPTY" };
|
|
45925
46057
|
|
|
@@ -46912,6 +47044,109 @@ const ungroupPivotHeadersAction = {
|
|
|
46912
47044
|
return areFieldValuesInGroups(definition, values, field, pivot.getFields());
|
|
46913
47045
|
},
|
|
46914
47046
|
};
|
|
47047
|
+
const toggleCollapsePivotGroupAction = {
|
|
47048
|
+
name: (env) => {
|
|
47049
|
+
const position = env.model.getters.getActivePosition();
|
|
47050
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47051
|
+
if (pivotCellState.isPivotGroup) {
|
|
47052
|
+
return pivotCellState.isCollapsed ? _t("Expand") : _t("Collapse");
|
|
47053
|
+
}
|
|
47054
|
+
return "";
|
|
47055
|
+
},
|
|
47056
|
+
execute(env) {
|
|
47057
|
+
const position = env.model.getters.getActivePosition();
|
|
47058
|
+
togglePivotCollapse(position, env);
|
|
47059
|
+
},
|
|
47060
|
+
isVisible: (env) => {
|
|
47061
|
+
const position = env.model.getters.getActivePosition();
|
|
47062
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47063
|
+
return pivotCellState.isPivotGroup;
|
|
47064
|
+
},
|
|
47065
|
+
};
|
|
47066
|
+
const collapseAllPivotGroupAction = {
|
|
47067
|
+
name: _t("Collapse all"),
|
|
47068
|
+
execute(env) {
|
|
47069
|
+
const position = env.model.getters.getActivePosition();
|
|
47070
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47071
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47072
|
+
return;
|
|
47073
|
+
}
|
|
47074
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47075
|
+
const definition = deepCopy(env.model.getters.getPivotCoreDefinition(pivotId));
|
|
47076
|
+
definition.collapsedDomains = definition.collapsedDomains || { COL: [], ROW: [] };
|
|
47077
|
+
const newCollapsed = [
|
|
47078
|
+
...(definition.collapsedDomains[pivotCell.dimension] || []),
|
|
47079
|
+
...siblingDomains,
|
|
47080
|
+
];
|
|
47081
|
+
const filteredCollapsed = newCollapsed.filter((domain, index) => index === newCollapsed.findIndex((d) => deepEquals(d, domain)));
|
|
47082
|
+
definition.collapsedDomains[pivotCell.dimension] = filteredCollapsed;
|
|
47083
|
+
env.model.dispatch("UPDATE_PIVOT", { pivotId, pivot: definition });
|
|
47084
|
+
},
|
|
47085
|
+
isVisible: (env) => {
|
|
47086
|
+
const position = env.model.getters.getActivePosition();
|
|
47087
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47088
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47089
|
+
return false;
|
|
47090
|
+
}
|
|
47091
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47092
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
47093
|
+
return !siblingDomains.every((domain) => (definition.collapsedDomains?.[pivotCell.dimension] || []).some((d) => deepEquals(d, domain)));
|
|
47094
|
+
},
|
|
47095
|
+
};
|
|
47096
|
+
const expandAllPivotGroupAction = {
|
|
47097
|
+
name: _t("Expand all"),
|
|
47098
|
+
execute(env) {
|
|
47099
|
+
const position = env.model.getters.getActivePosition();
|
|
47100
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47101
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47102
|
+
return;
|
|
47103
|
+
}
|
|
47104
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47105
|
+
const definition = deepCopy(env.model.getters.getPivotCoreDefinition(pivotId));
|
|
47106
|
+
definition.collapsedDomains = definition.collapsedDomains || { COL: [], ROW: [] };
|
|
47107
|
+
const domains = definition.collapsedDomains[pivotCell.dimension] || [];
|
|
47108
|
+
const filteredDomains = domains.filter((domain) => !siblingDomains.find((d) => deepEquals(d, domain)));
|
|
47109
|
+
definition.collapsedDomains[pivotCell.dimension] = filteredDomains;
|
|
47110
|
+
env.model.dispatch("UPDATE_PIVOT", { pivotId, pivot: definition });
|
|
47111
|
+
},
|
|
47112
|
+
isVisible: (env) => {
|
|
47113
|
+
const position = env.model.getters.getActivePosition();
|
|
47114
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47115
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47116
|
+
return false;
|
|
47117
|
+
}
|
|
47118
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47119
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
47120
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension] || [];
|
|
47121
|
+
return collapsedDomains.some((domain) => siblingDomains.some((d) => deepEquals(d, domain)));
|
|
47122
|
+
},
|
|
47123
|
+
};
|
|
47124
|
+
function getPivotCellCollapseState(getters, position) {
|
|
47125
|
+
if (!getters.isSpillPivotFormula(position)) {
|
|
47126
|
+
return { isPivotGroup: false };
|
|
47127
|
+
}
|
|
47128
|
+
const pivotCell = getters.getPivotCellFromPosition(position);
|
|
47129
|
+
const pivotId = getters.getPivotIdFromPosition(position);
|
|
47130
|
+
if (pivotCell.type !== "HEADER" || !pivotId || !pivotCell.domain.length) {
|
|
47131
|
+
return { isPivotGroup: false };
|
|
47132
|
+
}
|
|
47133
|
+
const definition = getters.getPivotCoreDefinition(pivotId);
|
|
47134
|
+
const isDashboard = getters.isDashboard();
|
|
47135
|
+
const fields = pivotCell.dimension === "COL" ? definition.columns : definition.rows;
|
|
47136
|
+
const hasIcon = !isDashboard && pivotCell.domain.length !== fields.length;
|
|
47137
|
+
if (!hasIcon) {
|
|
47138
|
+
return { isPivotGroup: false };
|
|
47139
|
+
}
|
|
47140
|
+
const domains = definition.collapsedDomains?.[pivotCell.dimension] ?? [];
|
|
47141
|
+
const isCollapsed = domains.some((domain) => deepEquals(domain, pivotCell.domain));
|
|
47142
|
+
const pivot = getters.getPivot(pivotId);
|
|
47143
|
+
const table = pivot.getExpandedTableStructure();
|
|
47144
|
+
const depth = pivotCell.domain.length - 1;
|
|
47145
|
+
const siblingDomains = pivotCell.dimension === "ROW"
|
|
47146
|
+
? table.getRowDomainsAtDepth(depth)
|
|
47147
|
+
: table.getColumnDomainsAtDepth(depth);
|
|
47148
|
+
return { isPivotGroup: true, isCollapsed, pivotCell, pivotId, siblingDomains };
|
|
47149
|
+
}
|
|
46915
47150
|
function canSortPivot(getters, position) {
|
|
46916
47151
|
const pivotId = getters.getPivotIdFromPosition(position);
|
|
46917
47152
|
if (!pivotId || !getters.isExistingPivot(pivotId) || !getters.isSpillPivotFormula(position)) {
|
|
@@ -47247,6 +47482,23 @@ cellMenuRegistry
|
|
|
47247
47482
|
sequence: 155,
|
|
47248
47483
|
icon: "o-spreadsheet-Icon.MINUS_IN_BOX",
|
|
47249
47484
|
...ungroupPivotHeadersAction,
|
|
47485
|
+
})
|
|
47486
|
+
.add("collapse_pivot", {
|
|
47487
|
+
sequence: 156,
|
|
47488
|
+
name: _t("Expand/Collapse"),
|
|
47489
|
+
icon: "o-spreadsheet-Icon.COLLAPSE",
|
|
47490
|
+
})
|
|
47491
|
+
.addChild("toggle_collapse_pivot_cell", ["collapse_pivot"], {
|
|
47492
|
+
sequence: 10,
|
|
47493
|
+
...toggleCollapsePivotGroupAction,
|
|
47494
|
+
})
|
|
47495
|
+
.addChild("collapse_all_pivot", ["collapse_pivot"], {
|
|
47496
|
+
sequence: 20,
|
|
47497
|
+
...collapseAllPivotGroupAction,
|
|
47498
|
+
})
|
|
47499
|
+
.addChild("expand_all_pivot", ["collapse_pivot"], {
|
|
47500
|
+
sequence: 30,
|
|
47501
|
+
...expandAllPivotGroupAction,
|
|
47250
47502
|
})
|
|
47251
47503
|
.add("pivot_sorting", {
|
|
47252
47504
|
name: _t("Sort pivot"),
|
|
@@ -47871,6 +48123,7 @@ function createHeaderGroupContainerContextMenu(sheetId, dimension) {
|
|
|
47871
48123
|
execute: (env) => {
|
|
47872
48124
|
env.model.dispatch("UNFOLD_ALL_HEADER_GROUPS", { sheetId, dimension });
|
|
47873
48125
|
},
|
|
48126
|
+
icon: "o-spreadsheet-Icon.EXPAND",
|
|
47874
48127
|
},
|
|
47875
48128
|
{
|
|
47876
48129
|
id: "fold_all",
|
|
@@ -47878,6 +48131,7 @@ function createHeaderGroupContainerContextMenu(sheetId, dimension) {
|
|
|
47878
48131
|
execute: (env) => {
|
|
47879
48132
|
env.model.dispatch("FOLD_ALL_HEADER_GROUPS", { sheetId, dimension });
|
|
47880
48133
|
},
|
|
48134
|
+
icon: "o-spreadsheet-Icon.COLLAPSE",
|
|
47881
48135
|
},
|
|
47882
48136
|
]);
|
|
47883
48137
|
}
|
|
@@ -47899,6 +48153,11 @@ function getHeaderGroupContextMenu(sheetId, dimension, start, end) {
|
|
|
47899
48153
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
47900
48154
|
interactiveToggleGroup(env, sheetId, dimension, start, end);
|
|
47901
48155
|
},
|
|
48156
|
+
icon: (env) => {
|
|
48157
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
48158
|
+
const groupIsFolded = env.model.getters.isGroupFolded(sheetId, dimension, start, end);
|
|
48159
|
+
return groupIsFolded ? "o-spreadsheet-Icon.EXPAND" : "o-spreadsheet-Icon.COLLAPSE";
|
|
48160
|
+
},
|
|
47902
48161
|
},
|
|
47903
48162
|
{
|
|
47904
48163
|
id: "remove_group",
|
|
@@ -47907,6 +48166,7 @@ function getHeaderGroupContextMenu(sheetId, dimension, start, end) {
|
|
|
47907
48166
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
47908
48167
|
env.model.dispatch("UNGROUP_HEADERS", { sheetId, dimension, start, end });
|
|
47909
48168
|
},
|
|
48169
|
+
icon: "o-spreadsheet-Icon.TRASH",
|
|
47910
48170
|
separator: true,
|
|
47911
48171
|
},
|
|
47912
48172
|
]);
|
|
@@ -48769,39 +49029,66 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
48769
49029
|
this.model.dispatch("AUTOFILL_TABLE_COLUMN", { ...this.currentEditedCell });
|
|
48770
49030
|
this.setContent("");
|
|
48771
49031
|
}
|
|
48772
|
-
getComposerContent(position) {
|
|
49032
|
+
getComposerContent(position, selection) {
|
|
48773
49033
|
const locale = this.getters.getLocale();
|
|
48774
49034
|
const cell = this.getters.getCell(position);
|
|
48775
49035
|
if (cell?.isFormula) {
|
|
48776
49036
|
const prettifiedContent = this.getPrettifiedFormula(cell);
|
|
48777
|
-
|
|
49037
|
+
// when a formula is prettified (multi lines, indented), adapt the cursor position
|
|
49038
|
+
// to take into account line breaks and tabs
|
|
49039
|
+
function adjustCursorIndex(targetIndex) {
|
|
49040
|
+
let adjustedIndex = 0;
|
|
49041
|
+
let originalIndex = 0;
|
|
49042
|
+
while (originalIndex < targetIndex) {
|
|
49043
|
+
adjustedIndex++;
|
|
49044
|
+
const char = prettifiedContent[adjustedIndex];
|
|
49045
|
+
if (char !== "\n" && char !== "\t") {
|
|
49046
|
+
originalIndex++;
|
|
49047
|
+
}
|
|
49048
|
+
}
|
|
49049
|
+
return adjustedIndex;
|
|
49050
|
+
}
|
|
49051
|
+
let adjustedSelection = selection;
|
|
49052
|
+
if (selection) {
|
|
49053
|
+
adjustedSelection = {
|
|
49054
|
+
start: adjustCursorIndex(selection.start),
|
|
49055
|
+
end: adjustCursorIndex(selection.end),
|
|
49056
|
+
};
|
|
49057
|
+
}
|
|
49058
|
+
return {
|
|
49059
|
+
text: localizeFormula(prettifiedContent, locale),
|
|
49060
|
+
adjustedSelection,
|
|
49061
|
+
};
|
|
48778
49062
|
}
|
|
48779
49063
|
const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
|
|
48780
49064
|
if (spreader) {
|
|
48781
|
-
return "";
|
|
49065
|
+
return { text: "" };
|
|
49066
|
+
}
|
|
49067
|
+
if (cell?.content.startsWith("'")) {
|
|
49068
|
+
return { text: cell.content };
|
|
48782
49069
|
}
|
|
48783
49070
|
const { format, value, type, formattedValue } = this.getters.getEvaluatedCell(position);
|
|
48784
49071
|
switch (type) {
|
|
48785
49072
|
case CellValueType.empty:
|
|
48786
|
-
return "";
|
|
49073
|
+
return { text: "" };
|
|
48787
49074
|
case CellValueType.text:
|
|
48788
49075
|
case CellValueType.error:
|
|
48789
|
-
return value;
|
|
49076
|
+
return { text: value };
|
|
48790
49077
|
case CellValueType.boolean:
|
|
48791
|
-
return formattedValue;
|
|
49078
|
+
return { text: formattedValue };
|
|
48792
49079
|
case CellValueType.number:
|
|
48793
49080
|
if (format && isDateTimeFormat(format)) {
|
|
48794
49081
|
if (parseDateTime(formattedValue, locale) !== null) {
|
|
48795
49082
|
// formatted string can be parsed again
|
|
48796
|
-
return formattedValue;
|
|
49083
|
+
return { text: formattedValue };
|
|
48797
49084
|
}
|
|
48798
49085
|
// display a simplified and parsable string otherwise
|
|
48799
49086
|
const timeFormat = Number.isInteger(value)
|
|
48800
49087
|
? locale.dateFormat
|
|
48801
49088
|
: getDateTimeFormat(locale);
|
|
48802
|
-
return formatValue(value, { locale, format: timeFormat });
|
|
49089
|
+
return { text: formatValue(value, { locale, format: timeFormat }) };
|
|
48803
49090
|
}
|
|
48804
|
-
return this.numberComposerContent(value, format, locale);
|
|
49091
|
+
return { text: this.numberComposerContent(value, format, locale) };
|
|
48805
49092
|
}
|
|
48806
49093
|
}
|
|
48807
49094
|
getPrettifiedFormula(cell) {
|
|
@@ -48948,8 +49235,9 @@ class GridComposer extends Component {
|
|
|
48948
49235
|
},
|
|
48949
49236
|
focus: this.focus,
|
|
48950
49237
|
isDefaultFocus: true,
|
|
48951
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
49238
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
48952
49239
|
focusMode: "contentFocus",
|
|
49240
|
+
selection,
|
|
48953
49241
|
}),
|
|
48954
49242
|
onComposerCellFocused: (content) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
48955
49243
|
focusMode: "cellFocus",
|
|
@@ -51342,6 +51630,9 @@ class GridRenderer extends SpreadsheetStore {
|
|
|
51342
51630
|
}
|
|
51343
51631
|
const { align } = this.getters.getCellStyle(position);
|
|
51344
51632
|
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
51633
|
+
if (formatHasRepeatedChar(evaluatedCell.value, evaluatedCell.format)) {
|
|
51634
|
+
return "left";
|
|
51635
|
+
}
|
|
51345
51636
|
if (isOverflowing && evaluatedCell.type === CellValueType.number) {
|
|
51346
51637
|
return align !== "center" ? "left" : align;
|
|
51347
51638
|
}
|
|
@@ -55634,12 +55925,13 @@ class DataValidationEditor extends Component {
|
|
|
55634
55925
|
onCloseSidePanel: { type: Function, optional: true },
|
|
55635
55926
|
};
|
|
55636
55927
|
state = useState({ rule: this.defaultDataValidationRule, errors: [] });
|
|
55928
|
+
editingSheetId;
|
|
55637
55929
|
setup() {
|
|
55930
|
+
this.editingSheetId = this.env.model.getters.getActiveSheetId();
|
|
55638
55931
|
if (this.props.rule) {
|
|
55639
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
55640
55932
|
this.state.rule = {
|
|
55641
55933
|
...this.props.rule,
|
|
55642
|
-
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range,
|
|
55934
|
+
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
|
|
55643
55935
|
};
|
|
55644
55936
|
this.state.rule.criterion.type = this.props.rule.criterion.type;
|
|
55645
55937
|
}
|
|
@@ -55673,7 +55965,6 @@ class DataValidationEditor extends Component {
|
|
|
55673
55965
|
const locale = this.env.model.getters.getLocale();
|
|
55674
55966
|
const criterion = rule.criterion;
|
|
55675
55967
|
const criterionEvaluator = criterionEvaluatorRegistry.get(criterion.type);
|
|
55676
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
55677
55968
|
const values = criterion.values
|
|
55678
55969
|
.slice(0, criterionEvaluator.numberOfValues(criterion))
|
|
55679
55970
|
.map((value) => value?.trim())
|
|
@@ -55681,8 +55972,8 @@ class DataValidationEditor extends Component {
|
|
|
55681
55972
|
.map((value) => canonicalizeContent(value, locale));
|
|
55682
55973
|
rule.criterion = { ...criterion, values };
|
|
55683
55974
|
return {
|
|
55684
|
-
sheetId,
|
|
55685
|
-
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(
|
|
55975
|
+
sheetId: this.editingSheetId,
|
|
55976
|
+
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(this.editingSheetId, xc)),
|
|
55686
55977
|
rule,
|
|
55687
55978
|
};
|
|
55688
55979
|
}
|
|
@@ -56813,7 +57104,7 @@ class PivotMeasureEditor extends Component {
|
|
|
56813
57104
|
return undefined;
|
|
56814
57105
|
}
|
|
56815
57106
|
get isCalculatedMeasureInvalid() {
|
|
56816
|
-
return
|
|
57107
|
+
return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
|
|
56817
57108
|
}
|
|
56818
57109
|
}
|
|
56819
57110
|
|
|
@@ -59528,16 +59819,16 @@ class ClickableCellSortIcon extends Component {
|
|
|
59528
59819
|
}
|
|
59529
59820
|
}
|
|
59530
59821
|
|
|
59531
|
-
class
|
|
59532
|
-
static template = "o-spreadsheet-
|
|
59822
|
+
class FullScreenFigure extends Component {
|
|
59823
|
+
static template = "o-spreadsheet-FullScreenFigure";
|
|
59533
59824
|
static props = {};
|
|
59534
|
-
static components = {
|
|
59535
|
-
|
|
59536
|
-
ref = useRef("
|
|
59825
|
+
static components = { ChartFigure };
|
|
59826
|
+
fullScreenFigureStore;
|
|
59827
|
+
ref = useRef("fullScreenFigure");
|
|
59537
59828
|
spreadsheetRect = useSpreadsheetRect();
|
|
59538
59829
|
figureRegistry = figureRegistry;
|
|
59539
59830
|
setup() {
|
|
59540
|
-
this.
|
|
59831
|
+
this.fullScreenFigureStore = useStore(FullScreenFigureStore);
|
|
59541
59832
|
const animationStore = useStore(ChartAnimationStore);
|
|
59542
59833
|
let lastFigureId = undefined;
|
|
59543
59834
|
onWillUpdateProps(() => {
|
|
@@ -59549,7 +59840,7 @@ class FullScreenChart extends Component {
|
|
|
59549
59840
|
useEffect((el) => el?.focus(), () => [this.ref.el]);
|
|
59550
59841
|
}
|
|
59551
59842
|
get figureUI() {
|
|
59552
|
-
return this.
|
|
59843
|
+
return this.fullScreenFigureStore.fullScreenFigure;
|
|
59553
59844
|
}
|
|
59554
59845
|
get chartId() {
|
|
59555
59846
|
if (!this.figureUI)
|
|
@@ -59558,7 +59849,7 @@ class FullScreenChart extends Component {
|
|
|
59558
59849
|
}
|
|
59559
59850
|
exitFullScreen() {
|
|
59560
59851
|
if (this.figureUI) {
|
|
59561
|
-
this.
|
|
59852
|
+
this.fullScreenFigureStore.toggleFullScreenFigure(this.figureUI.id);
|
|
59562
59853
|
}
|
|
59563
59854
|
}
|
|
59564
59855
|
onKeyDown(ev) {
|
|
@@ -59566,15 +59857,10 @@ class FullScreenChart extends Component {
|
|
|
59566
59857
|
this.exitFullScreen();
|
|
59567
59858
|
}
|
|
59568
59859
|
}
|
|
59569
|
-
get
|
|
59570
|
-
if (!this.
|
|
59860
|
+
get figureComponent() {
|
|
59861
|
+
if (!this.figureUI)
|
|
59571
59862
|
return undefined;
|
|
59572
|
-
|
|
59573
|
-
const component = chartComponentRegistry.get(type);
|
|
59574
|
-
if (!component) {
|
|
59575
|
-
throw new Error(`Component is not defined for type ${type}`);
|
|
59576
|
-
}
|
|
59577
|
-
return component;
|
|
59863
|
+
return figureRegistry.get(this.figureUI.tag).Component;
|
|
59578
59864
|
}
|
|
59579
59865
|
}
|
|
59580
59866
|
|
|
@@ -60797,7 +61083,7 @@ class CellPlugin extends CorePlugin {
|
|
|
60797
61083
|
(typeof parsedValue === "number"
|
|
60798
61084
|
? detectDateFormat(content, locale) || detectNumberFormat(content)
|
|
60799
61085
|
: undefined);
|
|
60800
|
-
if (!isTextFormat(format) && !isEvaluationError(content)) {
|
|
61086
|
+
if (!isTextFormat(format) && !content.startsWith("'") && !isEvaluationError(content)) {
|
|
60801
61087
|
content = toString(parsedValue);
|
|
60802
61088
|
}
|
|
60803
61089
|
return {
|
|
@@ -62277,11 +62563,11 @@ class HeaderSizePlugin extends CorePlugin {
|
|
|
62277
62563
|
break;
|
|
62278
62564
|
}
|
|
62279
62565
|
case "ADD_COLUMNS_ROWS": {
|
|
62280
|
-
const sizes =
|
|
62566
|
+
const sizes = this.sizes[cmd.sheetId][cmd.dimension];
|
|
62281
62567
|
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
62282
62568
|
const baseSize = sizes[cmd.base];
|
|
62283
|
-
sizes
|
|
62284
|
-
this.history.update("sizes", cmd.sheetId, cmd.dimension,
|
|
62569
|
+
const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
|
|
62570
|
+
this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
|
|
62285
62571
|
break;
|
|
62286
62572
|
}
|
|
62287
62573
|
case "RESIZE_COLUMNS_ROWS":
|
|
@@ -62432,9 +62718,8 @@ class HeaderVisibilityPlugin extends CorePlugin {
|
|
|
62432
62718
|
break;
|
|
62433
62719
|
}
|
|
62434
62720
|
case "ADD_COLUMNS_ROWS": {
|
|
62435
|
-
const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
|
|
62436
62721
|
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
62437
|
-
hiddenHeaders.
|
|
62722
|
+
const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
|
|
62438
62723
|
this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
|
|
62439
62724
|
break;
|
|
62440
62725
|
}
|
|
@@ -66618,12 +66903,12 @@ class SpreadsheetRTree {
|
|
|
66618
66903
|
this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
|
|
66619
66904
|
}
|
|
66620
66905
|
rtreeItemComparer(left, right) {
|
|
66621
|
-
return (left.
|
|
66622
|
-
left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
66906
|
+
return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
66623
66907
|
left.boundingBox?.zone.left === right.boundingBox.zone.left &&
|
|
66624
66908
|
left.boundingBox?.zone.top === right.boundingBox.zone.top &&
|
|
66625
66909
|
left.boundingBox?.zone.right === right.boundingBox.zone.right &&
|
|
66626
|
-
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom
|
|
66910
|
+
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
|
|
66911
|
+
deepEquals(left.data, right.data));
|
|
66627
66912
|
}
|
|
66628
66913
|
}
|
|
66629
66914
|
/**
|
|
@@ -66696,7 +66981,7 @@ class FormulaDependencyGraph {
|
|
|
66696
66981
|
* in the correct order they should be evaluated.
|
|
66697
66982
|
* This is called a topological ordering (excluding cycles)
|
|
66698
66983
|
*/
|
|
66699
|
-
getCellsDependingOn(ranges) {
|
|
66984
|
+
getCellsDependingOn(ranges, ignore) {
|
|
66700
66985
|
const visited = this.createEmptyPositionSet();
|
|
66701
66986
|
const queue = Array.from(ranges).reverse();
|
|
66702
66987
|
while (queue.length > 0) {
|
|
@@ -66711,7 +66996,7 @@ class FormulaDependencyGraph {
|
|
|
66711
66996
|
const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
|
|
66712
66997
|
const nextInQueue = {};
|
|
66713
66998
|
for (const position of impactedPositions) {
|
|
66714
|
-
if (!visited.has(position)) {
|
|
66999
|
+
if (!visited.has(position) && !ignore.has(position)) {
|
|
66715
67000
|
if (!nextInQueue[position.sheetId]) {
|
|
66716
67001
|
nextInQueue[position.sheetId] = [];
|
|
66717
67002
|
}
|
|
@@ -67269,7 +67554,7 @@ class Evaluator {
|
|
|
67269
67554
|
}
|
|
67270
67555
|
invalidatePositionsDependingOnSpread(sheetId, resultZone) {
|
|
67271
67556
|
// the result matrix is split in 2 zones to exclude the array formula position
|
|
67272
|
-
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
|
|
67557
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })), this.nextPositionsToUpdate);
|
|
67273
67558
|
invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
|
|
67274
67559
|
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
67275
67560
|
}
|
|
@@ -67387,7 +67672,7 @@ class Evaluator {
|
|
|
67387
67672
|
for (const sheetId in zonesBySheetIds) {
|
|
67388
67673
|
ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
|
|
67389
67674
|
}
|
|
67390
|
-
return this.formulaDependencies().getCellsDependingOn(ranges);
|
|
67675
|
+
return this.formulaDependencies().getCellsDependingOn(ranges, this.nextPositionsToUpdate);
|
|
67391
67676
|
}
|
|
67392
67677
|
}
|
|
67393
67678
|
function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
@@ -68654,32 +68939,6 @@ iconsOnCellRegistry.add("pivot_collapse", (getters, position) => {
|
|
|
68654
68939
|
}
|
|
68655
68940
|
return undefined;
|
|
68656
68941
|
});
|
|
68657
|
-
function togglePivotCollapse(position, env) {
|
|
68658
|
-
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
68659
|
-
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
68660
|
-
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
68661
|
-
return;
|
|
68662
|
-
}
|
|
68663
|
-
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
68664
|
-
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
68665
|
-
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
68666
|
-
: [];
|
|
68667
|
-
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
68668
|
-
if (index !== -1) {
|
|
68669
|
-
collapsedDomains.splice(index, 1);
|
|
68670
|
-
}
|
|
68671
|
-
else {
|
|
68672
|
-
collapsedDomains.push(pivotCell.domain);
|
|
68673
|
-
}
|
|
68674
|
-
const newDomains = definition.collapsedDomains
|
|
68675
|
-
? { ...definition.collapsedDomains }
|
|
68676
|
-
: { COL: [], ROW: [] };
|
|
68677
|
-
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
68678
|
-
env.model.dispatch("UPDATE_PIVOT", {
|
|
68679
|
-
pivotId,
|
|
68680
|
-
pivot: { ...definition, collapsedDomains: newDomains },
|
|
68681
|
-
});
|
|
68682
|
-
}
|
|
68683
68942
|
iconsOnCellRegistry.add("pivot_dashboard_sorting", (getters, position) => {
|
|
68684
68943
|
if (!getters.isDashboard()) {
|
|
68685
68944
|
return undefined;
|
|
@@ -68898,7 +69157,8 @@ class DynamicTablesPlugin extends CoreViewPlugin {
|
|
|
68898
69157
|
const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
|
|
68899
69158
|
const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
|
|
68900
69159
|
if (!parentSpreadingCell) {
|
|
68901
|
-
|
|
69160
|
+
const evaluatedCell = this.getters.getEvaluatedCell(topLeft);
|
|
69161
|
+
return (evaluatedCell.value === CellErrorType.SpilledBlocked && !evaluatedCell.errorOriginPosition);
|
|
68902
69162
|
}
|
|
68903
69163
|
else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
|
|
68904
69164
|
return true;
|
|
@@ -79471,8 +79731,8 @@ class RowGroup extends AbstractHeaderGroup {
|
|
|
79471
79731
|
left: `calc(50% - 1px)`, // -1px: we want the border to be on the center
|
|
79472
79732
|
width: `30%`,
|
|
79473
79733
|
height: `calc(100% - ${groupBox.headerRect.height / 2}px)`,
|
|
79474
|
-
"border-left": `1px solid
|
|
79475
|
-
"border-bottom": groupBox.isEndHidden ? "" : `1px solid
|
|
79734
|
+
"border-left": `1px solid`,
|
|
79735
|
+
"border-bottom": groupBox.isEndHidden ? "" : `1px solid`,
|
|
79476
79736
|
});
|
|
79477
79737
|
}
|
|
79478
79738
|
get groupHeaderStyle() {
|
|
@@ -79524,8 +79784,8 @@ class ColGroup extends AbstractHeaderGroup {
|
|
|
79524
79784
|
left: `${groupBox.headerRect.width / 2}px`,
|
|
79525
79785
|
width: `calc(100% - ${groupBox.headerRect.width / 2}px)`,
|
|
79526
79786
|
height: `30%`,
|
|
79527
|
-
"border-top": `1px solid
|
|
79528
|
-
"border-right": groupBox.isEndHidden ? "" : `1px solid
|
|
79787
|
+
"border-top": `1px solid`,
|
|
79788
|
+
"border-right": groupBox.isEndHidden ? "" : `1px solid`,
|
|
79529
79789
|
});
|
|
79530
79790
|
}
|
|
79531
79791
|
get groupHeaderStyle() {
|
|
@@ -79764,6 +80024,7 @@ class RibbonMenu extends Component {
|
|
|
79764
80024
|
static components = { Menu };
|
|
79765
80025
|
rootItems = topbarMenuRegistry.getMenuItems();
|
|
79766
80026
|
menuRef = useRef("menu");
|
|
80027
|
+
containerRef = useRef("container");
|
|
79767
80028
|
state = useState({
|
|
79768
80029
|
menuItems: this.rootItems,
|
|
79769
80030
|
title: _t("Menu Bar"),
|
|
@@ -79771,6 +80032,7 @@ class RibbonMenu extends Component {
|
|
|
79771
80032
|
});
|
|
79772
80033
|
setup() {
|
|
79773
80034
|
useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
80035
|
+
onMounted(this.updateShadows);
|
|
79774
80036
|
}
|
|
79775
80037
|
onExternalClick(ev) {
|
|
79776
80038
|
if (!this.menuRef.el?.contains(ev.target)) {
|
|
@@ -79783,6 +80045,7 @@ class RibbonMenu extends Component {
|
|
|
79783
80045
|
this.state.parentState = { ...this.state };
|
|
79784
80046
|
this.state.menuItems = children;
|
|
79785
80047
|
this.state.title = menu.name(this.env);
|
|
80048
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
79786
80049
|
}
|
|
79787
80050
|
else {
|
|
79788
80051
|
this.state.menuItems = this.rootItems;
|
|
@@ -79804,6 +80067,19 @@ class RibbonMenu extends Component {
|
|
|
79804
80067
|
height: `${this.props.height}px`,
|
|
79805
80068
|
});
|
|
79806
80069
|
}
|
|
80070
|
+
updateShadows() {
|
|
80071
|
+
if (!this.containerRef.el) {
|
|
80072
|
+
return;
|
|
80073
|
+
}
|
|
80074
|
+
this.containerRef.el.classList.remove("scroll-top", "scroll-bottom");
|
|
80075
|
+
const maxScroll = this.containerRef.el.scrollHeight - this.containerRef.el.clientHeight || 0;
|
|
80076
|
+
if (this.containerRef.el.scrollTop < maxScroll - 1) {
|
|
80077
|
+
this.containerRef.el.classList.add("scroll-bottom");
|
|
80078
|
+
}
|
|
80079
|
+
if (this.containerRef.el.scrollTop > 0) {
|
|
80080
|
+
this.containerRef.el.classList.add("scroll-top");
|
|
80081
|
+
}
|
|
80082
|
+
}
|
|
79807
80083
|
onClickBack() {
|
|
79808
80084
|
if (!this.state.parentState) {
|
|
79809
80085
|
this.props.onClose();
|
|
@@ -79812,6 +80088,7 @@ class RibbonMenu extends Component {
|
|
|
79812
80088
|
this.state.menuItems = this.state.parentState.menuItems;
|
|
79813
80089
|
this.state.title = this.state.parentState.title;
|
|
79814
80090
|
this.state.parentState = this.state.parentState.parentState;
|
|
80091
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
79815
80092
|
}
|
|
79816
80093
|
get backTitle() {
|
|
79817
80094
|
return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
|
|
@@ -79862,6 +80139,11 @@ class SmallBottomBar extends Component {
|
|
|
79862
80139
|
? this.composerFocusStore.focusMode
|
|
79863
80140
|
: "inactive";
|
|
79864
80141
|
}
|
|
80142
|
+
get showFxIcon() {
|
|
80143
|
+
return (this.focus === "inactive" &&
|
|
80144
|
+
!this.composerStore.currentContent &&
|
|
80145
|
+
!this.composerStore.placeholder);
|
|
80146
|
+
}
|
|
79865
80147
|
get rect() {
|
|
79866
80148
|
return this.composerRef.el
|
|
79867
80149
|
? getBoundingRectAsPOJO(this.composerRef.el)
|
|
@@ -79877,8 +80159,9 @@ class SmallBottomBar extends Component {
|
|
|
79877
80159
|
},
|
|
79878
80160
|
focus: this.focus,
|
|
79879
80161
|
composerStore: this.composerStore,
|
|
79880
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
80162
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
79881
80163
|
focusMode: "contentFocus",
|
|
80164
|
+
selection,
|
|
79882
80165
|
}),
|
|
79883
80166
|
isDefaultFocus: false,
|
|
79884
80167
|
inputStyle: cssPropertiesToCss({
|
|
@@ -79886,6 +80169,7 @@ class SmallBottomBar extends Component {
|
|
|
79886
80169
|
"max-height": `130px`,
|
|
79887
80170
|
}),
|
|
79888
80171
|
showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
|
|
80172
|
+
placeholder: this.composerStore.placeholder,
|
|
79889
80173
|
};
|
|
79890
80174
|
}
|
|
79891
80175
|
get symbols() {
|
|
@@ -79904,13 +80188,6 @@ class SmallBottomBar extends Component {
|
|
|
79904
80188
|
}
|
|
79905
80189
|
|
|
79906
80190
|
const COMPOSER_MAX_HEIGHT = 300;
|
|
79907
|
-
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
79908
|
-
// FIXME This svg is hardcoded in the css file. We should find a better way to handle it.
|
|
79909
|
-
// const FX_SVG = /*xml*/ `
|
|
79910
|
-
// <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
|
|
79911
|
-
// <path d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='#BDBDBD'/>
|
|
79912
|
-
// </svg>
|
|
79913
|
-
// `;
|
|
79914
80191
|
class TopBarComposer extends Component {
|
|
79915
80192
|
static template = "o-spreadsheet-TopBarComposer";
|
|
79916
80193
|
static props = {};
|
|
@@ -79937,6 +80214,11 @@ class TopBarComposer extends Component {
|
|
|
79937
80214
|
? this.composerFocusStore.focusMode
|
|
79938
80215
|
: "inactive";
|
|
79939
80216
|
}
|
|
80217
|
+
get showFxIcon() {
|
|
80218
|
+
return (this.focus === "inactive" &&
|
|
80219
|
+
!this.composerStore.currentContent &&
|
|
80220
|
+
!this.composerStore.placeholder);
|
|
80221
|
+
}
|
|
79940
80222
|
get composerStyle() {
|
|
79941
80223
|
const style = {
|
|
79942
80224
|
padding: "5px 0px 5px 8px",
|
|
@@ -80874,7 +81156,7 @@ class Spreadsheet extends Component {
|
|
|
80874
81156
|
SidePanels,
|
|
80875
81157
|
SpreadsheetDashboard,
|
|
80876
81158
|
HeaderGroupContainer,
|
|
80877
|
-
|
|
81159
|
+
FullScreenFigure,
|
|
80878
81160
|
};
|
|
80879
81161
|
sidePanel;
|
|
80880
81162
|
spreadsheetRef = useRef("spreadsheet");
|
|
@@ -85598,6 +85880,7 @@ const components = {
|
|
|
85598
85880
|
Grid,
|
|
85599
85881
|
GridOverlay,
|
|
85600
85882
|
ScorecardChart,
|
|
85883
|
+
GaugeChartComponent,
|
|
85601
85884
|
LineConfigPanel,
|
|
85602
85885
|
BarConfigPanel,
|
|
85603
85886
|
PieChartDesignPanel,
|
|
@@ -85636,7 +85919,7 @@ const components = {
|
|
|
85636
85919
|
RadioSelection,
|
|
85637
85920
|
GeoChartRegionSelectSection,
|
|
85638
85921
|
ChartDashboardMenu,
|
|
85639
|
-
|
|
85922
|
+
FullScreenFigure,
|
|
85640
85923
|
};
|
|
85641
85924
|
const hooks = {
|
|
85642
85925
|
useDragAndDropListItems,
|
|
@@ -85686,6 +85969,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
85686
85969
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
85687
85970
|
|
|
85688
85971
|
|
|
85689
|
-
__info__.version = "19.1.0-alpha.
|
|
85690
|
-
__info__.date = "2025-
|
|
85691
|
-
__info__.hash = "
|
|
85972
|
+
__info__.version = "19.1.0-alpha.5";
|
|
85973
|
+
__info__.date = "2025-10-16T06:39:55.925Z";
|
|
85974
|
+
__info__.hash = "1a0e3d5";
|