@odoo/o-spreadsheet 17.2.0-alpha.6 → 17.2.0-alpha.8
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 +478 -218
- package/dist/o-spreadsheet.d.ts +156 -119
- package/dist/o-spreadsheet.esm.js +478 -218
- package/dist/o-spreadsheet.iife.js +478 -218
- package/dist/o-spreadsheet.iife.min.js +280 -278
- package/dist/o_spreadsheet.xml +22 -13
- package/package.json +1 -1
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.2.0-alpha.
|
|
7
|
-
* @date 2024-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.2.0-alpha.8
|
|
7
|
+
* @date 2024-03-15T11:01:01.388Z
|
|
8
|
+
* @hash 11cf381
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
@@ -191,8 +191,8 @@ const DEFAULT_GAUGE_LOWER_COLOR = "#cc0000";
|
|
|
191
191
|
const DEFAULT_GAUGE_MIDDLE_COLOR = "#f1c232";
|
|
192
192
|
const DEFAULT_GAUGE_UPPER_COLOR = "#6aa84f";
|
|
193
193
|
const DEFAULT_SCORECARD_BASELINE_MODE = "difference";
|
|
194
|
-
const DEFAULT_SCORECARD_BASELINE_COLOR_UP = "#
|
|
195
|
-
const DEFAULT_SCORECARD_BASELINE_COLOR_DOWN = "#
|
|
194
|
+
const DEFAULT_SCORECARD_BASELINE_COLOR_UP = "#6aa84f";
|
|
195
|
+
const DEFAULT_SCORECARD_BASELINE_COLOR_DOWN = "#E06666";
|
|
196
196
|
const LINE_FILL_TRANSPARENCY = 0.4;
|
|
197
197
|
// session
|
|
198
198
|
const DEBOUNCE_TIME = 200;
|
|
@@ -2146,7 +2146,6 @@ const LAYERS = {
|
|
|
2146
2146
|
Background: 0,
|
|
2147
2147
|
Highlights: 1,
|
|
2148
2148
|
Clipboard: 2,
|
|
2149
|
-
Search: 3,
|
|
2150
2149
|
Chart: 4,
|
|
2151
2150
|
Autofill: 5,
|
|
2152
2151
|
Selection: 6,
|
|
@@ -6318,6 +6317,11 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
6318
6317
|
this.pasteTableCell(sheetId, tableCell, position, clipboardOptions);
|
|
6319
6318
|
}
|
|
6320
6319
|
}
|
|
6320
|
+
if (tableCells.length === 1) {
|
|
6321
|
+
for (let c = 0; c < tableCells[0].length; c++) {
|
|
6322
|
+
this.dispatch("AUTOFILL_TABLE_COLUMN", { col: col + c, row, sheetId });
|
|
6323
|
+
}
|
|
6324
|
+
}
|
|
6321
6325
|
}
|
|
6322
6326
|
pasteTableCell(sheetId, tableCell, position, options) {
|
|
6323
6327
|
if (tableCell.table && !options?.pasteOption) {
|
|
@@ -7444,6 +7448,7 @@ const TableTerms = {
|
|
|
7444
7448
|
firstColumn: _t("First column"),
|
|
7445
7449
|
lastColumn: _t("Last column"),
|
|
7446
7450
|
bandedColumns: _t("Banded columns"),
|
|
7451
|
+
automaticAutofill: _t("Automatically autofill formulas"),
|
|
7447
7452
|
totalRow: _t("Total row"),
|
|
7448
7453
|
},
|
|
7449
7454
|
Tooltips: {
|
|
@@ -8190,11 +8195,18 @@ function drawHighlight(renderingContext, highlight, rect) {
|
|
|
8190
8195
|
}
|
|
8191
8196
|
const color = highlight.color || HIGHLIGHT_COLOR;
|
|
8192
8197
|
const { ctx } = renderingContext;
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
+
if (!highlight.noBorder) {
|
|
8199
|
+
ctx.strokeStyle = color;
|
|
8200
|
+
if (highlight.thinLine) {
|
|
8201
|
+
ctx.lineWidth = 1;
|
|
8202
|
+
ctx.strokeRect(x, y, width, height);
|
|
8203
|
+
}
|
|
8204
|
+
else {
|
|
8205
|
+
ctx.lineWidth = 2;
|
|
8206
|
+
/** + 0.5 offset to have sharp lines. See comment in {@link RendererPlugin#drawBorder} for more details */
|
|
8207
|
+
ctx.strokeRect(x + 0.5, y + 0.5, width, height);
|
|
8208
|
+
}
|
|
8209
|
+
}
|
|
8198
8210
|
if (!highlight.noFill) {
|
|
8199
8211
|
ctx.fillStyle = setColorAlpha(color, highlight.fillAlpha ?? 0.12);
|
|
8200
8212
|
ctx.fillRect(x, y, width, height);
|
|
@@ -8568,6 +8580,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8568
8580
|
else if (cell.link) {
|
|
8569
8581
|
content = markdownLink(content, cell.link.url);
|
|
8570
8582
|
}
|
|
8583
|
+
this.addHeadersForSpreadingFormula(content);
|
|
8571
8584
|
this.model.dispatch("UPDATE_CELL", {
|
|
8572
8585
|
sheetId: this.sheetId,
|
|
8573
8586
|
col,
|
|
@@ -8583,6 +8596,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8583
8596
|
row,
|
|
8584
8597
|
});
|
|
8585
8598
|
}
|
|
8599
|
+
this.model.dispatch("AUTOFILL_TABLE_COLUMN", { col, row, sheetId: this.sheetId });
|
|
8586
8600
|
this.setContent("");
|
|
8587
8601
|
}
|
|
8588
8602
|
}
|
|
@@ -8785,6 +8799,38 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8785
8799
|
}
|
|
8786
8800
|
this.colorIndexByRange = colorsToKeep;
|
|
8787
8801
|
}
|
|
8802
|
+
/** Add headers at the end of the sheet so the formula in the composer has enough space to spread */
|
|
8803
|
+
addHeadersForSpreadingFormula(content) {
|
|
8804
|
+
if (!content.startsWith("=")) {
|
|
8805
|
+
return;
|
|
8806
|
+
}
|
|
8807
|
+
const evaluated = this.getters.evaluateFormula(this.sheetId, content);
|
|
8808
|
+
if (!isMatrix(evaluated)) {
|
|
8809
|
+
return;
|
|
8810
|
+
}
|
|
8811
|
+
const numberOfRows = this.getters.getNumberRows(this.sheetId);
|
|
8812
|
+
const numberOfCols = this.getters.getNumberCols(this.sheetId);
|
|
8813
|
+
const missingRows = this.row + evaluated[0].length - numberOfRows;
|
|
8814
|
+
const missingCols = this.col + evaluated.length - numberOfCols;
|
|
8815
|
+
if (missingCols > 0) {
|
|
8816
|
+
this.model.dispatch("ADD_COLUMNS_ROWS", {
|
|
8817
|
+
sheetId: this.sheetId,
|
|
8818
|
+
dimension: "COL",
|
|
8819
|
+
base: numberOfCols - 1,
|
|
8820
|
+
position: "after",
|
|
8821
|
+
quantity: missingCols + 20,
|
|
8822
|
+
});
|
|
8823
|
+
}
|
|
8824
|
+
if (missingRows > 0) {
|
|
8825
|
+
this.model.dispatch("ADD_COLUMNS_ROWS", {
|
|
8826
|
+
sheetId: this.sheetId,
|
|
8827
|
+
dimension: "ROW",
|
|
8828
|
+
base: numberOfRows - 1,
|
|
8829
|
+
position: "after",
|
|
8830
|
+
quantity: missingRows + 50,
|
|
8831
|
+
});
|
|
8832
|
+
}
|
|
8833
|
+
}
|
|
8788
8834
|
/**
|
|
8789
8835
|
* Highlight all ranges that can be found in the composer content.
|
|
8790
8836
|
*/
|
|
@@ -17418,10 +17464,11 @@ const DEFAULT_IS_SORTED = true;
|
|
|
17418
17464
|
const DEFAULT_MATCH_MODE = 0;
|
|
17419
17465
|
const DEFAULT_SEARCH_MODE = 1;
|
|
17420
17466
|
const DEFAULT_ABSOLUTE_RELATIVE_MODE = 1;
|
|
17421
|
-
function
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
|
|
17467
|
+
function valueNotAvailable(searchKey) {
|
|
17468
|
+
return {
|
|
17469
|
+
value: CellErrorType.NotAvailable,
|
|
17470
|
+
message: _t("Did not find value '%s' in [[FUNCTION_NAME]] evaluation.", toString(searchKey)),
|
|
17471
|
+
};
|
|
17425
17472
|
}
|
|
17426
17473
|
// -----------------------------------------------------------------------------
|
|
17427
17474
|
// ADDRESS
|
|
@@ -17518,7 +17565,9 @@ const HLOOKUP = {
|
|
|
17518
17565
|
? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range.length, getValueFromRange)
|
|
17519
17566
|
: linearSearch(range, searchKey, "wildcard", range.length, getValueFromRange);
|
|
17520
17567
|
const col = range[colIndex];
|
|
17521
|
-
|
|
17568
|
+
if (col === undefined) {
|
|
17569
|
+
return valueNotAvailable(searchKey);
|
|
17570
|
+
}
|
|
17522
17571
|
return col[_index - 1];
|
|
17523
17572
|
},
|
|
17524
17573
|
isExported: true,
|
|
@@ -17637,11 +17686,11 @@ const LOOKUP = {
|
|
|
17637
17686
|
: (range, index) => range[index][0].value;
|
|
17638
17687
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
17639
17688
|
const index = dichotomicSearch(searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
17640
|
-
if (index === -1
|
|
17641
|
-
|
|
17642
|
-
|
|
17643
|
-
|
|
17644
|
-
|
|
17689
|
+
if (index === -1 ||
|
|
17690
|
+
(verticalSearch && searchArray[0][index] === undefined) ||
|
|
17691
|
+
(!verticalSearch && searchArray[index][nbRow - 1] === undefined)) {
|
|
17692
|
+
return valueNotAvailable(searchKey);
|
|
17693
|
+
}
|
|
17645
17694
|
if (resultRange === undefined) {
|
|
17646
17695
|
return verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1];
|
|
17647
17696
|
}
|
|
@@ -17691,7 +17740,10 @@ const MATCH = {
|
|
|
17691
17740
|
index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
17692
17741
|
break;
|
|
17693
17742
|
}
|
|
17694
|
-
|
|
17743
|
+
if ((nbCol === 1 && range[0][index] === undefined) ||
|
|
17744
|
+
(nbCol !== 1 && range[index] === undefined)) {
|
|
17745
|
+
return valueNotAvailable(searchKey);
|
|
17746
|
+
}
|
|
17695
17747
|
return index + 1;
|
|
17696
17748
|
},
|
|
17697
17749
|
isExported: true,
|
|
@@ -17750,7 +17802,9 @@ const VLOOKUP = {
|
|
|
17750
17802
|
? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range[0].length, getValueFromRange)
|
|
17751
17803
|
: linearSearch(range, searchKey, "wildcard", range[0].length, getValueFromRange);
|
|
17752
17804
|
const value = range[_index - 1][rowIndex];
|
|
17753
|
-
|
|
17805
|
+
if (value === undefined) {
|
|
17806
|
+
return valueNotAvailable(searchKey);
|
|
17807
|
+
}
|
|
17754
17808
|
return value;
|
|
17755
17809
|
},
|
|
17756
17810
|
isExported: true,
|
|
@@ -17810,7 +17864,9 @@ const XLOOKUP = {
|
|
|
17810
17864
|
? returnRange.map((col) => [col[index]])
|
|
17811
17865
|
: [returnRange[index]];
|
|
17812
17866
|
}
|
|
17813
|
-
|
|
17867
|
+
if (defaultValue === undefined) {
|
|
17868
|
+
return valueNotAvailable(searchKey);
|
|
17869
|
+
}
|
|
17814
17870
|
return [[defaultValue]];
|
|
17815
17871
|
},
|
|
17816
17872
|
isExported: true,
|
|
@@ -18577,8 +18633,7 @@ class FunctionRegistry extends Registry {
|
|
|
18577
18633
|
function addErrorHandling(compute, functionName) {
|
|
18578
18634
|
return function (...args) {
|
|
18579
18635
|
try {
|
|
18580
|
-
|
|
18581
|
-
return computeFormula(...args);
|
|
18636
|
+
return compute.apply(this, args);
|
|
18582
18637
|
}
|
|
18583
18638
|
catch (e) {
|
|
18584
18639
|
return handleError(e, functionName);
|
|
@@ -18612,8 +18667,7 @@ function hasStringMessage(obj) {
|
|
|
18612
18667
|
}
|
|
18613
18668
|
function addResultHandling(compute) {
|
|
18614
18669
|
return function (...args) {
|
|
18615
|
-
const
|
|
18616
|
-
const result = computeResult(...args);
|
|
18670
|
+
const result = compute.apply(this, args);
|
|
18617
18671
|
if (!isMatrix(result)) {
|
|
18618
18672
|
if (typeof result === "object" && result !== null && "value" in result) {
|
|
18619
18673
|
return result;
|
|
@@ -18828,8 +18882,10 @@ function getGroup(cell, cells, filter) {
|
|
|
18828
18882
|
if (x === cell) {
|
|
18829
18883
|
found = true;
|
|
18830
18884
|
}
|
|
18831
|
-
const cellValue =
|
|
18832
|
-
|
|
18885
|
+
const cellValue = x?.isFormula
|
|
18886
|
+
? undefined
|
|
18887
|
+
: evaluateLiteral(x?.content, { locale: DEFAULT_LOCALE });
|
|
18888
|
+
if (cellValue && filter(cellValue)) {
|
|
18833
18889
|
group.push(cellValue);
|
|
18834
18890
|
}
|
|
18835
18891
|
else {
|
|
@@ -19478,9 +19534,15 @@ function getChartDatasetValues(getters, dataSets) {
|
|
|
19478
19534
|
: (label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`);
|
|
19479
19535
|
}
|
|
19480
19536
|
else {
|
|
19481
|
-
label =
|
|
19537
|
+
label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`;
|
|
19482
19538
|
}
|
|
19483
19539
|
let data = ds.dataRange ? getData(getters, ds) : [];
|
|
19540
|
+
if (data.every((e) => typeof e === "string" && !isEvaluationError(e))) {
|
|
19541
|
+
// In this case, we want a chart based on the string occurrences count
|
|
19542
|
+
// This will be done by associating each string with a value of 1 and
|
|
19543
|
+
// the using the classical aggregation method to sum the values.
|
|
19544
|
+
data.fill(1);
|
|
19545
|
+
}
|
|
19484
19546
|
datasetValues.push({ data, label });
|
|
19485
19547
|
}
|
|
19486
19548
|
return datasetValues;
|
|
@@ -19579,7 +19641,7 @@ class BarChart extends AbstractChart {
|
|
|
19579
19641
|
dataSets: context.range ? context.range : [],
|
|
19580
19642
|
dataSetsHaveTitle: false,
|
|
19581
19643
|
stacked: false,
|
|
19582
|
-
aggregated: false,
|
|
19644
|
+
aggregated: context.aggregated ?? false,
|
|
19583
19645
|
legendPosition: "top",
|
|
19584
19646
|
title: context.title || "",
|
|
19585
19647
|
type: "bar",
|
|
@@ -19595,6 +19657,7 @@ class BarChart extends AbstractChart {
|
|
|
19595
19657
|
auxiliaryRange: this.labelRange
|
|
19596
19658
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
19597
19659
|
: undefined,
|
|
19660
|
+
aggregated: this.aggregated,
|
|
19598
19661
|
};
|
|
19599
19662
|
}
|
|
19600
19663
|
copyForSheetId(sheetId) {
|
|
@@ -20344,7 +20407,7 @@ class LineChart extends AbstractChart {
|
|
|
20344
20407
|
verticalAxisPosition: "left",
|
|
20345
20408
|
labelRange: context.auxiliaryRange || undefined,
|
|
20346
20409
|
stacked: false,
|
|
20347
|
-
aggregated: false,
|
|
20410
|
+
aggregated: context.aggregated ?? false,
|
|
20348
20411
|
cumulative: false,
|
|
20349
20412
|
};
|
|
20350
20413
|
}
|
|
@@ -20377,6 +20440,7 @@ class LineChart extends AbstractChart {
|
|
|
20377
20440
|
auxiliaryRange: this.labelRange
|
|
20378
20441
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
20379
20442
|
: undefined,
|
|
20443
|
+
aggregated: this.aggregated,
|
|
20380
20444
|
};
|
|
20381
20445
|
}
|
|
20382
20446
|
updateRanges(applyChange) {
|
|
@@ -20451,7 +20515,7 @@ class PieChart extends AbstractChart {
|
|
|
20451
20515
|
title: context.title || "",
|
|
20452
20516
|
type: "pie",
|
|
20453
20517
|
labelRange: context.auxiliaryRange || undefined,
|
|
20454
|
-
aggregated: false,
|
|
20518
|
+
aggregated: context.aggregated ?? false,
|
|
20455
20519
|
};
|
|
20456
20520
|
}
|
|
20457
20521
|
getDefinition() {
|
|
@@ -20465,6 +20529,7 @@ class PieChart extends AbstractChart {
|
|
|
20465
20529
|
auxiliaryRange: this.labelRange
|
|
20466
20530
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
20467
20531
|
: undefined,
|
|
20532
|
+
aggregated: this.aggregated,
|
|
20468
20533
|
};
|
|
20469
20534
|
}
|
|
20470
20535
|
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
@@ -20656,7 +20721,7 @@ class ScatterChart extends AbstractChart {
|
|
|
20656
20721
|
type: "scatter",
|
|
20657
20722
|
verticalAxisPosition: "left",
|
|
20658
20723
|
labelRange: context.auxiliaryRange || undefined,
|
|
20659
|
-
aggregated: false,
|
|
20724
|
+
aggregated: context.aggregated ?? false,
|
|
20660
20725
|
};
|
|
20661
20726
|
}
|
|
20662
20727
|
getDefinition() {
|
|
@@ -20686,6 +20751,7 @@ class ScatterChart extends AbstractChart {
|
|
|
20686
20751
|
auxiliaryRange: this.labelRange
|
|
20687
20752
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
20688
20753
|
: undefined,
|
|
20754
|
+
aggregated: this.aggregated,
|
|
20689
20755
|
};
|
|
20690
20756
|
}
|
|
20691
20757
|
updateRanges(applyChange) {
|
|
@@ -22353,6 +22419,50 @@ function isCtrlKey(ev) {
|
|
|
22353
22419
|
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
22354
22420
|
}
|
|
22355
22421
|
|
|
22422
|
+
/**
|
|
22423
|
+
* Repeatedly calls a callback function with a time delay between calls.
|
|
22424
|
+
*/
|
|
22425
|
+
function useInterval(callback, delay) {
|
|
22426
|
+
let intervalId;
|
|
22427
|
+
const { setInterval, clearInterval } = window;
|
|
22428
|
+
owl.useEffect(() => {
|
|
22429
|
+
intervalId = setInterval(callback, delay);
|
|
22430
|
+
return () => clearInterval(intervalId);
|
|
22431
|
+
}, () => [delay]);
|
|
22432
|
+
return {
|
|
22433
|
+
pause: () => {
|
|
22434
|
+
clearInterval(intervalId);
|
|
22435
|
+
intervalId = undefined;
|
|
22436
|
+
},
|
|
22437
|
+
resume: () => {
|
|
22438
|
+
if (intervalId === undefined) {
|
|
22439
|
+
intervalId = setInterval(callback, delay);
|
|
22440
|
+
}
|
|
22441
|
+
},
|
|
22442
|
+
};
|
|
22443
|
+
}
|
|
22444
|
+
/**
|
|
22445
|
+
* Calls a callback function with a time delay
|
|
22446
|
+
*/
|
|
22447
|
+
function useTimeOut() {
|
|
22448
|
+
let timeOutId;
|
|
22449
|
+
function clear() {
|
|
22450
|
+
if (timeOutId !== undefined) {
|
|
22451
|
+
clearTimeout(timeOutId);
|
|
22452
|
+
timeOutId = undefined;
|
|
22453
|
+
}
|
|
22454
|
+
}
|
|
22455
|
+
function schedule(callback, delay) {
|
|
22456
|
+
clear();
|
|
22457
|
+
timeOutId = setTimeout(callback, delay);
|
|
22458
|
+
}
|
|
22459
|
+
owl.onWillUnmount(clear);
|
|
22460
|
+
return {
|
|
22461
|
+
clear,
|
|
22462
|
+
schedule,
|
|
22463
|
+
};
|
|
22464
|
+
}
|
|
22465
|
+
|
|
22356
22466
|
//------------------------------------------------------------------------------
|
|
22357
22467
|
// Context Menu Component
|
|
22358
22468
|
//------------------------------------------------------------------------------
|
|
@@ -22403,6 +22513,7 @@ css /* scss */ `
|
|
|
22403
22513
|
}
|
|
22404
22514
|
}
|
|
22405
22515
|
`;
|
|
22516
|
+
const TIMEOUT_DELAY = 250;
|
|
22406
22517
|
class Menu extends owl.Component {
|
|
22407
22518
|
static template = "o-spreadsheet-Menu";
|
|
22408
22519
|
static props = {
|
|
@@ -22413,6 +22524,7 @@ class Menu extends owl.Component {
|
|
|
22413
22524
|
onClose: Function,
|
|
22414
22525
|
onMenuClicked: { type: Function, optional: true },
|
|
22415
22526
|
menuId: { type: String, optional: true },
|
|
22527
|
+
onMouseOver: { type: Function, optional: true },
|
|
22416
22528
|
};
|
|
22417
22529
|
static components = { Menu, Popover };
|
|
22418
22530
|
static defaultProps = {
|
|
@@ -22423,10 +22535,12 @@ class Menu extends owl.Component {
|
|
|
22423
22535
|
position: null,
|
|
22424
22536
|
scrollOffset: 0,
|
|
22425
22537
|
menuItems: [],
|
|
22538
|
+
isHoveringChild: false,
|
|
22426
22539
|
});
|
|
22427
22540
|
menuRef = owl.useRef("menu");
|
|
22428
22541
|
hoveredMenu = undefined;
|
|
22429
22542
|
position = useAbsoluteBoundingRect(this.menuRef);
|
|
22543
|
+
openingTimeOut = useTimeOut();
|
|
22430
22544
|
setup() {
|
|
22431
22545
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
22432
22546
|
owl.useExternalListener(window, "contextmenu", this.onExternalClick, { capture: true });
|
|
@@ -22526,6 +22640,9 @@ class Menu extends owl.Component {
|
|
|
22526
22640
|
}
|
|
22527
22641
|
return false;
|
|
22528
22642
|
}
|
|
22643
|
+
isActive(menuItem) {
|
|
22644
|
+
return (this.subMenu?.isHoveringChild || false) && this.isParentMenu(this.subMenu, menuItem);
|
|
22645
|
+
}
|
|
22529
22646
|
onScroll(ev) {
|
|
22530
22647
|
this.subMenu.scrollOffset = ev.target.scrollTop;
|
|
22531
22648
|
}
|
|
@@ -22533,10 +22650,10 @@ class Menu extends owl.Component {
|
|
|
22533
22650
|
* If the given menu is not disabled, open it's submenu at the
|
|
22534
22651
|
* correct position according to available surrounding space.
|
|
22535
22652
|
*/
|
|
22536
|
-
openSubMenu(menu,
|
|
22537
|
-
|
|
22538
|
-
if (!parentMenuEl)
|
|
22653
|
+
openSubMenu(menu, parentMenuEl) {
|
|
22654
|
+
if (!parentMenuEl) {
|
|
22539
22655
|
return;
|
|
22656
|
+
}
|
|
22540
22657
|
const y = parentMenuEl.getBoundingClientRect().top;
|
|
22541
22658
|
this.subMenu.position = {
|
|
22542
22659
|
x: this.position.x + this.props.depth * MENU_WIDTH,
|
|
@@ -22550,32 +22667,50 @@ class Menu extends owl.Component {
|
|
|
22550
22667
|
return subMenu.parentMenu?.id === menuItem.id;
|
|
22551
22668
|
}
|
|
22552
22669
|
closeSubMenu() {
|
|
22670
|
+
if (this.subMenu.isHoveringChild) {
|
|
22671
|
+
return;
|
|
22672
|
+
}
|
|
22553
22673
|
this.subMenu.isOpen = false;
|
|
22554
22674
|
this.subMenu.parentMenu = undefined;
|
|
22555
22675
|
}
|
|
22556
22676
|
onClickMenu(menu, ev) {
|
|
22557
22677
|
if (this.isEnabled(menu)) {
|
|
22558
22678
|
if (this.isRoot(menu)) {
|
|
22559
|
-
this.openSubMenu(menu, ev);
|
|
22679
|
+
this.openSubMenu(menu, ev.currentTarget);
|
|
22560
22680
|
}
|
|
22561
22681
|
else {
|
|
22562
22682
|
this.activateMenu(menu);
|
|
22563
22683
|
}
|
|
22564
22684
|
}
|
|
22565
22685
|
}
|
|
22566
|
-
|
|
22567
|
-
this.hoveredMenu = menu;
|
|
22568
|
-
menu.onStartHover?.(this.env);
|
|
22686
|
+
onMouseOver(menu, ev) {
|
|
22569
22687
|
if (this.isEnabled(menu)) {
|
|
22570
|
-
if (this.
|
|
22571
|
-
this.
|
|
22688
|
+
if (this.isParentMenu(this.subMenu, menu)) {
|
|
22689
|
+
this.openingTimeOut.clear();
|
|
22690
|
+
return;
|
|
22572
22691
|
}
|
|
22573
|
-
|
|
22574
|
-
|
|
22692
|
+
const currentTarget = ev.currentTarget;
|
|
22693
|
+
if (this.isRoot(menu)) {
|
|
22694
|
+
this.openingTimeOut.schedule(() => {
|
|
22695
|
+
this.openSubMenu(menu, currentTarget);
|
|
22696
|
+
}, TIMEOUT_DELAY);
|
|
22575
22697
|
}
|
|
22576
22698
|
}
|
|
22577
22699
|
}
|
|
22700
|
+
onMouseOverMainMenu() {
|
|
22701
|
+
this.props.onMouseOver?.();
|
|
22702
|
+
this.subMenu.isHoveringChild = false;
|
|
22703
|
+
}
|
|
22704
|
+
onMouseOverChildMenu() {
|
|
22705
|
+
this.subMenu.isHoveringChild = true;
|
|
22706
|
+
this.openingTimeOut.clear();
|
|
22707
|
+
}
|
|
22708
|
+
onMouseEnter(menu, ev) {
|
|
22709
|
+
this.hoveredMenu = menu;
|
|
22710
|
+
menu.onStartHover?.(this.env);
|
|
22711
|
+
}
|
|
22578
22712
|
onMouseLeave(menu) {
|
|
22713
|
+
this.openingTimeOut.schedule(this.closeSubMenu.bind(this), TIMEOUT_DELAY);
|
|
22579
22714
|
this.hoveredMenu = undefined;
|
|
22580
22715
|
menu.onStopHover?.(this.env);
|
|
22581
22716
|
}
|
|
@@ -22827,7 +22962,8 @@ function getChartTypes() {
|
|
|
22827
22962
|
*/
|
|
22828
22963
|
function getSmartChartDefinition(zone, getters) {
|
|
22829
22964
|
let dataSetZone = zone;
|
|
22830
|
-
|
|
22965
|
+
const singleColumn = zoneToDimension(zone).numberOfCols === 1;
|
|
22966
|
+
if (!singleColumn) {
|
|
22831
22967
|
dataSetZone = { ...zone, left: zone.left + 1 };
|
|
22832
22968
|
}
|
|
22833
22969
|
const dataSets = [zoneToXc(dataSetZone)];
|
|
@@ -22861,7 +22997,7 @@ function getSmartChartDefinition(zone, getters) {
|
|
|
22861
22997
|
}
|
|
22862
22998
|
}
|
|
22863
22999
|
let labelRangeXc;
|
|
22864
|
-
if (
|
|
23000
|
+
if (!singleColumn) {
|
|
22865
23001
|
labelRangeXc = zoneToXc({
|
|
22866
23002
|
...zone,
|
|
22867
23003
|
right: zone.left,
|
|
@@ -22885,6 +23021,19 @@ function getSmartChartDefinition(zone, getters) {
|
|
|
22885
23021
|
legendPosition: newLegendPos,
|
|
22886
23022
|
};
|
|
22887
23023
|
}
|
|
23024
|
+
const _dataSets = createDataSets(getters, dataSets, sheetId, dataSetsHaveTitle);
|
|
23025
|
+
if (singleColumn &&
|
|
23026
|
+
getData(getters, _dataSets[0]).every((e) => typeof e === "string" && !isEvaluationError(e))) {
|
|
23027
|
+
return {
|
|
23028
|
+
title: "",
|
|
23029
|
+
dataSets,
|
|
23030
|
+
aggregated: true,
|
|
23031
|
+
labelRange: dataSets[0],
|
|
23032
|
+
type: "pie",
|
|
23033
|
+
legendPosition: "top",
|
|
23034
|
+
dataSetsHaveTitle: false,
|
|
23035
|
+
};
|
|
23036
|
+
}
|
|
22888
23037
|
return {
|
|
22889
23038
|
title,
|
|
22890
23039
|
dataSets,
|
|
@@ -22912,6 +23061,7 @@ const DEFAULT_TABLE_CONFIG = {
|
|
|
22912
23061
|
numberOfHeaders: 1,
|
|
22913
23062
|
bandedRows: true,
|
|
22914
23063
|
bandedColumns: false,
|
|
23064
|
+
automaticAutofill: true,
|
|
22915
23065
|
styleId: "TableStyleMedium2",
|
|
22916
23066
|
};
|
|
22917
23067
|
function generateColorSet(name, highlightColor) {
|
|
@@ -26395,7 +26545,7 @@ class LineBarPieConfigPanel extends owl.Component {
|
|
|
26395
26545
|
{
|
|
26396
26546
|
name: "aggregated",
|
|
26397
26547
|
label: _t("Aggregate"),
|
|
26398
|
-
value: this.props.definition.aggregated,
|
|
26548
|
+
value: this.props.definition.aggregated ?? false,
|
|
26399
26549
|
onChange: this.onUpdateAggregated.bind(this),
|
|
26400
26550
|
},
|
|
26401
26551
|
];
|
|
@@ -27566,15 +27716,15 @@ css /* scss */ `
|
|
|
27566
27716
|
// -----------------------------------------------------------------------------
|
|
27567
27717
|
// We need here the svg of the icons that we need to convert to images for the renderer
|
|
27568
27718
|
// -----------------------------------------------------------------------------
|
|
27569
|
-
const ARROW_DOWN = '<svg class="o-cf-icon arrow-down" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#
|
|
27570
|
-
const ARROW_UP = '<svg class="o-cf-icon arrow-up" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#
|
|
27719
|
+
const ARROW_DOWN = '<svg class="o-cf-icon arrow-down" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#E06666" d="M413.1 222.5l22.2 22.2c9.4 9.4 9.4 24.6 0 33.9L241 473c-9.4 9.4-24.6 9.4-33.9 0L12.7 278.6c-9.4-9.4-9.4-24.6 0-33.9l22.2-22.2c9.5-9.5 25-9.3 34.3.4L184 343.4V56c0-13.3 10.7-24 24-24h32c13.3 0 24 10.7 24 24v287.4l114.8-120.5c9.3-9.8 24.8-10 34.3-.4z"></path></svg>';
|
|
27720
|
+
const ARROW_UP = '<svg class="o-cf-icon arrow-up" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#6AA84F" d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"></path></svg>';
|
|
27571
27721
|
const ARROW_RIGHT = '<svg class="o-cf-icon arrow-right" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#F0AD4E" d="M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"></path></svg>';
|
|
27572
|
-
const SMILE = '<svg class="o-cf-icon smile" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#
|
|
27722
|
+
const SMILE = '<svg class="o-cf-icon smile" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#6AA84F" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"></path></svg>';
|
|
27573
27723
|
const MEH = '<svg class="o-cf-icon meh" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#F0AD4E" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z"></path></svg>';
|
|
27574
|
-
const FROWN = '<svg class="o-cf-icon frown" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#
|
|
27575
|
-
const GREEN_DOT = '<svg class="o-cf-icon green-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#
|
|
27724
|
+
const FROWN = '<svg class="o-cf-icon frown" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#E06666" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"></path></svg>';
|
|
27725
|
+
const GREEN_DOT = '<svg class="o-cf-icon green-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#6AA84F" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
|
|
27576
27726
|
const YELLOW_DOT = '<svg class="o-cf-icon yellow-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#F0AD4E" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
|
|
27577
|
-
const RED_DOT = '<svg class="o-cf-icon red-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#
|
|
27727
|
+
const RED_DOT = '<svg class="o-cf-icon red-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#E06666" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
|
|
27578
27728
|
function loadIconImage(svg) {
|
|
27579
27729
|
/** We have to add xmlns, as it's not added by owl in the canvas */
|
|
27580
27730
|
svg = `<svg xmlns="http://www.w3.org/2000/svg" ${svg.slice(4)}`;
|
|
@@ -29440,8 +29590,7 @@ class DataValidationPanel extends owl.Component {
|
|
|
29440
29590
|
}
|
|
29441
29591
|
}
|
|
29442
29592
|
|
|
29443
|
-
const
|
|
29444
|
-
const BACKGROUND_COLOR = "#8B008B33";
|
|
29593
|
+
const FIND_AND_REPLACE_HIGHLIGHT_COLOR = "#8B008B";
|
|
29445
29594
|
var Direction;
|
|
29446
29595
|
(function (Direction) {
|
|
29447
29596
|
Direction[Direction["previous"] = -1] = "previous";
|
|
@@ -29472,14 +29621,14 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
29472
29621
|
super(get);
|
|
29473
29622
|
this.initialShowFormulaState = this.model.getters.shouldShowFormulas();
|
|
29474
29623
|
this.searchOptions.searchFormulas = this.initialShowFormulaState;
|
|
29624
|
+
const highlightStore = get(HighlightStore);
|
|
29625
|
+
highlightStore.register(owl.toRaw(this));
|
|
29475
29626
|
this.onDispose(() => {
|
|
29476
29627
|
this.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
|
|
29477
29628
|
this.updateSearchContent.stopDebounce();
|
|
29629
|
+
highlightStore.unRegister(owl.toRaw(this));
|
|
29478
29630
|
});
|
|
29479
29631
|
}
|
|
29480
|
-
get renderingLayers() {
|
|
29481
|
-
return ["Search"];
|
|
29482
|
-
}
|
|
29483
29632
|
get searchMatches() {
|
|
29484
29633
|
switch (this.searchOptions.searchScope) {
|
|
29485
29634
|
case "allSheets":
|
|
@@ -29706,8 +29855,8 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
29706
29855
|
// ---------------------------------------------------------------------------
|
|
29707
29856
|
// Grid rendering
|
|
29708
29857
|
// ---------------------------------------------------------------------------
|
|
29709
|
-
|
|
29710
|
-
const
|
|
29858
|
+
get highlights() {
|
|
29859
|
+
const highlights = [];
|
|
29711
29860
|
const sheetId = this.getters.getActiveSheetId();
|
|
29712
29861
|
for (const [index, match] of this.searchMatches.entries()) {
|
|
29713
29862
|
if (match.sheetId !== sheetId) {
|
|
@@ -29715,26 +29864,31 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
29715
29864
|
}
|
|
29716
29865
|
const zone = positionToZone(match);
|
|
29717
29866
|
const zoneWithMerge = this.getters.expandZone(sheetId, zone);
|
|
29718
|
-
const {
|
|
29867
|
+
const { width, height } = this.getters.getVisibleRect(zoneWithMerge);
|
|
29719
29868
|
if (width > 0 && height > 0) {
|
|
29720
|
-
|
|
29721
|
-
|
|
29722
|
-
|
|
29723
|
-
|
|
29724
|
-
|
|
29725
|
-
|
|
29869
|
+
highlights.push({
|
|
29870
|
+
sheetId,
|
|
29871
|
+
zone: zoneWithMerge,
|
|
29872
|
+
color: FIND_AND_REPLACE_HIGHLIGHT_COLOR,
|
|
29873
|
+
noBorder: index !== this.selectedMatchIndex,
|
|
29874
|
+
thinLine: true,
|
|
29875
|
+
fillAlpha: 0.2,
|
|
29876
|
+
});
|
|
29726
29877
|
}
|
|
29727
29878
|
}
|
|
29728
|
-
// TODO: use Highlights helpers/stores when the Highlight PR is merged
|
|
29729
29879
|
if (this.searchOptions.searchScope === "specificRange") {
|
|
29730
29880
|
const range = this.searchOptions.specificRange;
|
|
29731
|
-
if (
|
|
29732
|
-
|
|
29881
|
+
if (range && range.sheetId === sheetId) {
|
|
29882
|
+
highlights.push({
|
|
29883
|
+
sheetId,
|
|
29884
|
+
zone: range.zone,
|
|
29885
|
+
color: FIND_AND_REPLACE_HIGHLIGHT_COLOR,
|
|
29886
|
+
noFill: true,
|
|
29887
|
+
thinLine: true,
|
|
29888
|
+
});
|
|
29733
29889
|
}
|
|
29734
|
-
const { x, y, width, height } = this.getters.getVisibleRect(range.zone);
|
|
29735
|
-
ctx.strokeStyle = BORDER_COLOR;
|
|
29736
|
-
ctx.strokeRect(x, y, width, height);
|
|
29737
29890
|
}
|
|
29891
|
+
return highlights;
|
|
29738
29892
|
}
|
|
29739
29893
|
}
|
|
29740
29894
|
|
|
@@ -30148,6 +30302,12 @@ const TABLE_ELEMENTS_BY_PRIORITY = [
|
|
|
30148
30302
|
"headerRow",
|
|
30149
30303
|
"totalRow",
|
|
30150
30304
|
];
|
|
30305
|
+
/** Return the content zone of the table, ie. the table zone without the headers */
|
|
30306
|
+
function getTableContentZone(tableZone, tableConfig) {
|
|
30307
|
+
const numberOfHeaders = tableConfig.numberOfHeaders;
|
|
30308
|
+
const contentZone = { ...tableZone, top: tableZone.top + numberOfHeaders };
|
|
30309
|
+
return contentZone.top <= contentZone.bottom ? contentZone : undefined;
|
|
30310
|
+
}
|
|
30151
30311
|
function getComputedTableStyle(tableConfig, numberOfCols, numberOfRows) {
|
|
30152
30312
|
return {
|
|
30153
30313
|
borders: getAllTableBorders(tableConfig, numberOfCols, numberOfRows),
|
|
@@ -30599,14 +30759,6 @@ class TablePanel extends owl.Component {
|
|
|
30599
30759
|
tableXc: this.env.model.getters.getRangeString(this.props.table.range, sheetId),
|
|
30600
30760
|
filtersEnabledIfPossible: this.props.table.config.hasFilters,
|
|
30601
30761
|
});
|
|
30602
|
-
owl.onWillUpdateProps((nextProps) => {
|
|
30603
|
-
if (this.props.table.id !== nextProps.table.id) {
|
|
30604
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30605
|
-
this.state.tableXc = this.env.model.getters.getRangeString(nextProps.table.range, sheetId);
|
|
30606
|
-
this.state.tableZoneErrors = [];
|
|
30607
|
-
this.state.filtersEnabledIfPossible = nextProps.table.config.hasFilters;
|
|
30608
|
-
}
|
|
30609
|
-
});
|
|
30610
30762
|
}
|
|
30611
30763
|
updateHasFilters(hasFilters) {
|
|
30612
30764
|
this.state.filtersEnabledIfPossible = hasFilters;
|
|
@@ -30755,7 +30907,11 @@ sidePanelRegistry.add("TableSidePanel", {
|
|
|
30755
30907
|
if (!table) {
|
|
30756
30908
|
return { isOpen: false };
|
|
30757
30909
|
}
|
|
30758
|
-
return {
|
|
30910
|
+
return {
|
|
30911
|
+
isOpen: true,
|
|
30912
|
+
props: { table },
|
|
30913
|
+
key: table.id,
|
|
30914
|
+
};
|
|
30759
30915
|
},
|
|
30760
30916
|
});
|
|
30761
30917
|
|
|
@@ -32470,19 +32626,21 @@ class GridCellIcon extends owl.Component {
|
|
|
32470
32626
|
slots: Object,
|
|
32471
32627
|
};
|
|
32472
32628
|
get iconStyle() {
|
|
32473
|
-
const
|
|
32474
|
-
const
|
|
32629
|
+
const cellPosition = this.props.cellPosition;
|
|
32630
|
+
const merge = this.env.model.getters.getMerge(cellPosition);
|
|
32631
|
+
const zone = merge || positionToZone(cellPosition);
|
|
32632
|
+
const rect = this.env.model.getters.getVisibleRectWithoutHeaders(zone);
|
|
32633
|
+
const x = this.getIconHorizontalPosition(rect, cellPosition);
|
|
32634
|
+
const y = this.getIconVerticalPosition(rect, cellPosition);
|
|
32475
32635
|
return cssPropertiesToCss({
|
|
32476
32636
|
top: `${y + (this.props.offset?.y || 0)}px`,
|
|
32477
32637
|
left: `${x + (this.props.offset?.x || 0)}px`,
|
|
32478
32638
|
});
|
|
32479
32639
|
}
|
|
32480
|
-
getIconVerticalPosition() {
|
|
32481
|
-
const
|
|
32482
|
-
const
|
|
32483
|
-
const
|
|
32484
|
-
const end = this.env.model.getters.getRowDimensionsInViewport(sheetId, merge ? merge.bottom : row).end;
|
|
32485
|
-
const cell = this.env.model.getters.getCell(this.props.cellPosition);
|
|
32640
|
+
getIconVerticalPosition(rect, cellPosition) {
|
|
32641
|
+
const start = rect.y;
|
|
32642
|
+
const end = rect.y + rect.height;
|
|
32643
|
+
const cell = this.env.model.getters.getCell(cellPosition);
|
|
32486
32644
|
const align = this.props.verticalAlign || cell?.style?.verticalAlign || DEFAULT_VERTICAL_ALIGN;
|
|
32487
32645
|
switch (align) {
|
|
32488
32646
|
case "bottom":
|
|
@@ -32494,13 +32652,11 @@ class GridCellIcon extends owl.Component {
|
|
|
32494
32652
|
return end - GRID_ICON_EDGE_LENGTH - centeringOffset;
|
|
32495
32653
|
}
|
|
32496
32654
|
}
|
|
32497
|
-
getIconHorizontalPosition() {
|
|
32498
|
-
const
|
|
32499
|
-
const
|
|
32500
|
-
const
|
|
32501
|
-
const
|
|
32502
|
-
const cell = this.env.model.getters.getCell(this.props.cellPosition);
|
|
32503
|
-
const evaluatedCell = this.env.model.getters.getEvaluatedCell(this.props.cellPosition);
|
|
32655
|
+
getIconHorizontalPosition(rect, cellPosition) {
|
|
32656
|
+
const start = rect.x;
|
|
32657
|
+
const end = rect.x + rect.width;
|
|
32658
|
+
const cell = this.env.model.getters.getCell(cellPosition);
|
|
32659
|
+
const evaluatedCell = this.env.model.getters.getEvaluatedCell(cellPosition);
|
|
32504
32660
|
const align = this.props.horizontalAlign || cell?.style?.align || evaluatedCell.defaultAlign;
|
|
32505
32661
|
switch (align) {
|
|
32506
32662
|
case "right":
|
|
@@ -32605,6 +32761,8 @@ css /* scss */ `
|
|
|
32605
32761
|
height: ${CHECKBOX_WIDTH}px;
|
|
32606
32762
|
accent-color: #808080;
|
|
32607
32763
|
margin: ${MARGIN}px;
|
|
32764
|
+
/** required to prevent the checkbox position to be sensible to the font-size (affects Firefox) */
|
|
32765
|
+
position: absolute;
|
|
32608
32766
|
}
|
|
32609
32767
|
`;
|
|
32610
32768
|
class DataValidationCheckbox extends owl.Component {
|
|
@@ -32623,7 +32781,7 @@ class DataValidationCheckbox extends owl.Component {
|
|
|
32623
32781
|
}
|
|
32624
32782
|
get isDisabled() {
|
|
32625
32783
|
const cell = this.env.model.getters.getCell(this.props.cellPosition);
|
|
32626
|
-
return !!cell?.isFormula;
|
|
32784
|
+
return this.env.model.getters.isReadonly() || !!cell?.isFormula;
|
|
32627
32785
|
}
|
|
32628
32786
|
}
|
|
32629
32787
|
|
|
@@ -32663,12 +32821,17 @@ class DataValidationOverlay extends owl.Component {
|
|
|
32663
32821
|
static props = {};
|
|
32664
32822
|
static components = { GridCellIcon, DataValidationCheckbox, DataValidationListIcon };
|
|
32665
32823
|
get checkBoxCellPositions() {
|
|
32666
|
-
return this.env.model.getters
|
|
32824
|
+
return this.env.model.getters
|
|
32825
|
+
.getVisibleCellPositions()
|
|
32826
|
+
.filter(this.env.model.getters.isCellValidCheckbox);
|
|
32667
32827
|
}
|
|
32668
32828
|
get listIconsCellPositions() {
|
|
32669
|
-
|
|
32670
|
-
|
|
32671
|
-
|
|
32829
|
+
if (this.env.model.getters.isReadonly()) {
|
|
32830
|
+
return [];
|
|
32831
|
+
}
|
|
32832
|
+
return this.env.model.getters
|
|
32833
|
+
.getVisibleCellPositions()
|
|
32834
|
+
.filter(this.env.model.getters.cellHasListDataValidationIcon);
|
|
32672
32835
|
}
|
|
32673
32836
|
}
|
|
32674
32837
|
|
|
@@ -32713,7 +32876,7 @@ function dragFigureForMove({ x: mouseX, y: mouseY }, { x: mouseInitialX, y: mous
|
|
|
32713
32876
|
const newY = clip(initialFigure.y + deltaY, minY, maxY - initialFigure.height - scrollY);
|
|
32714
32877
|
return { ...initialFigure, x: newX, y: newY };
|
|
32715
32878
|
}
|
|
32716
|
-
function dragFigureForResize(initialFigure, dirX, dirY, { x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, keepRatio, minFigSize) {
|
|
32879
|
+
function dragFigureForResize(initialFigure, dirX, dirY, { x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, keepRatio, minFigSize, { scrollX, scrollY }) {
|
|
32717
32880
|
let { x, y, width, height } = initialFigure;
|
|
32718
32881
|
if (keepRatio && dirX != 0 && dirY != 0) {
|
|
32719
32882
|
const deltaX = Math.min(dirX * (mouseInitialX - mouseX), initialFigure.width - minFigSize);
|
|
@@ -32740,14 +32903,14 @@ function dragFigureForResize(initialFigure, dirX, dirY, { x: mouseX, y: mouseY }
|
|
|
32740
32903
|
y = initialFigure.y - deltaY;
|
|
32741
32904
|
}
|
|
32742
32905
|
}
|
|
32743
|
-
//
|
|
32744
|
-
if (x
|
|
32745
|
-
width
|
|
32746
|
-
x =
|
|
32906
|
+
// Adjusts figure dimensions to ensure it remains within header boundaries and viewport during resizing.
|
|
32907
|
+
if (x + scrollX <= 0) {
|
|
32908
|
+
width = width + x + scrollX;
|
|
32909
|
+
x = -scrollX;
|
|
32747
32910
|
}
|
|
32748
|
-
if (y
|
|
32749
|
-
height
|
|
32750
|
-
y =
|
|
32911
|
+
if (y + scrollY <= 0) {
|
|
32912
|
+
height = height + y + scrollY;
|
|
32913
|
+
y = -scrollY;
|
|
32751
32914
|
}
|
|
32752
32915
|
return { ...initialFigure, x, y, width, height };
|
|
32753
32916
|
}
|
|
@@ -33167,7 +33330,7 @@ class FiguresContainer extends owl.Component {
|
|
|
33167
33330
|
const minFigSize = figureRegistry.get(figure.tag).minFigSize || MIN_FIG_SIZE;
|
|
33168
33331
|
const onMouseMove = (ev) => {
|
|
33169
33332
|
const currentMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
33170
|
-
const draggedFigure = dragFigureForResize(initialFig, dirX, dirY, currentMousePosition, initialMousePosition, keepRatio, minFigSize);
|
|
33333
|
+
const draggedFigure = dragFigureForResize(initialFig, dirX, dirY, currentMousePosition, initialMousePosition, keepRatio, minFigSize, this.env.model.getters.getActiveSheetScrollInfo());
|
|
33171
33334
|
const otherFigures = this.getOtherFigures(figure.id);
|
|
33172
33335
|
const snapResult = snapForResize(this.env.model.getters, dirX, dirY, draggedFigure, otherFigures);
|
|
33173
33336
|
this.dnd.draggedFigure = snapResult.snappedFigure;
|
|
@@ -33343,29 +33506,6 @@ class GridAddRowsFooter extends owl.Component {
|
|
|
33343
33506
|
}
|
|
33344
33507
|
}
|
|
33345
33508
|
|
|
33346
|
-
/**
|
|
33347
|
-
* Repeatedly calls a callback function with a time delay between calls.
|
|
33348
|
-
*/
|
|
33349
|
-
function useInterval(callback, delay) {
|
|
33350
|
-
let intervalId;
|
|
33351
|
-
const { setInterval, clearInterval } = window;
|
|
33352
|
-
owl.useEffect(() => {
|
|
33353
|
-
intervalId = setInterval(callback, delay);
|
|
33354
|
-
return () => clearInterval(intervalId);
|
|
33355
|
-
}, () => [delay]);
|
|
33356
|
-
return {
|
|
33357
|
-
pause: () => {
|
|
33358
|
-
clearInterval(intervalId);
|
|
33359
|
-
intervalId = undefined;
|
|
33360
|
-
},
|
|
33361
|
-
resume: () => {
|
|
33362
|
-
if (intervalId === undefined) {
|
|
33363
|
-
intervalId = setInterval(callback, delay);
|
|
33364
|
-
}
|
|
33365
|
-
},
|
|
33366
|
-
};
|
|
33367
|
-
}
|
|
33368
|
-
|
|
33369
33509
|
const CURSOR_SVG = /*xml*/ `
|
|
33370
33510
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="16"><path d="M6.5.4c1.3-.8 2.9-.1 3.8 1.4l2.9 5.1c.2.4.9 1.6-.4 2.3l-1.6.9 1.8 3.1c.2.4.1 1-.2 1.2l-1.6 1c-.3.1-.9 0-1.1-.4l-1.8-3.1-1.6 1c-.6.4-1.7 0-2.2-.8L0 4.3"/><path fill="#fff" d="M9.1 2a1.4 1.1 60 0 0-1.7-.6L5.5 2.5l.9 1.6-1 .6-.9-1.6-.6.4 1.8 3.1-1.3.7-1.8-3.1-1 .6 3.8 6.6 6.8-3.98M3.9 8.8 10.82 5l.795 1.4-6.81 3.96"/></svg>
|
|
33371
33511
|
`;
|
|
@@ -35250,10 +35390,17 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
35250
35390
|
get panelProps() {
|
|
35251
35391
|
const state = this.computeState(this.componentTag, this.initialPanelProps);
|
|
35252
35392
|
if (state.isOpen) {
|
|
35253
|
-
return state.props;
|
|
35393
|
+
return state.props ?? {};
|
|
35254
35394
|
}
|
|
35255
35395
|
return {};
|
|
35256
35396
|
}
|
|
35397
|
+
get panelKey() {
|
|
35398
|
+
const state = this.computeState(this.componentTag, this.initialPanelProps);
|
|
35399
|
+
if (state.isOpen) {
|
|
35400
|
+
return state.key;
|
|
35401
|
+
}
|
|
35402
|
+
return undefined;
|
|
35403
|
+
}
|
|
35257
35404
|
open(componentTag, panelProps = {}) {
|
|
35258
35405
|
const state = this.computeState(componentTag, panelProps);
|
|
35259
35406
|
if (state.isOpen === false) {
|
|
@@ -35263,7 +35410,7 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
35263
35410
|
this.initialPanelProps?.onCloseSidePanel?.();
|
|
35264
35411
|
}
|
|
35265
35412
|
this.componentTag = componentTag;
|
|
35266
|
-
this.initialPanelProps = state.props;
|
|
35413
|
+
this.initialPanelProps = state.props ?? {};
|
|
35267
35414
|
}
|
|
35268
35415
|
toggle(componentTag, panelProps) {
|
|
35269
35416
|
if (this.isOpen && componentTag === this.componentTag) {
|
|
@@ -40740,10 +40887,8 @@ function compileTokens(tokens) {
|
|
|
40740
40887
|
"ref", // a function to access a certain dependency at a given index
|
|
40741
40888
|
"range", // same as above, but guarantee that the result is in the form of a range
|
|
40742
40889
|
"ctx", code.toString());
|
|
40743
|
-
|
|
40744
|
-
|
|
40745
|
-
execute: baseFunction,
|
|
40746
|
-
};
|
|
40890
|
+
// @ts-ignore
|
|
40891
|
+
functionCache[cacheKey] = baseFunction;
|
|
40747
40892
|
/**
|
|
40748
40893
|
* This function compile the function arguments. It is mostly straightforward,
|
|
40749
40894
|
* except that there is a non trivial transformation in one situation:
|
|
@@ -40850,7 +40995,7 @@ function compileTokens(tokens) {
|
|
|
40850
40995
|
}
|
|
40851
40996
|
}
|
|
40852
40997
|
const compiledFormula = {
|
|
40853
|
-
execute: functionCache[cacheKey]
|
|
40998
|
+
execute: functionCache[cacheKey],
|
|
40854
40999
|
dependencies,
|
|
40855
41000
|
constantValues,
|
|
40856
41001
|
tokens,
|
|
@@ -42335,6 +42480,15 @@ class FigurePlugin extends CorePlugin {
|
|
|
42335
42480
|
return "Success" /* CommandResult.Success */;
|
|
42336
42481
|
}
|
|
42337
42482
|
}
|
|
42483
|
+
beforeHandle(cmd) {
|
|
42484
|
+
switch (cmd.type) {
|
|
42485
|
+
case "DELETE_SHEET":
|
|
42486
|
+
this.getters.getFigures(cmd.sheetId).forEach((figure) => {
|
|
42487
|
+
this.dispatch("DELETE_FIGURE", { id: figure.id, sheetId: cmd.sheetId });
|
|
42488
|
+
});
|
|
42489
|
+
break;
|
|
42490
|
+
}
|
|
42491
|
+
}
|
|
42338
42492
|
handle(cmd) {
|
|
42339
42493
|
switch (cmd.type) {
|
|
42340
42494
|
case "CREATE_SHEET":
|
|
@@ -43821,7 +43975,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
43821
43975
|
"getNumberHeaders",
|
|
43822
43976
|
"getGridLinesVisibility",
|
|
43823
43977
|
"getNextSheetName",
|
|
43824
|
-
"isEmpty",
|
|
43825
43978
|
"getSheetSize",
|
|
43826
43979
|
"getSheetZone",
|
|
43827
43980
|
"getPaneDivisions",
|
|
@@ -44193,14 +44346,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
44193
44346
|
// ---------------------------------------------------------------------------
|
|
44194
44347
|
// Row/Col manipulation
|
|
44195
44348
|
// ---------------------------------------------------------------------------
|
|
44196
|
-
/**
|
|
44197
|
-
* Check if a zone only contains empty cells
|
|
44198
|
-
*/
|
|
44199
|
-
isEmpty(sheetId, zone) {
|
|
44200
|
-
return positions(zone)
|
|
44201
|
-
.map(({ col, row }) => this.getCell({ sheetId, col, row }))
|
|
44202
|
-
.every((cell) => !cell || cell.content === "");
|
|
44203
|
-
}
|
|
44204
44349
|
getCommandZones(cmd) {
|
|
44205
44350
|
const zones = [];
|
|
44206
44351
|
if ("zone" in cmd) {
|
|
@@ -45004,13 +45149,15 @@ class TablePlugin extends CorePlugin {
|
|
|
45004
45149
|
if (zone.left !== zone.right) {
|
|
45005
45150
|
throw new Error("Can only define a filter on a single column");
|
|
45006
45151
|
}
|
|
45007
|
-
const
|
|
45008
|
-
const filteredRange =
|
|
45152
|
+
const contentZone = getTableContentZone(zone, config);
|
|
45153
|
+
const filteredRange = contentZone
|
|
45154
|
+
? this.getters.getRangeFromZone(range.sheetId, contentZone)
|
|
45155
|
+
: undefined;
|
|
45009
45156
|
return {
|
|
45010
45157
|
id,
|
|
45011
45158
|
rangeWithHeaders: range,
|
|
45012
45159
|
col: zone.left,
|
|
45013
|
-
filteredRange
|
|
45160
|
+
filteredRange,
|
|
45014
45161
|
};
|
|
45015
45162
|
}
|
|
45016
45163
|
copyTableForSheet(sheetId, table) {
|
|
@@ -45619,7 +45766,11 @@ class CompilationParametersBuilder {
|
|
|
45619
45766
|
});
|
|
45620
45767
|
}
|
|
45621
45768
|
getParameters() {
|
|
45622
|
-
return
|
|
45769
|
+
return {
|
|
45770
|
+
referenceDenormalizer: this.refFn.bind(this),
|
|
45771
|
+
ensureRange: this.range.bind(this),
|
|
45772
|
+
evalContext: this.evalContext,
|
|
45773
|
+
};
|
|
45623
45774
|
}
|
|
45624
45775
|
/**
|
|
45625
45776
|
* Returns the value of the cell(s) used in reference
|
|
@@ -46566,7 +46717,6 @@ const EMPTY_ARRAY = [];
|
|
|
46566
46717
|
const MAX_ITERATION = 30;
|
|
46567
46718
|
const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
|
|
46568
46719
|
const EMPTY_CELL = createEvaluatedCell({ value: null });
|
|
46569
|
-
const EVAL_CONTEXT_INDEX = 2;
|
|
46570
46720
|
class Evaluator {
|
|
46571
46721
|
context;
|
|
46572
46722
|
getters;
|
|
@@ -46619,9 +46769,8 @@ class Evaluator {
|
|
|
46619
46769
|
updateCompilationParameters() {
|
|
46620
46770
|
// rebuild the compilation parameters (with a clean cache)
|
|
46621
46771
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
46622
|
-
this.compilationParams
|
|
46623
|
-
|
|
46624
|
-
this.compilationParams[EVAL_CONTEXT_INDEX].addDependencies = this.addDependencies.bind(this);
|
|
46772
|
+
this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
|
|
46773
|
+
this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
|
|
46625
46774
|
}
|
|
46626
46775
|
evaluateCells(positions) {
|
|
46627
46776
|
const cells = positions.map((p) => this.encoder.encode(p));
|
|
@@ -46746,6 +46895,8 @@ class Evaluator {
|
|
|
46746
46895
|
: evaluateLiteral(cell.content, localeFormat);
|
|
46747
46896
|
}
|
|
46748
46897
|
catch (e) {
|
|
46898
|
+
e.value = e?.value || CellErrorType.GenericError;
|
|
46899
|
+
e.message = e?.message || implementationErrorMessage;
|
|
46749
46900
|
return createEvaluatedCell(e);
|
|
46750
46901
|
}
|
|
46751
46902
|
finally {
|
|
@@ -46968,16 +47119,16 @@ class PositionBitsEncoder {
|
|
|
46968
47119
|
}
|
|
46969
47120
|
}
|
|
46970
47121
|
function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
|
|
46971
|
-
compilationParams
|
|
47122
|
+
compilationParams.evalContext.__originCellXC = lazy(() => {
|
|
46972
47123
|
if (!cellId) {
|
|
46973
47124
|
return undefined;
|
|
46974
47125
|
}
|
|
46975
47126
|
// compute the value lazily for performance reasons
|
|
46976
|
-
const position = compilationParams
|
|
47127
|
+
const position = compilationParams.evalContext.getters.getCellPosition(cellId);
|
|
46977
47128
|
return toXC(position.col, position.row);
|
|
46978
47129
|
});
|
|
46979
|
-
compilationParams
|
|
46980
|
-
return compiledFormula.execute(compiledFormula.dependencies,
|
|
47130
|
+
compilationParams.evalContext.__originSheetId = sheetId;
|
|
47131
|
+
return compiledFormula.execute(compiledFormula.dependencies, compilationParams.referenceDenormalizer, compilationParams.ensureRange, compilationParams.evalContext);
|
|
46981
47132
|
}
|
|
46982
47133
|
|
|
46983
47134
|
//#region
|
|
@@ -47084,6 +47235,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
47084
47235
|
"getEvaluatedCellsInZone",
|
|
47085
47236
|
"getSpreadPositionsOf",
|
|
47086
47237
|
"getArrayFormulaSpreadingOn",
|
|
47238
|
+
"isEmpty",
|
|
47087
47239
|
];
|
|
47088
47240
|
shouldRebuildDependenciesGraph = true;
|
|
47089
47241
|
evaluator;
|
|
@@ -47189,6 +47341,14 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
47189
47341
|
getArrayFormulaSpreadingOn(position) {
|
|
47190
47342
|
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
47191
47343
|
}
|
|
47344
|
+
/**
|
|
47345
|
+
* Check if a zone only contains empty cells
|
|
47346
|
+
*/
|
|
47347
|
+
isEmpty(sheetId, zone) {
|
|
47348
|
+
return positions(zone)
|
|
47349
|
+
.map(({ col, row }) => this.getEvaluatedCell({ sheetId, col, row }))
|
|
47350
|
+
.every((cell) => cell.type === CellValueType.empty);
|
|
47351
|
+
}
|
|
47192
47352
|
// ---------------------------------------------------------------------------
|
|
47193
47353
|
// Export
|
|
47194
47354
|
// ---------------------------------------------------------------------------
|
|
@@ -47306,12 +47466,13 @@ function colorDistance(color1, color2) {
|
|
|
47306
47466
|
*/
|
|
47307
47467
|
class CustomColorsPlugin extends UIPlugin {
|
|
47308
47468
|
customColors = {};
|
|
47309
|
-
|
|
47310
|
-
shouldUpdateColors = false;
|
|
47469
|
+
shouldUpdateColors = true;
|
|
47311
47470
|
static getters = ["getCustomColors"];
|
|
47312
47471
|
constructor(config) {
|
|
47313
47472
|
super(config);
|
|
47314
|
-
|
|
47473
|
+
for (const color of config.customColors ?? []) {
|
|
47474
|
+
this.tryToAddColor(color);
|
|
47475
|
+
}
|
|
47315
47476
|
}
|
|
47316
47477
|
handle(cmd) {
|
|
47317
47478
|
switch (cmd.type) {
|
|
@@ -47322,31 +47483,29 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
47322
47483
|
case "SET_BORDER":
|
|
47323
47484
|
case "SET_ZONE_BORDERS":
|
|
47324
47485
|
case "SET_FORMATTING":
|
|
47486
|
+
case "CREATE_TABLE":
|
|
47487
|
+
case "UPDATE_TABLE":
|
|
47325
47488
|
this.history.update("shouldUpdateColors", true);
|
|
47489
|
+
break;
|
|
47326
47490
|
}
|
|
47327
47491
|
}
|
|
47328
47492
|
finalize() {
|
|
47329
47493
|
if (this.shouldUpdateColors) {
|
|
47330
47494
|
this.history.update("shouldUpdateColors", false);
|
|
47331
|
-
for (const color of this.
|
|
47495
|
+
for (const color of this.computeCustomColors()) {
|
|
47332
47496
|
this.tryToAddColor(color);
|
|
47333
47497
|
}
|
|
47334
47498
|
}
|
|
47335
47499
|
}
|
|
47336
47500
|
getCustomColors() {
|
|
47337
|
-
|
|
47501
|
+
return sortWithClusters(Object.keys(this.customColors));
|
|
47502
|
+
}
|
|
47503
|
+
computeCustomColors() {
|
|
47504
|
+
let usedColors = [];
|
|
47338
47505
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
47339
|
-
usedColors = usedColors.concat(this.getColorsFromCells(sheetId), this.getFormattingColors(sheetId), this.getChartColors(sheetId));
|
|
47340
|
-
}
|
|
47341
|
-
return
|
|
47342
|
-
...new Set(
|
|
47343
|
-
// remove duplicates first to check validity on a reduced
|
|
47344
|
-
// set of colors, then normalize to HEX and remove duplicates
|
|
47345
|
-
// again
|
|
47346
|
-
[...new Set([...usedColors, ...Object.keys(this.customColors)])]
|
|
47347
|
-
.filter(isColorValid)
|
|
47348
|
-
.map(toHex)),
|
|
47349
|
-
]).filter((color) => !COLOR_PICKER_DEFAULTS.includes(color));
|
|
47506
|
+
usedColors = usedColors.concat(this.getColorsFromCells(sheetId), this.getFormattingColors(sheetId), this.getChartColors(sheetId), this.getTableColors(sheetId));
|
|
47507
|
+
}
|
|
47508
|
+
return [...new Set([...usedColors])];
|
|
47350
47509
|
}
|
|
47351
47510
|
getColorsFromCells(sheetId) {
|
|
47352
47511
|
const cells = Object.values(this.getters.getCells(sheetId));
|
|
@@ -47408,7 +47567,43 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
47408
47567
|
}
|
|
47409
47568
|
return [...chartsColors];
|
|
47410
47569
|
}
|
|
47570
|
+
getTableColors(sheetId) {
|
|
47571
|
+
const tables = this.getters.getTables(sheetId);
|
|
47572
|
+
return tables.flatMap((table) => {
|
|
47573
|
+
const config = table.config;
|
|
47574
|
+
const style = TABLE_PRESETS[config.styleId];
|
|
47575
|
+
return [
|
|
47576
|
+
this.getTableStyleElementColors(style.wholeTable),
|
|
47577
|
+
config.numberOfHeaders > 0 ? this.getTableStyleElementColors(style.headerRow) : [],
|
|
47578
|
+
config.totalRow ? this.getTableStyleElementColors(style.totalRow) : [],
|
|
47579
|
+
config.bandedColumns ? this.getTableStyleElementColors(style.firstColumnStripe) : [],
|
|
47580
|
+
config.bandedColumns ? this.getTableStyleElementColors(style.secondColumnStripe) : [],
|
|
47581
|
+
config.bandedRows ? this.getTableStyleElementColors(style.firstRowStripe) : [],
|
|
47582
|
+
config.bandedRows ? this.getTableStyleElementColors(style.secondRowStripe) : [],
|
|
47583
|
+
config.firstColumn ? this.getTableStyleElementColors(style.firstColumn) : [],
|
|
47584
|
+
config.lastColumn ? this.getTableStyleElementColors(style.lastColumn) : [],
|
|
47585
|
+
].flat();
|
|
47586
|
+
});
|
|
47587
|
+
}
|
|
47588
|
+
getTableStyleElementColors(element) {
|
|
47589
|
+
if (!element) {
|
|
47590
|
+
return [];
|
|
47591
|
+
}
|
|
47592
|
+
return [
|
|
47593
|
+
element.style?.fillColor,
|
|
47594
|
+
element.style?.textColor,
|
|
47595
|
+
element.border?.bottom?.color,
|
|
47596
|
+
element.border?.top?.color,
|
|
47597
|
+
element.border?.left?.color,
|
|
47598
|
+
element.border?.right?.color,
|
|
47599
|
+
element.border?.horizontal?.color,
|
|
47600
|
+
element.border?.vertical?.color,
|
|
47601
|
+
].filter(isDefined$1);
|
|
47602
|
+
}
|
|
47411
47603
|
tryToAddColor(color) {
|
|
47604
|
+
if (!isColorValid(color)) {
|
|
47605
|
+
return;
|
|
47606
|
+
}
|
|
47412
47607
|
const formattedColor = toHex(color);
|
|
47413
47608
|
if (color && !COLOR_PICKER_DEFAULTS.includes(formattedColor)) {
|
|
47414
47609
|
this.history.update("customColors", formattedColor, true);
|
|
@@ -47832,8 +48027,6 @@ const VALID_RESULT = { isValid: true };
|
|
|
47832
48027
|
class EvaluationDataValidationPlugin extends UIPlugin {
|
|
47833
48028
|
static getters = [
|
|
47834
48029
|
"getDataValidationInvalidCriterionValueMessage",
|
|
47835
|
-
"getDataValidationCheckBoxCellPositions",
|
|
47836
|
-
"getDataValidationListCellsPositions",
|
|
47837
48030
|
"getInvalidDataValidationMessage",
|
|
47838
48031
|
"getValidationResultForCellValue",
|
|
47839
48032
|
"isCellValidCheckbox",
|
|
@@ -47911,19 +48104,6 @@ class EvaluationDataValidationPlugin extends UIPlugin {
|
|
|
47911
48104
|
const error = this.getRuleErrorForCellValue(cellValue, cellPosition, rule);
|
|
47912
48105
|
return error ? { error, rule, isValid: false } : VALID_RESULT;
|
|
47913
48106
|
}
|
|
47914
|
-
getDataValidationCheckBoxCellPositions() {
|
|
47915
|
-
const rules = this.getters
|
|
47916
|
-
.getDataValidationRules(this.getters.getActiveSheetId())
|
|
47917
|
-
.filter((rule) => rule.criterion.type === "isBoolean");
|
|
47918
|
-
return getCellPositionsInRanges(rules.map((rule) => rule.ranges).flat()).filter((position) => this.isCellValidCheckbox(position));
|
|
47919
|
-
}
|
|
47920
|
-
getDataValidationListCellsPositions() {
|
|
47921
|
-
const rules = this.getters
|
|
47922
|
-
.getDataValidationRules(this.getters.getActiveSheetId())
|
|
47923
|
-
.filter((rule) => (rule.criterion.type === "isValueInList" || rule.criterion.type === "isValueInRange") &&
|
|
47924
|
-
rule.criterion.displayStyle === "arrow");
|
|
47925
|
-
return getCellPositionsInRanges(rules.map((rule) => rule.ranges).flat());
|
|
47926
|
-
}
|
|
47927
48107
|
getValidationResultForCell(cellPosition) {
|
|
47928
48108
|
const { col, row, sheetId } = cellPosition;
|
|
47929
48109
|
if (!this.validationResults[sheetId]) {
|
|
@@ -48380,6 +48560,23 @@ class AutofillPlugin extends UIPlugin {
|
|
|
48380
48560
|
* autofiller
|
|
48381
48561
|
*/
|
|
48382
48562
|
autofillAuto() {
|
|
48563
|
+
const activePosition = this.getters.getActivePosition();
|
|
48564
|
+
const table = this.getters.getTable(activePosition);
|
|
48565
|
+
let autofillRow = table ? table.range.zone.bottom : this.getAutofillAutoLastRow();
|
|
48566
|
+
// Stop autofill at the next non-empty cell
|
|
48567
|
+
const selection = this.getters.getSelectedZone();
|
|
48568
|
+
for (let row = selection.bottom + 1; row <= autofillRow; row++) {
|
|
48569
|
+
if (this.getters.getEvaluatedCell({ ...activePosition, row }).type !== CellValueType.empty) {
|
|
48570
|
+
autofillRow = row - 1;
|
|
48571
|
+
break;
|
|
48572
|
+
}
|
|
48573
|
+
}
|
|
48574
|
+
if (autofillRow > selection.bottom) {
|
|
48575
|
+
this.select(activePosition.col, autofillRow);
|
|
48576
|
+
this.autofill(true);
|
|
48577
|
+
}
|
|
48578
|
+
}
|
|
48579
|
+
getAutofillAutoLastRow() {
|
|
48383
48580
|
const zone = this.getters.getSelectedZone();
|
|
48384
48581
|
const sheetId = this.getters.getActiveSheetId();
|
|
48385
48582
|
let col = zone.left;
|
|
@@ -48403,10 +48600,7 @@ class AutofillPlugin extends UIPlugin {
|
|
|
48403
48600
|
}
|
|
48404
48601
|
}
|
|
48405
48602
|
}
|
|
48406
|
-
|
|
48407
|
-
this.select(zone.left, row - 1);
|
|
48408
|
-
this.autofill(true);
|
|
48409
|
-
}
|
|
48603
|
+
return row - 1;
|
|
48410
48604
|
}
|
|
48411
48605
|
/**
|
|
48412
48606
|
* Generate the next cell
|
|
@@ -49948,7 +50142,6 @@ class DataCleanupPlugin extends UIPlugin {
|
|
|
49948
50142
|
* the search with a new value.
|
|
49949
50143
|
*/
|
|
49950
50144
|
class FindAndReplacePlugin extends UIPlugin {
|
|
49951
|
-
static layers = ["Search"];
|
|
49952
50145
|
static getters = [];
|
|
49953
50146
|
handle(cmd) {
|
|
49954
50147
|
switch (cmd.type) {
|
|
@@ -51018,6 +51211,51 @@ class SplitToColumnsPlugin extends UIPlugin {
|
|
|
51018
51211
|
}
|
|
51019
51212
|
}
|
|
51020
51213
|
|
|
51214
|
+
class TableAutofillPlugin extends UIPlugin {
|
|
51215
|
+
handle(cmd) {
|
|
51216
|
+
switch (cmd.type) {
|
|
51217
|
+
case "AUTOFILL_TABLE_COLUMN":
|
|
51218
|
+
const table = this.getters.getTable(cmd);
|
|
51219
|
+
const cell = this.getters.getCell(cmd);
|
|
51220
|
+
if (!table || !table.config.automaticAutofill || !cell?.isFormula)
|
|
51221
|
+
return;
|
|
51222
|
+
const { col, row } = cmd;
|
|
51223
|
+
const tableContentZone = getTableContentZone(table.range.zone, table.config);
|
|
51224
|
+
if (tableContentZone && isInside(col, row, tableContentZone)) {
|
|
51225
|
+
this.autofillTableZone(cmd, tableContentZone);
|
|
51226
|
+
}
|
|
51227
|
+
break;
|
|
51228
|
+
}
|
|
51229
|
+
}
|
|
51230
|
+
autofillTableZone(autofillSource, zone) {
|
|
51231
|
+
if (zone.top === zone.bottom) {
|
|
51232
|
+
return;
|
|
51233
|
+
}
|
|
51234
|
+
const { col, row, sheetId } = autofillSource;
|
|
51235
|
+
for (let r = zone.top; r <= zone.bottom; r++) {
|
|
51236
|
+
if (r === row) {
|
|
51237
|
+
continue;
|
|
51238
|
+
}
|
|
51239
|
+
if (this.getters.getEvaluatedCell({ col, row: r, sheetId }).type !== CellValueType.empty) {
|
|
51240
|
+
return;
|
|
51241
|
+
}
|
|
51242
|
+
}
|
|
51243
|
+
// TODO: seems odd that autofill a table column have side effects on the selection. Autofill commands should be
|
|
51244
|
+
// refactored to take the selection as a parameter
|
|
51245
|
+
const oldSelection = {
|
|
51246
|
+
zone: this.getters.getSelectedZone(),
|
|
51247
|
+
cell: this.getters.getActivePosition(),
|
|
51248
|
+
};
|
|
51249
|
+
this.selection.selectCell(col, row);
|
|
51250
|
+
this.dispatch("AUTOFILL_SELECT", { col, row: zone.bottom });
|
|
51251
|
+
this.dispatch("AUTOFILL");
|
|
51252
|
+
this.selection.selectCell(col, row);
|
|
51253
|
+
this.dispatch("AUTOFILL_SELECT", { col, row: zone.top });
|
|
51254
|
+
this.dispatch("AUTOFILL");
|
|
51255
|
+
this.selection.selectZone(oldSelection);
|
|
51256
|
+
}
|
|
51257
|
+
}
|
|
51258
|
+
|
|
51021
51259
|
class TableStylePlugin extends UIPlugin {
|
|
51022
51260
|
static getters = ["getCellTableStyle", "getCellTableBorder"];
|
|
51023
51261
|
tableStyles = {};
|
|
@@ -52885,6 +53123,8 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
52885
53123
|
"getEdgeScrollRow",
|
|
52886
53124
|
"getVisibleFigures",
|
|
52887
53125
|
"getVisibleRect",
|
|
53126
|
+
"getVisibleRectWithoutHeaders",
|
|
53127
|
+
"getVisibleCellPositions",
|
|
52888
53128
|
"getColRowOffsetInViewport",
|
|
52889
53129
|
"getMainViewportCoordinates",
|
|
52890
53130
|
"getActiveSheetScrollInfo",
|
|
@@ -53130,6 +53370,26 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
53130
53370
|
const viewports = this.getSubViewports(sheetId);
|
|
53131
53371
|
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
53132
53372
|
}
|
|
53373
|
+
/**
|
|
53374
|
+
* Get the positions of all the cells that are visible in the viewport, taking merges into account.
|
|
53375
|
+
*/
|
|
53376
|
+
getVisibleCellPositions() {
|
|
53377
|
+
const visibleCols = this.getSheetViewVisibleCols();
|
|
53378
|
+
const visibleRows = this.getSheetViewVisibleRows();
|
|
53379
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
53380
|
+
const positions = [];
|
|
53381
|
+
for (const col of visibleCols) {
|
|
53382
|
+
for (const row of visibleRows) {
|
|
53383
|
+
const position = { sheetId, col, row };
|
|
53384
|
+
const mainPosition = this.getters.getMainCellPosition(position);
|
|
53385
|
+
if (mainPosition.row !== row || mainPosition.col !== col) {
|
|
53386
|
+
continue;
|
|
53387
|
+
}
|
|
53388
|
+
positions.push(position);
|
|
53389
|
+
}
|
|
53390
|
+
}
|
|
53391
|
+
return positions;
|
|
53392
|
+
}
|
|
53133
53393
|
/**
|
|
53134
53394
|
* Return the main viewport maximum size relative to the client size.
|
|
53135
53395
|
*/
|
|
@@ -53249,6 +53509,13 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
53249
53509
|
* Computes the coordinates and size to draw the zone on the canvas
|
|
53250
53510
|
*/
|
|
53251
53511
|
getVisibleRect(zone) {
|
|
53512
|
+
const rect = this.getVisibleRectWithoutHeaders(zone);
|
|
53513
|
+
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
53514
|
+
}
|
|
53515
|
+
/**
|
|
53516
|
+
* Computes the coordinates and size to draw the zone without taking the grid offset into account
|
|
53517
|
+
*/
|
|
53518
|
+
getVisibleRectWithoutHeaders(zone) {
|
|
53252
53519
|
const sheetId = this.getters.getActiveSheetId();
|
|
53253
53520
|
const viewportRects = this.getSubViewports(sheetId)
|
|
53254
53521
|
.map((viewport) => viewport.getRect(zone))
|
|
@@ -53260,12 +53527,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
53260
53527
|
const y = Math.min(...viewportRects.map((rect) => rect.y));
|
|
53261
53528
|
const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
|
|
53262
53529
|
const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
|
|
53263
|
-
return {
|
|
53264
|
-
x: x + this.gridOffsetX,
|
|
53265
|
-
y: y + this.gridOffsetY,
|
|
53266
|
-
width,
|
|
53267
|
-
height,
|
|
53268
|
-
};
|
|
53530
|
+
return { x, y, width, height };
|
|
53269
53531
|
}
|
|
53270
53532
|
/**
|
|
53271
53533
|
* Returns the position of the MainViewport relatively to the start of the grid (without headers)
|
|
@@ -53519,13 +53781,8 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
53519
53781
|
}
|
|
53520
53782
|
break;
|
|
53521
53783
|
case "UPDATE_CELL":
|
|
53522
|
-
|
|
53523
|
-
|
|
53524
|
-
this.isDirty = true;
|
|
53525
|
-
}
|
|
53526
|
-
else {
|
|
53527
|
-
this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
|
|
53528
|
-
}
|
|
53784
|
+
this.headerPositions = {};
|
|
53785
|
+
this.isDirty = true;
|
|
53529
53786
|
break;
|
|
53530
53787
|
case "UPDATE_FILTER":
|
|
53531
53788
|
case "UPDATE_TABLE":
|
|
@@ -53648,7 +53905,8 @@ const featurePluginRegistry = new Registry()
|
|
|
53648
53905
|
.add("split_to_columns", SplitToColumnsPlugin)
|
|
53649
53906
|
.add("collaborative", CollaborativePlugin)
|
|
53650
53907
|
.add("history", HistoryPlugin)
|
|
53651
|
-
.add("data_cleanup", DataCleanupPlugin)
|
|
53908
|
+
.add("data_cleanup", DataCleanupPlugin)
|
|
53909
|
+
.add("table_autofill", TableAutofillPlugin);
|
|
53652
53910
|
// Plugins which have a state, but which should not be shared in collaborative
|
|
53653
53911
|
const statefulUIPluginRegistry = new Registry()
|
|
53654
53912
|
.add("selection", GridSelectionPlugin)
|
|
@@ -53991,6 +54249,9 @@ class BottomBarSheet extends owl.Component {
|
|
|
53991
54249
|
this.scrollToSheet();
|
|
53992
54250
|
}
|
|
53993
54251
|
onDblClick() {
|
|
54252
|
+
if (this.env.model.getters.isReadonly()) {
|
|
54253
|
+
return;
|
|
54254
|
+
}
|
|
53994
54255
|
this.startEdition();
|
|
53995
54256
|
}
|
|
53996
54257
|
onKeyDown(ev) {
|
|
@@ -55947,7 +56208,6 @@ class Spreadsheet extends owl.Component {
|
|
|
55947
56208
|
}
|
|
55948
56209
|
}, () => [this.env.model.getters.getActiveSheetId()]);
|
|
55949
56210
|
owl.useExternalListener(window, "resize", () => this.render(true));
|
|
55950
|
-
owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
55951
56211
|
this.bindModelEvents();
|
|
55952
56212
|
owl.onWillUpdateProps((nextProps) => {
|
|
55953
56213
|
if (nextProps.model !== this.props.model) {
|
|
@@ -59788,6 +60048,6 @@ exports.tokenColors = tokenColors;
|
|
|
59788
60048
|
exports.tokenize = tokenize;
|
|
59789
60049
|
|
|
59790
60050
|
|
|
59791
|
-
__info__.version = "17.2.0-alpha.
|
|
59792
|
-
__info__.date = "2024-
|
|
59793
|
-
__info__.hash = "
|
|
60051
|
+
__info__.version = "17.2.0-alpha.8";
|
|
60052
|
+
__info__.date = "2024-03-15T11:01:01.388Z";
|
|
60053
|
+
__info__.hash = "11cf381";
|