@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
|
'use strict';
|
|
@@ -593,7 +593,6 @@ const BACKGROUND_HEADER_COLOR = "#F8F9FA";
|
|
|
593
593
|
const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
|
|
594
594
|
const BACKGROUND_HEADER_ACTIVE_COLOR = "#595959";
|
|
595
595
|
const TEXT_HEADER_COLOR = "#666666";
|
|
596
|
-
const FIGURE_BORDER_COLOR = "#c9ccd2";
|
|
597
596
|
const SELECTION_BORDER_COLOR = "#3266ca";
|
|
598
597
|
const HEADER_BORDER_COLOR = "#C0C0C0";
|
|
599
598
|
const CELL_BORDER_COLOR = "#E2E3E3";
|
|
@@ -601,7 +600,6 @@ const BACKGROUND_CHART_COLOR = "#FFFFFF";
|
|
|
601
600
|
const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
|
|
602
601
|
const LINK_COLOR = HIGHLIGHT_COLOR;
|
|
603
602
|
const FILTERS_COLOR = "#188038";
|
|
604
|
-
const HEADER_GROUPING_BORDER_COLOR = "#999";
|
|
605
603
|
const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
|
|
606
604
|
const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
|
|
607
605
|
const COMPOSER_ASSISTANT_COLOR = "#9B359B";
|
|
@@ -844,22 +842,6 @@ const DRAG_THRESHOLD = 5; // in pixels, to avoid unwanted drag when clicking
|
|
|
844
842
|
// Miscellaneous
|
|
845
843
|
//------------------------------------------------------------------------------
|
|
846
844
|
const sanitizeSheetNameRegex = new RegExp(FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX, "g");
|
|
847
|
-
/**
|
|
848
|
-
* Remove quotes from a quoted string
|
|
849
|
-
* ```js
|
|
850
|
-
* removeStringQuotes('"Hello"')
|
|
851
|
-
* > 'Hello'
|
|
852
|
-
* ```
|
|
853
|
-
*/
|
|
854
|
-
function removeStringQuotes(str) {
|
|
855
|
-
if (str[0] === '"') {
|
|
856
|
-
str = str.slice(1);
|
|
857
|
-
}
|
|
858
|
-
if (str[str.length - 1] === '"' && str[str.length - 2] !== "\\") {
|
|
859
|
-
return str.slice(0, str.length - 1);
|
|
860
|
-
}
|
|
861
|
-
return str;
|
|
862
|
-
}
|
|
863
845
|
function isCloneable(obj) {
|
|
864
846
|
return "clone" in obj && obj.clone instanceof Function;
|
|
865
847
|
}
|
|
@@ -928,6 +910,13 @@ function isPlainObject(obj) {
|
|
|
928
910
|
function getUnquotedSheetName(sheetName) {
|
|
929
911
|
return unquote(sheetName, "'");
|
|
930
912
|
}
|
|
913
|
+
/**
|
|
914
|
+
* Remove quotes from a quoted string
|
|
915
|
+
* ```js
|
|
916
|
+
* unquote('"Hello"')
|
|
917
|
+
* > 'Hello'
|
|
918
|
+
* ```
|
|
919
|
+
*/
|
|
931
920
|
function unquote(string, quoteChar = '"') {
|
|
932
921
|
if (string.startsWith(quoteChar)) {
|
|
933
922
|
string = string.slice(1);
|
|
@@ -1332,9 +1321,7 @@ function removeIndexesFromArray(array, indexes) {
|
|
|
1332
1321
|
return newArray;
|
|
1333
1322
|
}
|
|
1334
1323
|
function insertItemsAtIndex(array, items, index) {
|
|
1335
|
-
|
|
1336
|
-
newArray.splice(index, 0, ...items);
|
|
1337
|
-
return newArray;
|
|
1324
|
+
return array.slice(0, index).concat(items).concat(array.slice(index));
|
|
1338
1325
|
}
|
|
1339
1326
|
function replaceItemAtIndex(array, newItem, index) {
|
|
1340
1327
|
const newArray = [...array];
|
|
@@ -4465,7 +4452,17 @@ function toNumberMatrix(data, argName) {
|
|
|
4465
4452
|
return toMatrix(data).map((row) => {
|
|
4466
4453
|
return row.map((cell) => {
|
|
4467
4454
|
if (typeof cell.value !== "number") {
|
|
4468
|
-
|
|
4455
|
+
let message = "";
|
|
4456
|
+
if (typeof cell === "object") {
|
|
4457
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got an empty value.", argName);
|
|
4458
|
+
}
|
|
4459
|
+
else if (typeof cell === "string") {
|
|
4460
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a string.", argName);
|
|
4461
|
+
}
|
|
4462
|
+
else if (typeof cell === "boolean") {
|
|
4463
|
+
message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a boolean.", argName);
|
|
4464
|
+
}
|
|
4465
|
+
throw new EvaluationError(message);
|
|
4469
4466
|
}
|
|
4470
4467
|
return cell.value;
|
|
4471
4468
|
});
|
|
@@ -5584,7 +5581,7 @@ function tokensToTextInternalFormat(tokens) {
|
|
|
5584
5581
|
* Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
|
|
5585
5582
|
*
|
|
5586
5583
|
* As per OpenXML specification, in date formats if a date token "m" or "mm" is followed by a date token "s" or
|
|
5587
|
-
* preceded by a data token "h", then it's not a month but
|
|
5584
|
+
* preceded by a data token "h", then it's not a month but a minute.
|
|
5588
5585
|
*/
|
|
5589
5586
|
function convertTokensToMinutesInDateFormat(tokens) {
|
|
5590
5587
|
const dateParts = tokens.filter((token) => token.type === "DATE_PART");
|
|
@@ -5627,6 +5624,9 @@ function internalFormatPartToFormat(internalFormat) {
|
|
|
5627
5624
|
case "REPEATED_CHAR":
|
|
5628
5625
|
format += "*" + token.value;
|
|
5629
5626
|
break;
|
|
5627
|
+
case "DATE_PART":
|
|
5628
|
+
format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
|
|
5629
|
+
break;
|
|
5630
5630
|
default:
|
|
5631
5631
|
format += token.value;
|
|
5632
5632
|
}
|
|
@@ -5700,7 +5700,7 @@ function formatValue(value, { format, locale, formatWidth }) {
|
|
|
5700
5700
|
return value;
|
|
5701
5701
|
}
|
|
5702
5702
|
const internalFormat = parseFormat(format);
|
|
5703
|
-
const formatToApply =
|
|
5703
|
+
const formatToApply = getFormatToApply(value, internalFormat).format;
|
|
5704
5704
|
if (!formatToApply || formatToApply.type !== "text") {
|
|
5705
5705
|
return value;
|
|
5706
5706
|
}
|
|
@@ -5711,16 +5711,15 @@ function formatValue(value, { format, locale, formatWidth }) {
|
|
|
5711
5711
|
format = createDefaultFormat(value);
|
|
5712
5712
|
}
|
|
5713
5713
|
const internalFormat = parseFormat(format);
|
|
5714
|
-
|
|
5715
|
-
|
|
5714
|
+
const { format: formatToApply, isNegativeFormat } = getFormatToApply(value, internalFormat);
|
|
5715
|
+
if (!formatToApply) {
|
|
5716
|
+
return value.toString();
|
|
5716
5717
|
}
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
formatToApply = internalFormat.negative;
|
|
5720
|
-
value = -value;
|
|
5718
|
+
if (formatToApply.type === "text") {
|
|
5719
|
+
return applyTextInternalFormat(value.toString(), formatToApply, formatWidth);
|
|
5721
5720
|
}
|
|
5722
|
-
|
|
5723
|
-
|
|
5721
|
+
if (isNegativeFormat) {
|
|
5722
|
+
value = Math.abs(value);
|
|
5724
5723
|
}
|
|
5725
5724
|
if (formatToApply.type === "date") {
|
|
5726
5725
|
return repeatCharToFitWidth(applyDateTimeFormat(value, formatToApply), formatWidth);
|
|
@@ -5732,6 +5731,31 @@ function formatValue(value, { format, locale, formatWidth }) {
|
|
|
5732
5731
|
return "";
|
|
5733
5732
|
}
|
|
5734
5733
|
}
|
|
5734
|
+
function getFormatToApply(value, internalFormat) {
|
|
5735
|
+
let formatToApply = undefined;
|
|
5736
|
+
let isNegativeFormat = false;
|
|
5737
|
+
switch (typeof value) {
|
|
5738
|
+
case "number":
|
|
5739
|
+
if (value < 0 && internalFormat.negative) {
|
|
5740
|
+
formatToApply = internalFormat.negative;
|
|
5741
|
+
isNegativeFormat = true;
|
|
5742
|
+
}
|
|
5743
|
+
else if (value === 0 && internalFormat.zero) {
|
|
5744
|
+
formatToApply = internalFormat.zero;
|
|
5745
|
+
}
|
|
5746
|
+
else {
|
|
5747
|
+
formatToApply = internalFormat.positive;
|
|
5748
|
+
}
|
|
5749
|
+
break;
|
|
5750
|
+
case "string":
|
|
5751
|
+
const format = internalFormat.text || internalFormat.positive;
|
|
5752
|
+
if (format.type === "text") {
|
|
5753
|
+
formatToApply = format;
|
|
5754
|
+
}
|
|
5755
|
+
break;
|
|
5756
|
+
}
|
|
5757
|
+
return { format: formatToApply, isNegativeFormat };
|
|
5758
|
+
}
|
|
5735
5759
|
function applyTextInternalFormat(value, internalFormat, formatWidth) {
|
|
5736
5760
|
let formattedValue = "";
|
|
5737
5761
|
for (const token of internalFormat.tokens) {
|
|
@@ -6343,6 +6367,27 @@ function isTextFormat(format) {
|
|
|
6343
6367
|
return false;
|
|
6344
6368
|
}
|
|
6345
6369
|
}
|
|
6370
|
+
function formatHasRepeatedChar(value, format) {
|
|
6371
|
+
if (!format) {
|
|
6372
|
+
return false;
|
|
6373
|
+
}
|
|
6374
|
+
try {
|
|
6375
|
+
const internalFormat = parseFormat(format);
|
|
6376
|
+
const { format: formatToApply } = getFormatToApply(value, internalFormat);
|
|
6377
|
+
if (formatToApply?.type === "text" || formatToApply?.type === "date") {
|
|
6378
|
+
const tokens = formatToApply.tokens;
|
|
6379
|
+
return tokens.some((token) => token.type === "REPEATED_CHAR");
|
|
6380
|
+
}
|
|
6381
|
+
else if (formatToApply?.type === "number") {
|
|
6382
|
+
return (formatToApply.integerPart.some((token) => token.type === "REPEATED_CHAR") ||
|
|
6383
|
+
(formatToApply.decimalPart
|
|
6384
|
+
? formatToApply.decimalPart.some((token) => token.type === "REPEATED_CHAR")
|
|
6385
|
+
: false));
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
6388
|
+
catch { }
|
|
6389
|
+
return false;
|
|
6390
|
+
}
|
|
6346
6391
|
|
|
6347
6392
|
function evaluateLiteral(literalCell, localeFormat, position) {
|
|
6348
6393
|
const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
|
|
@@ -6355,6 +6400,9 @@ function parseLiteral(content, locale) {
|
|
|
6355
6400
|
if (content.startsWith("=")) {
|
|
6356
6401
|
throw new Error(`Cannot parse "${content}" because it's not a literal value. It's a formula`);
|
|
6357
6402
|
}
|
|
6403
|
+
if (content.startsWith("'")) {
|
|
6404
|
+
return content.slice(1);
|
|
6405
|
+
}
|
|
6358
6406
|
if (content === "") {
|
|
6359
6407
|
return null;
|
|
6360
6408
|
}
|
|
@@ -9304,6 +9352,32 @@ function getCustomFieldWithParentField(definition, parentField, fields) {
|
|
|
9304
9352
|
groups: [],
|
|
9305
9353
|
});
|
|
9306
9354
|
}
|
|
9355
|
+
function togglePivotCollapse(position, env) {
|
|
9356
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
9357
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
9358
|
+
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
9359
|
+
return;
|
|
9360
|
+
}
|
|
9361
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
9362
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
9363
|
+
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
9364
|
+
: [];
|
|
9365
|
+
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
9366
|
+
if (index !== -1) {
|
|
9367
|
+
collapsedDomains.splice(index, 1);
|
|
9368
|
+
}
|
|
9369
|
+
else {
|
|
9370
|
+
collapsedDomains.push(pivotCell.domain);
|
|
9371
|
+
}
|
|
9372
|
+
const newDomains = definition.collapsedDomains
|
|
9373
|
+
? { ...definition.collapsedDomains }
|
|
9374
|
+
: { COL: [], ROW: [] };
|
|
9375
|
+
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
9376
|
+
env.model.dispatch("UPDATE_PIVOT", {
|
|
9377
|
+
pivotId,
|
|
9378
|
+
pivot: { ...definition, collapsedDomains: newDomains },
|
|
9379
|
+
});
|
|
9380
|
+
}
|
|
9307
9381
|
|
|
9308
9382
|
class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
9309
9383
|
isCutAllowed(data) {
|
|
@@ -9477,7 +9551,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
9477
9551
|
pasteCell(origin, target, clipboardOption) {
|
|
9478
9552
|
const { sheetId, col, row } = target;
|
|
9479
9553
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
9480
|
-
const originFormat = origin?.format
|
|
9554
|
+
const originFormat = origin?.format || origin.evaluatedCell.format;
|
|
9481
9555
|
if (clipboardOption?.pasteOption === "asValue") {
|
|
9482
9556
|
this.dispatch("UPDATE_CELL", {
|
|
9483
9557
|
...target,
|
|
@@ -13703,7 +13777,7 @@ const GROWTH = {
|
|
|
13703
13777
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
13704
13778
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
13705
13779
|
}
|
|
13706
|
-
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "
|
|
13780
|
+
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "known_data_y")), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b)));
|
|
13707
13781
|
},
|
|
13708
13782
|
};
|
|
13709
13783
|
// -----------------------------------------------------------------------------
|
|
@@ -13776,7 +13850,7 @@ const LINEST = {
|
|
|
13776
13850
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13777
13851
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13778
13852
|
}
|
|
13779
|
-
return fullLinearRegression(toNumberMatrix(dataX, "
|
|
13853
|
+
return fullLinearRegression(toNumberMatrix(dataX, "data_x"), toNumberMatrix(dataY, "data_y"), toBoolean(calculateB), toBoolean(verbose));
|
|
13780
13854
|
},
|
|
13781
13855
|
isExported: true,
|
|
13782
13856
|
};
|
|
@@ -13795,7 +13869,7 @@ const LOGEST = {
|
|
|
13795
13869
|
if (dataY.length === 0 || dataY[0].length === 0) {
|
|
13796
13870
|
return new EvaluationError(emptyDataErrorMessage("data_y"));
|
|
13797
13871
|
}
|
|
13798
|
-
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "
|
|
13872
|
+
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "data_x"), logM(toNumberMatrix(dataY, "data_y")), toBoolean(calculateB), toBoolean(verbose));
|
|
13799
13873
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13800
13874
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
13801
13875
|
}
|
|
@@ -14416,7 +14490,7 @@ const TREND = {
|
|
|
14416
14490
|
if (knownDataY.length === 0 || knownDataY[0].length === 0) {
|
|
14417
14491
|
return new EvaluationError(emptyDataErrorMessage("known_data_y"));
|
|
14418
14492
|
}
|
|
14419
|
-
return predictLinearValues(toNumberMatrix(knownDataY, "
|
|
14493
|
+
return predictLinearValues(toNumberMatrix(knownDataY, "known_data_y"), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b));
|
|
14420
14494
|
},
|
|
14421
14495
|
};
|
|
14422
14496
|
// -----------------------------------------------------------------------------
|
|
@@ -18637,7 +18711,7 @@ function parseOperand(tokens) {
|
|
|
18637
18711
|
case "STRING":
|
|
18638
18712
|
return {
|
|
18639
18713
|
type: "STRING",
|
|
18640
|
-
value:
|
|
18714
|
+
value: unquote(current.value),
|
|
18641
18715
|
tokenStartIndex: current.tokenIndex,
|
|
18642
18716
|
tokenEndIndex: current.tokenIndex,
|
|
18643
18717
|
};
|
|
@@ -22394,7 +22468,7 @@ function formulaArguments(tokens) {
|
|
|
22394
22468
|
dependencies.push(token.value);
|
|
22395
22469
|
break;
|
|
22396
22470
|
case "STRING":
|
|
22397
|
-
const value =
|
|
22471
|
+
const value = unquote(token.value);
|
|
22398
22472
|
literalValues.strings.push({ value });
|
|
22399
22473
|
break;
|
|
22400
22474
|
case "NUMBER": {
|
|
@@ -22937,6 +23011,10 @@ const chartShowValuesPlugin = {
|
|
|
22937
23011
|
}
|
|
22938
23012
|
const ctx = chart.ctx;
|
|
22939
23013
|
ctx.save();
|
|
23014
|
+
const { left, top, height, width } = chart.chartArea;
|
|
23015
|
+
ctx.beginPath();
|
|
23016
|
+
ctx.rect(left, top, width, height);
|
|
23017
|
+
ctx.clip();
|
|
22940
23018
|
ctx.textAlign = "center";
|
|
22941
23019
|
ctx.textBaseline = "middle";
|
|
22942
23020
|
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
@@ -23971,7 +24049,7 @@ class ChartJsComponent extends owl.Component {
|
|
|
23971
24049
|
this.chart.update();
|
|
23972
24050
|
}
|
|
23973
24051
|
hasChartDataChanged() {
|
|
23974
|
-
return !deepEquals(this.currentRuntime
|
|
24052
|
+
return !deepEquals(this.getChartDataInRuntime(this.currentRuntime), this.getChartDataInRuntime(this.chartRuntime));
|
|
23975
24053
|
}
|
|
23976
24054
|
enableAnimationInChartData(chartData) {
|
|
23977
24055
|
return {
|
|
@@ -23979,6 +24057,17 @@ class ChartJsComponent extends owl.Component {
|
|
|
23979
24057
|
options: { ...chartData.options, animation: { animateRotate: true } },
|
|
23980
24058
|
};
|
|
23981
24059
|
}
|
|
24060
|
+
getChartDataInRuntime(runtime) {
|
|
24061
|
+
const data = runtime.chartJsConfig.data;
|
|
24062
|
+
return {
|
|
24063
|
+
labels: data.labels,
|
|
24064
|
+
dataset: data.datasets.map((dataset) => ({
|
|
24065
|
+
data: dataset.data,
|
|
24066
|
+
label: dataset.label,
|
|
24067
|
+
tree: dataset.tree,
|
|
24068
|
+
})),
|
|
24069
|
+
};
|
|
24070
|
+
}
|
|
23982
24071
|
get animationChartId() {
|
|
23983
24072
|
return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
|
|
23984
24073
|
}
|
|
@@ -24646,6 +24735,7 @@ class ScorecardChart extends owl.Component {
|
|
|
24646
24735
|
static template = "o-spreadsheet-ScorecardChart";
|
|
24647
24736
|
static props = {
|
|
24648
24737
|
chartId: String,
|
|
24738
|
+
isFullScreen: { type: Boolean, optional: true },
|
|
24649
24739
|
};
|
|
24650
24740
|
canvas = owl.useRef("chartContainer");
|
|
24651
24741
|
get runtime() {
|
|
@@ -25401,6 +25491,7 @@ function getChartTimeOptions(labels, labelFormat, locale) {
|
|
|
25401
25491
|
parser: luxonFormat,
|
|
25402
25492
|
displayFormats,
|
|
25403
25493
|
unit: timeUnit ?? false,
|
|
25494
|
+
tooltipFormat: luxonFormat,
|
|
25404
25495
|
};
|
|
25405
25496
|
}
|
|
25406
25497
|
/**
|
|
@@ -26469,6 +26560,7 @@ function getLineChartScales(definition, args) {
|
|
|
26469
26560
|
};
|
|
26470
26561
|
Object.assign(scales.x, axis);
|
|
26471
26562
|
scales.x.ticks.maxTicksLimit = 15;
|
|
26563
|
+
delete scales?.x?.ticks?.callback;
|
|
26472
26564
|
}
|
|
26473
26565
|
else if (axisType === "linear") {
|
|
26474
26566
|
scales.x.type = "linear";
|
|
@@ -27409,26 +27501,6 @@ function createBarChartRuntime(chart, getters) {
|
|
|
27409
27501
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
27410
27502
|
}
|
|
27411
27503
|
|
|
27412
|
-
class FullScreenChartStore extends SpreadsheetStore {
|
|
27413
|
-
mutators = ["toggleFullScreenChart"];
|
|
27414
|
-
fullScreenFigure = undefined;
|
|
27415
|
-
toggleFullScreenChart(figureId) {
|
|
27416
|
-
if (this.fullScreenFigure?.id === figureId) {
|
|
27417
|
-
this.fullScreenFigure = undefined;
|
|
27418
|
-
}
|
|
27419
|
-
else {
|
|
27420
|
-
this.makeFullScreen(figureId);
|
|
27421
|
-
}
|
|
27422
|
-
}
|
|
27423
|
-
makeFullScreen(figureId) {
|
|
27424
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
27425
|
-
const figure = this.getters.getFigure(sheetId, figureId);
|
|
27426
|
-
if (figure) {
|
|
27427
|
-
this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
|
|
27428
|
-
}
|
|
27429
|
-
}
|
|
27430
|
-
}
|
|
27431
|
-
|
|
27432
27504
|
const TREND_LINE_AXES_IDS = [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID];
|
|
27433
27505
|
const ZOOMABLE_AXIS_IDS = ["x", ...TREND_LINE_AXES_IDS];
|
|
27434
27506
|
class ZoomableChartStore extends SpreadsheetStore {
|
|
@@ -27593,7 +27665,6 @@ chartJsExtensionRegistry.add("zoomWindowPlugin", {
|
|
|
27593
27665
|
class ZoomableChartJsComponent extends ChartJsComponent {
|
|
27594
27666
|
static template = "o-spreadsheet-ZoomableChartJsComponent";
|
|
27595
27667
|
store;
|
|
27596
|
-
fullScreenChartStore;
|
|
27597
27668
|
masterChartCanvas = owl.useRef("masterChartCanvas");
|
|
27598
27669
|
masterChart;
|
|
27599
27670
|
mode;
|
|
@@ -27604,7 +27675,6 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27604
27675
|
removeEventListeners = () => { };
|
|
27605
27676
|
setup() {
|
|
27606
27677
|
this.store = useStore(ZoomableChartStore);
|
|
27607
|
-
this.fullScreenChartStore = useStore(FullScreenChartStore);
|
|
27608
27678
|
super.setup();
|
|
27609
27679
|
}
|
|
27610
27680
|
unmount() {
|
|
@@ -27619,12 +27689,8 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27619
27689
|
`;
|
|
27620
27690
|
}
|
|
27621
27691
|
get sliceable() {
|
|
27622
|
-
if (this.
|
|
27623
|
-
|
|
27624
|
-
const chartFigureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
27625
|
-
if (fullScreenFigureId === chartFigureId) {
|
|
27626
|
-
return true;
|
|
27627
|
-
}
|
|
27692
|
+
if (this.props.isFullScreen) {
|
|
27693
|
+
return true;
|
|
27628
27694
|
}
|
|
27629
27695
|
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
27630
27696
|
return ("zoomable" in definition && definition?.zoomable) ?? false;
|
|
@@ -27687,9 +27753,6 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27687
27753
|
const xMax = Math.max(...xValues);
|
|
27688
27754
|
return { xMin, xMax };
|
|
27689
27755
|
}
|
|
27690
|
-
get shouldAnimate() {
|
|
27691
|
-
return this.env.model.getters.isDashboard() && !this.sliceable;
|
|
27692
|
-
}
|
|
27693
27756
|
createChart(chartRuntime) {
|
|
27694
27757
|
const chartData = chartRuntime.chartJsConfig;
|
|
27695
27758
|
this.isBarChart = chartData.type === "bar";
|
|
@@ -27708,6 +27771,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27708
27771
|
const masterChartCtx = this.masterChartCanvas.el.getContext("2d");
|
|
27709
27772
|
this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
|
|
27710
27773
|
this.resetAxesLimits();
|
|
27774
|
+
if (this.chart?.options) {
|
|
27775
|
+
this.chart.options.animation = false;
|
|
27776
|
+
}
|
|
27711
27777
|
}
|
|
27712
27778
|
updateChartJs(chartRuntime) {
|
|
27713
27779
|
const chartData = chartRuntime.chartJsConfig;
|
|
@@ -27741,6 +27807,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27741
27807
|
}
|
|
27742
27808
|
}
|
|
27743
27809
|
this.resetAxesLimits();
|
|
27810
|
+
if (this.chart?.options) {
|
|
27811
|
+
this.chart.options.animation = false;
|
|
27812
|
+
}
|
|
27744
27813
|
}
|
|
27745
27814
|
resetAxesLimits() {
|
|
27746
27815
|
if (!this.chart) {
|
|
@@ -27838,7 +27907,7 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27838
27907
|
onPointerDownInMasterChart(ev) {
|
|
27839
27908
|
this.removeEventListeners();
|
|
27840
27909
|
const position = ev.offsetX;
|
|
27841
|
-
if (!this.masterChart?.chartArea || !this.chart?.scales
|
|
27910
|
+
if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
|
|
27842
27911
|
return;
|
|
27843
27912
|
}
|
|
27844
27913
|
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
@@ -31396,6 +31465,26 @@ function getCarouselItemTitle(getters, item) {
|
|
|
31396
31465
|
return matchedChart.displayName;
|
|
31397
31466
|
}
|
|
31398
31467
|
|
|
31468
|
+
class FullScreenFigureStore extends SpreadsheetStore {
|
|
31469
|
+
mutators = ["toggleFullScreenFigure"];
|
|
31470
|
+
fullScreenFigure = undefined;
|
|
31471
|
+
toggleFullScreenFigure(figureId) {
|
|
31472
|
+
if (this.fullScreenFigure?.id === figureId) {
|
|
31473
|
+
this.fullScreenFigure = undefined;
|
|
31474
|
+
}
|
|
31475
|
+
else {
|
|
31476
|
+
this.makeFullScreen(figureId);
|
|
31477
|
+
}
|
|
31478
|
+
}
|
|
31479
|
+
makeFullScreen(figureId) {
|
|
31480
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
31481
|
+
const figure = this.getters.getFigure(sheetId, figureId);
|
|
31482
|
+
if (figure) {
|
|
31483
|
+
this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
|
|
31484
|
+
}
|
|
31485
|
+
}
|
|
31486
|
+
}
|
|
31487
|
+
|
|
31399
31488
|
/**
|
|
31400
31489
|
* This file is largely inspired by owl 1.
|
|
31401
31490
|
* `css` tag has been removed from owl 2 without workaround to manage css.
|
|
@@ -31550,7 +31639,8 @@ class Menu extends owl.Component {
|
|
|
31550
31639
|
const menuItemsAndSeparators = [];
|
|
31551
31640
|
for (let i = 0; i < this.props.menuItems.length; i++) {
|
|
31552
31641
|
const menuItem = this.props.menuItems[i];
|
|
31553
|
-
if (menuItem.isVisible(this.env)
|
|
31642
|
+
if (menuItem.isVisible(this.env) &&
|
|
31643
|
+
(!this.isRoot(menuItem) || this.hasVisibleChildren(menuItem))) {
|
|
31554
31644
|
menuItemsAndSeparators.push(menuItem);
|
|
31555
31645
|
}
|
|
31556
31646
|
if (menuItem.separator &&
|
|
@@ -31592,6 +31682,9 @@ class Menu extends owl.Component {
|
|
|
31592
31682
|
isRoot(menu) {
|
|
31593
31683
|
return !menu.execute;
|
|
31594
31684
|
}
|
|
31685
|
+
hasVisibleChildren(menu) {
|
|
31686
|
+
return menu.children(this.env).some((child) => child.isVisible(this.env));
|
|
31687
|
+
}
|
|
31595
31688
|
isEnabled(menu) {
|
|
31596
31689
|
if (menu.isEnabled(this.env)) {
|
|
31597
31690
|
return this.env.model.getters.isReadonly() ? menu.isReadonlyAllowed : true;
|
|
@@ -32133,12 +32226,13 @@ class MenuPopover extends owl.Component {
|
|
|
32133
32226
|
class ChartDashboardMenu extends owl.Component {
|
|
32134
32227
|
static template = "o-spreadsheet-ChartDashboardMenu";
|
|
32135
32228
|
static components = { MenuPopover };
|
|
32136
|
-
static props = { chartId: String };
|
|
32229
|
+
static props = { chartId: String, hasFullScreenButton: { type: Boolean, optional: true } };
|
|
32230
|
+
static defaultProps = { hasFullScreenButton: true };
|
|
32137
32231
|
fullScreenFigureStore;
|
|
32138
32232
|
menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
32139
32233
|
setup() {
|
|
32140
32234
|
super.setup();
|
|
32141
|
-
this.fullScreenFigureStore = useStore(
|
|
32235
|
+
this.fullScreenFigureStore = useStore(FullScreenFigureStore);
|
|
32142
32236
|
}
|
|
32143
32237
|
getMenuItems() {
|
|
32144
32238
|
return [this.fullScreenMenuItem].filter(isDefined);
|
|
@@ -32149,11 +32243,14 @@ class ChartDashboardMenu extends owl.Component {
|
|
|
32149
32243
|
}
|
|
32150
32244
|
openContextMenu(ev) {
|
|
32151
32245
|
this.menuState.isOpen = true;
|
|
32152
|
-
this.menuState.anchorRect =
|
|
32246
|
+
this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
|
|
32153
32247
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32154
32248
|
this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
|
|
32155
32249
|
}
|
|
32156
32250
|
get fullScreenMenuItem() {
|
|
32251
|
+
if (!this.props.hasFullScreenButton) {
|
|
32252
|
+
return undefined;
|
|
32253
|
+
}
|
|
32157
32254
|
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
32158
32255
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32159
32256
|
if (definition.type === "scorecard") {
|
|
@@ -32165,7 +32262,7 @@ class ChartDashboardMenu extends owl.Component {
|
|
|
32165
32262
|
label: isFullScreen ? _t("Exit Full Screen") : _t("Full Screen"),
|
|
32166
32263
|
class: `text-muted fa ${isFullScreen ? "fa-compress" : "fa-expand"}`,
|
|
32167
32264
|
onClick: () => {
|
|
32168
|
-
this.fullScreenFigureStore.
|
|
32265
|
+
this.fullScreenFigureStore.toggleFullScreenFigure(figureId);
|
|
32169
32266
|
},
|
|
32170
32267
|
};
|
|
32171
32268
|
}
|
|
@@ -32177,6 +32274,8 @@ class CarouselFigure extends owl.Component {
|
|
|
32177
32274
|
figureUI: Object,
|
|
32178
32275
|
onFigureDeleted: Function,
|
|
32179
32276
|
editFigureStyle: { type: Function, optional: true },
|
|
32277
|
+
isFullScreen: { type: Boolean, optional: true },
|
|
32278
|
+
openContextMenu: { type: Function, optional: true },
|
|
32180
32279
|
};
|
|
32181
32280
|
static components = { ChartDashboardMenu, MenuPopover };
|
|
32182
32281
|
carouselTabsRef = owl.useRef("carouselTabs");
|
|
@@ -32184,8 +32283,10 @@ class CarouselFigure extends owl.Component {
|
|
|
32184
32283
|
menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
32185
32284
|
hiddenItems = [];
|
|
32186
32285
|
animationStore;
|
|
32286
|
+
fullScreenFigureStore;
|
|
32187
32287
|
setup() {
|
|
32188
32288
|
this.animationStore = useStore(ChartAnimationStore);
|
|
32289
|
+
this.fullScreenFigureStore = useStore(FullScreenFigureStore);
|
|
32189
32290
|
owl.useEffect(() => {
|
|
32190
32291
|
if (this.selectedCarouselItem?.type === "carouselDataView") {
|
|
32191
32292
|
this.props.editFigureStyle?.({ "pointer-events": "none" });
|
|
@@ -32232,7 +32333,8 @@ class CarouselFigure extends owl.Component {
|
|
|
32232
32333
|
item,
|
|
32233
32334
|
});
|
|
32234
32335
|
if (item.type === "chart") {
|
|
32235
|
-
|
|
32336
|
+
const animationChartId = item.chartId + (this.props.isFullScreen ? "-fullscreen" : "");
|
|
32337
|
+
this.animationStore?.enableAnimationForChart(animationChartId);
|
|
32236
32338
|
}
|
|
32237
32339
|
}
|
|
32238
32340
|
get headerStyle() {
|
|
@@ -32296,6 +32398,23 @@ class CarouselFigure extends owl.Component {
|
|
|
32296
32398
|
this.menuState.anchorRect = rect;
|
|
32297
32399
|
this.menuState.menuItems = createActions(menuItems);
|
|
32298
32400
|
}
|
|
32401
|
+
toggleFullScreen() {
|
|
32402
|
+
if (this.selectedCarouselItem?.type === "chart") {
|
|
32403
|
+
this.fullScreenFigureStore.toggleFullScreenFigure(this.props.figureUI.id);
|
|
32404
|
+
}
|
|
32405
|
+
}
|
|
32406
|
+
get fullScreenButtonTitle() {
|
|
32407
|
+
return this.props.isFullScreen ? _t("Exit Full Screen") : _t("Full Screen");
|
|
32408
|
+
}
|
|
32409
|
+
get visibleCarouselItems() {
|
|
32410
|
+
return this.carousel.items.filter((item) => item.type === "carouselDataView" && this.props.isFullScreen ? false : true);
|
|
32411
|
+
}
|
|
32412
|
+
openContextMenu(event) {
|
|
32413
|
+
const target = event.currentTarget;
|
|
32414
|
+
if (target) {
|
|
32415
|
+
this.props.openContextMenu?.(getBoundingRectAsPOJO(target));
|
|
32416
|
+
}
|
|
32417
|
+
}
|
|
32299
32418
|
}
|
|
32300
32419
|
|
|
32301
32420
|
class ChartFigure extends owl.Component {
|
|
@@ -32304,6 +32423,8 @@ class ChartFigure extends owl.Component {
|
|
|
32304
32423
|
figureUI: Object,
|
|
32305
32424
|
onFigureDeleted: Function,
|
|
32306
32425
|
editFigureStyle: { type: Function, optional: true },
|
|
32426
|
+
isFullScreen: { type: Boolean, optional: true },
|
|
32427
|
+
openContextMenu: { type: Function, optional: true },
|
|
32307
32428
|
};
|
|
32308
32429
|
static components = { ChartDashboardMenu };
|
|
32309
32430
|
onDoubleClick() {
|
|
@@ -32336,6 +32457,7 @@ class ImageFigure extends owl.Component {
|
|
|
32336
32457
|
figureUI: Object,
|
|
32337
32458
|
onFigureDeleted: Function,
|
|
32338
32459
|
editFigureStyle: { type: Function, optional: true },
|
|
32460
|
+
openContextMenu: { type: Function, optional: true },
|
|
32339
32461
|
};
|
|
32340
32462
|
static components = {};
|
|
32341
32463
|
// ---------------------------------------------------------------------------
|
|
@@ -32406,9 +32528,7 @@ class FigureComponent extends owl.Component {
|
|
|
32406
32528
|
return this.isSelected ? ACTIVE_BORDER_WIDTH : this.borderWidth;
|
|
32407
32529
|
}
|
|
32408
32530
|
getBorderStyle(position) {
|
|
32409
|
-
|
|
32410
|
-
const borderColor = this.isSelected ? SELECTION_BORDER_COLOR : FIGURE_BORDER_COLOR;
|
|
32411
|
-
return `border-${position}: ${borderWidth}px solid ${borderColor};`;
|
|
32531
|
+
return `border-${position}-width: ${this.getBorderWidth()}px;`;
|
|
32412
32532
|
}
|
|
32413
32533
|
get wrapperStyle() {
|
|
32414
32534
|
const { x, y, width, height } = this.props.figureUI;
|
|
@@ -34140,8 +34260,11 @@ class Composer extends owl.Component {
|
|
|
34140
34260
|
}
|
|
34141
34261
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
34142
34262
|
this.props.composerStore.stopComposerRangeSelection();
|
|
34143
|
-
this.props.
|
|
34144
|
-
this.props.
|
|
34263
|
+
const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
|
|
34264
|
+
this.props.onComposerContentFocused(newSelection);
|
|
34265
|
+
if (!isCurrentlyInactive) {
|
|
34266
|
+
this.props.composerStore.changeComposerCursorSelection(newSelection.start, newSelection.end);
|
|
34267
|
+
}
|
|
34145
34268
|
this.processTokenAtCursor();
|
|
34146
34269
|
}
|
|
34147
34270
|
onDblClick() {
|
|
@@ -34636,13 +34759,6 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34636
34759
|
}
|
|
34637
34760
|
}
|
|
34638
34761
|
startEdition(text, selection) {
|
|
34639
|
-
if (selection) {
|
|
34640
|
-
const content = text || this.getComposerContent(this.getters.getActivePosition());
|
|
34641
|
-
const validSelection = this.isSelectionValid(content.length, selection.start, selection.end);
|
|
34642
|
-
if (!validSelection) {
|
|
34643
|
-
return;
|
|
34644
|
-
}
|
|
34645
|
-
}
|
|
34646
34762
|
const { col, row } = this.getters.getActivePosition();
|
|
34647
34763
|
this.model.dispatch("SELECT_FIGURE", { figureId: null });
|
|
34648
34764
|
this.model.dispatch("SCROLL_TO_CELL", { col, row });
|
|
@@ -34699,7 +34815,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34699
34815
|
// ---------------------------------------------------------------------------
|
|
34700
34816
|
get currentContent() {
|
|
34701
34817
|
if (this.editionMode === "inactive") {
|
|
34702
|
-
return this.getComposerContent(this.getters.getActivePosition());
|
|
34818
|
+
return this.getComposerContent(this.getters.getActivePosition()).text;
|
|
34703
34819
|
}
|
|
34704
34820
|
return this._currentContent;
|
|
34705
34821
|
}
|
|
@@ -34898,8 +35014,9 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
34898
35014
|
this.sheetId = sheetId;
|
|
34899
35015
|
this.row = row;
|
|
34900
35016
|
this.editionMode = "editing";
|
|
34901
|
-
|
|
34902
|
-
this.
|
|
35017
|
+
const { text, adjustedSelection } = this.getComposerContent({ sheetId, col, row }, selection);
|
|
35018
|
+
this.initialContent = text;
|
|
35019
|
+
this.setContent(str || this.initialContent, adjustedSelection ?? selection);
|
|
34903
35020
|
this.colorIndexByRange = {};
|
|
34904
35021
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
34905
35022
|
this.captureSelection(zone, col, row);
|
|
@@ -35376,7 +35493,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35376
35493
|
constructor(get, args) {
|
|
35377
35494
|
super(get);
|
|
35378
35495
|
this.args = args;
|
|
35379
|
-
this._currentContent = this.getComposerContent();
|
|
35496
|
+
this._currentContent = this.getComposerContent().text;
|
|
35380
35497
|
}
|
|
35381
35498
|
getAutoCompleteProviders() {
|
|
35382
35499
|
const providersDefinitions = super.getAutoCompleteProviders();
|
|
@@ -35413,7 +35530,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
35413
35530
|
})
|
|
35414
35531
|
.join("");
|
|
35415
35532
|
}
|
|
35416
|
-
return localizeContent(content, this.getters.getLocale());
|
|
35533
|
+
return { text: localizeContent(content, this.getters.getLocale()) };
|
|
35417
35534
|
}
|
|
35418
35535
|
stopEdition() {
|
|
35419
35536
|
this._stopEdition();
|
|
@@ -38633,6 +38750,74 @@ function getPath2D(svgPath) {
|
|
|
38633
38750
|
return path2D;
|
|
38634
38751
|
}
|
|
38635
38752
|
|
|
38753
|
+
/**
|
|
38754
|
+
* Get the relative path between two files
|
|
38755
|
+
*
|
|
38756
|
+
* Eg.:
|
|
38757
|
+
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
38758
|
+
*/
|
|
38759
|
+
function getRelativePath(from, to) {
|
|
38760
|
+
const fromPathParts = from.split("/");
|
|
38761
|
+
const toPathParts = to.split("/");
|
|
38762
|
+
let relPath = "";
|
|
38763
|
+
let startIndex = 0;
|
|
38764
|
+
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
38765
|
+
if (fromPathParts[i] === toPathParts[i]) {
|
|
38766
|
+
startIndex++;
|
|
38767
|
+
}
|
|
38768
|
+
else {
|
|
38769
|
+
relPath += "../";
|
|
38770
|
+
}
|
|
38771
|
+
}
|
|
38772
|
+
relPath += toPathParts.slice(startIndex).join("/");
|
|
38773
|
+
return relPath;
|
|
38774
|
+
}
|
|
38775
|
+
/**
|
|
38776
|
+
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
38777
|
+
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
38778
|
+
*
|
|
38779
|
+
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
38780
|
+
*/
|
|
38781
|
+
function arrayToObject(array, indexOffset = 0) {
|
|
38782
|
+
const obj = {};
|
|
38783
|
+
for (let i = 0; i < array.length; i++) {
|
|
38784
|
+
if (array[i]) {
|
|
38785
|
+
obj[i + indexOffset] = array[i];
|
|
38786
|
+
}
|
|
38787
|
+
}
|
|
38788
|
+
return obj;
|
|
38789
|
+
}
|
|
38790
|
+
/**
|
|
38791
|
+
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
38792
|
+
* Replace with characters understandable by JS
|
|
38793
|
+
*/
|
|
38794
|
+
function fixXlsxUnicode(str) {
|
|
38795
|
+
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
38796
|
+
return String.fromCharCode(parseInt(code, 16));
|
|
38797
|
+
});
|
|
38798
|
+
}
|
|
38799
|
+
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
38800
|
+
function getSheetDataHeader(sheetData, dimension, index) {
|
|
38801
|
+
if (dimension === "COL") {
|
|
38802
|
+
if (!sheetData.cols[index]) {
|
|
38803
|
+
sheetData.cols[index] = {};
|
|
38804
|
+
}
|
|
38805
|
+
return sheetData.cols[index];
|
|
38806
|
+
}
|
|
38807
|
+
if (!sheetData.rows[index]) {
|
|
38808
|
+
sheetData.rows[index] = {};
|
|
38809
|
+
}
|
|
38810
|
+
return sheetData.rows[index];
|
|
38811
|
+
}
|
|
38812
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
38813
|
+
function prefixFormulaWithEqual(formula) {
|
|
38814
|
+
if (formula[0] === "=") {
|
|
38815
|
+
return formula;
|
|
38816
|
+
}
|
|
38817
|
+
const tokens = tokenize(formula);
|
|
38818
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
38819
|
+
}
|
|
38820
|
+
|
|
38636
38821
|
/**
|
|
38637
38822
|
* Map of the different types of conversions warnings and their name in error messages
|
|
38638
38823
|
*/
|
|
@@ -39155,66 +39340,6 @@ function hexaToInt(hex) {
|
|
|
39155
39340
|
*/
|
|
39156
39341
|
const DEFAULT_SYSTEM_COLOR = "FF000000";
|
|
39157
39342
|
|
|
39158
|
-
/**
|
|
39159
|
-
* Get the relative path between two files
|
|
39160
|
-
*
|
|
39161
|
-
* Eg.:
|
|
39162
|
-
* from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
|
|
39163
|
-
*/
|
|
39164
|
-
function getRelativePath(from, to) {
|
|
39165
|
-
const fromPathParts = from.split("/");
|
|
39166
|
-
const toPathParts = to.split("/");
|
|
39167
|
-
let relPath = "";
|
|
39168
|
-
let startIndex = 0;
|
|
39169
|
-
for (let i = 0; i < fromPathParts.length - 1; i++) {
|
|
39170
|
-
if (fromPathParts[i] === toPathParts[i]) {
|
|
39171
|
-
startIndex++;
|
|
39172
|
-
}
|
|
39173
|
-
else {
|
|
39174
|
-
relPath += "../";
|
|
39175
|
-
}
|
|
39176
|
-
}
|
|
39177
|
-
relPath += toPathParts.slice(startIndex).join("/");
|
|
39178
|
-
return relPath;
|
|
39179
|
-
}
|
|
39180
|
-
/**
|
|
39181
|
-
* Convert an array of element into an object where the objects keys were the elements position in the array.
|
|
39182
|
-
* Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
|
|
39183
|
-
*
|
|
39184
|
-
* eg. : ["a", "b"] => {0:"a", 1:"b"}
|
|
39185
|
-
*/
|
|
39186
|
-
function arrayToObject(array, indexOffset = 0) {
|
|
39187
|
-
const obj = {};
|
|
39188
|
-
for (let i = 0; i < array.length; i++) {
|
|
39189
|
-
if (array[i]) {
|
|
39190
|
-
obj[i + indexOffset] = array[i];
|
|
39191
|
-
}
|
|
39192
|
-
}
|
|
39193
|
-
return obj;
|
|
39194
|
-
}
|
|
39195
|
-
/**
|
|
39196
|
-
* In xlsx we can have string with unicode characters with the format _x00fa_.
|
|
39197
|
-
* Replace with characters understandable by JS
|
|
39198
|
-
*/
|
|
39199
|
-
function fixXlsxUnicode(str) {
|
|
39200
|
-
return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
|
|
39201
|
-
return String.fromCharCode(parseInt(code, 16));
|
|
39202
|
-
});
|
|
39203
|
-
}
|
|
39204
|
-
/** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
|
|
39205
|
-
function getSheetDataHeader(sheetData, dimension, index) {
|
|
39206
|
-
if (dimension === "COL") {
|
|
39207
|
-
if (!sheetData.cols[index]) {
|
|
39208
|
-
sheetData.cols[index] = {};
|
|
39209
|
-
}
|
|
39210
|
-
return sheetData.cols[index];
|
|
39211
|
-
}
|
|
39212
|
-
if (!sheetData.rows[index]) {
|
|
39213
|
-
sheetData.rows[index] = {};
|
|
39214
|
-
}
|
|
39215
|
-
return sheetData.rows[index];
|
|
39216
|
-
}
|
|
39217
|
-
|
|
39218
39343
|
const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
|
|
39219
39344
|
/**
|
|
39220
39345
|
* Convert excel format to o_spreadsheet format
|
|
@@ -39429,9 +39554,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
39429
39554
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
39430
39555
|
continue;
|
|
39431
39556
|
operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
|
|
39432
|
-
values.push(
|
|
39557
|
+
values.push(prefixFormulaWithEqual(rule.formula[0]));
|
|
39433
39558
|
if (rule.formula.length === 2) {
|
|
39434
|
-
values.push(
|
|
39559
|
+
values.push(prefixFormulaWithEqual(rule.formula[1]));
|
|
39435
39560
|
}
|
|
39436
39561
|
break;
|
|
39437
39562
|
}
|
|
@@ -39589,11 +39714,6 @@ function convertIcons(xlsxIconSet, index) {
|
|
|
39589
39714
|
? ICON_SETS[iconSet].neutral
|
|
39590
39715
|
: ICON_SETS[iconSet].good;
|
|
39591
39716
|
}
|
|
39592
|
-
/** Prefix the string by "=" if the string looks like a formula */
|
|
39593
|
-
function prefixFormula(formula) {
|
|
39594
|
-
const tokens = tokenize(formula);
|
|
39595
|
-
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
39596
|
-
}
|
|
39597
39717
|
// ---------------------------------------------------------------------------
|
|
39598
39718
|
// Warnings
|
|
39599
39719
|
// ---------------------------------------------------------------------------
|
|
@@ -40069,7 +40189,7 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
40069
40189
|
dvRules.push(decimalRule);
|
|
40070
40190
|
break;
|
|
40071
40191
|
case "list":
|
|
40072
|
-
const listRule =
|
|
40192
|
+
const listRule = convertListRule(dvId++, dv);
|
|
40073
40193
|
dvRules.push(listRule);
|
|
40074
40194
|
break;
|
|
40075
40195
|
case "date":
|
|
@@ -40089,9 +40209,9 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
|
40089
40209
|
return dvRules;
|
|
40090
40210
|
}
|
|
40091
40211
|
function convertDecimalRule(id, dv) {
|
|
40092
|
-
const values = [dv.formula1.toString()];
|
|
40212
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
40093
40213
|
if (dv.formula2) {
|
|
40094
|
-
values.push(dv.formula2.toString());
|
|
40214
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
40095
40215
|
}
|
|
40096
40216
|
return {
|
|
40097
40217
|
id: id.toString(),
|
|
@@ -40103,7 +40223,7 @@ function convertDecimalRule(id, dv) {
|
|
|
40103
40223
|
},
|
|
40104
40224
|
};
|
|
40105
40225
|
}
|
|
40106
|
-
function
|
|
40226
|
+
function convertListRule(id, dv) {
|
|
40107
40227
|
const formula1 = dv.formula1.toString();
|
|
40108
40228
|
const isRangeRule = rangeReference.test(formula1);
|
|
40109
40229
|
return {
|
|
@@ -40119,9 +40239,9 @@ function convertListrule(id, dv) {
|
|
|
40119
40239
|
}
|
|
40120
40240
|
function convertDateRule(id, dv) {
|
|
40121
40241
|
let criterion;
|
|
40122
|
-
const values = [dv.formula1.toString()];
|
|
40242
|
+
const values = [prefixFormulaWithEqual(dv.formula1.toString())];
|
|
40123
40243
|
if (dv.formula2) {
|
|
40124
|
-
values.push(dv.formula2.toString());
|
|
40244
|
+
values.push(prefixFormulaWithEqual(dv.formula2.toString()));
|
|
40125
40245
|
criterion = {
|
|
40126
40246
|
type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
|
|
40127
40247
|
values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
|
|
@@ -40148,7 +40268,7 @@ function convertCustomRule(id, dv) {
|
|
|
40148
40268
|
isBlocking: dv.errorStyle !== "warning",
|
|
40149
40269
|
criterion: {
|
|
40150
40270
|
type: "customFormula",
|
|
40151
|
-
values: [
|
|
40271
|
+
values: [prefixFormulaWithEqual(dv.formula1.toString())],
|
|
40152
40272
|
},
|
|
40153
40273
|
};
|
|
40154
40274
|
}
|
|
@@ -45922,6 +46042,18 @@ class SpreadsheetPivotTable {
|
|
|
45922
46042
|
get numberOfCells() {
|
|
45923
46043
|
return this.rows.length * this.getNumberOfDataColumns();
|
|
45924
46044
|
}
|
|
46045
|
+
getColumnDomainsAtDepth(depth) {
|
|
46046
|
+
if (depth < 0 || depth >= this.columns.length - 1) {
|
|
46047
|
+
return [];
|
|
46048
|
+
}
|
|
46049
|
+
return this.columns[depth].map((col) => this.getDomain(col)).filter((d) => d.length);
|
|
46050
|
+
}
|
|
46051
|
+
getRowDomainsAtDepth(depth) {
|
|
46052
|
+
if (depth < 0 || depth > this.maxIndent) {
|
|
46053
|
+
return [];
|
|
46054
|
+
}
|
|
46055
|
+
return this.rows.filter((row) => row.indent === depth + 1).map((row) => this.getDomain(row));
|
|
46056
|
+
}
|
|
45925
46057
|
}
|
|
45926
46058
|
const EMPTY_PIVOT_CELL = { type: "EMPTY" };
|
|
45927
46059
|
|
|
@@ -46914,6 +47046,109 @@ const ungroupPivotHeadersAction = {
|
|
|
46914
47046
|
return areFieldValuesInGroups(definition, values, field, pivot.getFields());
|
|
46915
47047
|
},
|
|
46916
47048
|
};
|
|
47049
|
+
const toggleCollapsePivotGroupAction = {
|
|
47050
|
+
name: (env) => {
|
|
47051
|
+
const position = env.model.getters.getActivePosition();
|
|
47052
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47053
|
+
if (pivotCellState.isPivotGroup) {
|
|
47054
|
+
return pivotCellState.isCollapsed ? _t("Expand") : _t("Collapse");
|
|
47055
|
+
}
|
|
47056
|
+
return "";
|
|
47057
|
+
},
|
|
47058
|
+
execute(env) {
|
|
47059
|
+
const position = env.model.getters.getActivePosition();
|
|
47060
|
+
togglePivotCollapse(position, env);
|
|
47061
|
+
},
|
|
47062
|
+
isVisible: (env) => {
|
|
47063
|
+
const position = env.model.getters.getActivePosition();
|
|
47064
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47065
|
+
return pivotCellState.isPivotGroup;
|
|
47066
|
+
},
|
|
47067
|
+
};
|
|
47068
|
+
const collapseAllPivotGroupAction = {
|
|
47069
|
+
name: _t("Collapse all"),
|
|
47070
|
+
execute(env) {
|
|
47071
|
+
const position = env.model.getters.getActivePosition();
|
|
47072
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47073
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47074
|
+
return;
|
|
47075
|
+
}
|
|
47076
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47077
|
+
const definition = deepCopy(env.model.getters.getPivotCoreDefinition(pivotId));
|
|
47078
|
+
definition.collapsedDomains = definition.collapsedDomains || { COL: [], ROW: [] };
|
|
47079
|
+
const newCollapsed = [
|
|
47080
|
+
...(definition.collapsedDomains[pivotCell.dimension] || []),
|
|
47081
|
+
...siblingDomains,
|
|
47082
|
+
];
|
|
47083
|
+
const filteredCollapsed = newCollapsed.filter((domain, index) => index === newCollapsed.findIndex((d) => deepEquals(d, domain)));
|
|
47084
|
+
definition.collapsedDomains[pivotCell.dimension] = filteredCollapsed;
|
|
47085
|
+
env.model.dispatch("UPDATE_PIVOT", { pivotId, pivot: definition });
|
|
47086
|
+
},
|
|
47087
|
+
isVisible: (env) => {
|
|
47088
|
+
const position = env.model.getters.getActivePosition();
|
|
47089
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47090
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47091
|
+
return false;
|
|
47092
|
+
}
|
|
47093
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47094
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
47095
|
+
return !siblingDomains.every((domain) => (definition.collapsedDomains?.[pivotCell.dimension] || []).some((d) => deepEquals(d, domain)));
|
|
47096
|
+
},
|
|
47097
|
+
};
|
|
47098
|
+
const expandAllPivotGroupAction = {
|
|
47099
|
+
name: _t("Expand all"),
|
|
47100
|
+
execute(env) {
|
|
47101
|
+
const position = env.model.getters.getActivePosition();
|
|
47102
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47103
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47104
|
+
return;
|
|
47105
|
+
}
|
|
47106
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47107
|
+
const definition = deepCopy(env.model.getters.getPivotCoreDefinition(pivotId));
|
|
47108
|
+
definition.collapsedDomains = definition.collapsedDomains || { COL: [], ROW: [] };
|
|
47109
|
+
const domains = definition.collapsedDomains[pivotCell.dimension] || [];
|
|
47110
|
+
const filteredDomains = domains.filter((domain) => !siblingDomains.find((d) => deepEquals(d, domain)));
|
|
47111
|
+
definition.collapsedDomains[pivotCell.dimension] = filteredDomains;
|
|
47112
|
+
env.model.dispatch("UPDATE_PIVOT", { pivotId, pivot: definition });
|
|
47113
|
+
},
|
|
47114
|
+
isVisible: (env) => {
|
|
47115
|
+
const position = env.model.getters.getActivePosition();
|
|
47116
|
+
const pivotCellState = getPivotCellCollapseState(env.model.getters, position);
|
|
47117
|
+
if (!pivotCellState.isPivotGroup) {
|
|
47118
|
+
return false;
|
|
47119
|
+
}
|
|
47120
|
+
const { pivotCell, pivotId, siblingDomains } = pivotCellState;
|
|
47121
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
47122
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension] || [];
|
|
47123
|
+
return collapsedDomains.some((domain) => siblingDomains.some((d) => deepEquals(d, domain)));
|
|
47124
|
+
},
|
|
47125
|
+
};
|
|
47126
|
+
function getPivotCellCollapseState(getters, position) {
|
|
47127
|
+
if (!getters.isSpillPivotFormula(position)) {
|
|
47128
|
+
return { isPivotGroup: false };
|
|
47129
|
+
}
|
|
47130
|
+
const pivotCell = getters.getPivotCellFromPosition(position);
|
|
47131
|
+
const pivotId = getters.getPivotIdFromPosition(position);
|
|
47132
|
+
if (pivotCell.type !== "HEADER" || !pivotId || !pivotCell.domain.length) {
|
|
47133
|
+
return { isPivotGroup: false };
|
|
47134
|
+
}
|
|
47135
|
+
const definition = getters.getPivotCoreDefinition(pivotId);
|
|
47136
|
+
const isDashboard = getters.isDashboard();
|
|
47137
|
+
const fields = pivotCell.dimension === "COL" ? definition.columns : definition.rows;
|
|
47138
|
+
const hasIcon = !isDashboard && pivotCell.domain.length !== fields.length;
|
|
47139
|
+
if (!hasIcon) {
|
|
47140
|
+
return { isPivotGroup: false };
|
|
47141
|
+
}
|
|
47142
|
+
const domains = definition.collapsedDomains?.[pivotCell.dimension] ?? [];
|
|
47143
|
+
const isCollapsed = domains.some((domain) => deepEquals(domain, pivotCell.domain));
|
|
47144
|
+
const pivot = getters.getPivot(pivotId);
|
|
47145
|
+
const table = pivot.getExpandedTableStructure();
|
|
47146
|
+
const depth = pivotCell.domain.length - 1;
|
|
47147
|
+
const siblingDomains = pivotCell.dimension === "ROW"
|
|
47148
|
+
? table.getRowDomainsAtDepth(depth)
|
|
47149
|
+
: table.getColumnDomainsAtDepth(depth);
|
|
47150
|
+
return { isPivotGroup: true, isCollapsed, pivotCell, pivotId, siblingDomains };
|
|
47151
|
+
}
|
|
46917
47152
|
function canSortPivot(getters, position) {
|
|
46918
47153
|
const pivotId = getters.getPivotIdFromPosition(position);
|
|
46919
47154
|
if (!pivotId || !getters.isExistingPivot(pivotId) || !getters.isSpillPivotFormula(position)) {
|
|
@@ -47249,6 +47484,23 @@ cellMenuRegistry
|
|
|
47249
47484
|
sequence: 155,
|
|
47250
47485
|
icon: "o-spreadsheet-Icon.MINUS_IN_BOX",
|
|
47251
47486
|
...ungroupPivotHeadersAction,
|
|
47487
|
+
})
|
|
47488
|
+
.add("collapse_pivot", {
|
|
47489
|
+
sequence: 156,
|
|
47490
|
+
name: _t("Expand/Collapse"),
|
|
47491
|
+
icon: "o-spreadsheet-Icon.COLLAPSE",
|
|
47492
|
+
})
|
|
47493
|
+
.addChild("toggle_collapse_pivot_cell", ["collapse_pivot"], {
|
|
47494
|
+
sequence: 10,
|
|
47495
|
+
...toggleCollapsePivotGroupAction,
|
|
47496
|
+
})
|
|
47497
|
+
.addChild("collapse_all_pivot", ["collapse_pivot"], {
|
|
47498
|
+
sequence: 20,
|
|
47499
|
+
...collapseAllPivotGroupAction,
|
|
47500
|
+
})
|
|
47501
|
+
.addChild("expand_all_pivot", ["collapse_pivot"], {
|
|
47502
|
+
sequence: 30,
|
|
47503
|
+
...expandAllPivotGroupAction,
|
|
47252
47504
|
})
|
|
47253
47505
|
.add("pivot_sorting", {
|
|
47254
47506
|
name: _t("Sort pivot"),
|
|
@@ -47873,6 +48125,7 @@ function createHeaderGroupContainerContextMenu(sheetId, dimension) {
|
|
|
47873
48125
|
execute: (env) => {
|
|
47874
48126
|
env.model.dispatch("UNFOLD_ALL_HEADER_GROUPS", { sheetId, dimension });
|
|
47875
48127
|
},
|
|
48128
|
+
icon: "o-spreadsheet-Icon.EXPAND",
|
|
47876
48129
|
},
|
|
47877
48130
|
{
|
|
47878
48131
|
id: "fold_all",
|
|
@@ -47880,6 +48133,7 @@ function createHeaderGroupContainerContextMenu(sheetId, dimension) {
|
|
|
47880
48133
|
execute: (env) => {
|
|
47881
48134
|
env.model.dispatch("FOLD_ALL_HEADER_GROUPS", { sheetId, dimension });
|
|
47882
48135
|
},
|
|
48136
|
+
icon: "o-spreadsheet-Icon.COLLAPSE",
|
|
47883
48137
|
},
|
|
47884
48138
|
]);
|
|
47885
48139
|
}
|
|
@@ -47901,6 +48155,11 @@ function getHeaderGroupContextMenu(sheetId, dimension, start, end) {
|
|
|
47901
48155
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
47902
48156
|
interactiveToggleGroup(env, sheetId, dimension, start, end);
|
|
47903
48157
|
},
|
|
48158
|
+
icon: (env) => {
|
|
48159
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
48160
|
+
const groupIsFolded = env.model.getters.isGroupFolded(sheetId, dimension, start, end);
|
|
48161
|
+
return groupIsFolded ? "o-spreadsheet-Icon.EXPAND" : "o-spreadsheet-Icon.COLLAPSE";
|
|
48162
|
+
},
|
|
47904
48163
|
},
|
|
47905
48164
|
{
|
|
47906
48165
|
id: "remove_group",
|
|
@@ -47909,6 +48168,7 @@ function getHeaderGroupContextMenu(sheetId, dimension, start, end) {
|
|
|
47909
48168
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
47910
48169
|
env.model.dispatch("UNGROUP_HEADERS", { sheetId, dimension, start, end });
|
|
47911
48170
|
},
|
|
48171
|
+
icon: "o-spreadsheet-Icon.TRASH",
|
|
47912
48172
|
separator: true,
|
|
47913
48173
|
},
|
|
47914
48174
|
]);
|
|
@@ -48771,39 +49031,66 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
48771
49031
|
this.model.dispatch("AUTOFILL_TABLE_COLUMN", { ...this.currentEditedCell });
|
|
48772
49032
|
this.setContent("");
|
|
48773
49033
|
}
|
|
48774
|
-
getComposerContent(position) {
|
|
49034
|
+
getComposerContent(position, selection) {
|
|
48775
49035
|
const locale = this.getters.getLocale();
|
|
48776
49036
|
const cell = this.getters.getCell(position);
|
|
48777
49037
|
if (cell?.isFormula) {
|
|
48778
49038
|
const prettifiedContent = this.getPrettifiedFormula(cell);
|
|
48779
|
-
|
|
49039
|
+
// when a formula is prettified (multi lines, indented), adapt the cursor position
|
|
49040
|
+
// to take into account line breaks and tabs
|
|
49041
|
+
function adjustCursorIndex(targetIndex) {
|
|
49042
|
+
let adjustedIndex = 0;
|
|
49043
|
+
let originalIndex = 0;
|
|
49044
|
+
while (originalIndex < targetIndex) {
|
|
49045
|
+
adjustedIndex++;
|
|
49046
|
+
const char = prettifiedContent[adjustedIndex];
|
|
49047
|
+
if (char !== "\n" && char !== "\t") {
|
|
49048
|
+
originalIndex++;
|
|
49049
|
+
}
|
|
49050
|
+
}
|
|
49051
|
+
return adjustedIndex;
|
|
49052
|
+
}
|
|
49053
|
+
let adjustedSelection = selection;
|
|
49054
|
+
if (selection) {
|
|
49055
|
+
adjustedSelection = {
|
|
49056
|
+
start: adjustCursorIndex(selection.start),
|
|
49057
|
+
end: adjustCursorIndex(selection.end),
|
|
49058
|
+
};
|
|
49059
|
+
}
|
|
49060
|
+
return {
|
|
49061
|
+
text: localizeFormula(prettifiedContent, locale),
|
|
49062
|
+
adjustedSelection,
|
|
49063
|
+
};
|
|
48780
49064
|
}
|
|
48781
49065
|
const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
|
|
48782
49066
|
if (spreader) {
|
|
48783
|
-
return "";
|
|
49067
|
+
return { text: "" };
|
|
49068
|
+
}
|
|
49069
|
+
if (cell?.content.startsWith("'")) {
|
|
49070
|
+
return { text: cell.content };
|
|
48784
49071
|
}
|
|
48785
49072
|
const { format, value, type, formattedValue } = this.getters.getEvaluatedCell(position);
|
|
48786
49073
|
switch (type) {
|
|
48787
49074
|
case CellValueType.empty:
|
|
48788
|
-
return "";
|
|
49075
|
+
return { text: "" };
|
|
48789
49076
|
case CellValueType.text:
|
|
48790
49077
|
case CellValueType.error:
|
|
48791
|
-
return value;
|
|
49078
|
+
return { text: value };
|
|
48792
49079
|
case CellValueType.boolean:
|
|
48793
|
-
return formattedValue;
|
|
49080
|
+
return { text: formattedValue };
|
|
48794
49081
|
case CellValueType.number:
|
|
48795
49082
|
if (format && isDateTimeFormat(format)) {
|
|
48796
49083
|
if (parseDateTime(formattedValue, locale) !== null) {
|
|
48797
49084
|
// formatted string can be parsed again
|
|
48798
|
-
return formattedValue;
|
|
49085
|
+
return { text: formattedValue };
|
|
48799
49086
|
}
|
|
48800
49087
|
// display a simplified and parsable string otherwise
|
|
48801
49088
|
const timeFormat = Number.isInteger(value)
|
|
48802
49089
|
? locale.dateFormat
|
|
48803
49090
|
: getDateTimeFormat(locale);
|
|
48804
|
-
return formatValue(value, { locale, format: timeFormat });
|
|
49091
|
+
return { text: formatValue(value, { locale, format: timeFormat }) };
|
|
48805
49092
|
}
|
|
48806
|
-
return this.numberComposerContent(value, format, locale);
|
|
49093
|
+
return { text: this.numberComposerContent(value, format, locale) };
|
|
48807
49094
|
}
|
|
48808
49095
|
}
|
|
48809
49096
|
getPrettifiedFormula(cell) {
|
|
@@ -48950,8 +49237,9 @@ class GridComposer extends owl.Component {
|
|
|
48950
49237
|
},
|
|
48951
49238
|
focus: this.focus,
|
|
48952
49239
|
isDefaultFocus: true,
|
|
48953
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
49240
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
48954
49241
|
focusMode: "contentFocus",
|
|
49242
|
+
selection,
|
|
48955
49243
|
}),
|
|
48956
49244
|
onComposerCellFocused: (content) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
48957
49245
|
focusMode: "cellFocus",
|
|
@@ -51344,6 +51632,9 @@ class GridRenderer extends SpreadsheetStore {
|
|
|
51344
51632
|
}
|
|
51345
51633
|
const { align } = this.getters.getCellStyle(position);
|
|
51346
51634
|
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
51635
|
+
if (formatHasRepeatedChar(evaluatedCell.value, evaluatedCell.format)) {
|
|
51636
|
+
return "left";
|
|
51637
|
+
}
|
|
51347
51638
|
if (isOverflowing && evaluatedCell.type === CellValueType.number) {
|
|
51348
51639
|
return align !== "center" ? "left" : align;
|
|
51349
51640
|
}
|
|
@@ -55636,12 +55927,13 @@ class DataValidationEditor extends owl.Component {
|
|
|
55636
55927
|
onCloseSidePanel: { type: Function, optional: true },
|
|
55637
55928
|
};
|
|
55638
55929
|
state = owl.useState({ rule: this.defaultDataValidationRule, errors: [] });
|
|
55930
|
+
editingSheetId;
|
|
55639
55931
|
setup() {
|
|
55932
|
+
this.editingSheetId = this.env.model.getters.getActiveSheetId();
|
|
55640
55933
|
if (this.props.rule) {
|
|
55641
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
55642
55934
|
this.state.rule = {
|
|
55643
55935
|
...this.props.rule,
|
|
55644
|
-
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range,
|
|
55936
|
+
ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
|
|
55645
55937
|
};
|
|
55646
55938
|
this.state.rule.criterion.type = this.props.rule.criterion.type;
|
|
55647
55939
|
}
|
|
@@ -55675,7 +55967,6 @@ class DataValidationEditor extends owl.Component {
|
|
|
55675
55967
|
const locale = this.env.model.getters.getLocale();
|
|
55676
55968
|
const criterion = rule.criterion;
|
|
55677
55969
|
const criterionEvaluator = criterionEvaluatorRegistry.get(criterion.type);
|
|
55678
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
55679
55970
|
const values = criterion.values
|
|
55680
55971
|
.slice(0, criterionEvaluator.numberOfValues(criterion))
|
|
55681
55972
|
.map((value) => value?.trim())
|
|
@@ -55683,8 +55974,8 @@ class DataValidationEditor extends owl.Component {
|
|
|
55683
55974
|
.map((value) => canonicalizeContent(value, locale));
|
|
55684
55975
|
rule.criterion = { ...criterion, values };
|
|
55685
55976
|
return {
|
|
55686
|
-
sheetId,
|
|
55687
|
-
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(
|
|
55977
|
+
sheetId: this.editingSheetId,
|
|
55978
|
+
ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(this.editingSheetId, xc)),
|
|
55688
55979
|
rule,
|
|
55689
55980
|
};
|
|
55690
55981
|
}
|
|
@@ -56815,7 +57106,7 @@ class PivotMeasureEditor extends owl.Component {
|
|
|
56815
57106
|
return undefined;
|
|
56816
57107
|
}
|
|
56817
57108
|
get isCalculatedMeasureInvalid() {
|
|
56818
|
-
return
|
|
57109
|
+
return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
|
|
56819
57110
|
}
|
|
56820
57111
|
}
|
|
56821
57112
|
|
|
@@ -59530,16 +59821,16 @@ class ClickableCellSortIcon extends owl.Component {
|
|
|
59530
59821
|
}
|
|
59531
59822
|
}
|
|
59532
59823
|
|
|
59533
|
-
class
|
|
59534
|
-
static template = "o-spreadsheet-
|
|
59824
|
+
class FullScreenFigure extends owl.Component {
|
|
59825
|
+
static template = "o-spreadsheet-FullScreenFigure";
|
|
59535
59826
|
static props = {};
|
|
59536
|
-
static components = {
|
|
59537
|
-
|
|
59538
|
-
ref = owl.useRef("
|
|
59827
|
+
static components = { ChartFigure };
|
|
59828
|
+
fullScreenFigureStore;
|
|
59829
|
+
ref = owl.useRef("fullScreenFigure");
|
|
59539
59830
|
spreadsheetRect = useSpreadsheetRect();
|
|
59540
59831
|
figureRegistry = figureRegistry;
|
|
59541
59832
|
setup() {
|
|
59542
|
-
this.
|
|
59833
|
+
this.fullScreenFigureStore = useStore(FullScreenFigureStore);
|
|
59543
59834
|
const animationStore = useStore(ChartAnimationStore);
|
|
59544
59835
|
let lastFigureId = undefined;
|
|
59545
59836
|
owl.onWillUpdateProps(() => {
|
|
@@ -59551,7 +59842,7 @@ class FullScreenChart extends owl.Component {
|
|
|
59551
59842
|
owl.useEffect((el) => el?.focus(), () => [this.ref.el]);
|
|
59552
59843
|
}
|
|
59553
59844
|
get figureUI() {
|
|
59554
|
-
return this.
|
|
59845
|
+
return this.fullScreenFigureStore.fullScreenFigure;
|
|
59555
59846
|
}
|
|
59556
59847
|
get chartId() {
|
|
59557
59848
|
if (!this.figureUI)
|
|
@@ -59560,7 +59851,7 @@ class FullScreenChart extends owl.Component {
|
|
|
59560
59851
|
}
|
|
59561
59852
|
exitFullScreen() {
|
|
59562
59853
|
if (this.figureUI) {
|
|
59563
|
-
this.
|
|
59854
|
+
this.fullScreenFigureStore.toggleFullScreenFigure(this.figureUI.id);
|
|
59564
59855
|
}
|
|
59565
59856
|
}
|
|
59566
59857
|
onKeyDown(ev) {
|
|
@@ -59568,15 +59859,10 @@ class FullScreenChart extends owl.Component {
|
|
|
59568
59859
|
this.exitFullScreen();
|
|
59569
59860
|
}
|
|
59570
59861
|
}
|
|
59571
|
-
get
|
|
59572
|
-
if (!this.
|
|
59862
|
+
get figureComponent() {
|
|
59863
|
+
if (!this.figureUI)
|
|
59573
59864
|
return undefined;
|
|
59574
|
-
|
|
59575
|
-
const component = chartComponentRegistry.get(type);
|
|
59576
|
-
if (!component) {
|
|
59577
|
-
throw new Error(`Component is not defined for type ${type}`);
|
|
59578
|
-
}
|
|
59579
|
-
return component;
|
|
59865
|
+
return figureRegistry.get(this.figureUI.tag).Component;
|
|
59580
59866
|
}
|
|
59581
59867
|
}
|
|
59582
59868
|
|
|
@@ -60799,7 +61085,7 @@ class CellPlugin extends CorePlugin {
|
|
|
60799
61085
|
(typeof parsedValue === "number"
|
|
60800
61086
|
? detectDateFormat(content, locale) || detectNumberFormat(content)
|
|
60801
61087
|
: undefined);
|
|
60802
|
-
if (!isTextFormat(format) && !isEvaluationError(content)) {
|
|
61088
|
+
if (!isTextFormat(format) && !content.startsWith("'") && !isEvaluationError(content)) {
|
|
60803
61089
|
content = toString(parsedValue);
|
|
60804
61090
|
}
|
|
60805
61091
|
return {
|
|
@@ -62279,11 +62565,11 @@ class HeaderSizePlugin extends CorePlugin {
|
|
|
62279
62565
|
break;
|
|
62280
62566
|
}
|
|
62281
62567
|
case "ADD_COLUMNS_ROWS": {
|
|
62282
|
-
const sizes =
|
|
62568
|
+
const sizes = this.sizes[cmd.sheetId][cmd.dimension];
|
|
62283
62569
|
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
62284
62570
|
const baseSize = sizes[cmd.base];
|
|
62285
|
-
sizes
|
|
62286
|
-
this.history.update("sizes", cmd.sheetId, cmd.dimension,
|
|
62571
|
+
const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
|
|
62572
|
+
this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
|
|
62287
62573
|
break;
|
|
62288
62574
|
}
|
|
62289
62575
|
case "RESIZE_COLUMNS_ROWS":
|
|
@@ -62434,9 +62720,8 @@ class HeaderVisibilityPlugin extends CorePlugin {
|
|
|
62434
62720
|
break;
|
|
62435
62721
|
}
|
|
62436
62722
|
case "ADD_COLUMNS_ROWS": {
|
|
62437
|
-
const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
|
|
62438
62723
|
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
62439
|
-
hiddenHeaders.
|
|
62724
|
+
const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
|
|
62440
62725
|
this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
|
|
62441
62726
|
break;
|
|
62442
62727
|
}
|
|
@@ -66620,12 +66905,12 @@ class SpreadsheetRTree {
|
|
|
66620
66905
|
this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
|
|
66621
66906
|
}
|
|
66622
66907
|
rtreeItemComparer(left, right) {
|
|
66623
|
-
return (left.
|
|
66624
|
-
left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
66908
|
+
return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
66625
66909
|
left.boundingBox?.zone.left === right.boundingBox.zone.left &&
|
|
66626
66910
|
left.boundingBox?.zone.top === right.boundingBox.zone.top &&
|
|
66627
66911
|
left.boundingBox?.zone.right === right.boundingBox.zone.right &&
|
|
66628
|
-
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom
|
|
66912
|
+
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
|
|
66913
|
+
deepEquals(left.data, right.data));
|
|
66629
66914
|
}
|
|
66630
66915
|
}
|
|
66631
66916
|
/**
|
|
@@ -66698,7 +66983,7 @@ class FormulaDependencyGraph {
|
|
|
66698
66983
|
* in the correct order they should be evaluated.
|
|
66699
66984
|
* This is called a topological ordering (excluding cycles)
|
|
66700
66985
|
*/
|
|
66701
|
-
getCellsDependingOn(ranges) {
|
|
66986
|
+
getCellsDependingOn(ranges, ignore) {
|
|
66702
66987
|
const visited = this.createEmptyPositionSet();
|
|
66703
66988
|
const queue = Array.from(ranges).reverse();
|
|
66704
66989
|
while (queue.length > 0) {
|
|
@@ -66713,7 +66998,7 @@ class FormulaDependencyGraph {
|
|
|
66713
66998
|
const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
|
|
66714
66999
|
const nextInQueue = {};
|
|
66715
67000
|
for (const position of impactedPositions) {
|
|
66716
|
-
if (!visited.has(position)) {
|
|
67001
|
+
if (!visited.has(position) && !ignore.has(position)) {
|
|
66717
67002
|
if (!nextInQueue[position.sheetId]) {
|
|
66718
67003
|
nextInQueue[position.sheetId] = [];
|
|
66719
67004
|
}
|
|
@@ -67271,7 +67556,7 @@ class Evaluator {
|
|
|
67271
67556
|
}
|
|
67272
67557
|
invalidatePositionsDependingOnSpread(sheetId, resultZone) {
|
|
67273
67558
|
// the result matrix is split in 2 zones to exclude the array formula position
|
|
67274
|
-
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
|
|
67559
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })), this.nextPositionsToUpdate);
|
|
67275
67560
|
invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
|
|
67276
67561
|
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
67277
67562
|
}
|
|
@@ -67389,7 +67674,7 @@ class Evaluator {
|
|
|
67389
67674
|
for (const sheetId in zonesBySheetIds) {
|
|
67390
67675
|
ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
|
|
67391
67676
|
}
|
|
67392
|
-
return this.formulaDependencies().getCellsDependingOn(ranges);
|
|
67677
|
+
return this.formulaDependencies().getCellsDependingOn(ranges, this.nextPositionsToUpdate);
|
|
67393
67678
|
}
|
|
67394
67679
|
}
|
|
67395
67680
|
function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
@@ -68656,32 +68941,6 @@ iconsOnCellRegistry.add("pivot_collapse", (getters, position) => {
|
|
|
68656
68941
|
}
|
|
68657
68942
|
return undefined;
|
|
68658
68943
|
});
|
|
68659
|
-
function togglePivotCollapse(position, env) {
|
|
68660
|
-
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
68661
|
-
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
68662
|
-
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
68663
|
-
return;
|
|
68664
|
-
}
|
|
68665
|
-
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
68666
|
-
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
68667
|
-
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
68668
|
-
: [];
|
|
68669
|
-
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
68670
|
-
if (index !== -1) {
|
|
68671
|
-
collapsedDomains.splice(index, 1);
|
|
68672
|
-
}
|
|
68673
|
-
else {
|
|
68674
|
-
collapsedDomains.push(pivotCell.domain);
|
|
68675
|
-
}
|
|
68676
|
-
const newDomains = definition.collapsedDomains
|
|
68677
|
-
? { ...definition.collapsedDomains }
|
|
68678
|
-
: { COL: [], ROW: [] };
|
|
68679
|
-
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
68680
|
-
env.model.dispatch("UPDATE_PIVOT", {
|
|
68681
|
-
pivotId,
|
|
68682
|
-
pivot: { ...definition, collapsedDomains: newDomains },
|
|
68683
|
-
});
|
|
68684
|
-
}
|
|
68685
68944
|
iconsOnCellRegistry.add("pivot_dashboard_sorting", (getters, position) => {
|
|
68686
68945
|
if (!getters.isDashboard()) {
|
|
68687
68946
|
return undefined;
|
|
@@ -68900,7 +69159,8 @@ class DynamicTablesPlugin extends CoreViewPlugin {
|
|
|
68900
69159
|
const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
|
|
68901
69160
|
const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
|
|
68902
69161
|
if (!parentSpreadingCell) {
|
|
68903
|
-
|
|
69162
|
+
const evaluatedCell = this.getters.getEvaluatedCell(topLeft);
|
|
69163
|
+
return (evaluatedCell.value === CellErrorType.SpilledBlocked && !evaluatedCell.errorOriginPosition);
|
|
68904
69164
|
}
|
|
68905
69165
|
else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
|
|
68906
69166
|
return true;
|
|
@@ -79473,8 +79733,8 @@ class RowGroup extends AbstractHeaderGroup {
|
|
|
79473
79733
|
left: `calc(50% - 1px)`, // -1px: we want the border to be on the center
|
|
79474
79734
|
width: `30%`,
|
|
79475
79735
|
height: `calc(100% - ${groupBox.headerRect.height / 2}px)`,
|
|
79476
|
-
"border-left": `1px solid
|
|
79477
|
-
"border-bottom": groupBox.isEndHidden ? "" : `1px solid
|
|
79736
|
+
"border-left": `1px solid`,
|
|
79737
|
+
"border-bottom": groupBox.isEndHidden ? "" : `1px solid`,
|
|
79478
79738
|
});
|
|
79479
79739
|
}
|
|
79480
79740
|
get groupHeaderStyle() {
|
|
@@ -79526,8 +79786,8 @@ class ColGroup extends AbstractHeaderGroup {
|
|
|
79526
79786
|
left: `${groupBox.headerRect.width / 2}px`,
|
|
79527
79787
|
width: `calc(100% - ${groupBox.headerRect.width / 2}px)`,
|
|
79528
79788
|
height: `30%`,
|
|
79529
|
-
"border-top": `1px solid
|
|
79530
|
-
"border-right": groupBox.isEndHidden ? "" : `1px solid
|
|
79789
|
+
"border-top": `1px solid`,
|
|
79790
|
+
"border-right": groupBox.isEndHidden ? "" : `1px solid`,
|
|
79531
79791
|
});
|
|
79532
79792
|
}
|
|
79533
79793
|
get groupHeaderStyle() {
|
|
@@ -79766,6 +80026,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79766
80026
|
static components = { Menu };
|
|
79767
80027
|
rootItems = topbarMenuRegistry.getMenuItems();
|
|
79768
80028
|
menuRef = owl.useRef("menu");
|
|
80029
|
+
containerRef = owl.useRef("container");
|
|
79769
80030
|
state = owl.useState({
|
|
79770
80031
|
menuItems: this.rootItems,
|
|
79771
80032
|
title: _t("Menu Bar"),
|
|
@@ -79773,6 +80034,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79773
80034
|
});
|
|
79774
80035
|
setup() {
|
|
79775
80036
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
80037
|
+
owl.onMounted(this.updateShadows);
|
|
79776
80038
|
}
|
|
79777
80039
|
onExternalClick(ev) {
|
|
79778
80040
|
if (!this.menuRef.el?.contains(ev.target)) {
|
|
@@ -79785,6 +80047,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79785
80047
|
this.state.parentState = { ...this.state };
|
|
79786
80048
|
this.state.menuItems = children;
|
|
79787
80049
|
this.state.title = menu.name(this.env);
|
|
80050
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
79788
80051
|
}
|
|
79789
80052
|
else {
|
|
79790
80053
|
this.state.menuItems = this.rootItems;
|
|
@@ -79806,6 +80069,19 @@ class RibbonMenu extends owl.Component {
|
|
|
79806
80069
|
height: `${this.props.height}px`,
|
|
79807
80070
|
});
|
|
79808
80071
|
}
|
|
80072
|
+
updateShadows() {
|
|
80073
|
+
if (!this.containerRef.el) {
|
|
80074
|
+
return;
|
|
80075
|
+
}
|
|
80076
|
+
this.containerRef.el.classList.remove("scroll-top", "scroll-bottom");
|
|
80077
|
+
const maxScroll = this.containerRef.el.scrollHeight - this.containerRef.el.clientHeight || 0;
|
|
80078
|
+
if (this.containerRef.el.scrollTop < maxScroll - 1) {
|
|
80079
|
+
this.containerRef.el.classList.add("scroll-bottom");
|
|
80080
|
+
}
|
|
80081
|
+
if (this.containerRef.el.scrollTop > 0) {
|
|
80082
|
+
this.containerRef.el.classList.add("scroll-top");
|
|
80083
|
+
}
|
|
80084
|
+
}
|
|
79809
80085
|
onClickBack() {
|
|
79810
80086
|
if (!this.state.parentState) {
|
|
79811
80087
|
this.props.onClose();
|
|
@@ -79814,6 +80090,7 @@ class RibbonMenu extends owl.Component {
|
|
|
79814
80090
|
this.state.menuItems = this.state.parentState.menuItems;
|
|
79815
80091
|
this.state.title = this.state.parentState.title;
|
|
79816
80092
|
this.state.parentState = this.state.parentState.parentState;
|
|
80093
|
+
this.containerRef.el?.scrollTo({ top: 0 });
|
|
79817
80094
|
}
|
|
79818
80095
|
get backTitle() {
|
|
79819
80096
|
return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
|
|
@@ -79864,6 +80141,11 @@ class SmallBottomBar extends owl.Component {
|
|
|
79864
80141
|
? this.composerFocusStore.focusMode
|
|
79865
80142
|
: "inactive";
|
|
79866
80143
|
}
|
|
80144
|
+
get showFxIcon() {
|
|
80145
|
+
return (this.focus === "inactive" &&
|
|
80146
|
+
!this.composerStore.currentContent &&
|
|
80147
|
+
!this.composerStore.placeholder);
|
|
80148
|
+
}
|
|
79867
80149
|
get rect() {
|
|
79868
80150
|
return this.composerRef.el
|
|
79869
80151
|
? getBoundingRectAsPOJO(this.composerRef.el)
|
|
@@ -79879,8 +80161,9 @@ class SmallBottomBar extends owl.Component {
|
|
|
79879
80161
|
},
|
|
79880
80162
|
focus: this.focus,
|
|
79881
80163
|
composerStore: this.composerStore,
|
|
79882
|
-
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
80164
|
+
onComposerContentFocused: (selection) => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
79883
80165
|
focusMode: "contentFocus",
|
|
80166
|
+
selection,
|
|
79884
80167
|
}),
|
|
79885
80168
|
isDefaultFocus: false,
|
|
79886
80169
|
inputStyle: cssPropertiesToCss({
|
|
@@ -79888,6 +80171,7 @@ class SmallBottomBar extends owl.Component {
|
|
|
79888
80171
|
"max-height": `130px`,
|
|
79889
80172
|
}),
|
|
79890
80173
|
showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
|
|
80174
|
+
placeholder: this.composerStore.placeholder,
|
|
79891
80175
|
};
|
|
79892
80176
|
}
|
|
79893
80177
|
get symbols() {
|
|
@@ -79906,13 +80190,6 @@ class SmallBottomBar extends owl.Component {
|
|
|
79906
80190
|
}
|
|
79907
80191
|
|
|
79908
80192
|
const COMPOSER_MAX_HEIGHT = 300;
|
|
79909
|
-
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
79910
|
-
// FIXME This svg is hardcoded in the css file. We should find a better way to handle it.
|
|
79911
|
-
// const FX_SVG = /*xml*/ `
|
|
79912
|
-
// <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
|
|
79913
|
-
// <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'/>
|
|
79914
|
-
// </svg>
|
|
79915
|
-
// `;
|
|
79916
80193
|
class TopBarComposer extends owl.Component {
|
|
79917
80194
|
static template = "o-spreadsheet-TopBarComposer";
|
|
79918
80195
|
static props = {};
|
|
@@ -79939,6 +80216,11 @@ class TopBarComposer extends owl.Component {
|
|
|
79939
80216
|
? this.composerFocusStore.focusMode
|
|
79940
80217
|
: "inactive";
|
|
79941
80218
|
}
|
|
80219
|
+
get showFxIcon() {
|
|
80220
|
+
return (this.focus === "inactive" &&
|
|
80221
|
+
!this.composerStore.currentContent &&
|
|
80222
|
+
!this.composerStore.placeholder);
|
|
80223
|
+
}
|
|
79942
80224
|
get composerStyle() {
|
|
79943
80225
|
const style = {
|
|
79944
80226
|
padding: "5px 0px 5px 8px",
|
|
@@ -80876,7 +81158,7 @@ class Spreadsheet extends owl.Component {
|
|
|
80876
81158
|
SidePanels,
|
|
80877
81159
|
SpreadsheetDashboard,
|
|
80878
81160
|
HeaderGroupContainer,
|
|
80879
|
-
|
|
81161
|
+
FullScreenFigure,
|
|
80880
81162
|
};
|
|
80881
81163
|
sidePanel;
|
|
80882
81164
|
spreadsheetRef = owl.useRef("spreadsheet");
|
|
@@ -85600,6 +85882,7 @@ const components = {
|
|
|
85600
85882
|
Grid,
|
|
85601
85883
|
GridOverlay,
|
|
85602
85884
|
ScorecardChart,
|
|
85885
|
+
GaugeChartComponent,
|
|
85603
85886
|
LineConfigPanel,
|
|
85604
85887
|
BarConfigPanel,
|
|
85605
85888
|
PieChartDesignPanel,
|
|
@@ -85638,7 +85921,7 @@ const components = {
|
|
|
85638
85921
|
RadioSelection,
|
|
85639
85922
|
GeoChartRegionSelectSection,
|
|
85640
85923
|
ChartDashboardMenu,
|
|
85641
|
-
|
|
85924
|
+
FullScreenFigure,
|
|
85642
85925
|
};
|
|
85643
85926
|
const hooks = {
|
|
85644
85927
|
useDragAndDropListItems,
|
|
@@ -85738,6 +86021,6 @@ exports.tokenColors = tokenColors;
|
|
|
85738
86021
|
exports.tokenize = tokenize;
|
|
85739
86022
|
|
|
85740
86023
|
|
|
85741
|
-
__info__.version = "19.1.0-alpha.
|
|
85742
|
-
__info__.date = "2025-
|
|
85743
|
-
__info__.hash = "
|
|
86024
|
+
__info__.version = "19.1.0-alpha.5";
|
|
86025
|
+
__info__.date = "2025-10-16T06:39:55.925Z";
|
|
86026
|
+
__info__.hash = "1a0e3d5";
|