@odoo/o-spreadsheet 18.4.0-alpha.6 → 18.4.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 +1320 -669
- package/dist/o-spreadsheet.d.ts +337 -166
- package/dist/o-spreadsheet.esm.js +1320 -670
- package/dist/o-spreadsheet.iife.js +1320 -669
- package/dist/o-spreadsheet.iife.min.js +476 -495
- package/dist/o_spreadsheet.xml +210 -156
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.4.0-alpha.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.4.0-alpha.8
|
|
6
|
+
* @date 2025-06-12T09:53:48.133Z
|
|
7
|
+
* @hash 9b7a8d0
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -132,7 +132,7 @@ class Registry {
|
|
|
132
132
|
|
|
133
133
|
const CANVAS_SHIFT = 0.5;
|
|
134
134
|
// Colors
|
|
135
|
-
const HIGHLIGHT_COLOR = "#
|
|
135
|
+
const HIGHLIGHT_COLOR = "#017E84";
|
|
136
136
|
const BACKGROUND_GRAY_COLOR = "#f5f5f5";
|
|
137
137
|
const BACKGROUND_HEADER_COLOR = "#F8F9FA";
|
|
138
138
|
const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
|
|
@@ -145,7 +145,7 @@ const CELL_BORDER_COLOR = "#E2E3E3";
|
|
|
145
145
|
const BACKGROUND_CHART_COLOR = "#FFFFFF";
|
|
146
146
|
const DISABLED_TEXT_COLOR = "#CACACA";
|
|
147
147
|
const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
|
|
148
|
-
const LINK_COLOR =
|
|
148
|
+
const LINK_COLOR = HIGHLIGHT_COLOR;
|
|
149
149
|
const FILTERS_COLOR = "#188038";
|
|
150
150
|
const SEPARATOR_COLOR = "#E0E2E4";
|
|
151
151
|
const ICONS_COLOR = "#4A4F59";
|
|
@@ -174,7 +174,7 @@ const BUTTON_HOVER_BG = GRAY_300;
|
|
|
174
174
|
const BUTTON_HOVER_TEXT_COLOR = "#111827";
|
|
175
175
|
const BUTTON_ACTIVE_BG = "#e6f2f3";
|
|
176
176
|
const BUTTON_ACTIVE_TEXT_COLOR = "#111827";
|
|
177
|
-
const ACTION_COLOR =
|
|
177
|
+
const ACTION_COLOR = HIGHLIGHT_COLOR;
|
|
178
178
|
const ACTION_COLOR_HOVER = "#01585c";
|
|
179
179
|
const ALERT_WARNING_BG = "#FBEBCC";
|
|
180
180
|
const ALERT_WARNING_BORDER = "#F8E2B3";
|
|
@@ -281,8 +281,10 @@ const MIN_ROW_HEIGHT = 10;
|
|
|
281
281
|
const MIN_COL_WIDTH = 5;
|
|
282
282
|
const HEADER_HEIGHT = 26;
|
|
283
283
|
const HEADER_WIDTH = 48;
|
|
284
|
-
const
|
|
285
|
-
const
|
|
284
|
+
const DESKTOP_TOPBAR_TOOLBAR_HEIGHT = 34;
|
|
285
|
+
const MOBILE_TOPBAR_TOOLBAR_HEIGHT = 44;
|
|
286
|
+
const DESKTOP_BOTTOMBAR_HEIGHT = 36;
|
|
287
|
+
const MOBILE_BOTTOMBAR_HEIGHT = 44;
|
|
286
288
|
const DEFAULT_CELL_WIDTH = 96;
|
|
287
289
|
const DEFAULT_CELL_HEIGHT = 23;
|
|
288
290
|
const SCROLLBAR_WIDTH = 15;
|
|
@@ -303,7 +305,8 @@ const MOBILE_WIDTH_BREAKPOINT = 768;
|
|
|
303
305
|
// Menus
|
|
304
306
|
const MENU_WIDTH = 250;
|
|
305
307
|
const MENU_VERTICAL_PADDING = 6;
|
|
306
|
-
const
|
|
308
|
+
const DESKTOP_MENU_ITEM_HEIGHT = 26;
|
|
309
|
+
const MOBILE_MENU_ITEM_HEIGHT = 35;
|
|
307
310
|
const MENU_ITEM_PADDING_HORIZONTAL = 11;
|
|
308
311
|
const MENU_ITEM_PADDING_VERTICAL = 4;
|
|
309
312
|
const MENU_SEPARATOR_BORDER_WIDTH = 1;
|
|
@@ -401,6 +404,7 @@ const PIVOT_TABLE_CONFIG = {
|
|
|
401
404
|
automaticAutofill: false,
|
|
402
405
|
};
|
|
403
406
|
const PIVOT_INDENT = 15;
|
|
407
|
+
const PIVOT_COLLAPSE_ICON_SIZE = 12;
|
|
404
408
|
const DEFAULT_CURRENCY = {
|
|
405
409
|
symbol: "$",
|
|
406
410
|
position: "before",
|
|
@@ -1564,6 +1568,19 @@ class AlternatingColorGenerator extends ColorGenerator {
|
|
|
1564
1568
|
this.palette = getAlternatingColorsPalette(paletteSize).filter((c) => !preferredColors.includes(c));
|
|
1565
1569
|
}
|
|
1566
1570
|
}
|
|
1571
|
+
class AlternatingColorMap {
|
|
1572
|
+
availableColors;
|
|
1573
|
+
colors = {};
|
|
1574
|
+
constructor(paletteSize = 12) {
|
|
1575
|
+
this.availableColors = new AlternatingColorGenerator(paletteSize);
|
|
1576
|
+
}
|
|
1577
|
+
get(id) {
|
|
1578
|
+
if (!this.colors[id]) {
|
|
1579
|
+
this.colors[id] = this.availableColors.next();
|
|
1580
|
+
}
|
|
1581
|
+
return this.colors[id];
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1567
1584
|
/**
|
|
1568
1585
|
* Returns a function that maps a value to a color using a color scale defined by the given
|
|
1569
1586
|
* color/threshold values pairs.
|
|
@@ -5003,7 +5020,9 @@ function isTextFormat(format) {
|
|
|
5003
5020
|
}
|
|
5004
5021
|
|
|
5005
5022
|
function evaluateLiteral(literalCell, localeFormat) {
|
|
5006
|
-
const value = isTextFormat(localeFormat.format)
|
|
5023
|
+
const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
|
|
5024
|
+
? literalCell.content
|
|
5025
|
+
: literalCell.parsedValue;
|
|
5007
5026
|
const functionResult = { value, format: localeFormat.format };
|
|
5008
5027
|
return createEvaluatedCell(functionResult, localeFormat.locale);
|
|
5009
5028
|
}
|
|
@@ -5052,6 +5071,9 @@ function _createEvaluatedCell(functionResult, locale, cell) {
|
|
|
5052
5071
|
if (isEvaluationError(value)) {
|
|
5053
5072
|
return errorCell(value, message);
|
|
5054
5073
|
}
|
|
5074
|
+
if (value === null) {
|
|
5075
|
+
return emptyCell(format);
|
|
5076
|
+
}
|
|
5055
5077
|
if (isTextFormat(format)) {
|
|
5056
5078
|
// TO DO:
|
|
5057
5079
|
// with the next line, the value of the cell is transformed depending on the format.
|
|
@@ -5059,9 +5081,6 @@ function _createEvaluatedCell(functionResult, locale, cell) {
|
|
|
5059
5081
|
// to interpret the value as a number.
|
|
5060
5082
|
return textCell(toString(value), format, formattedValue);
|
|
5061
5083
|
}
|
|
5062
|
-
if (value === null) {
|
|
5063
|
-
return emptyCell(format);
|
|
5064
|
-
}
|
|
5065
5084
|
if (typeof value === "number") {
|
|
5066
5085
|
if (isDateTimeFormat(format || "")) {
|
|
5067
5086
|
return dateTimeCell(value, format, formattedValue);
|
|
@@ -19349,8 +19368,9 @@ const PIVOT = {
|
|
|
19349
19368
|
arg("include_total (boolean, default=TRUE)", _t("Whether to include total/sub-totals or not.")),
|
|
19350
19369
|
arg("include_column_titles (boolean, default=TRUE)", _t("Whether to include the column titles or not.")),
|
|
19351
19370
|
arg("column_count (number, optional)", _t("number of columns")),
|
|
19371
|
+
arg("include_measure_titles (boolean, default=TRUE)", _t("Whether to include the measure titles row or not.")),
|
|
19352
19372
|
],
|
|
19353
|
-
compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }, columnCount = { value: Number.MAX_VALUE }) {
|
|
19373
|
+
compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }, columnCount = { value: Number.MAX_VALUE }, includeMeasureTitles = { value: true }) {
|
|
19354
19374
|
const _pivotFormulaId = toString(pivotFormulaId);
|
|
19355
19375
|
const _rowCount = toNumber(rowCount, this.locale);
|
|
19356
19376
|
if (_rowCount < 0) {
|
|
@@ -19360,8 +19380,11 @@ const PIVOT = {
|
|
|
19360
19380
|
if (_columnCount < 0) {
|
|
19361
19381
|
return new EvaluationError(_t("The number of columns must be positive."));
|
|
19362
19382
|
}
|
|
19363
|
-
const
|
|
19364
|
-
|
|
19383
|
+
const visibilityOptions = {
|
|
19384
|
+
displayColumnHeaders: toBoolean(includeColumnHeaders),
|
|
19385
|
+
displayTotals: toBoolean(includeTotal),
|
|
19386
|
+
displayMeasuresRow: toBoolean(includeMeasureTitles),
|
|
19387
|
+
};
|
|
19365
19388
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19366
19389
|
const pivot = this.getters.getPivot(pivotId);
|
|
19367
19390
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
@@ -19372,9 +19395,15 @@ const PIVOT = {
|
|
|
19372
19395
|
return error;
|
|
19373
19396
|
}
|
|
19374
19397
|
const table = pivot.getCollapsedTableStructure();
|
|
19375
|
-
const cells = table.getPivotCells(
|
|
19376
|
-
|
|
19377
|
-
|
|
19398
|
+
const cells = table.getPivotCells(visibilityOptions);
|
|
19399
|
+
let headerRows = 0;
|
|
19400
|
+
if (visibilityOptions.displayColumnHeaders) {
|
|
19401
|
+
headerRows = table.columns.length - 1;
|
|
19402
|
+
}
|
|
19403
|
+
if (visibilityOptions.displayMeasuresRow) {
|
|
19404
|
+
headerRows++;
|
|
19405
|
+
}
|
|
19406
|
+
const pivotTitle = this.getters.getPivotName(pivotId);
|
|
19378
19407
|
const tableHeight = Math.min(headerRows + _rowCount, cells[0].length);
|
|
19379
19408
|
if (tableHeight === 0) {
|
|
19380
19409
|
return [[{ value: pivotTitle }]];
|
|
@@ -19402,7 +19431,7 @@ const PIVOT = {
|
|
|
19402
19431
|
}
|
|
19403
19432
|
}
|
|
19404
19433
|
}
|
|
19405
|
-
if (
|
|
19434
|
+
if (visibilityOptions.displayColumnHeaders || visibilityOptions.displayMeasuresRow) {
|
|
19406
19435
|
result[0][0] = { value: pivotTitle };
|
|
19407
19436
|
}
|
|
19408
19437
|
return result;
|
|
@@ -20558,7 +20587,7 @@ const TEXT = {
|
|
|
20558
20587
|
description: _t("Converts a number to text according to a specified format."),
|
|
20559
20588
|
args: [
|
|
20560
20589
|
arg("number (number)", _t("The number, date or time to format.")),
|
|
20561
|
-
arg("format (string)", _t(
|
|
20590
|
+
arg("format (string)", _t('The case-sensitive format of the result, enclosed in quotation marks. Examples: "0.00" rounded to 2 decimal places, "hh:mm:ss" for hour:minutes:seconds.')),
|
|
20562
20591
|
],
|
|
20563
20592
|
compute: function (number, format) {
|
|
20564
20593
|
const _number = toNumber(number, this.locale);
|
|
@@ -21665,8 +21694,6 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
|
|
|
21665
21694
|
if (isNaN(value)) {
|
|
21666
21695
|
continue;
|
|
21667
21696
|
}
|
|
21668
|
-
const axisId = chart.config.type === "radar" ? dataset.rAxisID : dataset.yAxisID;
|
|
21669
|
-
const displayValue = options.callback(Number(value), axisId);
|
|
21670
21697
|
const point = dataset.data[i];
|
|
21671
21698
|
const xPosition = point.x;
|
|
21672
21699
|
let yPosition = 0;
|
|
@@ -21690,7 +21717,8 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
|
|
|
21690
21717
|
textsPositions[xPosition].push(yPosition);
|
|
21691
21718
|
ctx.fillStyle = point.options.backgroundColor;
|
|
21692
21719
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
21693
|
-
|
|
21720
|
+
const valueToDisplay = options.callback(Number(value), dataset, i);
|
|
21721
|
+
drawTextWithBackground(valueToDisplay, xPosition, yPosition, ctx);
|
|
21694
21722
|
}
|
|
21695
21723
|
}
|
|
21696
21724
|
}
|
|
@@ -21707,7 +21735,7 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
|
|
|
21707
21735
|
if (isNaN(value)) {
|
|
21708
21736
|
continue;
|
|
21709
21737
|
}
|
|
21710
|
-
const displayValue = options.callback(value, dataset
|
|
21738
|
+
const displayValue = options.callback(value, dataset, i);
|
|
21711
21739
|
const point = dataset.data[i];
|
|
21712
21740
|
const yPosition = point.y;
|
|
21713
21741
|
let xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
@@ -21742,10 +21770,22 @@ function drawPieChartValues(chart, options, ctx) {
|
|
|
21742
21770
|
const midAngle = (startAngle + endAngle) / 2;
|
|
21743
21771
|
const midRadius = (innerRadius + outerRadius) / 2;
|
|
21744
21772
|
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
21745
|
-
const y = bar.y + midRadius * Math.sin(midAngle)
|
|
21773
|
+
const y = bar.y + midRadius * Math.sin(midAngle);
|
|
21774
|
+
const displayValue = options.callback(value, dataset, i);
|
|
21775
|
+
const textHeight = 12; // ChartJS default
|
|
21776
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: textHeight }, "px");
|
|
21777
|
+
const radius = outerRadius - innerRadius;
|
|
21778
|
+
// Check if the text fits in the slice. Not perfect, but good enough heuristic.
|
|
21779
|
+
if (textWidth >= radius || radius < textHeight) {
|
|
21780
|
+
continue;
|
|
21781
|
+
}
|
|
21782
|
+
const sliceAngle = endAngle - startAngle;
|
|
21783
|
+
const midWidth = 2 * midRadius * Math.tan(sliceAngle / 2);
|
|
21784
|
+
if (sliceAngle < Math.PI / 2 && (textWidth >= midWidth || midWidth < textHeight)) {
|
|
21785
|
+
continue;
|
|
21786
|
+
}
|
|
21746
21787
|
ctx.fillStyle = chartFontColor(options.background);
|
|
21747
21788
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
21748
|
-
const displayValue = options.callback(value, "y");
|
|
21749
21789
|
drawTextWithBackground(displayValue, x, y, ctx);
|
|
21750
21790
|
}
|
|
21751
21791
|
}
|
|
@@ -23492,7 +23532,7 @@ function isMacOS() {
|
|
|
23492
23532
|
* On Mac, this is the "meta" or "command" key.
|
|
23493
23533
|
*/
|
|
23494
23534
|
function isCtrlKey(ev) {
|
|
23495
|
-
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
23535
|
+
return isMacOS() || isIOS() ? ev.metaKey : ev.ctrlKey;
|
|
23496
23536
|
}
|
|
23497
23537
|
/**
|
|
23498
23538
|
* @param {MouseEvent} ev - The mouse event.
|
|
@@ -23531,6 +23571,23 @@ function downloadFile(dataUrl, fileName) {
|
|
|
23531
23571
|
function isBrowserFirefox() {
|
|
23532
23572
|
return /Firefox/i.test(navigator.userAgent);
|
|
23533
23573
|
}
|
|
23574
|
+
// Mobile detection
|
|
23575
|
+
function maxTouchPoints() {
|
|
23576
|
+
return navigator.maxTouchPoints || 1;
|
|
23577
|
+
}
|
|
23578
|
+
function isAndroid() {
|
|
23579
|
+
return /Android/i.test(navigator.userAgent);
|
|
23580
|
+
}
|
|
23581
|
+
function isIOS() {
|
|
23582
|
+
return (/(iPad|iPhone|iPod)/i.test(navigator.userAgent) ||
|
|
23583
|
+
(navigator.platform === "MacIntel" && maxTouchPoints() > 1));
|
|
23584
|
+
}
|
|
23585
|
+
function isOtherMobileOS() {
|
|
23586
|
+
return /(webOS|BlackBerry|Windows Phone)/i.test(navigator.userAgent);
|
|
23587
|
+
}
|
|
23588
|
+
function isMobileOS() {
|
|
23589
|
+
return isAndroid() || isIOS() || isOtherMobileOS();
|
|
23590
|
+
}
|
|
23534
23591
|
|
|
23535
23592
|
/**
|
|
23536
23593
|
* Convert a JS color hexadecimal to an excel compatible color.
|
|
@@ -25051,14 +25108,14 @@ function getPieChartLegend(definition, args) {
|
|
|
25051
25108
|
...getLegendDisplayOptions(definition),
|
|
25052
25109
|
labels: {
|
|
25053
25110
|
usePointStyle: true,
|
|
25054
|
-
generateLabels: (c) => c.data.labels?.map((label, index) => ({
|
|
25111
|
+
generateLabels: (c) => (c.data.labels?.map((label, index) => ({
|
|
25055
25112
|
text: truncateLabel(String(label)),
|
|
25056
25113
|
strokeStyle: colors[index],
|
|
25057
25114
|
fillStyle: colors[index],
|
|
25058
25115
|
pointStyle: "rect",
|
|
25059
25116
|
lineWidth: 2,
|
|
25060
25117
|
fontColor,
|
|
25061
|
-
})) || [],
|
|
25118
|
+
})) || []).filter((label) => label.text),
|
|
25062
25119
|
filter: (legendItem, data) => {
|
|
25063
25120
|
return "datasetIndex" in legendItem
|
|
25064
25121
|
? !data.datasets[legendItem.datasetIndex].hidden
|
|
@@ -25218,7 +25275,8 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
|
|
|
25218
25275
|
labels: {
|
|
25219
25276
|
color: fontColor,
|
|
25220
25277
|
usePointStyle: true,
|
|
25221
|
-
generateLabels: (chart) => chart.data.datasets
|
|
25278
|
+
generateLabels: (chart) => chart.data.datasets
|
|
25279
|
+
.map((dataset, index) => {
|
|
25222
25280
|
if (isTrendLineAxis(dataset["xAxisID"])) {
|
|
25223
25281
|
return {
|
|
25224
25282
|
text: truncateLabel(dataset.label),
|
|
@@ -25240,7 +25298,8 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
|
|
|
25240
25298
|
datasetIndex: index,
|
|
25241
25299
|
...legendLabelConfig,
|
|
25242
25300
|
};
|
|
25243
|
-
})
|
|
25301
|
+
})
|
|
25302
|
+
.filter((label) => label.text),
|
|
25244
25303
|
filter: (legendItem, data) => {
|
|
25245
25304
|
return "datasetIndex" in legendItem
|
|
25246
25305
|
? !data.datasets[legendItem.datasetIndex].hidden
|
|
@@ -25594,7 +25653,10 @@ function getChartShowValues(definition, args) {
|
|
|
25594
25653
|
horizontal: "horizontal" in definition && definition.horizontal,
|
|
25595
25654
|
showValues: "showValues" in definition ? !!definition.showValues : false,
|
|
25596
25655
|
background: definition.background,
|
|
25597
|
-
callback:
|
|
25656
|
+
callback: (value, dataset) => {
|
|
25657
|
+
const axisId = getDatasetAxisId(definition, dataset);
|
|
25658
|
+
return formatChartDatasetValue(axisFormats, locale)(value, axisId);
|
|
25659
|
+
},
|
|
25598
25660
|
};
|
|
25599
25661
|
}
|
|
25600
25662
|
function getSunburstShowValues(definition, args) {
|
|
@@ -25612,6 +25674,45 @@ function getSunburstShowValues(definition, args) {
|
|
|
25612
25674
|
},
|
|
25613
25675
|
};
|
|
25614
25676
|
}
|
|
25677
|
+
function getPyramidChartShowValues(definition, args) {
|
|
25678
|
+
const { axisFormats, locale } = args;
|
|
25679
|
+
return {
|
|
25680
|
+
horizontal: true,
|
|
25681
|
+
showValues: "showValues" in definition ? !!definition.showValues : false,
|
|
25682
|
+
background: definition.background,
|
|
25683
|
+
callback: (value, dataset) => {
|
|
25684
|
+
value = Math.abs(Number(value));
|
|
25685
|
+
return formatChartDatasetValue(axisFormats, locale)(value, dataset.xAxisID || "x");
|
|
25686
|
+
},
|
|
25687
|
+
};
|
|
25688
|
+
}
|
|
25689
|
+
function getWaterfallChartShowValues(definition, args) {
|
|
25690
|
+
const { axisFormats, locale, dataSetsValues } = args;
|
|
25691
|
+
const subtotalIndexes = dataSetsValues.reduce((subtotalIndexes, ds) => {
|
|
25692
|
+
subtotalIndexes.push((subtotalIndexes.at(-1) || -1) + ds.data.length + 1);
|
|
25693
|
+
return subtotalIndexes;
|
|
25694
|
+
}, []);
|
|
25695
|
+
return {
|
|
25696
|
+
showValues: "showValues" in definition ? !!definition.showValues : false,
|
|
25697
|
+
background: definition.background,
|
|
25698
|
+
callback: (value, dataset, index) => {
|
|
25699
|
+
const raw = dataset._dataset.data[index];
|
|
25700
|
+
const delta = raw[1] - raw[0];
|
|
25701
|
+
let sign = delta >= 0 ? "+" : "";
|
|
25702
|
+
if (definition.showSubTotals && subtotalIndexes.includes(index) && sign === "+") {
|
|
25703
|
+
sign = "";
|
|
25704
|
+
}
|
|
25705
|
+
return `${sign}${formatChartDatasetValue(axisFormats, locale)(delta, dataset.yAxisID)}`;
|
|
25706
|
+
},
|
|
25707
|
+
};
|
|
25708
|
+
}
|
|
25709
|
+
function getDatasetAxisId(definition, dataset) {
|
|
25710
|
+
if (dataset.rAxisID) {
|
|
25711
|
+
return dataset.rAxisID;
|
|
25712
|
+
}
|
|
25713
|
+
const axisId = "horizontal" in definition && definition.horizontal ? dataset.xAxisID : dataset.yAxisID;
|
|
25714
|
+
return axisId || "y";
|
|
25715
|
+
}
|
|
25615
25716
|
|
|
25616
25717
|
function getChartTitle(definition) {
|
|
25617
25718
|
const chartTitle = definition.title;
|
|
@@ -26014,6 +26115,7 @@ var CHART_RUNTIME_HELPERS = /*#__PURE__*/Object.freeze({
|
|
|
26014
26115
|
getPieChartTooltip: getPieChartTooltip,
|
|
26015
26116
|
getPyramidChartData: getPyramidChartData,
|
|
26016
26117
|
getPyramidChartScales: getPyramidChartScales,
|
|
26118
|
+
getPyramidChartShowValues: getPyramidChartShowValues,
|
|
26017
26119
|
getPyramidChartTooltip: getPyramidChartTooltip,
|
|
26018
26120
|
getRadarChartData: getRadarChartData,
|
|
26019
26121
|
getRadarChartDatasets: getRadarChartDatasets,
|
|
@@ -26034,6 +26136,7 @@ var CHART_RUNTIME_HELPERS = /*#__PURE__*/Object.freeze({
|
|
|
26034
26136
|
getTrendDatasetForLineChart: getTrendDatasetForLineChart,
|
|
26035
26137
|
getWaterfallChartLegend: getWaterfallChartLegend,
|
|
26036
26138
|
getWaterfallChartScales: getWaterfallChartScales,
|
|
26139
|
+
getWaterfallChartShowValues: getWaterfallChartShowValues,
|
|
26037
26140
|
getWaterfallChartTooltip: getWaterfallChartTooltip,
|
|
26038
26141
|
getWaterfallDatasetAndLabels: getWaterfallDatasetAndLabels,
|
|
26039
26142
|
makeDatasetsCumulative: makeDatasetsCumulative
|
|
@@ -27346,7 +27449,7 @@ function createPyramidChartRuntime(chart, getters) {
|
|
|
27346
27449
|
title: getChartTitle(definition),
|
|
27347
27450
|
legend: getBarChartLegend(definition),
|
|
27348
27451
|
tooltip: getPyramidChartTooltip(definition, chartData),
|
|
27349
|
-
chartShowValuesPlugin:
|
|
27452
|
+
chartShowValuesPlugin: getPyramidChartShowValues(definition, chartData),
|
|
27350
27453
|
},
|
|
27351
27454
|
},
|
|
27352
27455
|
};
|
|
@@ -28094,7 +28197,7 @@ function createWaterfallChartRuntime(chart, getters) {
|
|
|
28094
28197
|
title: getChartTitle(definition),
|
|
28095
28198
|
legend: getWaterfallChartLegend(definition),
|
|
28096
28199
|
tooltip: getWaterfallChartTooltip(definition, chartData),
|
|
28097
|
-
chartShowValuesPlugin:
|
|
28200
|
+
chartShowValuesPlugin: getWaterfallChartShowValues(definition, chartData),
|
|
28098
28201
|
waterfallLinesPlugin: { showConnectorLines: definition.showConnectorLines },
|
|
28099
28202
|
},
|
|
28100
28203
|
},
|
|
@@ -28886,6 +28989,7 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
|
|
|
28886
28989
|
env.openSidePanel("ChartPanel");
|
|
28887
28990
|
},
|
|
28888
28991
|
icon: "o-spreadsheet-Icon.EDIT",
|
|
28992
|
+
isEnabled: (env) => !env.isSmall,
|
|
28889
28993
|
},
|
|
28890
28994
|
getCopyMenuItem(figureId, env),
|
|
28891
28995
|
getCutMenuItem(figureId, env),
|
|
@@ -29100,6 +29204,147 @@ function useTimeOut() {
|
|
|
29100
29204
|
};
|
|
29101
29205
|
}
|
|
29102
29206
|
|
|
29207
|
+
//------------------------------------------------------------------------------
|
|
29208
|
+
// Context Menu Component
|
|
29209
|
+
//------------------------------------------------------------------------------
|
|
29210
|
+
css /* scss */ `
|
|
29211
|
+
.o-menu {
|
|
29212
|
+
background-color: white;
|
|
29213
|
+
user-select: none;
|
|
29214
|
+
|
|
29215
|
+
.o-menu-item {
|
|
29216
|
+
height: ${DESKTOP_MENU_ITEM_HEIGHT}px;
|
|
29217
|
+
padding: ${MENU_ITEM_PADDING_VERTICAL}px ${MENU_ITEM_PADDING_HORIZONTAL}px;
|
|
29218
|
+
cursor: pointer;
|
|
29219
|
+
user-select: none;
|
|
29220
|
+
|
|
29221
|
+
.o-menu-item-name {
|
|
29222
|
+
min-width: 40%;
|
|
29223
|
+
}
|
|
29224
|
+
|
|
29225
|
+
.o-menu-item-icon {
|
|
29226
|
+
display: inline-block;
|
|
29227
|
+
margin: 0px 8px 0px 0px;
|
|
29228
|
+
width: ${DESKTOP_MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
29229
|
+
line-height: ${DESKTOP_MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
29230
|
+
}
|
|
29231
|
+
|
|
29232
|
+
&:not(.disabled) {
|
|
29233
|
+
&:hover,
|
|
29234
|
+
&.o-menu-item-active {
|
|
29235
|
+
background-color: ${BUTTON_ACTIVE_BG};
|
|
29236
|
+
color: ${BUTTON_ACTIVE_TEXT_COLOR};
|
|
29237
|
+
}
|
|
29238
|
+
.o-menu-item-description {
|
|
29239
|
+
color: grey;
|
|
29240
|
+
}
|
|
29241
|
+
.o-menu-item-icon {
|
|
29242
|
+
.o-icon {
|
|
29243
|
+
color: ${ICONS_COLOR};
|
|
29244
|
+
}
|
|
29245
|
+
}
|
|
29246
|
+
}
|
|
29247
|
+
&.disabled {
|
|
29248
|
+
color: ${DISABLED_TEXT_COLOR};
|
|
29249
|
+
cursor: not-allowed;
|
|
29250
|
+
}
|
|
29251
|
+
}
|
|
29252
|
+
}
|
|
29253
|
+
|
|
29254
|
+
.o-spreadsheet-mobile {
|
|
29255
|
+
.o-menu-item {
|
|
29256
|
+
height: ${MOBILE_MENU_ITEM_HEIGHT}px;
|
|
29257
|
+
}
|
|
29258
|
+
}
|
|
29259
|
+
`;
|
|
29260
|
+
class Menu extends owl.Component {
|
|
29261
|
+
static template = "o-spreadsheet-Menu";
|
|
29262
|
+
static props = {
|
|
29263
|
+
menuItems: Array,
|
|
29264
|
+
onClose: Function,
|
|
29265
|
+
onClickMenu: { type: Function, optional: true },
|
|
29266
|
+
onMouseEnter: { type: Function, optional: true },
|
|
29267
|
+
onMouseOver: { type: Function, optional: true },
|
|
29268
|
+
onMouseLeave: { type: Function, optional: true },
|
|
29269
|
+
width: { type: Number, optional: true },
|
|
29270
|
+
isActive: { type: Function, optional: true },
|
|
29271
|
+
onScroll: { type: Function, optional: true },
|
|
29272
|
+
};
|
|
29273
|
+
static components = {};
|
|
29274
|
+
static defaultProps = {};
|
|
29275
|
+
hoveredMenu = undefined;
|
|
29276
|
+
setup() {
|
|
29277
|
+
owl.onWillUnmount(() => {
|
|
29278
|
+
this.hoveredMenu?.onStopHover?.(this.env);
|
|
29279
|
+
});
|
|
29280
|
+
}
|
|
29281
|
+
get menuItemsAndSeparators() {
|
|
29282
|
+
const menuItemsAndSeparators = [];
|
|
29283
|
+
for (let i = 0; i < this.props.menuItems.length; i++) {
|
|
29284
|
+
const menuItem = this.props.menuItems[i];
|
|
29285
|
+
if (menuItem.isVisible(this.env)) {
|
|
29286
|
+
menuItemsAndSeparators.push(menuItem);
|
|
29287
|
+
}
|
|
29288
|
+
if (menuItem.separator &&
|
|
29289
|
+
i !== this.props.menuItems.length - 1 && // no separator at the end
|
|
29290
|
+
menuItemsAndSeparators[menuItemsAndSeparators.length - 1] !== "separator" // no double separator
|
|
29291
|
+
) {
|
|
29292
|
+
menuItemsAndSeparators.push("separator");
|
|
29293
|
+
}
|
|
29294
|
+
}
|
|
29295
|
+
if (menuItemsAndSeparators[menuItemsAndSeparators.length - 1] === "separator") {
|
|
29296
|
+
menuItemsAndSeparators.pop();
|
|
29297
|
+
}
|
|
29298
|
+
if (menuItemsAndSeparators.length === 1 && menuItemsAndSeparators[0] === "separator") {
|
|
29299
|
+
return [];
|
|
29300
|
+
}
|
|
29301
|
+
return menuItemsAndSeparators;
|
|
29302
|
+
}
|
|
29303
|
+
get childrenHaveIcon() {
|
|
29304
|
+
return this.props.menuItems.some((menuItem) => !!this.getIconName(menuItem));
|
|
29305
|
+
}
|
|
29306
|
+
getIconName(menu) {
|
|
29307
|
+
if (menu.icon(this.env)) {
|
|
29308
|
+
return menu.icon(this.env);
|
|
29309
|
+
}
|
|
29310
|
+
if (menu.isActive?.(this.env)) {
|
|
29311
|
+
return "o-spreadsheet-Icon.CHECK";
|
|
29312
|
+
}
|
|
29313
|
+
return "";
|
|
29314
|
+
}
|
|
29315
|
+
getColor(menu) {
|
|
29316
|
+
return cssPropertiesToCss({ color: menu.textColor });
|
|
29317
|
+
}
|
|
29318
|
+
getIconColor(menu) {
|
|
29319
|
+
return cssPropertiesToCss({ color: menu.iconColor });
|
|
29320
|
+
}
|
|
29321
|
+
getName(menu) {
|
|
29322
|
+
return menu.name(this.env);
|
|
29323
|
+
}
|
|
29324
|
+
isRoot(menu) {
|
|
29325
|
+
return !menu.execute;
|
|
29326
|
+
}
|
|
29327
|
+
isEnabled(menu) {
|
|
29328
|
+
if (menu.isEnabled(this.env)) {
|
|
29329
|
+
return this.env.model.getters.isReadonly() ? menu.isReadonlyAllowed : true;
|
|
29330
|
+
}
|
|
29331
|
+
return false;
|
|
29332
|
+
}
|
|
29333
|
+
get menuStyle() {
|
|
29334
|
+
return this.props.width ? cssPropertiesToCss({ width: this.props.width + "px" }) : "";
|
|
29335
|
+
}
|
|
29336
|
+
onMouseEnter(menu, ev) {
|
|
29337
|
+
this.hoveredMenu = menu;
|
|
29338
|
+
menu.onStartHover?.(this.env);
|
|
29339
|
+
this.props.onMouseEnter?.(menu, ev);
|
|
29340
|
+
}
|
|
29341
|
+
onMouseLeave(menu, ev) {
|
|
29342
|
+
this.hoveredMenu = undefined;
|
|
29343
|
+
menu.onStopHover?.(this.env);
|
|
29344
|
+
this.props.onMouseLeave?.(menu, ev);
|
|
29345
|
+
}
|
|
29346
|
+
}
|
|
29347
|
+
|
|
29103
29348
|
/**
|
|
29104
29349
|
* Compute the intersection of two rectangles. Returns nothing if the two rectangles don't overlap
|
|
29105
29350
|
*/
|
|
@@ -29128,6 +29373,9 @@ function zoneToRect(zone) {
|
|
|
29128
29373
|
height: zone.bottom - zone.top,
|
|
29129
29374
|
};
|
|
29130
29375
|
}
|
|
29376
|
+
function isPointInsideRect(x, y, rect) {
|
|
29377
|
+
return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
|
|
29378
|
+
}
|
|
29131
29379
|
|
|
29132
29380
|
/**
|
|
29133
29381
|
* Return the o-spreadsheet element position relative
|
|
@@ -29425,57 +29673,17 @@ class TopRightPopoverContext extends PopoverPositionContext {
|
|
|
29425
29673
|
}
|
|
29426
29674
|
|
|
29427
29675
|
//------------------------------------------------------------------------------
|
|
29428
|
-
// Context
|
|
29676
|
+
// Context MenuPopover Component
|
|
29429
29677
|
//------------------------------------------------------------------------------
|
|
29430
29678
|
css /* scss */ `
|
|
29431
|
-
.o-menu {
|
|
29432
|
-
background-color: white;
|
|
29679
|
+
.o-menu-wrapper {
|
|
29433
29680
|
padding: ${MENU_VERTICAL_PADDING}px 0px;
|
|
29434
|
-
|
|
29435
|
-
user-select: none;
|
|
29436
|
-
|
|
29437
|
-
.o-menu-item {
|
|
29438
|
-
height: ${MENU_ITEM_HEIGHT}px;
|
|
29439
|
-
padding: ${MENU_ITEM_PADDING_VERTICAL}px ${MENU_ITEM_PADDING_HORIZONTAL}px;
|
|
29440
|
-
cursor: pointer;
|
|
29441
|
-
user-select: none;
|
|
29442
|
-
|
|
29443
|
-
.o-menu-item-name {
|
|
29444
|
-
min-width: 40%;
|
|
29445
|
-
}
|
|
29446
|
-
|
|
29447
|
-
.o-menu-item-icon {
|
|
29448
|
-
display: inline-block;
|
|
29449
|
-
margin: 0px 8px 0px 0px;
|
|
29450
|
-
width: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
29451
|
-
line-height: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
29452
|
-
}
|
|
29453
|
-
|
|
29454
|
-
&:not(.disabled) {
|
|
29455
|
-
&:hover,
|
|
29456
|
-
&.o-menu-item-active {
|
|
29457
|
-
background-color: ${BUTTON_ACTIVE_BG};
|
|
29458
|
-
color: ${BUTTON_ACTIVE_TEXT_COLOR};
|
|
29459
|
-
}
|
|
29460
|
-
.o-menu-item-description {
|
|
29461
|
-
color: grey;
|
|
29462
|
-
}
|
|
29463
|
-
.o-menu-item-icon {
|
|
29464
|
-
.o-icon {
|
|
29465
|
-
color: ${ICONS_COLOR};
|
|
29466
|
-
}
|
|
29467
|
-
}
|
|
29468
|
-
}
|
|
29469
|
-
&.disabled {
|
|
29470
|
-
color: ${DISABLED_TEXT_COLOR};
|
|
29471
|
-
cursor: not-allowed;
|
|
29472
|
-
}
|
|
29473
|
-
}
|
|
29681
|
+
background-color: white;
|
|
29474
29682
|
}
|
|
29475
29683
|
`;
|
|
29476
29684
|
const TIMEOUT_DELAY = 250;
|
|
29477
|
-
class
|
|
29478
|
-
static template = "o-spreadsheet-Menu";
|
|
29685
|
+
class MenuPopover extends owl.Component {
|
|
29686
|
+
static template = "o-spreadsheet-Menu-Popover";
|
|
29479
29687
|
static props = {
|
|
29480
29688
|
anchorRect: Object,
|
|
29481
29689
|
popoverPositioning: { type: String, optional: true },
|
|
@@ -29488,7 +29696,7 @@ class Menu extends owl.Component {
|
|
|
29488
29696
|
onMouseOver: { type: Function, optional: true },
|
|
29489
29697
|
width: { type: Number, optional: true },
|
|
29490
29698
|
};
|
|
29491
|
-
static components = { Menu, Popover };
|
|
29699
|
+
static components = { MenuPopover, Menu, Popover };
|
|
29492
29700
|
static defaultProps = {
|
|
29493
29701
|
depth: 1,
|
|
29494
29702
|
popoverPositioning: "top-right",
|
|
@@ -29515,27 +29723,18 @@ class Menu extends owl.Component {
|
|
|
29515
29723
|
this.hoveredMenu?.onStopHover?.(this.env);
|
|
29516
29724
|
});
|
|
29517
29725
|
}
|
|
29518
|
-
get
|
|
29519
|
-
|
|
29520
|
-
|
|
29521
|
-
|
|
29522
|
-
|
|
29523
|
-
|
|
29524
|
-
|
|
29525
|
-
|
|
29526
|
-
|
|
29527
|
-
|
|
29528
|
-
)
|
|
29529
|
-
|
|
29530
|
-
}
|
|
29531
|
-
}
|
|
29532
|
-
if (menuItemsAndSeparators[menuItemsAndSeparators.length - 1] === "separator") {
|
|
29533
|
-
menuItemsAndSeparators.pop();
|
|
29534
|
-
}
|
|
29535
|
-
if (menuItemsAndSeparators.length === 1 && menuItemsAndSeparators[0] === "separator") {
|
|
29536
|
-
return [];
|
|
29537
|
-
}
|
|
29538
|
-
return menuItemsAndSeparators;
|
|
29726
|
+
get menuProps() {
|
|
29727
|
+
return {
|
|
29728
|
+
menuItems: this.props.menuItems,
|
|
29729
|
+
onClose: this.close.bind(this),
|
|
29730
|
+
// @ts-ignore
|
|
29731
|
+
onClickMenu: this.onClickMenu.bind(this),
|
|
29732
|
+
onMouseOver: this.onMouseOver.bind(this),
|
|
29733
|
+
onMouseLeave: this.onMouseLeave.bind(this),
|
|
29734
|
+
width: this.props.width || MENU_WIDTH,
|
|
29735
|
+
isActive: this.isActive.bind(this),
|
|
29736
|
+
onScroll: this.onScroll.bind(this),
|
|
29737
|
+
};
|
|
29539
29738
|
}
|
|
29540
29739
|
get subMenuAnchorRect() {
|
|
29541
29740
|
const anchorRect = Object.assign({}, this.subMenu.anchorRect);
|
|
@@ -29549,12 +29748,13 @@ class Menu extends owl.Component {
|
|
|
29549
29748
|
x: this.props.anchorRect.x,
|
|
29550
29749
|
y: this.props.anchorRect.y,
|
|
29551
29750
|
width: isRoot ? this.props.anchorRect.width : this.props.width || MENU_WIDTH,
|
|
29552
|
-
height: isRoot ? this.props.anchorRect.height :
|
|
29751
|
+
height: isRoot ? this.props.anchorRect.height : DESKTOP_MENU_ITEM_HEIGHT,
|
|
29553
29752
|
},
|
|
29554
29753
|
positioning: this.props.popoverPositioning,
|
|
29555
29754
|
verticalOffset: isRoot ? 0 : MENU_VERTICAL_PADDING,
|
|
29556
29755
|
onPopoverHidden: () => this.closeSubMenu(),
|
|
29557
29756
|
onPopoverMoved: () => this.closeSubMenu(),
|
|
29757
|
+
maxHeight: this.props.maxHeight,
|
|
29558
29758
|
};
|
|
29559
29759
|
}
|
|
29560
29760
|
get childrenHaveIcon() {
|
|
@@ -29624,7 +29824,7 @@ class Menu extends owl.Component {
|
|
|
29624
29824
|
x: getRefBoundingRect(this.menuRef).x,
|
|
29625
29825
|
y: y - (this.subMenu.scrollOffset || 0),
|
|
29626
29826
|
width: this.props.width || MENU_WIDTH,
|
|
29627
|
-
height:
|
|
29827
|
+
height: DESKTOP_MENU_ITEM_HEIGHT,
|
|
29628
29828
|
};
|
|
29629
29829
|
this.subMenu.menuItems = menu.children(this.env);
|
|
29630
29830
|
this.subMenu.isOpen = true;
|
|
@@ -29673,14 +29873,8 @@ class Menu extends owl.Component {
|
|
|
29673
29873
|
this.subMenu.isHoveringChild = true;
|
|
29674
29874
|
this.openingTimeOut.clear();
|
|
29675
29875
|
}
|
|
29676
|
-
onMouseEnter(menu, ev) {
|
|
29677
|
-
this.hoveredMenu = menu;
|
|
29678
|
-
menu.onStartHover?.(this.env);
|
|
29679
|
-
}
|
|
29680
29876
|
onMouseLeave(menu) {
|
|
29681
29877
|
this.openingTimeOut.schedule(this.closeSubMenu.bind(this), TIMEOUT_DELAY);
|
|
29682
|
-
this.hoveredMenu = undefined;
|
|
29683
|
-
menu.onStopHover?.(this.env);
|
|
29684
29878
|
}
|
|
29685
29879
|
get menuStyle() {
|
|
29686
29880
|
return this.props.width ? cssPropertiesToCss({ width: this.props.width + "px" }) : "";
|
|
@@ -29689,7 +29883,7 @@ class Menu extends owl.Component {
|
|
|
29689
29883
|
|
|
29690
29884
|
class ChartDashboardMenu extends owl.Component {
|
|
29691
29885
|
static template = "spreadsheet.ChartDashboardMenu";
|
|
29692
|
-
static components = {
|
|
29886
|
+
static components = { MenuPopover };
|
|
29693
29887
|
static props = { figureUI: Object };
|
|
29694
29888
|
originalChartDefinition;
|
|
29695
29889
|
fullScreenFigureStore;
|
|
@@ -29953,7 +30147,7 @@ class FigureComponent extends owl.Component {
|
|
|
29953
30147
|
onMouseDown: { type: Function, optional: true },
|
|
29954
30148
|
onClickAnchor: { type: Function, optional: true },
|
|
29955
30149
|
};
|
|
29956
|
-
static components = {
|
|
30150
|
+
static components = { MenuPopover };
|
|
29957
30151
|
static defaultProps = {
|
|
29958
30152
|
onFigureDeleted: () => { },
|
|
29959
30153
|
onMouseDown: () => { },
|
|
@@ -30040,7 +30234,14 @@ class FigureComponent extends owl.Component {
|
|
|
30040
30234
|
this.props.onClickAnchor(dirX, dirY, ev);
|
|
30041
30235
|
}
|
|
30042
30236
|
onMouseDown(ev) {
|
|
30043
|
-
this.
|
|
30237
|
+
if (!this.env.isMobile()) {
|
|
30238
|
+
this.props.onMouseDown(ev);
|
|
30239
|
+
}
|
|
30240
|
+
}
|
|
30241
|
+
onClick(ev) {
|
|
30242
|
+
if (this.env.isMobile()) {
|
|
30243
|
+
this.props.onMouseDown(ev);
|
|
30244
|
+
}
|
|
30044
30245
|
}
|
|
30045
30246
|
onKeyDown(ev) {
|
|
30046
30247
|
const keyDownShortcut = keyboardEventToShortcutString(ev);
|
|
@@ -31507,15 +31708,15 @@ class HighlightStore extends SpreadsheetStore {
|
|
|
31507
31708
|
const activeSheetId = this.getters.getActiveSheetId();
|
|
31508
31709
|
return this.providers
|
|
31509
31710
|
.flatMap((h) => h.highlights)
|
|
31510
|
-
.filter((h) => h.sheetId === activeSheetId)
|
|
31711
|
+
.filter((h) => h.range.sheetId === activeSheetId)
|
|
31511
31712
|
.map((highlight) => {
|
|
31512
|
-
const { numberOfRows, numberOfCols } = zoneToDimension(highlight.zone);
|
|
31713
|
+
const { numberOfRows, numberOfCols } = zoneToDimension(highlight.range.zone);
|
|
31513
31714
|
const zone = numberOfRows * numberOfCols === 1
|
|
31514
|
-
? this.getters.expandZone(highlight.sheetId, highlight.zone)
|
|
31515
|
-
: highlight.
|
|
31715
|
+
? this.getters.expandZone(highlight.range.sheetId, highlight.range.zone)
|
|
31716
|
+
: highlight.range.unboundedZone;
|
|
31516
31717
|
return {
|
|
31517
31718
|
...highlight,
|
|
31518
|
-
zone,
|
|
31719
|
+
range: this.model.getters.getRangeFromZone(highlight.range.sheetId, zone),
|
|
31519
31720
|
};
|
|
31520
31721
|
});
|
|
31521
31722
|
}
|
|
@@ -31528,7 +31729,7 @@ class HighlightStore extends SpreadsheetStore {
|
|
|
31528
31729
|
drawLayer(ctx, layer) {
|
|
31529
31730
|
if (layer === "Highlights") {
|
|
31530
31731
|
for (const highlight of this.highlights) {
|
|
31531
|
-
const rect = this.getters.getVisibleRect(highlight.zone);
|
|
31732
|
+
const rect = this.getters.getVisibleRect(highlight.range.zone);
|
|
31532
31733
|
drawHighlight(ctx, highlight, rect);
|
|
31533
31734
|
}
|
|
31534
31735
|
}
|
|
@@ -32156,12 +32357,12 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
32156
32357
|
rangeColor(xc, sheetName) {
|
|
32157
32358
|
const refSheet = sheetName ? this.model.getters.getSheetIdByName(sheetName) : this.sheetId;
|
|
32158
32359
|
const highlight = this.highlights.find((highlight) => {
|
|
32159
|
-
if (highlight.sheetId !== refSheet)
|
|
32360
|
+
if (highlight.range.sheetId !== refSheet)
|
|
32160
32361
|
return false;
|
|
32161
32362
|
const range = this.model.getters.getRangeFromSheetXC(refSheet, xc);
|
|
32162
32363
|
let zone = range.zone;
|
|
32163
32364
|
zone = getZoneArea(zone) === 1 ? this.model.getters.expandZone(refSheet, zone) : zone;
|
|
32164
|
-
return isEqual(zone, highlight.zone);
|
|
32365
|
+
return isEqual(zone, highlight.range.zone);
|
|
32165
32366
|
});
|
|
32166
32367
|
return highlight && highlight.color ? highlight.color : undefined;
|
|
32167
32368
|
}
|
|
@@ -32271,11 +32472,10 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
32271
32472
|
const { numberOfRows, numberOfCols } = zoneToDimension(range.zone);
|
|
32272
32473
|
const zone = numberOfRows * numberOfCols === 1
|
|
32273
32474
|
? this.getters.expandZone(range.sheetId, range.zone)
|
|
32274
|
-
: range.
|
|
32475
|
+
: range.unboundedZone;
|
|
32275
32476
|
return {
|
|
32276
|
-
zone,
|
|
32477
|
+
range: this.model.getters.getRangeFromZone(range.sheetId, zone),
|
|
32277
32478
|
color: rangeColor(rangeString),
|
|
32278
|
-
sheetId: range.sheetId,
|
|
32279
32479
|
interactive: true,
|
|
32280
32480
|
};
|
|
32281
32481
|
});
|
|
@@ -32528,11 +32728,15 @@ class Composer extends owl.Component {
|
|
|
32528
32728
|
onInputContextMenu: { type: Function, optional: true },
|
|
32529
32729
|
composerStore: Object,
|
|
32530
32730
|
placeholder: { type: String, optional: true },
|
|
32731
|
+
inputMode: { type: String, optional: true },
|
|
32732
|
+
showAssistant: { type: Boolean, optional: true },
|
|
32531
32733
|
};
|
|
32532
32734
|
static components = { TextValueProvider, FunctionDescriptionProvider, SpeechBubble };
|
|
32533
32735
|
static defaultProps = {
|
|
32534
32736
|
inputStyle: "",
|
|
32535
32737
|
isDefaultFocus: false,
|
|
32738
|
+
inputMode: "text",
|
|
32739
|
+
showAssistant: true,
|
|
32536
32740
|
};
|
|
32537
32741
|
DOMFocusableElementStore;
|
|
32538
32742
|
composerRef = owl.useRef("o_composer");
|
|
@@ -32583,8 +32787,7 @@ class Composer extends owl.Component {
|
|
|
32583
32787
|
assistantStyle["max-height"] = `${availableSpaceAbove - CLOSE_ICON_RADIUS}px`;
|
|
32584
32788
|
// render top
|
|
32585
32789
|
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
32586
|
-
assistantStyle.
|
|
32587
|
-
assistantStyle.transform = `translate(0, -100%)`;
|
|
32790
|
+
assistantStyle.transform = `translate(0, calc(-100% - ${cellHeight + 3}px))`;
|
|
32588
32791
|
}
|
|
32589
32792
|
if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) {
|
|
32590
32793
|
// render left
|
|
@@ -32863,6 +33066,9 @@ class Composer extends owl.Component {
|
|
|
32863
33066
|
// not main button, probably a context menu
|
|
32864
33067
|
return;
|
|
32865
33068
|
}
|
|
33069
|
+
if (this.env.isMobile() && !isIOS()) {
|
|
33070
|
+
return;
|
|
33071
|
+
}
|
|
32866
33072
|
this.contentHelper.removeSelection();
|
|
32867
33073
|
}
|
|
32868
33074
|
onMouseup() {
|
|
@@ -33486,7 +33692,7 @@ class ListCriterionForm extends CriterionForm {
|
|
|
33486
33692
|
*/
|
|
33487
33693
|
function startDnd(onPointerMove, onPointerUp) {
|
|
33488
33694
|
const removeListeners = () => {
|
|
33489
|
-
window.removeEventListener("pointerup", _onPointerUp);
|
|
33695
|
+
window.removeEventListener("pointerup", _onPointerUp, { capture: true });
|
|
33490
33696
|
window.removeEventListener("dragstart", _onDragStart);
|
|
33491
33697
|
window.removeEventListener("pointermove", onPointerMove);
|
|
33492
33698
|
window.removeEventListener("wheel", onPointerMove);
|
|
@@ -33498,7 +33704,7 @@ function startDnd(onPointerMove, onPointerUp) {
|
|
|
33498
33704
|
function _onDragStart(ev) {
|
|
33499
33705
|
ev.preventDefault();
|
|
33500
33706
|
}
|
|
33501
|
-
window.addEventListener("pointerup", _onPointerUp);
|
|
33707
|
+
window.addEventListener("pointerup", _onPointerUp, { capture: true });
|
|
33502
33708
|
window.addEventListener("dragstart", _onDragStart);
|
|
33503
33709
|
window.addEventListener("pointermove", onPointerMove);
|
|
33504
33710
|
// mouse wheel on window is by default a passive event.
|
|
@@ -34120,9 +34326,9 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
34120
34326
|
.filter((reference) => this.shouldBeHighlighted(this.inputSheetId, reference));
|
|
34121
34327
|
return XCs.map((xc) => {
|
|
34122
34328
|
const { sheetName } = splitReference(xc);
|
|
34329
|
+
const sheetId = (sheetName && this.getters.getSheetIdByName(sheetName)) || this.inputSheetId;
|
|
34123
34330
|
return {
|
|
34124
|
-
|
|
34125
|
-
sheetId: (sheetName && this.getters.getSheetIdByName(sheetName)) || this.inputSheetId,
|
|
34331
|
+
range: this.getters.getRangeFromSheetXC(sheetId, xc),
|
|
34126
34332
|
color,
|
|
34127
34333
|
interactive: true,
|
|
34128
34334
|
};
|
|
@@ -34591,7 +34797,7 @@ function getCriterionMenuItems(callback, availableTypes) {
|
|
|
34591
34797
|
return createActions(actionSpecs);
|
|
34592
34798
|
}
|
|
34593
34799
|
|
|
34594
|
-
/** This component looks like a select input, but on click it opens a
|
|
34800
|
+
/** This component looks like a select input, but on click it opens a MenuPopover with the items given as props instead of a dropdown */
|
|
34595
34801
|
class SelectMenu extends owl.Component {
|
|
34596
34802
|
static template = "o-spreadsheet-SelectMenu";
|
|
34597
34803
|
static props = {
|
|
@@ -34599,7 +34805,7 @@ class SelectMenu extends owl.Component {
|
|
|
34599
34805
|
selectedValue: String,
|
|
34600
34806
|
class: { type: String, optional: true },
|
|
34601
34807
|
};
|
|
34602
|
-
static components = {
|
|
34808
|
+
static components = { MenuPopover };
|
|
34603
34809
|
menuId = new UuidGenerator().uuidv4();
|
|
34604
34810
|
selectRef = owl.useRef("select");
|
|
34605
34811
|
state = owl.useState({
|
|
@@ -34772,17 +34978,22 @@ class FilterMenuValueList extends owl.Component {
|
|
|
34772
34978
|
static components = { FilterMenuValueItem };
|
|
34773
34979
|
state = owl.useState({
|
|
34774
34980
|
values: [],
|
|
34981
|
+
displayedValues: [],
|
|
34775
34982
|
textFilter: "",
|
|
34776
34983
|
selectedValue: undefined,
|
|
34984
|
+
numberOfDisplayedValues: 50,
|
|
34985
|
+
hasMoreValues: false,
|
|
34777
34986
|
});
|
|
34778
34987
|
searchBar = owl.useRef("filterMenuSearchBar");
|
|
34779
34988
|
setup() {
|
|
34780
34989
|
owl.onWillUpdateProps((nextProps) => {
|
|
34781
34990
|
if (!deepEquals(nextProps.filterPosition, this.props.filterPosition)) {
|
|
34782
34991
|
this.state.values = this.getFilterHiddenValues(nextProps.filterPosition);
|
|
34992
|
+
this.computeDisplayedValues();
|
|
34783
34993
|
}
|
|
34784
34994
|
});
|
|
34785
34995
|
this.state.values = this.getFilterHiddenValues(this.props.filterPosition);
|
|
34996
|
+
this.computeDisplayedValues();
|
|
34786
34997
|
}
|
|
34787
34998
|
getFilterHiddenValues(position) {
|
|
34788
34999
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -34800,21 +35011,28 @@ class FilterMenuValueList extends owl.Component {
|
|
|
34800
35011
|
}
|
|
34801
35012
|
const cellValues = cells.map((val) => val.cellValue);
|
|
34802
35013
|
const filterValues = filterValue?.filterType === "values" ? filterValue.hiddenValues : [];
|
|
34803
|
-
const
|
|
34804
|
-
const
|
|
34805
|
-
|
|
34806
|
-
const
|
|
34807
|
-
|
|
34808
|
-
|
|
34809
|
-
|
|
34810
|
-
|
|
34811
|
-
|
|
35014
|
+
const normalizedFilteredValues = new Set(filterValues.map(toLowerCase));
|
|
35015
|
+
const set = new Set();
|
|
35016
|
+
const values = [];
|
|
35017
|
+
const addValue = (value) => {
|
|
35018
|
+
const normalizedValue = toLowerCase(value);
|
|
35019
|
+
if (!set.has(normalizedValue)) {
|
|
35020
|
+
values.push({
|
|
35021
|
+
string: value || "",
|
|
35022
|
+
checked: filterValue?.filterType !== "criterion"
|
|
35023
|
+
? !normalizedFilteredValues.has(normalizedValue)
|
|
35024
|
+
: false,
|
|
35025
|
+
normalizedValue,
|
|
35026
|
+
});
|
|
35027
|
+
set.add(normalizedValue);
|
|
34812
35028
|
}
|
|
34813
|
-
|
|
34814
|
-
|
|
34815
|
-
|
|
34816
|
-
|
|
34817
|
-
|
|
35029
|
+
};
|
|
35030
|
+
cellValues.forEach(addValue);
|
|
35031
|
+
filterValues.forEach(addValue);
|
|
35032
|
+
return values.sort((val1, val2) => val1.normalizedValue.localeCompare(val2.normalizedValue, undefined, {
|
|
35033
|
+
numeric: true,
|
|
35034
|
+
sensitivity: "base",
|
|
35035
|
+
}));
|
|
34818
35036
|
}
|
|
34819
35037
|
checkValue(value) {
|
|
34820
35038
|
this.state.selectedValue = value.string;
|
|
@@ -34826,25 +35044,37 @@ class FilterMenuValueList extends owl.Component {
|
|
|
34826
35044
|
this.state.selectedValue = value.string;
|
|
34827
35045
|
}
|
|
34828
35046
|
selectAll() {
|
|
34829
|
-
this.displayedValues.forEach((value) => (value.checked = true));
|
|
34830
|
-
this.
|
|
35047
|
+
this.state.displayedValues.forEach((value) => (value.checked = true));
|
|
35048
|
+
this.props.onUpdateHiddenValues([]);
|
|
34831
35049
|
}
|
|
34832
35050
|
clearAll() {
|
|
34833
|
-
this.displayedValues.forEach((value) => (value.checked = false));
|
|
34834
|
-
this.
|
|
35051
|
+
this.state.displayedValues.forEach((value) => (value.checked = false));
|
|
35052
|
+
const hiddenValues = this.state.values.map((val) => val.string);
|
|
35053
|
+
this.props.onUpdateHiddenValues(hiddenValues);
|
|
34835
35054
|
}
|
|
34836
35055
|
updateHiddenValues() {
|
|
34837
35056
|
const hiddenValues = this.state.values.filter((val) => !val.checked).map((val) => val.string);
|
|
34838
35057
|
this.props.onUpdateHiddenValues(hiddenValues);
|
|
34839
35058
|
}
|
|
34840
|
-
|
|
34841
|
-
|
|
34842
|
-
|
|
34843
|
-
|
|
34844
|
-
|
|
35059
|
+
updateSearch(ev) {
|
|
35060
|
+
const target = ev.target;
|
|
35061
|
+
this.state.textFilter = target.value;
|
|
35062
|
+
this.state.selectedValue = undefined;
|
|
35063
|
+
this.computeDisplayedValues();
|
|
35064
|
+
}
|
|
35065
|
+
computeDisplayedValues() {
|
|
35066
|
+
const values = !this.state.textFilter
|
|
35067
|
+
? this.state.values
|
|
35068
|
+
: fuzzyLookup(this.state.textFilter, this.state.values, (val) => val.string);
|
|
35069
|
+
this.state.displayedValues = values.slice(0, this.state.numberOfDisplayedValues);
|
|
35070
|
+
this.state.hasMoreValues = values.length > this.state.numberOfDisplayedValues;
|
|
35071
|
+
}
|
|
35072
|
+
loadMoreValues() {
|
|
35073
|
+
this.state.numberOfDisplayedValues += 100;
|
|
35074
|
+
this.computeDisplayedValues();
|
|
34845
35075
|
}
|
|
34846
35076
|
onKeyDown(ev) {
|
|
34847
|
-
const displayedValues = this.displayedValues;
|
|
35077
|
+
const displayedValues = this.state.displayedValues;
|
|
34848
35078
|
if (displayedValues.length === 0)
|
|
34849
35079
|
return;
|
|
34850
35080
|
let selectedIndex = undefined;
|
|
@@ -35347,7 +35577,7 @@ class MenuItemRegistry extends Registry {
|
|
|
35347
35577
|
}
|
|
35348
35578
|
|
|
35349
35579
|
//------------------------------------------------------------------------------
|
|
35350
|
-
// Link
|
|
35580
|
+
// Link MenuPopover Registry
|
|
35351
35581
|
//------------------------------------------------------------------------------
|
|
35352
35582
|
const linkMenuRegistry = new MenuItemRegistry();
|
|
35353
35583
|
linkMenuRegistry.add("sheet", {
|
|
@@ -35409,7 +35639,7 @@ class LinkEditor extends owl.Component {
|
|
|
35409
35639
|
cellPosition: Object,
|
|
35410
35640
|
onClosed: { type: Function, optional: true },
|
|
35411
35641
|
};
|
|
35412
|
-
static components = {
|
|
35642
|
+
static components = { MenuPopover };
|
|
35413
35643
|
menuItems = linkMenuRegistry.getMenuItems();
|
|
35414
35644
|
link = owl.useState(this.defaultState);
|
|
35415
35645
|
menu = owl.useState({
|
|
@@ -35866,58 +36096,149 @@ css /* scss */ `
|
|
|
35866
36096
|
const ARROW_DOWN = {
|
|
35867
36097
|
width: 448,
|
|
35868
36098
|
height: 512,
|
|
35869
|
-
|
|
35870
|
-
|
|
36099
|
+
paths: [
|
|
36100
|
+
{
|
|
36101
|
+
fillColor: "#E06666",
|
|
36102
|
+
path: "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",
|
|
36103
|
+
},
|
|
36104
|
+
],
|
|
35871
36105
|
};
|
|
35872
36106
|
const ARROW_UP = {
|
|
35873
36107
|
width: 448,
|
|
35874
36108
|
height: 512,
|
|
35875
|
-
|
|
35876
|
-
|
|
36109
|
+
paths: [
|
|
36110
|
+
{
|
|
36111
|
+
fillColor: "#6AA84F",
|
|
36112
|
+
path: "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",
|
|
36113
|
+
},
|
|
36114
|
+
],
|
|
35877
36115
|
};
|
|
35878
36116
|
const ARROW_RIGHT = {
|
|
35879
36117
|
width: 448,
|
|
35880
36118
|
height: 512,
|
|
35881
|
-
|
|
35882
|
-
|
|
36119
|
+
paths: [
|
|
36120
|
+
{
|
|
36121
|
+
fillColor: "#F0AD4E",
|
|
36122
|
+
path: "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",
|
|
36123
|
+
},
|
|
36124
|
+
],
|
|
35883
36125
|
};
|
|
35884
36126
|
const SMILE = {
|
|
35885
36127
|
width: 496,
|
|
35886
36128
|
height: 512,
|
|
35887
|
-
|
|
35888
|
-
|
|
36129
|
+
paths: [
|
|
36130
|
+
{
|
|
36131
|
+
fillColor: "#6AA84F",
|
|
36132
|
+
path: "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",
|
|
36133
|
+
},
|
|
36134
|
+
],
|
|
35889
36135
|
};
|
|
35890
36136
|
const MEH = {
|
|
35891
36137
|
width: 496,
|
|
35892
36138
|
height: 512,
|
|
35893
|
-
|
|
35894
|
-
|
|
36139
|
+
paths: [
|
|
36140
|
+
{
|
|
36141
|
+
fillColor: "#F0AD4E",
|
|
36142
|
+
path: "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",
|
|
36143
|
+
},
|
|
36144
|
+
],
|
|
35895
36145
|
};
|
|
35896
36146
|
const FROWN = {
|
|
35897
36147
|
width: 496,
|
|
35898
36148
|
height: 512,
|
|
35899
|
-
|
|
35900
|
-
|
|
36149
|
+
paths: [
|
|
36150
|
+
{
|
|
36151
|
+
fillColor: "#E06666",
|
|
36152
|
+
path: "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",
|
|
36153
|
+
},
|
|
36154
|
+
],
|
|
35901
36155
|
};
|
|
35902
36156
|
const DOT_PATH = "M256 9 a247 247 0 1 0.1 0 0";
|
|
35903
36157
|
const GREEN_DOT = {
|
|
35904
36158
|
width: 512,
|
|
35905
36159
|
height: 512,
|
|
35906
|
-
fillColor: "#6AA84F",
|
|
35907
|
-
path: DOT_PATH,
|
|
36160
|
+
paths: [{ fillColor: "#6AA84F", path: DOT_PATH }],
|
|
35908
36161
|
};
|
|
35909
36162
|
const YELLOW_DOT = {
|
|
35910
36163
|
width: 512,
|
|
35911
36164
|
height: 512,
|
|
35912
|
-
fillColor: "#F0AD4E",
|
|
35913
|
-
path: DOT_PATH,
|
|
36165
|
+
paths: [{ fillColor: "#F0AD4E", path: DOT_PATH }],
|
|
35914
36166
|
};
|
|
35915
36167
|
const RED_DOT = {
|
|
35916
36168
|
width: 512,
|
|
35917
36169
|
height: 512,
|
|
35918
|
-
fillColor: "#E06666",
|
|
35919
|
-
|
|
36170
|
+
paths: [{ fillColor: "#E06666", path: DOT_PATH }],
|
|
36171
|
+
};
|
|
36172
|
+
const CARET_DOWN = {
|
|
36173
|
+
width: 512,
|
|
36174
|
+
height: 512,
|
|
36175
|
+
paths: [{ fillColor: TEXT_BODY_MUTED, path: "M120 195 h270 l-135 130" }],
|
|
36176
|
+
};
|
|
36177
|
+
const HOVERED_CARET_DOWN = {
|
|
36178
|
+
width: 512,
|
|
36179
|
+
height: 512,
|
|
36180
|
+
paths: [
|
|
36181
|
+
{ fillColor: TEXT_BODY_MUTED, path: "M15 15 h482 v482 h-482" },
|
|
36182
|
+
{ fillColor: "#fff", path: "M120 195 h270 l-135 130" },
|
|
36183
|
+
],
|
|
36184
|
+
};
|
|
36185
|
+
const CHECKBOX_UNCHECKED = {
|
|
36186
|
+
width: 512,
|
|
36187
|
+
height: 512,
|
|
36188
|
+
paths: [{ fillColor: GRAY_300, path: "M45,45 h422 v422 h-422 v-422 m30,30 v362 h362 v-362" }],
|
|
36189
|
+
};
|
|
36190
|
+
const CHECKBOX_UNCHECKED_HOVERED = {
|
|
36191
|
+
width: 512,
|
|
36192
|
+
height: 512,
|
|
36193
|
+
paths: [{ fillColor: ACTION_COLOR, path: "M45,45 h422 v422 h-422 v-422 m30,30 v362 h362 v-362" }],
|
|
36194
|
+
};
|
|
36195
|
+
const CHECKBOX_CHECKED = {
|
|
36196
|
+
width: 512,
|
|
36197
|
+
height: 512,
|
|
36198
|
+
paths: [
|
|
36199
|
+
{ fillColor: ACTION_COLOR, path: "M45,45 h422 v422 h-422 v-422" },
|
|
36200
|
+
{ fillColor: "#FFF", path: "M165,240 l45,45 l135,-135 h60 l-195,195 l-105,-105" },
|
|
36201
|
+
],
|
|
35920
36202
|
};
|
|
36203
|
+
function getPivotIconSvg(isCollapsed, isHovered) {
|
|
36204
|
+
const symbolPath = isCollapsed
|
|
36205
|
+
? "M149,235 h213 v43 h-213 M235,149 h43 v213 h-43" // +
|
|
36206
|
+
: "M149,235 h213 v43 h-213"; // -
|
|
36207
|
+
return {
|
|
36208
|
+
width: 512,
|
|
36209
|
+
height: 512,
|
|
36210
|
+
paths: [
|
|
36211
|
+
{ path: "M21,21 h469 v469 h-469", fillColor: isHovered ? GRAY_900 : "#777" }, // borders
|
|
36212
|
+
{ path: "M64,64 v384 h384 v-384", fillColor: isHovered ? GRAY_200 : "#eee" }, // background
|
|
36213
|
+
{ path: symbolPath, fillColor: isHovered ? GRAY_900 : "#777" },
|
|
36214
|
+
],
|
|
36215
|
+
};
|
|
36216
|
+
}
|
|
36217
|
+
function getDataFilterIcon(isActive, isHighContrast, isHovered) {
|
|
36218
|
+
const symbolPath = isActive
|
|
36219
|
+
? "M18.6 3.5H4.29c-.7 0-1.06.85-.56 1.35l6.1 6.1v6.8c0 .26.13.5.34.65l2.64 1.85a.79.79 0 0 0 1.25-.65v-8.64l6.1-6.1a.79.79 0 0 0-.56-1.35"
|
|
36220
|
+
: "M 339.667 681 L 510.333 681 L 510.333 595.667 L 339.667 595.667 L 339.667 681 Z M 41 169 L 41 254.333 L 809 254.333 L 809 169 L 41 169 Z M 169 467.667 L 681 467.667 L 681 382.333 L 169 382.333 L 169 467.667 Z";
|
|
36221
|
+
const hoverBackgroundPath = isActive ? "M0,0 h24 v24 h-24" : "M0,0 h850 v850 h-850";
|
|
36222
|
+
const colors = { iconColor: FILTERS_COLOR, hoverBackgroundColor: FILTERS_COLOR };
|
|
36223
|
+
if (isHovered && !isHighContrast) {
|
|
36224
|
+
colors.iconColor = "#fff";
|
|
36225
|
+
}
|
|
36226
|
+
else if (!isHovered && isHighContrast) {
|
|
36227
|
+
colors.iconColor = "#defade";
|
|
36228
|
+
}
|
|
36229
|
+
else if (isHovered && isHighContrast) {
|
|
36230
|
+
colors.iconColor = FILTERS_COLOR;
|
|
36231
|
+
colors.hoverBackgroundColor = "#fff";
|
|
36232
|
+
}
|
|
36233
|
+
return {
|
|
36234
|
+
width: isActive ? 24 : 850,
|
|
36235
|
+
height: isActive ? 24 : 850,
|
|
36236
|
+
paths: [
|
|
36237
|
+
isHovered ? { path: hoverBackgroundPath, fillColor: colors.hoverBackgroundColor } : undefined,
|
|
36238
|
+
{ path: symbolPath, fillColor: colors.iconColor },
|
|
36239
|
+
].filter(isDefined),
|
|
36240
|
+
};
|
|
36241
|
+
}
|
|
35921
36242
|
const ICONS = {
|
|
35922
36243
|
arrowGood: {
|
|
35923
36244
|
template: "ARROW_UP",
|
|
@@ -35973,6 +36294,15 @@ const ICON_SETS = {
|
|
|
35973
36294
|
bad: "dotBad",
|
|
35974
36295
|
},
|
|
35975
36296
|
};
|
|
36297
|
+
const path2DCache = {};
|
|
36298
|
+
function getPath2D(svgPath) {
|
|
36299
|
+
if (path2DCache[svgPath]) {
|
|
36300
|
+
return path2DCache[svgPath];
|
|
36301
|
+
}
|
|
36302
|
+
const path2D = new Path2D(svgPath);
|
|
36303
|
+
path2DCache[svgPath] = path2D;
|
|
36304
|
+
return path2D;
|
|
36305
|
+
}
|
|
35976
36306
|
|
|
35977
36307
|
/**
|
|
35978
36308
|
* Map of the different types of conversions warnings and their name in error messages
|
|
@@ -38217,7 +38547,7 @@ class XlsxBaseExtractor {
|
|
|
38217
38547
|
*/
|
|
38218
38548
|
handleMissingValue(parentElement, missingElementName, optionalArgs) {
|
|
38219
38549
|
if (optionalArgs?.required) {
|
|
38220
|
-
if (optionalArgs?.default) {
|
|
38550
|
+
if (optionalArgs?.default !== undefined) {
|
|
38221
38551
|
this.warningManager.addParsingWarning(`Missing required ${missingElementName} in element <${parentElement.tagName}> of ${this.currentFile}, replacing it by the default value ${optionalArgs.default}`);
|
|
38222
38552
|
}
|
|
38223
38553
|
else {
|
|
@@ -41944,6 +42274,7 @@ const findAndReplace = {
|
|
|
41944
42274
|
execute: (env) => {
|
|
41945
42275
|
env.openSidePanel("FindAndReplace", {});
|
|
41946
42276
|
},
|
|
42277
|
+
isEnabled: (env) => !env.isSmall,
|
|
41947
42278
|
icon: "o-spreadsheet-Icon.SEARCH",
|
|
41948
42279
|
};
|
|
41949
42280
|
const deleteValues = {
|
|
@@ -42200,11 +42531,13 @@ const insertCellShiftRight = {
|
|
|
42200
42531
|
const insertChart = {
|
|
42201
42532
|
name: _t("Chart"),
|
|
42202
42533
|
execute: CREATE_CHART,
|
|
42534
|
+
isEnabled: (env) => !env.isSmall,
|
|
42203
42535
|
icon: "o-spreadsheet-Icon.INSERT_CHART",
|
|
42204
42536
|
};
|
|
42205
42537
|
const insertPivot = {
|
|
42206
42538
|
name: _t("Pivot table"),
|
|
42207
42539
|
execute: CREATE_PIVOT,
|
|
42540
|
+
isEnabled: (env) => !env.isSmall,
|
|
42208
42541
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
42209
42542
|
};
|
|
42210
42543
|
const insertImage = {
|
|
@@ -42212,12 +42545,14 @@ const insertImage = {
|
|
|
42212
42545
|
description: "Ctrl+O",
|
|
42213
42546
|
execute: CREATE_IMAGE,
|
|
42214
42547
|
isVisible: (env) => env.imageProvider !== undefined,
|
|
42548
|
+
isEnabled: (env) => !env.isSmall,
|
|
42215
42549
|
icon: "o-spreadsheet-Icon.INSERT_IMAGE",
|
|
42216
42550
|
};
|
|
42217
42551
|
const insertTable = {
|
|
42218
42552
|
name: () => _t("Table"),
|
|
42219
42553
|
execute: INSERT_TABLE,
|
|
42220
42554
|
isVisible: (env) => IS_SELECTION_CONTINUOUS(env) && !env.model.getters.getFirstTableInSelection(),
|
|
42555
|
+
isEnabled: (env) => !env.isSmall,
|
|
42221
42556
|
icon: "o-spreadsheet-Icon.PAINT_TABLE",
|
|
42222
42557
|
};
|
|
42223
42558
|
const insertFunction = {
|
|
@@ -42323,6 +42658,7 @@ const insertDropdown = {
|
|
|
42323
42658
|
},
|
|
42324
42659
|
});
|
|
42325
42660
|
},
|
|
42661
|
+
isEnabled: (env) => !env.isSmall,
|
|
42326
42662
|
icon: "o-spreadsheet-Icon.INSERT_DROPDOWN",
|
|
42327
42663
|
};
|
|
42328
42664
|
const insertSheet = {
|
|
@@ -42592,7 +42928,7 @@ const pivotProperties = {
|
|
|
42592
42928
|
isVisible: (env) => {
|
|
42593
42929
|
const position = env.model.getters.getActivePosition();
|
|
42594
42930
|
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
42595
|
-
return (pivotId && env.model.getters.isExistingPivot(pivotId)) || false;
|
|
42931
|
+
return (!env.isSmall && pivotId && env.model.getters.isExistingPivot(pivotId)) || false;
|
|
42596
42932
|
},
|
|
42597
42933
|
isReadonlyAllowed: true,
|
|
42598
42934
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
@@ -42710,7 +43046,7 @@ function isPivotSortMenuItemActive(env, order) {
|
|
|
42710
43046
|
}
|
|
42711
43047
|
|
|
42712
43048
|
//------------------------------------------------------------------------------
|
|
42713
|
-
// Context
|
|
43049
|
+
// Context MenuPopover Registry
|
|
42714
43050
|
//------------------------------------------------------------------------------
|
|
42715
43051
|
const cellMenuRegistry = new MenuItemRegistry();
|
|
42716
43052
|
cellMenuRegistry
|
|
@@ -42793,6 +43129,7 @@ cellMenuRegistry
|
|
|
42793
43129
|
.add("edit_table", {
|
|
42794
43130
|
...editTable,
|
|
42795
43131
|
isVisible: SELECTION_CONTAINS_SINGLE_TABLE,
|
|
43132
|
+
isEnabled: (env) => !env.isSmall,
|
|
42796
43133
|
sequence: 140,
|
|
42797
43134
|
})
|
|
42798
43135
|
.add("delete_table", {
|
|
@@ -42861,6 +43198,7 @@ const removeDuplicates = {
|
|
|
42861
43198
|
}
|
|
42862
43199
|
env.openSidePanel("RemoveDuplicates", {});
|
|
42863
43200
|
},
|
|
43201
|
+
isEnabled: (env) => !env.isSmall,
|
|
42864
43202
|
};
|
|
42865
43203
|
const trimWhitespace = {
|
|
42866
43204
|
name: _t("Trim whitespace"),
|
|
@@ -42888,7 +43226,7 @@ const splitToColumns = {
|
|
|
42888
43226
|
name: _t("Split text to columns"),
|
|
42889
43227
|
sequence: 1,
|
|
42890
43228
|
execute: (env) => env.openSidePanel("SplitToColumns", {}),
|
|
42891
|
-
isEnabled: (env) => env.model.getters.isSingleColSelected(),
|
|
43229
|
+
isEnabled: (env) => !env.isSmall && env.model.getters.isSingleColSelected(),
|
|
42892
43230
|
icon: "o-spreadsheet-Icon.SPLIT_TEXT",
|
|
42893
43231
|
};
|
|
42894
43232
|
const reinsertDynamicPivotMenu = {
|
|
@@ -42975,7 +43313,7 @@ const formatNumberAccounting = createFormatActionSpec({
|
|
|
42975
43313
|
const EXAMPLE_DATE = parseLiteral("2023/09/26 10:43:00 PM", DEFAULT_LOCALE);
|
|
42976
43314
|
const formatCustomCurrency = {
|
|
42977
43315
|
name: _t("Custom currency"),
|
|
42978
|
-
isVisible: (env) => env.loadCurrencies !== undefined,
|
|
43316
|
+
isVisible: (env) => env.loadCurrencies !== undefined && !env.isSmall,
|
|
42979
43317
|
execute: (env) => env.openSidePanel("CustomCurrency", {}),
|
|
42980
43318
|
};
|
|
42981
43319
|
const formatNumberDate = createFormatActionSpec({
|
|
@@ -43198,6 +43536,7 @@ const formatWrappingClip = {
|
|
|
43198
43536
|
const formatCF = {
|
|
43199
43537
|
name: _t("Conditional formatting"),
|
|
43200
43538
|
execute: OPEN_CF_SIDEPANEL_ACTION,
|
|
43539
|
+
isEnabled: (env) => !env.isSmall,
|
|
43201
43540
|
icon: "o-spreadsheet-Icon.CONDITIONAL_FORMAT",
|
|
43202
43541
|
};
|
|
43203
43542
|
const clearFormat = {
|
|
@@ -43581,8 +43920,7 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
|
|
|
43581
43920
|
}
|
|
43582
43921
|
return [
|
|
43583
43922
|
{
|
|
43584
|
-
|
|
43585
|
-
zone,
|
|
43923
|
+
range: this.model.getters.getRangeFromZone(position.sheetId, zone),
|
|
43586
43924
|
dashed: cell.value === CellErrorType.SpilledBlocked,
|
|
43587
43925
|
color: "#17A2B8",
|
|
43588
43926
|
noFill: true,
|
|
@@ -43667,6 +44005,7 @@ function useDragAndDropBeyondTheViewport(env) {
|
|
|
43667
44005
|
let previousEvClientPosition;
|
|
43668
44006
|
let startingX;
|
|
43669
44007
|
let startingY;
|
|
44008
|
+
let scrollDirection = "all";
|
|
43670
44009
|
const getters = env.model.getters;
|
|
43671
44010
|
let cleanUpFns = [];
|
|
43672
44011
|
const cleanUp = () => {
|
|
@@ -43692,55 +44031,59 @@ function useDragAndDropBeyondTheViewport(env) {
|
|
|
43692
44031
|
let timeoutDelay = MAX_DELAY;
|
|
43693
44032
|
const x = currentEv.clientX - position.left;
|
|
43694
44033
|
let colIndex = getters.getColIndex(x);
|
|
43695
|
-
|
|
43696
|
-
|
|
43697
|
-
|
|
43698
|
-
canEdgeScroll
|
|
43699
|
-
|
|
43700
|
-
|
|
43701
|
-
|
|
43702
|
-
|
|
43703
|
-
|
|
43704
|
-
|
|
43705
|
-
|
|
43706
|
-
|
|
43707
|
-
|
|
43708
|
-
|
|
43709
|
-
|
|
43710
|
-
|
|
43711
|
-
|
|
43712
|
-
colIndex
|
|
43713
|
-
|
|
43714
|
-
|
|
43715
|
-
|
|
44034
|
+
if (scrollDirection !== "vertical") {
|
|
44035
|
+
const previousX = previousEvClientPosition.clientX - position.left;
|
|
44036
|
+
const edgeScrollInfoX = getters.getEdgeScrollCol(x, previousX, startingX);
|
|
44037
|
+
if (edgeScrollInfoX.canEdgeScroll) {
|
|
44038
|
+
canEdgeScroll = true;
|
|
44039
|
+
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoX.delay);
|
|
44040
|
+
let newTarget = colIndex;
|
|
44041
|
+
switch (edgeScrollInfoX.direction) {
|
|
44042
|
+
case "reset":
|
|
44043
|
+
colIndex = newTarget = xSplit;
|
|
44044
|
+
break;
|
|
44045
|
+
case 1:
|
|
44046
|
+
colIndex = right;
|
|
44047
|
+
newTarget = left + 1;
|
|
44048
|
+
break;
|
|
44049
|
+
case -1:
|
|
44050
|
+
colIndex = left - 1;
|
|
44051
|
+
while (env.model.getters.isColHidden(sheetId, colIndex)) {
|
|
44052
|
+
colIndex--;
|
|
44053
|
+
}
|
|
44054
|
+
newTarget = colIndex;
|
|
44055
|
+
break;
|
|
44056
|
+
}
|
|
44057
|
+
scrollX = getters.getColDimensions(sheetId, newTarget).start - offsetCorrectionX;
|
|
43716
44058
|
}
|
|
43717
|
-
scrollX = getters.getColDimensions(sheetId, newTarget).start - offsetCorrectionX;
|
|
43718
44059
|
}
|
|
43719
44060
|
const y = currentEv.clientY - position.top;
|
|
43720
44061
|
let rowIndex = getters.getRowIndex(y);
|
|
43721
|
-
|
|
43722
|
-
|
|
43723
|
-
|
|
43724
|
-
canEdgeScroll
|
|
43725
|
-
|
|
43726
|
-
|
|
43727
|
-
|
|
43728
|
-
|
|
43729
|
-
|
|
43730
|
-
|
|
43731
|
-
|
|
43732
|
-
|
|
43733
|
-
|
|
43734
|
-
|
|
43735
|
-
|
|
43736
|
-
|
|
43737
|
-
|
|
43738
|
-
rowIndex
|
|
43739
|
-
|
|
43740
|
-
|
|
43741
|
-
|
|
44062
|
+
if (scrollDirection !== "horizontal") {
|
|
44063
|
+
const previousY = previousEvClientPosition.clientY - position.top;
|
|
44064
|
+
const edgeScrollInfoY = getters.getEdgeScrollRow(y, previousY, startingY);
|
|
44065
|
+
if (edgeScrollInfoY.canEdgeScroll) {
|
|
44066
|
+
canEdgeScroll = true;
|
|
44067
|
+
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoY.delay);
|
|
44068
|
+
let newTarget = rowIndex;
|
|
44069
|
+
switch (edgeScrollInfoY.direction) {
|
|
44070
|
+
case "reset":
|
|
44071
|
+
rowIndex = newTarget = ySplit;
|
|
44072
|
+
break;
|
|
44073
|
+
case 1:
|
|
44074
|
+
rowIndex = bottom;
|
|
44075
|
+
newTarget = top + 1;
|
|
44076
|
+
break;
|
|
44077
|
+
case -1:
|
|
44078
|
+
rowIndex = top - 1;
|
|
44079
|
+
while (env.model.getters.isRowHidden(sheetId, rowIndex)) {
|
|
44080
|
+
rowIndex--;
|
|
44081
|
+
}
|
|
44082
|
+
newTarget = rowIndex;
|
|
44083
|
+
break;
|
|
44084
|
+
}
|
|
44085
|
+
scrollY = env.model.getters.getRowDimensions(sheetId, newTarget).start - offsetCorrectionY;
|
|
43742
44086
|
}
|
|
43743
|
-
scrollY = env.model.getters.getRowDimensions(sheetId, newTarget).start - offsetCorrectionY;
|
|
43744
44087
|
}
|
|
43745
44088
|
if (!canEdgeScroll) {
|
|
43746
44089
|
colIndex = adjustIndexWithinBounds(colIndex, x, getters.getNumberCols(sheetId) - 1);
|
|
@@ -43760,9 +44103,10 @@ function useDragAndDropBeyondTheViewport(env) {
|
|
|
43760
44103
|
pointerUpCallback?.();
|
|
43761
44104
|
cleanUp();
|
|
43762
44105
|
};
|
|
43763
|
-
const startFn = (initialPointerCoordinates, onPointerMove, onPointerUp) => {
|
|
44106
|
+
const startFn = (initialPointerCoordinates, onPointerMove, onPointerUp, startScrollDirection = "all") => {
|
|
43764
44107
|
cleanUp();
|
|
43765
44108
|
const position = gridOverlayPosition();
|
|
44109
|
+
scrollDirection = startScrollDirection;
|
|
43766
44110
|
startingX = initialPointerCoordinates.clientX - position.left;
|
|
43767
44111
|
startingY = initialPointerCoordinates.clientY - position.top;
|
|
43768
44112
|
previousEvClientPosition = {
|
|
@@ -44240,7 +44584,7 @@ class GridComposer extends owl.Component {
|
|
|
44240
44584
|
});
|
|
44241
44585
|
}
|
|
44242
44586
|
get shouldDisplayCellReference() {
|
|
44243
|
-
return this.isCellReferenceVisible;
|
|
44587
|
+
return !this.env.isMobile() && this.isCellReferenceVisible;
|
|
44244
44588
|
}
|
|
44245
44589
|
get cellReference() {
|
|
44246
44590
|
const { col, row, sheetId } = this.composerStore.currentEditedCell;
|
|
@@ -44281,11 +44625,12 @@ class GridComposer extends owl.Component {
|
|
|
44281
44625
|
onInputContextMenu: this.props.onInputContextMenu,
|
|
44282
44626
|
composerStore: this.composerStore,
|
|
44283
44627
|
inputStyle: `max-height: ${maxHeight}px;`,
|
|
44628
|
+
inputMode: this.composerStore.editionMode === "inactive" ? "none" : undefined,
|
|
44284
44629
|
};
|
|
44285
44630
|
}
|
|
44286
44631
|
get containerStyle() {
|
|
44287
|
-
if (this.composerStore.editionMode === "inactive") {
|
|
44288
|
-
return `z-index: -1000;`;
|
|
44632
|
+
if (this.composerStore.editionMode === "inactive" || this.env.isMobile()) {
|
|
44633
|
+
return `z-index: -1000; opacity: 0;`; // opacity 0 for safari on ios
|
|
44289
44634
|
}
|
|
44290
44635
|
const _isFormula = isFormula(this.composerStore.currentContent);
|
|
44291
44636
|
const cell = this.env.model.getters.getActiveCell();
|
|
@@ -44314,11 +44659,13 @@ class GridComposer extends owl.Component {
|
|
|
44314
44659
|
*
|
|
44315
44660
|
* The +-1 are there to include cell borders in the composer sizing/positioning
|
|
44316
44661
|
*/
|
|
44662
|
+
const minHeight = Math.min(height + 1, maxHeight);
|
|
44663
|
+
const minWidth = Math.min(width + 1, maxWidth);
|
|
44317
44664
|
return cssPropertiesToCss({
|
|
44318
44665
|
left: `${left - 1}px`,
|
|
44319
44666
|
top: `${top}px`,
|
|
44320
|
-
"min-width": `${
|
|
44321
|
-
"min-height": `${
|
|
44667
|
+
"min-width": `${minWidth}px`,
|
|
44668
|
+
"min-height": `${minHeight}px`,
|
|
44322
44669
|
"max-width": `${maxWidth}px`,
|
|
44323
44670
|
"max-height": `${maxHeight}px`,
|
|
44324
44671
|
background,
|
|
@@ -44815,6 +45162,9 @@ class FiguresContainer extends owl.Component {
|
|
|
44815
45162
|
if (!selectResult.isSuccessful) {
|
|
44816
45163
|
return;
|
|
44817
45164
|
}
|
|
45165
|
+
if (this.env.isMobile()) {
|
|
45166
|
+
return;
|
|
45167
|
+
}
|
|
44818
45168
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
44819
45169
|
const initialMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
44820
45170
|
const initialScrollPosition = this.env.model.getters.getActiveSheetScrollInfo();
|
|
@@ -45107,78 +45457,6 @@ class GridAddRowsFooter extends owl.Component {
|
|
|
45107
45457
|
}
|
|
45108
45458
|
}
|
|
45109
45459
|
|
|
45110
|
-
class GridCellIcon extends owl.Component {
|
|
45111
|
-
static template = "o-spreadsheet-GridCellIcon";
|
|
45112
|
-
static props = {
|
|
45113
|
-
icon: Object,
|
|
45114
|
-
verticalAlign: { type: String, optional: true },
|
|
45115
|
-
slots: Object,
|
|
45116
|
-
};
|
|
45117
|
-
get iconStyle() {
|
|
45118
|
-
const cellPosition = this.props.icon.position;
|
|
45119
|
-
const merge = this.env.model.getters.getMerge(cellPosition);
|
|
45120
|
-
const zone = merge || positionToZone(cellPosition);
|
|
45121
|
-
const rect = this.env.model.getters.getVisibleRectWithoutHeaders(zone);
|
|
45122
|
-
const x = this.getIconHorizontalPosition(rect, cellPosition);
|
|
45123
|
-
const y = this.getIconVerticalPosition(rect, cellPosition);
|
|
45124
|
-
return cssPropertiesToCss({
|
|
45125
|
-
top: `${y}px`,
|
|
45126
|
-
left: `${x}px`,
|
|
45127
|
-
width: `${this.props.icon.size}px`,
|
|
45128
|
-
height: `${this.props.icon.size}px`,
|
|
45129
|
-
});
|
|
45130
|
-
}
|
|
45131
|
-
getIconVerticalPosition(rect, cellPosition) {
|
|
45132
|
-
const start = rect.y;
|
|
45133
|
-
const end = rect.y + rect.height;
|
|
45134
|
-
const cell = this.env.model.getters.getCell(cellPosition);
|
|
45135
|
-
const align = this.props.verticalAlign || cell?.style?.verticalAlign || DEFAULT_VERTICAL_ALIGN;
|
|
45136
|
-
switch (align) {
|
|
45137
|
-
case "bottom":
|
|
45138
|
-
return end - GRID_ICON_MARGIN - GRID_ICON_EDGE_LENGTH;
|
|
45139
|
-
case "top":
|
|
45140
|
-
return start + GRID_ICON_MARGIN;
|
|
45141
|
-
default:
|
|
45142
|
-
const centeringOffset = Math.floor((end - start - GRID_ICON_EDGE_LENGTH) / 2);
|
|
45143
|
-
return end - GRID_ICON_EDGE_LENGTH - centeringOffset;
|
|
45144
|
-
}
|
|
45145
|
-
}
|
|
45146
|
-
getIconHorizontalPosition(rect, cellPosition) {
|
|
45147
|
-
const start = rect.x;
|
|
45148
|
-
const end = rect.x + rect.width;
|
|
45149
|
-
const cell = this.env.model.getters.getCell(cellPosition);
|
|
45150
|
-
const evaluatedCell = this.env.model.getters.getEvaluatedCell(cellPosition);
|
|
45151
|
-
const align = this.props.icon.horizontalAlign || cell?.style?.align || evaluatedCell.defaultAlign;
|
|
45152
|
-
switch (align) {
|
|
45153
|
-
case "right":
|
|
45154
|
-
return end - this.props.icon.size - this.props.icon.margin;
|
|
45155
|
-
case "left":
|
|
45156
|
-
return start + this.props.icon.margin;
|
|
45157
|
-
default:
|
|
45158
|
-
const centeringOffset = Math.floor((end - start - this.props.icon.size) / 2);
|
|
45159
|
-
return end - this.props.icon.size - centeringOffset;
|
|
45160
|
-
}
|
|
45161
|
-
}
|
|
45162
|
-
isPositionVisible(position) {
|
|
45163
|
-
const rect = this.env.model.getters.getVisibleRect(positionToZone(position));
|
|
45164
|
-
return !(rect.width === 0 || rect.height === 0);
|
|
45165
|
-
}
|
|
45166
|
-
}
|
|
45167
|
-
|
|
45168
|
-
class GridCellIconOverlay extends owl.Component {
|
|
45169
|
-
static template = "o-spreadsheet-GridCellIconOverlay";
|
|
45170
|
-
static props = {};
|
|
45171
|
-
static components = { GridCellIcon };
|
|
45172
|
-
get icons() {
|
|
45173
|
-
const icons = [];
|
|
45174
|
-
for (const position of this.env.model.getters.getVisibleCellPositions()) {
|
|
45175
|
-
const cellIcons = this.env.model.getters.getCellIcons(position);
|
|
45176
|
-
icons.push(...cellIcons.filter((icon) => icon.component));
|
|
45177
|
-
}
|
|
45178
|
-
return icons;
|
|
45179
|
-
}
|
|
45180
|
-
}
|
|
45181
|
-
|
|
45182
45460
|
/**
|
|
45183
45461
|
* Manages an event listener on a ref. Useful for hooks that want to manage
|
|
45184
45462
|
* event listeners, especially more than one. Prefer using t-on directly in
|
|
@@ -45267,7 +45545,7 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
45267
45545
|
return [];
|
|
45268
45546
|
}
|
|
45269
45547
|
return data.zones.map((zone) => ({
|
|
45270
|
-
zone,
|
|
45548
|
+
range: this.model.getters.getRangeFromZone(data.sheetId, zone),
|
|
45271
45549
|
color: SELECTION_BORDER_COLOR,
|
|
45272
45550
|
dashed: true,
|
|
45273
45551
|
sheetId: data.sheetId,
|
|
@@ -45290,7 +45568,7 @@ class HoveredTableStore extends SpreadsheetStore {
|
|
|
45290
45568
|
}
|
|
45291
45569
|
}
|
|
45292
45570
|
hover(position) {
|
|
45293
|
-
if (position.col === this.col && position.row === this.row) {
|
|
45571
|
+
if (!this.getters.isDashboard() || (position.col === this.col && position.row === this.row)) {
|
|
45294
45572
|
return "noStateChange";
|
|
45295
45573
|
}
|
|
45296
45574
|
this.col = position.col;
|
|
@@ -45324,6 +45602,14 @@ class HoveredTableStore extends SpreadsheetStore {
|
|
|
45324
45602
|
}
|
|
45325
45603
|
}
|
|
45326
45604
|
|
|
45605
|
+
class HoveredIconStore extends SpreadsheetStore {
|
|
45606
|
+
mutators = ["setHoveredIcon"];
|
|
45607
|
+
hoveredIcon = undefined;
|
|
45608
|
+
setHoveredIcon(icon) {
|
|
45609
|
+
this.hoveredIcon = icon;
|
|
45610
|
+
}
|
|
45611
|
+
}
|
|
45612
|
+
|
|
45327
45613
|
const CURSOR_SVG = /*xml*/ `
|
|
45328
45614
|
<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>
|
|
45329
45615
|
`;
|
|
@@ -45395,10 +45681,11 @@ function useCellHovered(env, gridRef) {
|
|
|
45395
45681
|
return pause();
|
|
45396
45682
|
}
|
|
45397
45683
|
}
|
|
45398
|
-
useRefListener(gridRef, "pointermove", updateMousePosition);
|
|
45684
|
+
useRefListener(gridRef, "pointermove", (ev) => !env.isMobile() && updateMousePosition(ev));
|
|
45399
45685
|
useRefListener(gridRef, "mouseleave", onMouseLeave);
|
|
45400
45686
|
useRefListener(gridRef, "mouseenter", resume);
|
|
45401
45687
|
useRefListener(gridRef, "pointerdown", recompute);
|
|
45688
|
+
useRefListener(gridRef, "pointerdown", (ev) => env.isMobile() && updateMousePosition(ev));
|
|
45402
45689
|
owl.useExternalListener(window, "click", handleGlobalClick);
|
|
45403
45690
|
function handleGlobalClick(e) {
|
|
45404
45691
|
const target = e.target;
|
|
@@ -45427,11 +45714,11 @@ class GridOverlay extends owl.Component {
|
|
|
45427
45714
|
onGridMoved: Function,
|
|
45428
45715
|
gridOverlayDimensions: String,
|
|
45429
45716
|
slots: { type: Object, optional: true },
|
|
45717
|
+
getGridSize: Function,
|
|
45430
45718
|
};
|
|
45431
45719
|
static components = {
|
|
45432
45720
|
FiguresContainer,
|
|
45433
45721
|
GridAddRowsFooter,
|
|
45434
|
-
GridCellIconOverlay,
|
|
45435
45722
|
};
|
|
45436
45723
|
static defaultProps = {
|
|
45437
45724
|
onCellDoubleClicked: () => { },
|
|
@@ -45443,15 +45730,17 @@ class GridOverlay extends owl.Component {
|
|
|
45443
45730
|
gridOverlay = owl.useRef("gridOverlay");
|
|
45444
45731
|
cellPopovers;
|
|
45445
45732
|
paintFormatStore;
|
|
45733
|
+
hoveredIconStore;
|
|
45446
45734
|
setup() {
|
|
45447
45735
|
useCellHovered(this.env, this.gridOverlay);
|
|
45448
45736
|
const resizeObserver = new ResizeObserver(() => {
|
|
45449
45737
|
const boundingRect = this.gridOverlayEl.getBoundingClientRect();
|
|
45738
|
+
const { width, height } = this.props.getGridSize();
|
|
45450
45739
|
this.props.onGridResized({
|
|
45451
45740
|
x: boundingRect.left,
|
|
45452
45741
|
y: boundingRect.top,
|
|
45453
|
-
height:
|
|
45454
|
-
width:
|
|
45742
|
+
height: height,
|
|
45743
|
+
width: width,
|
|
45455
45744
|
});
|
|
45456
45745
|
});
|
|
45457
45746
|
owl.onMounted(() => {
|
|
@@ -45462,6 +45751,7 @@ class GridOverlay extends owl.Component {
|
|
|
45462
45751
|
});
|
|
45463
45752
|
this.cellPopovers = useStore(CellPopoverStore);
|
|
45464
45753
|
this.paintFormatStore = useStore(PaintFormatStore);
|
|
45754
|
+
this.hoveredIconStore = useStore(HoveredIconStore);
|
|
45465
45755
|
}
|
|
45466
45756
|
get gridOverlayEl() {
|
|
45467
45757
|
if (!this.gridOverlay.el) {
|
|
@@ -45470,26 +45760,59 @@ class GridOverlay extends owl.Component {
|
|
|
45470
45760
|
return this.gridOverlay.el;
|
|
45471
45761
|
}
|
|
45472
45762
|
get style() {
|
|
45473
|
-
return this.props.gridOverlayDimensions
|
|
45763
|
+
return (this.props.gridOverlayDimensions +
|
|
45764
|
+
cssPropertiesToCss({ cursor: this.hoveredIconStore.hoveredIcon ? "pointer" : "default" }));
|
|
45474
45765
|
}
|
|
45475
45766
|
get isPaintingFormat() {
|
|
45476
45767
|
return this.paintFormatStore.isActive;
|
|
45477
45768
|
}
|
|
45478
|
-
|
|
45479
|
-
if (
|
|
45769
|
+
onPointerMove(ev) {
|
|
45770
|
+
if (this.env.isMobile()) {
|
|
45771
|
+
return;
|
|
45772
|
+
}
|
|
45773
|
+
const icon = this.getInteractiveIconAtEvent(ev);
|
|
45774
|
+
const hoveredIcon = icon?.type ? { id: icon.type, position: icon.position } : undefined;
|
|
45775
|
+
if (!deepEquals(hoveredIcon, this.hoveredIconStore.hoveredIcon)) {
|
|
45776
|
+
this.hoveredIconStore.setHoveredIcon(hoveredIcon);
|
|
45777
|
+
}
|
|
45778
|
+
}
|
|
45779
|
+
onPointerDown(ev) {
|
|
45780
|
+
if (ev.button > 0 || this.env.isMobile()) {
|
|
45480
45781
|
// not main button, probably a context menu
|
|
45481
45782
|
return;
|
|
45482
45783
|
}
|
|
45483
|
-
|
|
45484
|
-
|
|
45784
|
+
this.onCellClicked(ev);
|
|
45785
|
+
}
|
|
45786
|
+
onClick(ev) {
|
|
45787
|
+
if (ev.button > 0 || !this.env.isMobile()) {
|
|
45788
|
+
// not main button, probably a context menu
|
|
45789
|
+
return;
|
|
45485
45790
|
}
|
|
45791
|
+
this.onCellClicked(ev);
|
|
45792
|
+
}
|
|
45793
|
+
onCellClicked(ev) {
|
|
45794
|
+
const openedPopover = this.cellPopovers.persistentCellPopover;
|
|
45486
45795
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
45487
45796
|
this.props.onCellClicked(col, row, {
|
|
45488
45797
|
expandZone: ev.shiftKey,
|
|
45489
45798
|
addZone: isCtrlKey(ev),
|
|
45490
45799
|
}, ev);
|
|
45800
|
+
const clickedIcon = this.getInteractiveIconAtEvent(ev);
|
|
45801
|
+
if (clickedIcon?.onClick) {
|
|
45802
|
+
clickedIcon.onClick(clickedIcon.position, this.env);
|
|
45803
|
+
}
|
|
45804
|
+
if (ev.target === this.gridOverlay.el &&
|
|
45805
|
+
this.cellPopovers.isOpen &&
|
|
45806
|
+
deepEquals(openedPopover, this.cellPopovers.persistentCellPopover)) {
|
|
45807
|
+
// Only close the popover if props.click/icon.click didn't open a new one
|
|
45808
|
+
this.cellPopovers.close();
|
|
45809
|
+
return;
|
|
45810
|
+
}
|
|
45491
45811
|
}
|
|
45492
45812
|
onDoubleClick(ev) {
|
|
45813
|
+
if (this.getInteractiveIconAtEvent(ev)) {
|
|
45814
|
+
return;
|
|
45815
|
+
}
|
|
45493
45816
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
45494
45817
|
this.props.onCellDoubleClicked(col, row);
|
|
45495
45818
|
}
|
|
@@ -45505,6 +45828,24 @@ class GridOverlay extends owl.Component {
|
|
|
45505
45828
|
const rowIndex = this.env.model.getters.getRowIndex(y);
|
|
45506
45829
|
return [colIndex, rowIndex];
|
|
45507
45830
|
}
|
|
45831
|
+
getInteractiveIconAtEvent(ev) {
|
|
45832
|
+
const gridOverLayRect = getRefBoundingRect(this.gridOverlay);
|
|
45833
|
+
const gridOffset = this.env.model.getters.getGridOffset();
|
|
45834
|
+
const x = ev.clientX - gridOverLayRect.x + gridOffset.x;
|
|
45835
|
+
const y = ev.clientY - gridOverLayRect.y + gridOffset.y;
|
|
45836
|
+
const [col, row] = this.getCartesianCoordinates(ev);
|
|
45837
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
45838
|
+
let position = { col, row, sheetId };
|
|
45839
|
+
const merge = this.env.model.getters.getMerge(position);
|
|
45840
|
+
if (merge) {
|
|
45841
|
+
position = { col: merge.left, row: merge.top, sheetId };
|
|
45842
|
+
}
|
|
45843
|
+
const icons = this.env.model.getters.getCellIcons(position);
|
|
45844
|
+
const icon = icons.find((icon) => {
|
|
45845
|
+
return isPointInsideRect(x, y, this.env.model.getters.getCellIconRect(icon));
|
|
45846
|
+
});
|
|
45847
|
+
return icon?.onClick ? icon : undefined;
|
|
45848
|
+
}
|
|
45508
45849
|
}
|
|
45509
45850
|
|
|
45510
45851
|
class GridPopover extends owl.Component {
|
|
@@ -45665,6 +46006,9 @@ class AbstractResizer extends owl.Component {
|
|
|
45665
46006
|
this.state.waitingForMove = false;
|
|
45666
46007
|
}
|
|
45667
46008
|
onMouseMove(ev) {
|
|
46009
|
+
if (this.env.isMobile()) {
|
|
46010
|
+
return;
|
|
46011
|
+
}
|
|
45668
46012
|
if (this.state.isResizing || this.state.isMoving || this.state.isSelecting) {
|
|
45669
46013
|
return;
|
|
45670
46014
|
}
|
|
@@ -45709,7 +46053,21 @@ class AbstractResizer extends owl.Component {
|
|
|
45709
46053
|
};
|
|
45710
46054
|
startDnd(onMouseMove, onMouseUp);
|
|
45711
46055
|
}
|
|
46056
|
+
onClick(ev) {
|
|
46057
|
+
if (!this.env.isMobile()) {
|
|
46058
|
+
return;
|
|
46059
|
+
}
|
|
46060
|
+
if (ev.button > 0) {
|
|
46061
|
+
// not main button, probably a context menu
|
|
46062
|
+
return;
|
|
46063
|
+
}
|
|
46064
|
+
const index = this._getElementIndex(this._getEvOffset(ev));
|
|
46065
|
+
this._selectElement(index, false);
|
|
46066
|
+
}
|
|
45712
46067
|
select(ev) {
|
|
46068
|
+
if (this.env.isMobile()) {
|
|
46069
|
+
return;
|
|
46070
|
+
}
|
|
45713
46071
|
if (ev.button > 0) {
|
|
45714
46072
|
// not main button, probably a context menu
|
|
45715
46073
|
return;
|
|
@@ -45778,6 +46136,9 @@ class AbstractResizer extends owl.Component {
|
|
|
45778
46136
|
this.dragNDropGrid.start(ev, mouseMoveMovement, mouseUpMovement);
|
|
45779
46137
|
}
|
|
45780
46138
|
startSelection(ev, index) {
|
|
46139
|
+
if (this.env.isMobile()) {
|
|
46140
|
+
return;
|
|
46141
|
+
}
|
|
45781
46142
|
this.state.isSelecting = true;
|
|
45782
46143
|
if (ev.shiftKey) {
|
|
45783
46144
|
this._increaseSelection(index);
|
|
@@ -46223,11 +46584,13 @@ class GridRenderer {
|
|
|
46223
46584
|
renderer;
|
|
46224
46585
|
fingerprints;
|
|
46225
46586
|
hoveredTables;
|
|
46587
|
+
hoveredIcon;
|
|
46226
46588
|
constructor(get) {
|
|
46227
46589
|
this.getters = get(ModelStore).getters;
|
|
46228
46590
|
this.renderer = get(RendererStore);
|
|
46229
46591
|
this.fingerprints = get(FormulaFingerprintStore);
|
|
46230
46592
|
this.hoveredTables = get(HoveredTableStore);
|
|
46593
|
+
this.hoveredIcon = get(HoveredIconStore);
|
|
46231
46594
|
this.renderer.register(this);
|
|
46232
46595
|
}
|
|
46233
46596
|
get renderingLayers() {
|
|
@@ -46464,7 +46827,7 @@ class GridRenderer {
|
|
|
46464
46827
|
// compute vertical align start point parameter:
|
|
46465
46828
|
const textLineHeight = computeTextFontSizeInPixels(style);
|
|
46466
46829
|
const numberOfLines = box.content.textLines.length;
|
|
46467
|
-
let y = this.computeTextYCoordinate(box, textLineHeight, numberOfLines);
|
|
46830
|
+
let y = this.getters.computeTextYCoordinate(box, textLineHeight, style.verticalAlign, numberOfLines);
|
|
46468
46831
|
// use the horizontal and the vertical start points to:
|
|
46469
46832
|
// fill text / fill strikethrough / fill underline
|
|
46470
46833
|
for (const brokenLine of box.content.textLines) {
|
|
@@ -46481,7 +46844,12 @@ class GridRenderer {
|
|
|
46481
46844
|
const { ctx } = renderingContext;
|
|
46482
46845
|
for (const box of boxes) {
|
|
46483
46846
|
for (const icon of Object.values(box.icons)) {
|
|
46484
|
-
if (!icon
|
|
46847
|
+
if (!icon) {
|
|
46848
|
+
continue;
|
|
46849
|
+
}
|
|
46850
|
+
const isHovered = deepEquals({ id: icon.type, position: icon.position }, this.hoveredIcon.hoveredIcon);
|
|
46851
|
+
const svg = isHovered ? icon.hoverSvg || icon.svg : icon.svg;
|
|
46852
|
+
if (!svg) {
|
|
46485
46853
|
continue;
|
|
46486
46854
|
}
|
|
46487
46855
|
ctx.save();
|
|
@@ -46489,46 +46857,17 @@ class GridRenderer {
|
|
|
46489
46857
|
ctx.rect(box.x, box.y, box.width, box.height);
|
|
46490
46858
|
ctx.clip();
|
|
46491
46859
|
const iconSize = icon.size;
|
|
46492
|
-
const
|
|
46493
|
-
|
|
46494
|
-
let x;
|
|
46495
|
-
if (icon.horizontalAlign === "left") {
|
|
46496
|
-
x = box.x + icon.margin;
|
|
46497
|
-
}
|
|
46498
|
-
else if (icon.horizontalAlign === "right") {
|
|
46499
|
-
x = box.x + box.width - iconSize - icon.margin;
|
|
46500
|
-
}
|
|
46501
|
-
else {
|
|
46502
|
-
x = box.x + (box.width - iconSize) / 2;
|
|
46503
|
-
}
|
|
46504
|
-
ctx.translate(x, iconY);
|
|
46860
|
+
const { x, y } = this.getters.getCellIconRect(icon);
|
|
46861
|
+
ctx.translate(x, y);
|
|
46505
46862
|
ctx.scale(iconSize / svg.width, iconSize / svg.height);
|
|
46506
|
-
|
|
46507
|
-
|
|
46863
|
+
for (const path of svg.paths) {
|
|
46864
|
+
ctx.fillStyle = path.fillColor;
|
|
46865
|
+
ctx.fill(getPath2D(path.path));
|
|
46866
|
+
}
|
|
46508
46867
|
ctx.restore();
|
|
46509
46868
|
}
|
|
46510
46869
|
}
|
|
46511
46870
|
}
|
|
46512
|
-
/** Computes the vertical start point from which a text line should be draw.
|
|
46513
|
-
*
|
|
46514
|
-
* Note that in case the cell does not have enough spaces to display its text lines,
|
|
46515
|
-
* (wrapping cell case) then the vertical align should be at the top.
|
|
46516
|
-
* */
|
|
46517
|
-
computeTextYCoordinate(box, textLineHeight, numberOfLines = 1) {
|
|
46518
|
-
const y = box.y + 1;
|
|
46519
|
-
const textHeight = computeTextLinesHeight(textLineHeight, numberOfLines);
|
|
46520
|
-
const hasEnoughSpaces = box.height > textHeight + MIN_CELL_TEXT_MARGIN * 2;
|
|
46521
|
-
const verticalAlign = box.verticalAlign || DEFAULT_VERTICAL_ALIGN;
|
|
46522
|
-
if (hasEnoughSpaces) {
|
|
46523
|
-
if (verticalAlign === "middle") {
|
|
46524
|
-
return y + (box.height - textHeight) / 2;
|
|
46525
|
-
}
|
|
46526
|
-
if (verticalAlign === "bottom") {
|
|
46527
|
-
return y + box.height - textHeight - MIN_CELL_TEXT_MARGIN;
|
|
46528
|
-
}
|
|
46529
|
-
}
|
|
46530
|
-
return y + MIN_CELL_TEXT_MARGIN;
|
|
46531
|
-
}
|
|
46532
46871
|
drawHeaders(renderingContext) {
|
|
46533
46872
|
const { ctx, thinLineWidth } = renderingContext;
|
|
46534
46873
|
const visibleCols = this.getters.getSheetViewVisibleCols();
|
|
@@ -46965,6 +47304,9 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
|
46965
47304
|
const deltaX = lastX - clientX;
|
|
46966
47305
|
const deltaY = lastY - clientY;
|
|
46967
47306
|
const elapsedTime = currentTime - lastTime;
|
|
47307
|
+
if (!elapsedTime) {
|
|
47308
|
+
return;
|
|
47309
|
+
}
|
|
46968
47310
|
velocityX = deltaX / elapsedTime;
|
|
46969
47311
|
velocityY = deltaY / elapsedTime;
|
|
46970
47312
|
lastX = clientX;
|
|
@@ -46985,6 +47327,11 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
|
46985
47327
|
function onTouchEnd(ev) {
|
|
46986
47328
|
isMouseDown = false;
|
|
46987
47329
|
lastX = lastY = 0;
|
|
47330
|
+
if (resetTimeout) {
|
|
47331
|
+
clearTimeout(resetTimeout);
|
|
47332
|
+
}
|
|
47333
|
+
velocityX *= 1.2;
|
|
47334
|
+
velocityY *= 1.2;
|
|
46988
47335
|
requestAnimationFrame(scroll);
|
|
46989
47336
|
}
|
|
46990
47337
|
function scroll() {
|
|
@@ -47069,12 +47416,16 @@ class Border extends owl.Component {
|
|
|
47069
47416
|
}
|
|
47070
47417
|
}
|
|
47071
47418
|
|
|
47419
|
+
const MOBILE_HANDLER_WIDTH = 40;
|
|
47072
47420
|
css /* scss */ `
|
|
47073
47421
|
.o-corner {
|
|
47074
47422
|
position: absolute;
|
|
47075
|
-
|
|
47076
|
-
|
|
47423
|
+
}
|
|
47424
|
+
|
|
47425
|
+
.o-corner-button {
|
|
47077
47426
|
border: 1px solid white;
|
|
47427
|
+
height: ${AUTOFILL_EDGE_LENGTH}px;
|
|
47428
|
+
width: ${AUTOFILL_EDGE_LENGTH}px;
|
|
47078
47429
|
}
|
|
47079
47430
|
.o-corner-nw,
|
|
47080
47431
|
.o-corner-se {
|
|
@@ -47101,34 +47452,61 @@ class Corner extends owl.Component {
|
|
|
47101
47452
|
isResizing: Boolean,
|
|
47102
47453
|
onResizeHighlight: Function,
|
|
47103
47454
|
};
|
|
47104
|
-
|
|
47105
|
-
|
|
47106
|
-
|
|
47455
|
+
dirX;
|
|
47456
|
+
dirY;
|
|
47457
|
+
setup() {
|
|
47458
|
+
const { dirX, dirY } = orientationToDir(this.props.orientation);
|
|
47459
|
+
this.dirX = dirX;
|
|
47460
|
+
this.dirY = dirY;
|
|
47461
|
+
}
|
|
47462
|
+
get handlerStyle() {
|
|
47107
47463
|
const z = this.props.zone;
|
|
47108
|
-
const col = this.isLeft ? z.left : z.right;
|
|
47109
|
-
const row = this.isTop ? z.top : z.bottom;
|
|
47110
47464
|
const rect = this.env.model.getters.getVisibleRect({
|
|
47111
|
-
left:
|
|
47112
|
-
right:
|
|
47113
|
-
top:
|
|
47114
|
-
bottom:
|
|
47465
|
+
left: this.dirX === 1 ? z.right : z.left,
|
|
47466
|
+
right: this.dirX === -1 ? z.left : z.right,
|
|
47467
|
+
top: this.dirY === 1 ? z.bottom : z.top,
|
|
47468
|
+
bottom: this.dirY === -1 ? z.top : z.bottom,
|
|
47115
47469
|
});
|
|
47116
47470
|
// Don't show if not visible in the viewport
|
|
47117
47471
|
if (rect.width * rect.height === 0) {
|
|
47118
|
-
return `display:none
|
|
47472
|
+
return `display: none !important;`;
|
|
47473
|
+
}
|
|
47474
|
+
const leftValue = rect.x + rect.width / 2 + (this.dirX * rect.width) / 2;
|
|
47475
|
+
const topValue = rect.y + rect.height / 2 + (this.dirY * rect.height) / 2;
|
|
47476
|
+
const edgeLength = this.getHandlerEdgeLength();
|
|
47477
|
+
const css = {
|
|
47478
|
+
left: `${leftValue - edgeLength / 2}px`,
|
|
47479
|
+
top: `${topValue - edgeLength / 2}px`,
|
|
47480
|
+
height: `${edgeLength}px`,
|
|
47481
|
+
width: `${edgeLength}px`,
|
|
47482
|
+
};
|
|
47483
|
+
if (this.env.isMobile()) {
|
|
47484
|
+
css["border-radius"] = `${edgeLength / 2}px`;
|
|
47119
47485
|
}
|
|
47120
|
-
|
|
47121
|
-
|
|
47122
|
-
|
|
47123
|
-
|
|
47124
|
-
|
|
47486
|
+
return cssPropertiesToCss(css);
|
|
47487
|
+
}
|
|
47488
|
+
getHandlerEdgeLength() {
|
|
47489
|
+
return this.env.isMobile() ? MOBILE_HANDLER_WIDTH : AUTOFILL_EDGE_LENGTH;
|
|
47490
|
+
}
|
|
47491
|
+
get buttonLook() {
|
|
47492
|
+
const css = {
|
|
47125
47493
|
"background-color": this.props.color,
|
|
47126
|
-
|
|
47494
|
+
cursor: `${this.props.orientation}-resize`,
|
|
47495
|
+
};
|
|
47496
|
+
if (this.env.isMobile()) {
|
|
47497
|
+
css["border-radius"] = `${AUTOFILL_EDGE_LENGTH / 2}px`;
|
|
47498
|
+
}
|
|
47499
|
+
return cssPropertiesToCss(css);
|
|
47127
47500
|
}
|
|
47128
47501
|
onMouseDown(ev) {
|
|
47129
|
-
this.props.onResizeHighlight(ev, this.
|
|
47502
|
+
this.props.onResizeHighlight(ev, this.dirX, this.dirY);
|
|
47130
47503
|
}
|
|
47131
47504
|
}
|
|
47505
|
+
function orientationToDir(or) {
|
|
47506
|
+
const dirX = or.includes("w") ? -1 : or.includes("e") ? 1 : 0;
|
|
47507
|
+
const dirY = or.includes("n") ? -1 : or.includes("s") ? 1 : 0;
|
|
47508
|
+
return { dirX, dirY };
|
|
47509
|
+
}
|
|
47132
47510
|
|
|
47133
47511
|
css /*SCSS*/ `
|
|
47134
47512
|
.o-highlight {
|
|
@@ -47138,7 +47516,7 @@ css /*SCSS*/ `
|
|
|
47138
47516
|
class Highlight extends owl.Component {
|
|
47139
47517
|
static template = "o-spreadsheet-Highlight";
|
|
47140
47518
|
static props = {
|
|
47141
|
-
|
|
47519
|
+
range: Object,
|
|
47142
47520
|
color: String,
|
|
47143
47521
|
};
|
|
47144
47522
|
static components = {
|
|
@@ -47149,26 +47527,49 @@ class Highlight extends owl.Component {
|
|
|
47149
47527
|
shiftingMode: "none",
|
|
47150
47528
|
});
|
|
47151
47529
|
dragNDropGrid = useDragAndDropBeyondTheViewport(this.env);
|
|
47152
|
-
|
|
47530
|
+
get cornerOrientations() {
|
|
47531
|
+
if (!this.env.isMobile()) {
|
|
47532
|
+
return ["nw", "ne", "sw", "se"];
|
|
47533
|
+
}
|
|
47534
|
+
const z = this.props.range.unboundedZone;
|
|
47535
|
+
if (z.bottom === undefined) {
|
|
47536
|
+
return ["w", "e"];
|
|
47537
|
+
}
|
|
47538
|
+
else if (z.right === undefined) {
|
|
47539
|
+
return ["n", "s"];
|
|
47540
|
+
}
|
|
47541
|
+
else {
|
|
47542
|
+
return ["nw", "se"];
|
|
47543
|
+
}
|
|
47544
|
+
}
|
|
47545
|
+
onResizeHighlight(ev, dirX, dirY) {
|
|
47153
47546
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
47154
47547
|
this.highlightState.shiftingMode = "isResizing";
|
|
47155
|
-
const z = this.props.zone;
|
|
47156
|
-
const pivotCol =
|
|
47157
|
-
const pivotRow =
|
|
47158
|
-
let lastCol =
|
|
47159
|
-
let lastRow =
|
|
47548
|
+
const z = this.props.range.zone;
|
|
47549
|
+
const pivotCol = dirX === 1 ? z.left : z.right;
|
|
47550
|
+
const pivotRow = dirY === 1 ? z.top : z.bottom;
|
|
47551
|
+
let lastCol = dirX === 1 ? z.right : z.left;
|
|
47552
|
+
let lastRow = dirY === 1 ? z.bottom : z.top;
|
|
47160
47553
|
let currentZone = z;
|
|
47554
|
+
let scrollDirection = "all";
|
|
47555
|
+
if (this.env.isMobile()) {
|
|
47556
|
+
scrollDirection = dirX === 0 ? "vertical" : dirY === 0 ? "horizontal" : "all";
|
|
47557
|
+
}
|
|
47161
47558
|
this.env.model.dispatch("START_CHANGE_HIGHLIGHT", { zone: currentZone });
|
|
47162
47559
|
const mouseMove = (col, row) => {
|
|
47163
47560
|
if (lastCol !== col || lastRow !== row) {
|
|
47164
|
-
|
|
47165
|
-
|
|
47166
|
-
|
|
47167
|
-
|
|
47168
|
-
|
|
47169
|
-
|
|
47170
|
-
|
|
47171
|
-
|
|
47561
|
+
let { left, right, top, bottom } = currentZone;
|
|
47562
|
+
if (scrollDirection !== "horizontal") {
|
|
47563
|
+
lastRow = lastRow = clip(row === -1 ? lastRow : row, 0, this.env.model.getters.getNumberRows(activeSheetId) - 1);
|
|
47564
|
+
top = Math.min(pivotRow, lastRow);
|
|
47565
|
+
bottom = Math.max(pivotRow, lastRow);
|
|
47566
|
+
}
|
|
47567
|
+
if (scrollDirection !== "vertical") {
|
|
47568
|
+
lastCol = clip(col === -1 ? lastCol : col, 0, this.env.model.getters.getNumberCols(activeSheetId) - 1);
|
|
47569
|
+
left = Math.min(pivotCol, lastCol);
|
|
47570
|
+
right = Math.max(pivotCol, lastCol);
|
|
47571
|
+
}
|
|
47572
|
+
const newZone = { left, right, top, bottom };
|
|
47172
47573
|
if (!isEqual(newZone, currentZone)) {
|
|
47173
47574
|
this.env.model.selection.selectZone({
|
|
47174
47575
|
cell: { col: newZone.left, row: newZone.top },
|
|
@@ -47181,11 +47582,11 @@ class Highlight extends owl.Component {
|
|
|
47181
47582
|
const mouseUp = () => {
|
|
47182
47583
|
this.highlightState.shiftingMode = "none";
|
|
47183
47584
|
};
|
|
47184
|
-
this.dragNDropGrid.start(ev, mouseMove, mouseUp);
|
|
47585
|
+
this.dragNDropGrid.start(ev, mouseMove, mouseUp, scrollDirection);
|
|
47185
47586
|
}
|
|
47186
47587
|
onMoveHighlight(ev) {
|
|
47187
47588
|
this.highlightState.shiftingMode = "isMoving";
|
|
47188
|
-
const z = this.props.zone;
|
|
47589
|
+
const z = this.props.range.zone;
|
|
47189
47590
|
const position = gridOverlayPosition();
|
|
47190
47591
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
47191
47592
|
const initCol = this.env.model.getters.getColIndex(ev.clientX - position.left);
|
|
@@ -47407,6 +47808,18 @@ class VerticalScrollBar extends owl.Component {
|
|
|
47407
47808
|
}
|
|
47408
47809
|
}
|
|
47409
47810
|
|
|
47811
|
+
class Selection extends owl.Component {
|
|
47812
|
+
static template = "o-spreadsheet-Selection";
|
|
47813
|
+
static props = {};
|
|
47814
|
+
static components = { Highlight };
|
|
47815
|
+
get highlightProps() {
|
|
47816
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
47817
|
+
const zone = this.env.model.getters.getUnboundedZone(sheetId, this.env.model.getters.getSelectedZone());
|
|
47818
|
+
const range = this.env.model.getters.getRangeFromZone(sheetId, zone);
|
|
47819
|
+
return { range, color: SELECTION_BORDER_COLOR };
|
|
47820
|
+
}
|
|
47821
|
+
}
|
|
47822
|
+
|
|
47410
47823
|
class Section extends owl.Component {
|
|
47411
47824
|
static template = "o_spreadsheet.Section";
|
|
47412
47825
|
static props = {
|
|
@@ -48352,11 +48765,13 @@ class ColorPickerWidget extends owl.Component {
|
|
|
48352
48765
|
|
|
48353
48766
|
css /* scss */ `
|
|
48354
48767
|
.o-font-size-editor {
|
|
48768
|
+
width: max-content !important;
|
|
48355
48769
|
height: calc(100% - 4px);
|
|
48356
48770
|
input.o-font-size {
|
|
48357
48771
|
outline: none;
|
|
48358
48772
|
height: 20px;
|
|
48359
|
-
width:
|
|
48773
|
+
width: 31px;
|
|
48774
|
+
text-align: center;
|
|
48360
48775
|
}
|
|
48361
48776
|
}
|
|
48362
48777
|
.o-text-options > div {
|
|
@@ -50500,8 +50915,7 @@ class ConditionalFormatPreview extends owl.Component {
|
|
|
50500
50915
|
get highlights() {
|
|
50501
50916
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
50502
50917
|
return this.props.conditionalFormat.ranges.map((range) => ({
|
|
50503
|
-
sheetId,
|
|
50504
|
-
zone: this.env.model.getters.getRangeFromSheetXC(sheetId, range).zone,
|
|
50918
|
+
range: this.env.model.getters.getRangeFromSheetXC(sheetId, range),
|
|
50505
50919
|
color: HIGHLIGHT_COLOR,
|
|
50506
50920
|
fillAlpha: 0.06,
|
|
50507
50921
|
}));
|
|
@@ -51459,8 +51873,7 @@ class DataValidationPreview extends owl.Component {
|
|
|
51459
51873
|
}
|
|
51460
51874
|
get highlights() {
|
|
51461
51875
|
return this.props.rule.ranges.map((range) => ({
|
|
51462
|
-
|
|
51463
|
-
zone: range.zone,
|
|
51876
|
+
range,
|
|
51464
51877
|
color: HIGHLIGHT_COLOR,
|
|
51465
51878
|
fillAlpha: 0.06,
|
|
51466
51879
|
}));
|
|
@@ -51789,13 +52202,15 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
51789
52202
|
if (this.selectedMatchIndex === null) {
|
|
51790
52203
|
return;
|
|
51791
52204
|
}
|
|
52205
|
+
this.preserveSelectedMatchIndex = true;
|
|
52206
|
+
this.shouldFinalizeUpdateSelection = true;
|
|
51792
52207
|
this.model.dispatch("REPLACE_SEARCH", {
|
|
51793
52208
|
searchString: this.toSearch,
|
|
51794
52209
|
replaceWith: this.toReplace,
|
|
51795
52210
|
matches: [this.searchMatches[this.selectedMatchIndex]],
|
|
51796
52211
|
searchOptions: this.searchOptions,
|
|
51797
52212
|
});
|
|
51798
|
-
this.
|
|
52213
|
+
this.preserveSelectedMatchIndex = false;
|
|
51799
52214
|
}
|
|
51800
52215
|
/**
|
|
51801
52216
|
* Apply the replace function to all the matches one time.
|
|
@@ -51867,8 +52282,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
51867
52282
|
const { width, height } = this.getters.getVisibleRect(zoneWithMerge);
|
|
51868
52283
|
if (width > 0 && height > 0) {
|
|
51869
52284
|
highlights.push({
|
|
51870
|
-
sheetId,
|
|
51871
|
-
zone: zoneWithMerge,
|
|
52285
|
+
range: this.model.getters.getRangeFromZone(sheetId, zoneWithMerge),
|
|
51872
52286
|
color: FIND_AND_REPLACE_HIGHLIGHT_COLOR,
|
|
51873
52287
|
noBorder: index !== this.selectedMatchIndex,
|
|
51874
52288
|
thinLine: true,
|
|
@@ -51880,8 +52294,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
51880
52294
|
const range = this.searchOptions.specificRange;
|
|
51881
52295
|
if (range && range.sheetId === sheetId) {
|
|
51882
52296
|
highlights.push({
|
|
51883
|
-
|
|
51884
|
-
zone: range.zone,
|
|
52297
|
+
range,
|
|
51885
52298
|
color: FIND_AND_REPLACE_HIGHLIGHT_COLOR,
|
|
51886
52299
|
noFill: true,
|
|
51887
52300
|
thinLine: true,
|
|
@@ -52255,7 +52668,11 @@ function getPivotHighlights(getters, pivotId) {
|
|
|
52255
52668
|
const sheetId = getters.getActiveSheetId();
|
|
52256
52669
|
const pivotCellPositions = getVisiblePivotCellPositions(getters, pivotId);
|
|
52257
52670
|
const mergedZones = mergeContiguousZones(pivotCellPositions.map(positionToZone));
|
|
52258
|
-
return mergedZones.map((zone) => ({
|
|
52671
|
+
return mergedZones.map((zone) => ({
|
|
52672
|
+
range: getters.getRangeFromZone(sheetId, zone),
|
|
52673
|
+
noFill: true,
|
|
52674
|
+
color: HIGHLIGHT_COLOR,
|
|
52675
|
+
}));
|
|
52259
52676
|
}
|
|
52260
52677
|
function getVisiblePivotCellPositions(getters, pivotId) {
|
|
52261
52678
|
const positions = [];
|
|
@@ -52524,7 +52941,7 @@ class TextInput extends owl.Component {
|
|
|
52524
52941
|
|
|
52525
52942
|
class CogWheelMenu extends owl.Component {
|
|
52526
52943
|
static template = "o-spreadsheet-CogWheelMenu";
|
|
52527
|
-
static components = {
|
|
52944
|
+
static components = { MenuPopover };
|
|
52528
52945
|
static props = {
|
|
52529
52946
|
items: Array,
|
|
52530
52947
|
};
|
|
@@ -53432,28 +53849,45 @@ class SpreadsheetPivotTable {
|
|
|
53432
53849
|
getNumberOfDataColumns() {
|
|
53433
53850
|
return this.columns.at(-1)?.length || 0;
|
|
53434
53851
|
}
|
|
53435
|
-
|
|
53436
|
-
const
|
|
53852
|
+
getSkippedRows(visibilityOptions) {
|
|
53853
|
+
const skippedRows = new Set();
|
|
53854
|
+
if (!visibilityOptions.displayColumnHeaders) {
|
|
53855
|
+
for (let i = 0; i < this.columns.length - 1; i++) {
|
|
53856
|
+
skippedRows.add(i);
|
|
53857
|
+
}
|
|
53858
|
+
}
|
|
53859
|
+
if (!visibilityOptions.displayMeasuresRow) {
|
|
53860
|
+
skippedRows.add(this.columns.length - 1);
|
|
53861
|
+
}
|
|
53862
|
+
return skippedRows;
|
|
53863
|
+
}
|
|
53864
|
+
getPivotCells(visibilityOptions = {
|
|
53865
|
+
displayColumnHeaders: true,
|
|
53866
|
+
displayTotals: true,
|
|
53867
|
+
displayMeasuresRow: true,
|
|
53868
|
+
}) {
|
|
53869
|
+
const key = JSON.stringify(visibilityOptions);
|
|
53437
53870
|
if (!this.pivotCells[key]) {
|
|
53871
|
+
const { displayTotals } = visibilityOptions;
|
|
53438
53872
|
const numberOfDataRows = this.rows.length;
|
|
53439
53873
|
const numberOfDataColumns = this.getNumberOfDataColumns();
|
|
53440
53874
|
let pivotHeight = this.columns.length + numberOfDataRows;
|
|
53441
53875
|
let pivotWidth = 1 /*(row headers)*/ + numberOfDataColumns;
|
|
53442
|
-
if (!
|
|
53876
|
+
if (!displayTotals && numberOfDataRows !== 1) {
|
|
53443
53877
|
pivotHeight -= 1;
|
|
53444
53878
|
}
|
|
53445
|
-
if (!
|
|
53879
|
+
if (!displayTotals && numberOfDataColumns !== this.measures.length) {
|
|
53446
53880
|
pivotWidth -= this.measures.length;
|
|
53447
53881
|
}
|
|
53448
53882
|
const domainArray = [];
|
|
53449
|
-
const
|
|
53883
|
+
const skippedRows = this.getSkippedRows(visibilityOptions);
|
|
53450
53884
|
for (let col = 0; col < pivotWidth; col++) {
|
|
53451
53885
|
domainArray.push([]);
|
|
53452
|
-
for (let row =
|
|
53453
|
-
if (
|
|
53886
|
+
for (let row = 0; row < pivotHeight; row++) {
|
|
53887
|
+
if (skippedRows.has(row)) {
|
|
53454
53888
|
continue;
|
|
53455
53889
|
}
|
|
53456
|
-
domainArray[col].push(this.getPivotCell(col, row,
|
|
53890
|
+
domainArray[col].push(this.getPivotCell(col, row, displayTotals));
|
|
53457
53891
|
}
|
|
53458
53892
|
}
|
|
53459
53893
|
this.pivotCells[key] = domainArray;
|
|
@@ -55094,6 +55528,7 @@ function createTableStyleContextMenuActions(env, styleId) {
|
|
|
55094
55528
|
id: "editTableStyle",
|
|
55095
55529
|
name: _t("Edit table style"),
|
|
55096
55530
|
execute: (env) => env.openSidePanel("TableStyleEditorPanel", { styleId }),
|
|
55531
|
+
isEnabled: (env) => !env.isSmall,
|
|
55097
55532
|
icon: "o-spreadsheet-Icon.EDIT",
|
|
55098
55533
|
},
|
|
55099
55534
|
{
|
|
@@ -55215,7 +55650,7 @@ css /* scss */ `
|
|
|
55215
55650
|
`;
|
|
55216
55651
|
class TableStylePreview extends owl.Component {
|
|
55217
55652
|
static template = "o-spreadsheet-TableStylePreview";
|
|
55218
|
-
static components = {
|
|
55653
|
+
static components = { MenuPopover };
|
|
55219
55654
|
static props = {
|
|
55220
55655
|
tableConfig: Object,
|
|
55221
55656
|
tableStyle: Object,
|
|
@@ -55786,6 +56221,17 @@ sidePanelRegistry.add("PivotMeasureDisplayPanel", {
|
|
|
55786
56221
|
},
|
|
55787
56222
|
});
|
|
55788
56223
|
|
|
56224
|
+
class ScreenWidthStore {
|
|
56225
|
+
mutators = ["setSmallThreshhold"];
|
|
56226
|
+
_isSmallCallback = () => false;
|
|
56227
|
+
get isSmall() {
|
|
56228
|
+
return this._isSmallCallback();
|
|
56229
|
+
}
|
|
56230
|
+
setSmallThreshhold(isSmall) {
|
|
56231
|
+
this._isSmallCallback = isSmall;
|
|
56232
|
+
}
|
|
56233
|
+
}
|
|
56234
|
+
|
|
55789
56235
|
const DEFAULT_SIDE_PANEL_SIZE = 350;
|
|
55790
56236
|
const MIN_SHEET_VIEW_WIDTH = 150;
|
|
55791
56237
|
class SidePanelStore extends SpreadsheetStore {
|
|
@@ -55793,6 +56239,7 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
55793
56239
|
initialPanelProps = {};
|
|
55794
56240
|
componentTag = "";
|
|
55795
56241
|
panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
56242
|
+
screenWidthStore = this.get(ScreenWidthStore);
|
|
55796
56243
|
get isOpen() {
|
|
55797
56244
|
if (!this.componentTag) {
|
|
55798
56245
|
return false;
|
|
@@ -55814,6 +56261,9 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
55814
56261
|
return undefined;
|
|
55815
56262
|
}
|
|
55816
56263
|
open(componentTag, panelProps = {}) {
|
|
56264
|
+
if (this.screenWidthStore.isSmall) {
|
|
56265
|
+
return;
|
|
56266
|
+
}
|
|
55817
56267
|
const state = this.computeState(componentTag, panelProps);
|
|
55818
56268
|
if (!state.isOpen) {
|
|
55819
56269
|
return;
|
|
@@ -55928,8 +56378,7 @@ class TableResizer extends owl.Component {
|
|
|
55928
56378
|
return [];
|
|
55929
56379
|
return [
|
|
55930
56380
|
{
|
|
55931
|
-
|
|
55932
|
-
sheetId: this.props.table.range.sheetId,
|
|
56381
|
+
range: this.env.model.getters.getRangeFromZone(this.props.table.range.sheetId, this.state.highlightZone),
|
|
55933
56382
|
color: COLOR,
|
|
55934
56383
|
noFill: true,
|
|
55935
56384
|
},
|
|
@@ -55951,13 +56400,14 @@ class Grid extends owl.Component {
|
|
|
55951
56400
|
static template = "o-spreadsheet-Grid";
|
|
55952
56401
|
static props = {
|
|
55953
56402
|
exposeFocus: Function,
|
|
56403
|
+
getGridSize: Function,
|
|
55954
56404
|
};
|
|
55955
56405
|
static components = {
|
|
55956
56406
|
GridComposer,
|
|
55957
56407
|
GridOverlay,
|
|
55958
56408
|
GridPopover,
|
|
55959
56409
|
HeadersOverlay,
|
|
55960
|
-
|
|
56410
|
+
MenuPopover,
|
|
55961
56411
|
Autofill,
|
|
55962
56412
|
ClientTag,
|
|
55963
56413
|
Highlight,
|
|
@@ -55965,6 +56415,7 @@ class Grid extends owl.Component {
|
|
|
55965
56415
|
VerticalScrollBar,
|
|
55966
56416
|
HorizontalScrollBar,
|
|
55967
56417
|
TableResizer,
|
|
56418
|
+
Selection,
|
|
55968
56419
|
};
|
|
55969
56420
|
HEADER_HEIGHT = HEADER_HEIGHT;
|
|
55970
56421
|
HEADER_WIDTH = HEADER_WIDTH;
|
|
@@ -56247,8 +56698,8 @@ class Grid extends owl.Component {
|
|
|
56247
56698
|
}
|
|
56248
56699
|
onGridResized({ height, width }) {
|
|
56249
56700
|
this.env.model.dispatch("RESIZE_SHEETVIEW", {
|
|
56250
|
-
width: width,
|
|
56251
|
-
height: height,
|
|
56701
|
+
width: width - HEADER_WIDTH,
|
|
56702
|
+
height: height - HEADER_HEIGHT,
|
|
56252
56703
|
gridOffsetX: HEADER_WIDTH,
|
|
56253
56704
|
gridOffsetY: HEADER_HEIGHT,
|
|
56254
56705
|
});
|
|
@@ -56302,6 +56753,9 @@ class Grid extends owl.Component {
|
|
|
56302
56753
|
else {
|
|
56303
56754
|
this.env.model.selection.selectCell(col, row);
|
|
56304
56755
|
}
|
|
56756
|
+
if (this.env.isMobile()) {
|
|
56757
|
+
return;
|
|
56758
|
+
}
|
|
56305
56759
|
let prevCol = col;
|
|
56306
56760
|
let prevRow = row;
|
|
56307
56761
|
const onMouseMove = (col, row, ev) => {
|
|
@@ -56587,6 +57041,9 @@ class Grid extends owl.Component {
|
|
|
56587
57041
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
56588
57042
|
return this.env.model.getters.getCoreTables(sheetId).filter(isStaticTable);
|
|
56589
57043
|
}
|
|
57044
|
+
get displaySelectionHandler() {
|
|
57045
|
+
return this.env.isMobile() && this.composerFocusStore.activeComposer.editionMode === "inactive";
|
|
57046
|
+
}
|
|
56590
57047
|
}
|
|
56591
57048
|
|
|
56592
57049
|
/**
|
|
@@ -61621,7 +62078,9 @@ class TablePlugin extends CorePlugin {
|
|
|
61621
62078
|
const ranges = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData));
|
|
61622
62079
|
const union = this.getters.getRangesUnion(ranges);
|
|
61623
62080
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
61624
|
-
|
|
62081
|
+
if (mergesInTarget.length) {
|
|
62082
|
+
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
62083
|
+
}
|
|
61625
62084
|
const id = this.consumeNextId();
|
|
61626
62085
|
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
61627
62086
|
const newTable = cmd.tableType === "dynamic"
|
|
@@ -61720,14 +62179,16 @@ class TablePlugin extends CorePlugin {
|
|
|
61720
62179
|
const zoneToCheckIfEmpty = direction === "down"
|
|
61721
62180
|
? { ...zone, bottom: zone.bottom + 1, top: zone.bottom + 1 }
|
|
61722
62181
|
: { ...zone, right: zone.right + 1, left: zone.right + 1 };
|
|
61723
|
-
for (
|
|
61724
|
-
|
|
61725
|
-
|
|
61726
|
-
|
|
61727
|
-
|
|
61728
|
-
|
|
61729
|
-
|
|
61730
|
-
|
|
62182
|
+
for (let row = zoneToCheckIfEmpty.top; row <= zoneToCheckIfEmpty.bottom; row++) {
|
|
62183
|
+
for (let col = zoneToCheckIfEmpty.left; col <= zoneToCheckIfEmpty.right; col++) {
|
|
62184
|
+
const cellPosition = { sheetId, col, row };
|
|
62185
|
+
// Since this plugin is loaded before CellPlugin, the getters still give us the old cell content
|
|
62186
|
+
const cellContent = this.getters.getCell(cellPosition)?.content;
|
|
62187
|
+
if (cellContent ||
|
|
62188
|
+
this.getters.isInMerge(cellPosition) ||
|
|
62189
|
+
this.getTablesOverlappingZones(sheetId, [positionToZone(cellPosition)]).length) {
|
|
62190
|
+
return "none";
|
|
62191
|
+
}
|
|
61731
62192
|
}
|
|
61732
62193
|
}
|
|
61733
62194
|
return direction;
|
|
@@ -62513,7 +62974,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62513
62974
|
break;
|
|
62514
62975
|
}
|
|
62515
62976
|
case "UPDATE_PIVOT": {
|
|
62516
|
-
this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
|
|
62977
|
+
this.history.update("pivots", cmd.pivotId, "definition", this.repairSortedColumn(deepCopy(cmd.pivot)));
|
|
62517
62978
|
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
62518
62979
|
break;
|
|
62519
62980
|
}
|
|
@@ -62584,7 +63045,10 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62584
63045
|
// Private
|
|
62585
63046
|
// -------------------------------------------------------------------------
|
|
62586
63047
|
addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
|
|
62587
|
-
this.history.update("pivots", pivotId, {
|
|
63048
|
+
this.history.update("pivots", pivotId, {
|
|
63049
|
+
definition: this.repairSortedColumn(deepCopy(pivot)),
|
|
63050
|
+
formulaId,
|
|
63051
|
+
});
|
|
62588
63052
|
this.compileCalculatedMeasures(pivot.measures);
|
|
62589
63053
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
62590
63054
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
@@ -62673,6 +63137,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62673
63137
|
}
|
|
62674
63138
|
}
|
|
62675
63139
|
checkSortedColumnInMeasures(definition) {
|
|
63140
|
+
definition = this.repairSortedColumn(definition);
|
|
62676
63141
|
const measures = definition.measures.map((measure) => measure.id);
|
|
62677
63142
|
if (definition.sortedColumn && !measures.includes(definition.sortedColumn.measure)) {
|
|
62678
63143
|
return "InvalidDefinition" /* CommandResult.InvalidDefinition */;
|
|
@@ -62686,6 +63151,26 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62686
63151
|
}
|
|
62687
63152
|
return "Success" /* CommandResult.Success */;
|
|
62688
63153
|
}
|
|
63154
|
+
repairSortedColumn(definition) {
|
|
63155
|
+
if (definition.sortedColumn) {
|
|
63156
|
+
// Fix for an upgrade issue: the sortedColumn measure was not updated
|
|
63157
|
+
// from using fieldName to using id. If the sortedColumn measure matches
|
|
63158
|
+
// a measure fieldName in the definition, update it to use the measure's id instead
|
|
63159
|
+
// of its fieldName.
|
|
63160
|
+
// TODO: add an upgrade step to fix this in master and remove this code
|
|
63161
|
+
const sortedMeasure = definition.measures.find((measure) => measure.fieldName === definition.sortedColumn?.measure);
|
|
63162
|
+
if (sortedMeasure) {
|
|
63163
|
+
return {
|
|
63164
|
+
...definition,
|
|
63165
|
+
sortedColumn: {
|
|
63166
|
+
...definition.sortedColumn,
|
|
63167
|
+
measure: sortedMeasure.id,
|
|
63168
|
+
},
|
|
63169
|
+
};
|
|
63170
|
+
}
|
|
63171
|
+
}
|
|
63172
|
+
return definition;
|
|
63173
|
+
}
|
|
62689
63174
|
// ---------------------------------------------------------------------
|
|
62690
63175
|
// Import/Export
|
|
62691
63176
|
// ---------------------------------------------------------------------
|
|
@@ -65553,186 +66038,6 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
|
|
|
65553
66038
|
}
|
|
65554
66039
|
}
|
|
65555
66040
|
|
|
65556
|
-
const MARGIN = (GRID_ICON_EDGE_LENGTH - CHECKBOX_WIDTH) / 2;
|
|
65557
|
-
css /* scss */ `
|
|
65558
|
-
.o-dv-checkbox {
|
|
65559
|
-
margin: ${MARGIN}px;
|
|
65560
|
-
/* required to prevent the checkbox position to be sensible to the font-size (affects Firefox) */
|
|
65561
|
-
position: absolute;
|
|
65562
|
-
}
|
|
65563
|
-
`;
|
|
65564
|
-
class DataValidationCheckbox extends owl.Component {
|
|
65565
|
-
static template = "o-spreadsheet-DataValidationCheckbox";
|
|
65566
|
-
static components = {
|
|
65567
|
-
Checkbox,
|
|
65568
|
-
};
|
|
65569
|
-
static props = {
|
|
65570
|
-
cellPosition: Object,
|
|
65571
|
-
};
|
|
65572
|
-
onCheckboxChange(value) {
|
|
65573
|
-
const { sheetId, col, row } = this.props.cellPosition;
|
|
65574
|
-
const cellContent = value ? "TRUE" : "FALSE";
|
|
65575
|
-
this.env.model.dispatch("UPDATE_CELL", { sheetId, col, row, content: cellContent });
|
|
65576
|
-
}
|
|
65577
|
-
get checkBoxValue() {
|
|
65578
|
-
return !!this.env.model.getters.getEvaluatedCell(this.props.cellPosition).value;
|
|
65579
|
-
}
|
|
65580
|
-
get isDisabled() {
|
|
65581
|
-
const cell = this.env.model.getters.getCell(this.props.cellPosition);
|
|
65582
|
-
return this.env.model.getters.isReadonly() || !!cell?.isFormula;
|
|
65583
|
-
}
|
|
65584
|
-
}
|
|
65585
|
-
|
|
65586
|
-
const ICON_WIDTH = 13;
|
|
65587
|
-
css /* scss */ `
|
|
65588
|
-
.o-dv-list-icon {
|
|
65589
|
-
color: ${TEXT_BODY_MUTED};
|
|
65590
|
-
border-radius: 1px;
|
|
65591
|
-
height: ${GRID_ICON_EDGE_LENGTH}px;
|
|
65592
|
-
width: ${GRID_ICON_EDGE_LENGTH}px;
|
|
65593
|
-
|
|
65594
|
-
&:hover {
|
|
65595
|
-
color: #ffffff;
|
|
65596
|
-
background-color: ${TEXT_BODY_MUTED};
|
|
65597
|
-
}
|
|
65598
|
-
|
|
65599
|
-
svg {
|
|
65600
|
-
width: ${ICON_WIDTH}px;
|
|
65601
|
-
height: ${ICON_WIDTH}px;
|
|
65602
|
-
}
|
|
65603
|
-
}
|
|
65604
|
-
`;
|
|
65605
|
-
class DataValidationListIcon extends owl.Component {
|
|
65606
|
-
static template = "o-spreadsheet-DataValidationListIcon";
|
|
65607
|
-
static props = {
|
|
65608
|
-
cellPosition: Object,
|
|
65609
|
-
};
|
|
65610
|
-
onClick() {
|
|
65611
|
-
const { col, row } = this.props.cellPosition;
|
|
65612
|
-
this.env.model.selection.selectCell(col, row);
|
|
65613
|
-
this.env.startCellEdition();
|
|
65614
|
-
}
|
|
65615
|
-
}
|
|
65616
|
-
|
|
65617
|
-
css /* scss */ `
|
|
65618
|
-
.o-filter-icon {
|
|
65619
|
-
color: ${FILTERS_COLOR};
|
|
65620
|
-
display: flex;
|
|
65621
|
-
align-items: center;
|
|
65622
|
-
justify-content: center;
|
|
65623
|
-
width: ${GRID_ICON_EDGE_LENGTH}px;
|
|
65624
|
-
height: ${GRID_ICON_EDGE_LENGTH}px;
|
|
65625
|
-
|
|
65626
|
-
&:hover {
|
|
65627
|
-
background: ${FILTERS_COLOR};
|
|
65628
|
-
color: #fff;
|
|
65629
|
-
}
|
|
65630
|
-
|
|
65631
|
-
&.o-high-contrast {
|
|
65632
|
-
color: #defade;
|
|
65633
|
-
}
|
|
65634
|
-
&.o-high-contrast:hover {
|
|
65635
|
-
color: ${FILTERS_COLOR};
|
|
65636
|
-
background: #fff;
|
|
65637
|
-
}
|
|
65638
|
-
}
|
|
65639
|
-
.o-filter-icon:hover {
|
|
65640
|
-
background: ${FILTERS_COLOR};
|
|
65641
|
-
color: #fff;
|
|
65642
|
-
}
|
|
65643
|
-
`;
|
|
65644
|
-
class FilterIcon extends owl.Component {
|
|
65645
|
-
static template = "o-spreadsheet-FilterIcon";
|
|
65646
|
-
static props = {
|
|
65647
|
-
cellPosition: Object,
|
|
65648
|
-
};
|
|
65649
|
-
cellPopovers;
|
|
65650
|
-
setup() {
|
|
65651
|
-
this.cellPopovers = useStore(CellPopoverStore);
|
|
65652
|
-
}
|
|
65653
|
-
onClick() {
|
|
65654
|
-
const position = this.props.cellPosition;
|
|
65655
|
-
const activePopover = this.cellPopovers.persistentCellPopover;
|
|
65656
|
-
const { col, row } = position;
|
|
65657
|
-
if (activePopover.isOpen &&
|
|
65658
|
-
activePopover.col === col &&
|
|
65659
|
-
activePopover.row === row &&
|
|
65660
|
-
activePopover.type === "FilterMenu") {
|
|
65661
|
-
this.cellPopovers.close();
|
|
65662
|
-
return;
|
|
65663
|
-
}
|
|
65664
|
-
this.cellPopovers.open({ col, row }, "FilterMenu");
|
|
65665
|
-
}
|
|
65666
|
-
get isFilterActive() {
|
|
65667
|
-
return this.env.model.getters.isFilterActive(this.props.cellPosition);
|
|
65668
|
-
}
|
|
65669
|
-
get iconClass() {
|
|
65670
|
-
const cellStyle = this.env.model.getters.getCellComputedStyle(this.props.cellPosition);
|
|
65671
|
-
const luminance = relativeLuminance(cellStyle.fillColor || "#fff");
|
|
65672
|
-
return luminance < 0.45 ? "o-high-contrast" : "";
|
|
65673
|
-
}
|
|
65674
|
-
}
|
|
65675
|
-
|
|
65676
|
-
css /* scss */ `
|
|
65677
|
-
.o-spreadsheet {
|
|
65678
|
-
.o-pivot-collapse-icon {
|
|
65679
|
-
cursor: pointer;
|
|
65680
|
-
width: 11px;
|
|
65681
|
-
height: 11px;
|
|
65682
|
-
border: 1px solid #777;
|
|
65683
|
-
background-color: #eee;
|
|
65684
|
-
margin: 3px 0 3px 6px;
|
|
65685
|
-
|
|
65686
|
-
.o-icon {
|
|
65687
|
-
width: 5px;
|
|
65688
|
-
height: 5px;
|
|
65689
|
-
}
|
|
65690
|
-
}
|
|
65691
|
-
}
|
|
65692
|
-
`;
|
|
65693
|
-
class PivotCollapseIcon extends owl.Component {
|
|
65694
|
-
static template = "o-spreadsheet-PivotCollapseIcon";
|
|
65695
|
-
static props = {
|
|
65696
|
-
cellPosition: Object,
|
|
65697
|
-
};
|
|
65698
|
-
onClick() {
|
|
65699
|
-
const pivotCell = this.env.model.getters.getPivotCellFromPosition(this.props.cellPosition);
|
|
65700
|
-
const pivotId = this.env.model.getters.getPivotIdFromPosition(this.props.cellPosition);
|
|
65701
|
-
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
65702
|
-
return;
|
|
65703
|
-
}
|
|
65704
|
-
const definition = this.env.model.getters.getPivotCoreDefinition(pivotId);
|
|
65705
|
-
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
65706
|
-
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
65707
|
-
: [];
|
|
65708
|
-
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
65709
|
-
if (index !== -1) {
|
|
65710
|
-
collapsedDomains.splice(index, 1);
|
|
65711
|
-
}
|
|
65712
|
-
else {
|
|
65713
|
-
collapsedDomains.push(pivotCell.domain);
|
|
65714
|
-
}
|
|
65715
|
-
const newDomains = definition.collapsedDomains
|
|
65716
|
-
? { ...definition.collapsedDomains }
|
|
65717
|
-
: { COL: [], ROW: [] };
|
|
65718
|
-
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
65719
|
-
this.env.model.dispatch("UPDATE_PIVOT", {
|
|
65720
|
-
pivotId,
|
|
65721
|
-
pivot: { ...definition, collapsedDomains: newDomains },
|
|
65722
|
-
});
|
|
65723
|
-
}
|
|
65724
|
-
get isCollapsed() {
|
|
65725
|
-
const pivotCell = this.env.model.getters.getPivotCellFromPosition(this.props.cellPosition);
|
|
65726
|
-
const pivotId = this.env.model.getters.getPivotIdFromPosition(this.props.cellPosition);
|
|
65727
|
-
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
65728
|
-
return false;
|
|
65729
|
-
}
|
|
65730
|
-
const definition = this.env.model.getters.getPivotCoreDefinition(pivotId);
|
|
65731
|
-
const domains = definition.collapsedDomains?.[pivotCell.dimension] ?? [];
|
|
65732
|
-
return domains?.some((domain) => deepEquals(domain, pivotCell.domain));
|
|
65733
|
-
}
|
|
65734
|
-
}
|
|
65735
|
-
|
|
65736
66041
|
/**
|
|
65737
66042
|
* Registry to draw icons on cells
|
|
65738
66043
|
*/
|
|
@@ -65740,14 +66045,25 @@ const iconsOnCellRegistry = new Registry();
|
|
|
65740
66045
|
iconsOnCellRegistry.add("data_validation_checkbox", (getters, position) => {
|
|
65741
66046
|
const hasIcon = getters.isCellValidCheckbox(position);
|
|
65742
66047
|
if (hasIcon) {
|
|
66048
|
+
const value = !!getters.getEvaluatedCell(position).value;
|
|
65743
66049
|
return {
|
|
65744
|
-
svg:
|
|
66050
|
+
svg: value ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED,
|
|
66051
|
+
hoverSvg: value ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED_HOVERED,
|
|
65745
66052
|
priority: 2,
|
|
65746
66053
|
horizontalAlign: "center",
|
|
65747
66054
|
size: GRID_ICON_EDGE_LENGTH,
|
|
65748
66055
|
margin: GRID_ICON_MARGIN,
|
|
65749
|
-
component: DataValidationCheckbox,
|
|
65750
66056
|
position,
|
|
66057
|
+
type: "data_validation_checkbox",
|
|
66058
|
+
onClick: (position, env) => {
|
|
66059
|
+
const cell = env.model.getters.getCell(position);
|
|
66060
|
+
const isDisabled = env.model.getters.isReadonly() || !!cell?.isFormula;
|
|
66061
|
+
if (isDisabled) {
|
|
66062
|
+
return;
|
|
66063
|
+
}
|
|
66064
|
+
const cellContent = value ? "FALSE" : "TRUE";
|
|
66065
|
+
env.model.dispatch("UPDATE_CELL", { ...position, content: cellContent });
|
|
66066
|
+
},
|
|
65751
66067
|
};
|
|
65752
66068
|
}
|
|
65753
66069
|
return undefined;
|
|
@@ -65756,13 +66072,19 @@ iconsOnCellRegistry.add("data_validation_list_icon", (getters, position) => {
|
|
|
65756
66072
|
const hasIcon = !getters.isReadonly() && getters.cellHasListDataValidationIcon(position);
|
|
65757
66073
|
if (hasIcon) {
|
|
65758
66074
|
return {
|
|
65759
|
-
svg:
|
|
66075
|
+
svg: CARET_DOWN,
|
|
66076
|
+
hoverSvg: HOVERED_CARET_DOWN,
|
|
65760
66077
|
priority: 2,
|
|
65761
66078
|
horizontalAlign: "right",
|
|
65762
66079
|
size: GRID_ICON_EDGE_LENGTH,
|
|
65763
66080
|
margin: GRID_ICON_MARGIN,
|
|
65764
|
-
component: DataValidationListIcon,
|
|
65765
66081
|
position,
|
|
66082
|
+
onClick: (position, env) => {
|
|
66083
|
+
const { col, row } = position;
|
|
66084
|
+
env.model.selection.selectCell(col, row);
|
|
66085
|
+
env.startCellEdition();
|
|
66086
|
+
},
|
|
66087
|
+
type: "data_validation_list_icon",
|
|
65766
66088
|
};
|
|
65767
66089
|
}
|
|
65768
66090
|
return undefined;
|
|
@@ -65770,14 +66092,30 @@ iconsOnCellRegistry.add("data_validation_list_icon", (getters, position) => {
|
|
|
65770
66092
|
iconsOnCellRegistry.add("filter_icon", (getters, position) => {
|
|
65771
66093
|
const hasIcon = getters.isFilterHeader(position);
|
|
65772
66094
|
if (hasIcon) {
|
|
66095
|
+
const isFilterActive = getters.isFilterActive(position);
|
|
66096
|
+
const cellStyle = getters.getCellComputedStyle(position);
|
|
66097
|
+
const isHighContrast = relativeLuminance(cellStyle.fillColor || "#fff") < 0.45;
|
|
65773
66098
|
return {
|
|
65774
|
-
|
|
66099
|
+
type: "filter_icon",
|
|
66100
|
+
svg: getDataFilterIcon(isFilterActive, isHighContrast, false),
|
|
66101
|
+
hoverSvg: getDataFilterIcon(isFilterActive, isHighContrast, true),
|
|
65775
66102
|
priority: 3,
|
|
65776
66103
|
horizontalAlign: "right",
|
|
65777
66104
|
size: GRID_ICON_EDGE_LENGTH,
|
|
65778
66105
|
margin: GRID_ICON_MARGIN,
|
|
65779
|
-
component: FilterIcon,
|
|
65780
66106
|
position,
|
|
66107
|
+
onClick: (position, env) => {
|
|
66108
|
+
const cellPopovers = env.getStore(CellPopoverStore);
|
|
66109
|
+
const activePopover = cellPopovers.persistentCellPopover;
|
|
66110
|
+
if (activePopover.isOpen &&
|
|
66111
|
+
activePopover.col === position.col &&
|
|
66112
|
+
activePopover.row === position.row &&
|
|
66113
|
+
activePopover.type === "FilterMenu") {
|
|
66114
|
+
cellPopovers.close();
|
|
66115
|
+
return;
|
|
66116
|
+
}
|
|
66117
|
+
cellPopovers.open(position, "FilterMenu");
|
|
66118
|
+
},
|
|
65781
66119
|
};
|
|
65782
66120
|
}
|
|
65783
66121
|
return undefined;
|
|
@@ -65787,6 +66125,7 @@ iconsOnCellRegistry.add("conditional_formatting", (getters, position) => {
|
|
|
65787
66125
|
if (icon) {
|
|
65788
66126
|
const style = getters.getCellStyle(position);
|
|
65789
66127
|
return {
|
|
66128
|
+
type: "conditional_formatting",
|
|
65790
66129
|
svg: ICONS[icon].svg,
|
|
65791
66130
|
priority: 1,
|
|
65792
66131
|
horizontalAlign: "left",
|
|
@@ -65807,23 +66146,55 @@ iconsOnCellRegistry.add("pivot_collapse", (getters, position) => {
|
|
|
65807
66146
|
const definition = getters.getPivotCoreDefinition(pivotId);
|
|
65808
66147
|
const isDashboard = getters.isDashboard();
|
|
65809
66148
|
const fields = pivotCell.dimension === "COL" ? definition.columns : definition.rows;
|
|
65810
|
-
const
|
|
66149
|
+
const hasIcon = !isDashboard && pivotCell.domain.length !== fields.length;
|
|
66150
|
+
const domains = definition.collapsedDomains?.[pivotCell.dimension] ?? [];
|
|
66151
|
+
const isCollapsed = domains.some((domain) => deepEquals(domain, pivotCell.domain));
|
|
66152
|
+
const indent = pivotCell.dimension === "ROW" ? (pivotCell.domain.length - 1) * PIVOT_INDENT : 0;
|
|
65811
66153
|
return {
|
|
66154
|
+
type: "pivot_collapse",
|
|
65812
66155
|
priority: 4,
|
|
65813
66156
|
horizontalAlign: "left",
|
|
65814
|
-
size:
|
|
65815
|
-
?
|
|
66157
|
+
size: hasIcon || (!isDashboard && pivotCell.dimension === "ROW" && definition.rows.length > 1)
|
|
66158
|
+
? PIVOT_COLLAPSE_ICON_SIZE
|
|
65816
66159
|
: 0,
|
|
65817
|
-
margin:
|
|
65818
|
-
|
|
66160
|
+
margin: hasIcon ? GRID_ICON_MARGIN * 2 + indent : indent,
|
|
66161
|
+
svg: hasIcon ? getPivotIconSvg(isCollapsed, false) : undefined,
|
|
66162
|
+
hoverSvg: hasIcon ? getPivotIconSvg(isCollapsed, true) : undefined,
|
|
65819
66163
|
position,
|
|
66164
|
+
onClick: togglePivotCollapse,
|
|
65820
66165
|
};
|
|
65821
66166
|
}
|
|
65822
66167
|
return undefined;
|
|
65823
66168
|
});
|
|
66169
|
+
function togglePivotCollapse(position, env) {
|
|
66170
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
66171
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
66172
|
+
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
66173
|
+
return;
|
|
66174
|
+
}
|
|
66175
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
66176
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
66177
|
+
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
66178
|
+
: [];
|
|
66179
|
+
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
66180
|
+
if (index !== -1) {
|
|
66181
|
+
collapsedDomains.splice(index, 1);
|
|
66182
|
+
}
|
|
66183
|
+
else {
|
|
66184
|
+
collapsedDomains.push(pivotCell.domain);
|
|
66185
|
+
}
|
|
66186
|
+
const newDomains = definition.collapsedDomains
|
|
66187
|
+
? { ...definition.collapsedDomains }
|
|
66188
|
+
: { COL: [], ROW: [] };
|
|
66189
|
+
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
66190
|
+
env.model.dispatch("UPDATE_PIVOT", {
|
|
66191
|
+
pivotId,
|
|
66192
|
+
pivot: { ...definition, collapsedDomains: newDomains },
|
|
66193
|
+
});
|
|
66194
|
+
}
|
|
65824
66195
|
|
|
65825
66196
|
class CellIconPlugin extends CoreViewPlugin {
|
|
65826
|
-
static getters = ["doesCellHaveGridIcon", "getCellIcons"];
|
|
66197
|
+
static getters = ["doesCellHaveGridIcon", "getCellIcons", "getCellIconRect"];
|
|
65827
66198
|
cellIconsCache = {};
|
|
65828
66199
|
handle(cmd) {
|
|
65829
66200
|
if (cmd.type !== "SET_VIEWPORT_OFFSET") {
|
|
@@ -65843,6 +66214,29 @@ class CellIconPlugin extends CoreViewPlugin {
|
|
|
65843
66214
|
}
|
|
65844
66215
|
return this.cellIconsCache[position.sheetId][position.col][position.row];
|
|
65845
66216
|
}
|
|
66217
|
+
getCellIconRect(icon) {
|
|
66218
|
+
const cellPosition = icon.position;
|
|
66219
|
+
const merge = this.getters.getMerge(cellPosition);
|
|
66220
|
+
const zone = merge || positionToZone(cellPosition);
|
|
66221
|
+
const cellRect = this.getters.getRect(zone);
|
|
66222
|
+
const cell = this.getters.getCell(cellPosition);
|
|
66223
|
+
const x = this.getIconHorizontalPosition(cellRect, icon.horizontalAlign, icon);
|
|
66224
|
+
const y = this.getters.computeTextYCoordinate(cellRect, icon.size, cell?.style?.verticalAlign);
|
|
66225
|
+
return { x: x, y: y, width: icon.size, height: icon.size };
|
|
66226
|
+
}
|
|
66227
|
+
getIconHorizontalPosition(rect, align, icon) {
|
|
66228
|
+
const start = rect.x;
|
|
66229
|
+
const end = rect.x + rect.width;
|
|
66230
|
+
switch (align) {
|
|
66231
|
+
case "right":
|
|
66232
|
+
return end - icon.margin - icon.size;
|
|
66233
|
+
case "left":
|
|
66234
|
+
return start + icon.margin;
|
|
66235
|
+
default:
|
|
66236
|
+
const centeringOffset = Math.floor((end - start - icon.size) / 2);
|
|
66237
|
+
return end - icon.size - centeringOffset;
|
|
66238
|
+
}
|
|
66239
|
+
}
|
|
65846
66240
|
computeCellIcons(position) {
|
|
65847
66241
|
const icons = { left: undefined, right: undefined, center: undefined };
|
|
65848
66242
|
const callbacks = iconsOnCellRegistry.getAll();
|
|
@@ -66947,10 +67341,15 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
66947
67341
|
const includeTotal = toScalar(args[2]);
|
|
66948
67342
|
const shouldIncludeTotal = includeTotal === undefined ? true : toBoolean(includeTotal);
|
|
66949
67343
|
const includeColumnHeaders = toScalar(args[3]);
|
|
67344
|
+
const includeMeasures = toScalar(args[5]);
|
|
67345
|
+
const shouldIncludeMeasures = includeMeasures === undefined ? true : toBoolean(includeMeasures);
|
|
66950
67346
|
const shouldIncludeColumnHeaders = includeColumnHeaders === undefined ? true : toBoolean(includeColumnHeaders);
|
|
66951
|
-
const
|
|
66952
|
-
|
|
66953
|
-
|
|
67347
|
+
const visibilityOptions = {
|
|
67348
|
+
displayColumnHeaders: shouldIncludeColumnHeaders,
|
|
67349
|
+
displayTotals: shouldIncludeTotal,
|
|
67350
|
+
displayMeasuresRow: shouldIncludeMeasures,
|
|
67351
|
+
};
|
|
67352
|
+
const pivotCells = pivot.getCollapsedTableStructure().getPivotCells(visibilityOptions);
|
|
66954
67353
|
const pivotCol = position.col - mainPosition.col;
|
|
66955
67354
|
const pivotRow = position.row - mainPosition.row;
|
|
66956
67355
|
return pivotCells[pivotCol][pivotRow];
|
|
@@ -69172,8 +69571,7 @@ class CollaborativePlugin extends UIPlugin {
|
|
|
69172
69571
|
"isFullySynchronized",
|
|
69173
69572
|
];
|
|
69174
69573
|
static layers = ["Selection"];
|
|
69175
|
-
|
|
69176
|
-
colors = {};
|
|
69574
|
+
colors = new AlternatingColorMap(12);
|
|
69177
69575
|
session;
|
|
69178
69576
|
constructor(config) {
|
|
69179
69577
|
super(config);
|
|
@@ -69191,7 +69589,7 @@ class CollaborativePlugin extends UIPlugin {
|
|
|
69191
69589
|
}
|
|
69192
69590
|
getConnectedClients() {
|
|
69193
69591
|
return [...this.session.getConnectedClients()].map((client) => {
|
|
69194
|
-
return { ...client, color: this.colors
|
|
69592
|
+
return { ...client, color: this.colors.get(client.id) };
|
|
69195
69593
|
});
|
|
69196
69594
|
}
|
|
69197
69595
|
isFullySynchronized() {
|
|
@@ -69220,10 +69618,7 @@ class CollaborativePlugin extends UIPlugin {
|
|
|
69220
69618
|
client.position &&
|
|
69221
69619
|
client.position.sheetId === sheetId &&
|
|
69222
69620
|
this.isPositionValid(client.position)) {
|
|
69223
|
-
|
|
69224
|
-
this.colors[client.id] = this.availableColors.next();
|
|
69225
|
-
}
|
|
69226
|
-
clients.push({ ...client, color: this.colors[client.id], position: client.position });
|
|
69621
|
+
clients.push({ ...client, position: client.position });
|
|
69227
69622
|
}
|
|
69228
69623
|
}
|
|
69229
69624
|
return clients;
|
|
@@ -70069,6 +70464,7 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
70069
70464
|
"getCellText",
|
|
70070
70465
|
"getCellMultiLineText",
|
|
70071
70466
|
"getContiguousZone",
|
|
70467
|
+
"computeTextYCoordinate",
|
|
70072
70468
|
];
|
|
70073
70469
|
ctx = document.createElement("canvas").getContext("2d");
|
|
70074
70470
|
// ---------------------------------------------------------------------------
|
|
@@ -70171,6 +70567,25 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
70171
70567
|
});
|
|
70172
70568
|
return splitTextToWidth(this.ctx, text, style, args.wrapText ? args.maxWidth : undefined);
|
|
70173
70569
|
}
|
|
70570
|
+
/** Computes the vertical start point from which a text line should be draw in a cell.
|
|
70571
|
+
*
|
|
70572
|
+
* Note that in case the cell does not have enough spaces to display its text lines,
|
|
70573
|
+
* (wrapping cell case) then the vertical align should be at the top.
|
|
70574
|
+
* */
|
|
70575
|
+
computeTextYCoordinate(cellRect, textLineHeight, verticalAlign = DEFAULT_VERTICAL_ALIGN, numberOfLines = 1) {
|
|
70576
|
+
const y = cellRect.y + 1; // +1 to skip the cell grid line at the top
|
|
70577
|
+
const textHeight = computeTextLinesHeight(textLineHeight, numberOfLines);
|
|
70578
|
+
const hasEnoughSpaces = cellRect.height > textHeight + MIN_CELL_TEXT_MARGIN * 2;
|
|
70579
|
+
if (hasEnoughSpaces) {
|
|
70580
|
+
if (verticalAlign === "middle") {
|
|
70581
|
+
return Math.ceil(y + (cellRect.height - textHeight) / 2);
|
|
70582
|
+
}
|
|
70583
|
+
if (verticalAlign === "bottom") {
|
|
70584
|
+
return y + cellRect.height - textHeight - MIN_CELL_TEXT_MARGIN;
|
|
70585
|
+
}
|
|
70586
|
+
}
|
|
70587
|
+
return y + MIN_CELL_TEXT_MARGIN;
|
|
70588
|
+
}
|
|
70174
70589
|
/**
|
|
70175
70590
|
* Expands the given zone until bordered by empty cells or reached the sheet boundaries.
|
|
70176
70591
|
*/
|
|
@@ -72077,9 +72492,10 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
72077
72492
|
const filteredValues = filterValue.hiddenValues?.map(toLowerCase);
|
|
72078
72493
|
if (!filteredValues)
|
|
72079
72494
|
continue;
|
|
72495
|
+
const filteredValuesSet = new Set(filteredValues);
|
|
72080
72496
|
for (let row = filteredZone.top; row <= filteredZone.bottom; row++) {
|
|
72081
72497
|
const value = this.getCellValueAsString(sheetId, filter.col, row);
|
|
72082
|
-
if (
|
|
72498
|
+
if (filteredValuesSet.has(value)) {
|
|
72083
72499
|
hiddenRows.add(row);
|
|
72084
72500
|
}
|
|
72085
72501
|
}
|
|
@@ -72196,6 +72612,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72196
72612
|
"getElementsFromSelection",
|
|
72197
72613
|
"tryGetActiveSheetId",
|
|
72198
72614
|
"isGridSelectionActive",
|
|
72615
|
+
"getSelectecUnboundedZone",
|
|
72199
72616
|
];
|
|
72200
72617
|
gridSelection = {
|
|
72201
72618
|
anchor: {
|
|
@@ -72207,12 +72624,14 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72207
72624
|
selectedFigureId = null;
|
|
72208
72625
|
sheetsData = {};
|
|
72209
72626
|
moveClient;
|
|
72627
|
+
isUnbounded;
|
|
72210
72628
|
// This flag is used to avoid to historize the ACTIVE_SHEET command when it's
|
|
72211
72629
|
// the main command.
|
|
72212
72630
|
activeSheet = null;
|
|
72213
72631
|
constructor(config) {
|
|
72214
72632
|
super(config);
|
|
72215
72633
|
this.moveClient = config.moveClient;
|
|
72634
|
+
this.isUnbounded = false;
|
|
72216
72635
|
}
|
|
72217
72636
|
// ---------------------------------------------------------------------------
|
|
72218
72637
|
// Command Handling
|
|
@@ -72238,6 +72657,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72238
72657
|
handleEvent(event) {
|
|
72239
72658
|
const anchor = event.anchor;
|
|
72240
72659
|
let zones = [];
|
|
72660
|
+
this.isUnbounded = event.options?.unbounded || false;
|
|
72241
72661
|
switch (event.mode) {
|
|
72242
72662
|
case "overrideSelection":
|
|
72243
72663
|
zones = [anchor.zone];
|
|
@@ -72427,6 +72847,12 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72427
72847
|
getSelectedZone() {
|
|
72428
72848
|
return deepCopy(this.gridSelection.anchor.zone);
|
|
72429
72849
|
}
|
|
72850
|
+
getSelectecUnboundedZone() {
|
|
72851
|
+
const zone = this.isUnbounded
|
|
72852
|
+
? this.getters.getUnboundedZone(this.activeSheet.id, this.gridSelection.anchor.zone)
|
|
72853
|
+
: this.gridSelection.anchor.zone;
|
|
72854
|
+
return deepCopy(zone);
|
|
72855
|
+
}
|
|
72430
72856
|
getSelection() {
|
|
72431
72857
|
return deepCopy(this.gridSelection);
|
|
72432
72858
|
}
|
|
@@ -72620,11 +73046,6 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72620
73046
|
},
|
|
72621
73047
|
];
|
|
72622
73048
|
const sheetId = this.getActiveSheetId();
|
|
72623
|
-
const handler = new CellClipboardHandler(this.getters, this.dispatch);
|
|
72624
|
-
const data = handler.copy(getClipboardDataPositions(sheetId, target));
|
|
72625
|
-
if (!data) {
|
|
72626
|
-
return;
|
|
72627
|
-
}
|
|
72628
73049
|
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
72629
73050
|
const pasteTarget = [
|
|
72630
73051
|
{
|
|
@@ -72634,7 +73055,14 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72634
73055
|
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
72635
73056
|
},
|
|
72636
73057
|
];
|
|
72637
|
-
|
|
73058
|
+
for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
|
|
73059
|
+
const handler = new Handler(this.getters, this.dispatch);
|
|
73060
|
+
const data = handler.copy(getClipboardDataPositions(sheetId, target));
|
|
73061
|
+
if (!data) {
|
|
73062
|
+
continue;
|
|
73063
|
+
}
|
|
73064
|
+
handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
|
|
73065
|
+
}
|
|
72638
73066
|
const selection = pasteTarget[0];
|
|
72639
73067
|
const col = selection.left;
|
|
72640
73068
|
const row = selection.top;
|
|
@@ -73180,6 +73608,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
73180
73608
|
"getRect",
|
|
73181
73609
|
"getFigureUI",
|
|
73182
73610
|
"getPositionAnchorOffset",
|
|
73611
|
+
"getGridOffset",
|
|
73183
73612
|
];
|
|
73184
73613
|
viewports = {};
|
|
73185
73614
|
/**
|
|
@@ -73369,6 +73798,9 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
73369
73798
|
height: this.sheetViewHeight,
|
|
73370
73799
|
};
|
|
73371
73800
|
}
|
|
73801
|
+
getGridOffset() {
|
|
73802
|
+
return { x: this.gridOffsetX, y: this.gridOffsetY };
|
|
73803
|
+
}
|
|
73372
73804
|
/** type as pane, not viewport but basically pane extends viewport */
|
|
73373
73805
|
getActiveMainViewport() {
|
|
73374
73806
|
const sheetId = this.getters.getActiveSheetId();
|
|
@@ -74745,8 +75177,9 @@ topbarMenuRegistry
|
|
|
74745
75177
|
})
|
|
74746
75178
|
.addChild("settings", ["file"], {
|
|
74747
75179
|
name: _t("Settings"),
|
|
74748
|
-
sequence:
|
|
75180
|
+
sequence: 200,
|
|
74749
75181
|
execute: (env) => env.openSidePanel("Settings"),
|
|
75182
|
+
isEnabled: (env) => !env.isSmall,
|
|
74750
75183
|
icon: "o-spreadsheet-Icon.COG",
|
|
74751
75184
|
})
|
|
74752
75185
|
// ---------------------------------------------------------------------
|
|
@@ -75164,6 +75597,7 @@ topbarMenuRegistry
|
|
|
75164
75597
|
execute: (env) => {
|
|
75165
75598
|
env.openSidePanel("DataValidation");
|
|
75166
75599
|
},
|
|
75600
|
+
isEnabled: (env) => !env.isSmall,
|
|
75167
75601
|
icon: "o-spreadsheet-Icon.DATA_VALIDATION",
|
|
75168
75602
|
sequence: 30,
|
|
75169
75603
|
separator: true,
|
|
@@ -75187,6 +75621,7 @@ topbarMenuRegistry
|
|
|
75187
75621
|
sequence: sequence + index,
|
|
75188
75622
|
isReadonlyAllowed: true,
|
|
75189
75623
|
execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
|
|
75624
|
+
isEnabled: (env) => !env.isSmall,
|
|
75190
75625
|
onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
|
|
75191
75626
|
onStopHover: (env) => env.getStore(HighlightStore).unRegister(highlightProvider),
|
|
75192
75627
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
@@ -75458,7 +75893,7 @@ css /* scss */ `
|
|
|
75458
75893
|
.o-sheet {
|
|
75459
75894
|
padding: 0 15px;
|
|
75460
75895
|
padding-right: 10px;
|
|
75461
|
-
height: ${
|
|
75896
|
+
height: ${DESKTOP_BOTTOMBAR_HEIGHT}px;
|
|
75462
75897
|
border-left: 1px solid #c1c1c1;
|
|
75463
75898
|
border-right: 1px solid #c1c1c1;
|
|
75464
75899
|
margin-left: -1px;
|
|
@@ -75502,6 +75937,10 @@ css /* scss */ `
|
|
|
75502
75937
|
width: calc(100% - 1px);
|
|
75503
75938
|
}
|
|
75504
75939
|
}
|
|
75940
|
+
|
|
75941
|
+
.o-spreadshet-mobile .o-sheet {
|
|
75942
|
+
height: ${MOBILE_BOTTOMBAR_HEIGHT}px;
|
|
75943
|
+
}
|
|
75505
75944
|
`;
|
|
75506
75945
|
class BottomBarSheet extends owl.Component {
|
|
75507
75946
|
static template = "o-spreadsheet-BottomBarSheet";
|
|
@@ -75556,7 +75995,16 @@ class BottomBarSheet extends owl.Component {
|
|
|
75556
75995
|
this.stopEdition();
|
|
75557
75996
|
}
|
|
75558
75997
|
}
|
|
75998
|
+
onClick() {
|
|
75999
|
+
if (!this.env.isMobile()) {
|
|
76000
|
+
return;
|
|
76001
|
+
}
|
|
76002
|
+
this.activateSheet();
|
|
76003
|
+
}
|
|
75559
76004
|
onMouseDown(ev) {
|
|
76005
|
+
if (this.env.isMobile()) {
|
|
76006
|
+
return;
|
|
76007
|
+
}
|
|
75560
76008
|
this.activateSheet();
|
|
75561
76009
|
this.props.onMouseDown(ev);
|
|
75562
76010
|
}
|
|
@@ -75900,8 +76348,8 @@ css /* scss */ `
|
|
|
75900
76348
|
}
|
|
75901
76349
|
}
|
|
75902
76350
|
|
|
75903
|
-
.mobile.o-spreadsheet-bottom-bar {
|
|
75904
|
-
padding-left:
|
|
76351
|
+
.o-spreadsheet-mobile .o-spreadsheet-bottom-bar {
|
|
76352
|
+
padding-left: 0;
|
|
75905
76353
|
|
|
75906
76354
|
.add-sheet-container {
|
|
75907
76355
|
order: 2;
|
|
@@ -75918,10 +76366,8 @@ css /* scss */ `
|
|
|
75918
76366
|
`;
|
|
75919
76367
|
class BottomBar extends owl.Component {
|
|
75920
76368
|
static template = "o-spreadsheet-BottomBar";
|
|
75921
|
-
static props = {
|
|
75922
|
-
|
|
75923
|
-
};
|
|
75924
|
-
static components = { Menu, Ripple, BottomBarSheet, BottomBarStatistic };
|
|
76369
|
+
static props = { onClick: Function };
|
|
76370
|
+
static components = { MenuPopover, Ripple, BottomBarSheet, BottomBarStatistic };
|
|
75925
76371
|
bottomBarRef = owl.useRef("bottomBar");
|
|
75926
76372
|
sheetListRef = owl.useRef("sheetList");
|
|
75927
76373
|
dragAndDrop = useDragAndDropListItems();
|
|
@@ -76058,6 +76504,9 @@ class BottomBar extends owl.Component {
|
|
|
76058
76504
|
if (event.button !== 0 || this.env.model.getters.isReadonly())
|
|
76059
76505
|
return;
|
|
76060
76506
|
this.closeMenu();
|
|
76507
|
+
if (this.env.isMobile()) {
|
|
76508
|
+
return;
|
|
76509
|
+
}
|
|
76061
76510
|
const visibleSheets = this.getVisibleSheets();
|
|
76062
76511
|
const sheetRects = this.getSheetItemRects();
|
|
76063
76512
|
const sheets = visibleSheets.map((sheet, index) => ({
|
|
@@ -76177,7 +76626,7 @@ css /* scss */ `
|
|
|
76177
76626
|
`;
|
|
76178
76627
|
class SpreadsheetDashboard extends owl.Component {
|
|
76179
76628
|
static template = "o-spreadsheet-SpreadsheetDashboard";
|
|
76180
|
-
static props = {};
|
|
76629
|
+
static props = { getGridSize: Function };
|
|
76181
76630
|
static components = {
|
|
76182
76631
|
GridOverlay,
|
|
76183
76632
|
GridPopover,
|
|
@@ -76464,7 +76913,7 @@ class HeaderGroupContainer extends owl.Component {
|
|
|
76464
76913
|
dimension: String,
|
|
76465
76914
|
layers: Array,
|
|
76466
76915
|
};
|
|
76467
|
-
static components = { RowGroup, ColGroup,
|
|
76916
|
+
static components = { RowGroup, ColGroup, MenuPopover };
|
|
76468
76917
|
menu = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
76469
76918
|
getLayerOffset(layerIndex) {
|
|
76470
76919
|
return layerIndex * GROUP_LAYER_WIDTH;
|
|
@@ -76680,6 +77129,158 @@ class SidePanel extends owl.Component {
|
|
|
76680
77129
|
}
|
|
76681
77130
|
}
|
|
76682
77131
|
|
|
77132
|
+
class RibbonMenu extends owl.Component {
|
|
77133
|
+
static template = "o-spreadsheet-RibbonMenu";
|
|
77134
|
+
static props = {
|
|
77135
|
+
onClose: Function,
|
|
77136
|
+
};
|
|
77137
|
+
static components = { Menu };
|
|
77138
|
+
rootItems = topbarMenuRegistry.getMenuItems();
|
|
77139
|
+
menuRef = owl.useRef("menu");
|
|
77140
|
+
state = owl.useState({
|
|
77141
|
+
menuItems: this.rootItems,
|
|
77142
|
+
title: _t("Menu Bar"),
|
|
77143
|
+
parentState: undefined,
|
|
77144
|
+
});
|
|
77145
|
+
setup() {
|
|
77146
|
+
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
77147
|
+
}
|
|
77148
|
+
onExternalClick(ev) {
|
|
77149
|
+
if (!this.menuRef.el?.contains(ev.target)) {
|
|
77150
|
+
this.props.onClose();
|
|
77151
|
+
}
|
|
77152
|
+
}
|
|
77153
|
+
onClickMenu(menu) {
|
|
77154
|
+
const children = menu.children(this.env);
|
|
77155
|
+
if (children.length) {
|
|
77156
|
+
this.state.parentState = { ...this.state };
|
|
77157
|
+
this.state.menuItems = children;
|
|
77158
|
+
this.state.title = menu.name(this.env);
|
|
77159
|
+
}
|
|
77160
|
+
else {
|
|
77161
|
+
this.state.menuItems = this.rootItems;
|
|
77162
|
+
this.state.title = undefined;
|
|
77163
|
+
this.state.parentState = undefined;
|
|
77164
|
+
menu.execute?.(this.env);
|
|
77165
|
+
this.props.onClose();
|
|
77166
|
+
}
|
|
77167
|
+
}
|
|
77168
|
+
get menuProps() {
|
|
77169
|
+
return {
|
|
77170
|
+
menuItems: this.state.menuItems,
|
|
77171
|
+
onClose: this.props.onClose,
|
|
77172
|
+
onClickMenu: this.onClickMenu.bind(this),
|
|
77173
|
+
};
|
|
77174
|
+
}
|
|
77175
|
+
get style() {
|
|
77176
|
+
return cssPropertiesToCss({
|
|
77177
|
+
height: `${this.props.height}px`,
|
|
77178
|
+
});
|
|
77179
|
+
}
|
|
77180
|
+
onClickBack() {
|
|
77181
|
+
if (!this.state.parentState) {
|
|
77182
|
+
this.props.onClose();
|
|
77183
|
+
return;
|
|
77184
|
+
}
|
|
77185
|
+
this.state.menuItems = this.state.parentState.menuItems;
|
|
77186
|
+
this.state.title = this.state.parentState.title;
|
|
77187
|
+
this.state.parentState = this.state.parentState.parentState;
|
|
77188
|
+
}
|
|
77189
|
+
get backTitle() {
|
|
77190
|
+
return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
|
|
77191
|
+
}
|
|
77192
|
+
}
|
|
77193
|
+
|
|
77194
|
+
css `
|
|
77195
|
+
.o-small-composer {
|
|
77196
|
+
z-index: ${ComponentsImportance.TopBarComposer};
|
|
77197
|
+
}
|
|
77198
|
+
`;
|
|
77199
|
+
class SmallBottomBar extends owl.Component {
|
|
77200
|
+
static components = { Composer, BottomBar, Ripple, RibbonMenu };
|
|
77201
|
+
static template = "o-spreadsheet-SmallBottomBar";
|
|
77202
|
+
static props = {
|
|
77203
|
+
onClick: Function,
|
|
77204
|
+
};
|
|
77205
|
+
composerFocusStore;
|
|
77206
|
+
composerStore;
|
|
77207
|
+
composerInterface;
|
|
77208
|
+
composerRef = owl.useRef("bottombarComposer");
|
|
77209
|
+
menuState = owl.useState({
|
|
77210
|
+
isOpen: false,
|
|
77211
|
+
});
|
|
77212
|
+
setup() {
|
|
77213
|
+
this.composerFocusStore = useStore(ComposerFocusStore);
|
|
77214
|
+
const composerStore = useStore(CellComposerStore);
|
|
77215
|
+
this.composerStore = composerStore;
|
|
77216
|
+
this.composerInterface = {
|
|
77217
|
+
id: "bottombarComposer",
|
|
77218
|
+
get editionMode() {
|
|
77219
|
+
return composerStore.editionMode;
|
|
77220
|
+
},
|
|
77221
|
+
startEdition: this.composerStore.startEdition,
|
|
77222
|
+
setCurrentContent: this.composerStore.setCurrentContent,
|
|
77223
|
+
stopEdition: this.composerStore.stopEdition,
|
|
77224
|
+
};
|
|
77225
|
+
owl.useEffect(() => {
|
|
77226
|
+
if (
|
|
77227
|
+
// we hide the grid composer on mobile so we need to autofocus this composer
|
|
77228
|
+
this.env.isMobile() &&
|
|
77229
|
+
!this.menuState.isOpen &&
|
|
77230
|
+
this.composerStore.editionMode !== "inactive" &&
|
|
77231
|
+
this.composerFocusStore.activeComposer !== this.composerInterface) {
|
|
77232
|
+
this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
77233
|
+
focusMode: "contentFocus",
|
|
77234
|
+
});
|
|
77235
|
+
}
|
|
77236
|
+
});
|
|
77237
|
+
}
|
|
77238
|
+
get focus() {
|
|
77239
|
+
return this.composerFocusStore.activeComposer === this.composerInterface
|
|
77240
|
+
? this.composerFocusStore.focusMode
|
|
77241
|
+
: "inactive";
|
|
77242
|
+
}
|
|
77243
|
+
get rect() {
|
|
77244
|
+
return this.composerRef.el
|
|
77245
|
+
? getBoundingRectAsPOJO(this.composerRef.el)
|
|
77246
|
+
: { x: 0, y: 0, width: 0, height: 0 };
|
|
77247
|
+
}
|
|
77248
|
+
get composerProps() {
|
|
77249
|
+
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
77250
|
+
return {
|
|
77251
|
+
rect: { ...this.rect },
|
|
77252
|
+
delimitation: {
|
|
77253
|
+
width,
|
|
77254
|
+
height,
|
|
77255
|
+
},
|
|
77256
|
+
focus: this.focus,
|
|
77257
|
+
composerStore: this.composerStore,
|
|
77258
|
+
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
77259
|
+
focusMode: "contentFocus",
|
|
77260
|
+
}),
|
|
77261
|
+
isDefaultFocus: false,
|
|
77262
|
+
inputStyle: cssPropertiesToCss({
|
|
77263
|
+
height: this.focus === "inactive" ? "26px" : "fit-content",
|
|
77264
|
+
"max-height": `130px`,
|
|
77265
|
+
}),
|
|
77266
|
+
showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
|
|
77267
|
+
};
|
|
77268
|
+
}
|
|
77269
|
+
get symbols() {
|
|
77270
|
+
return ["=", "(", ")", ":", "-", "/", "*", ",", "+", "$", "."];
|
|
77271
|
+
}
|
|
77272
|
+
insertSymbol(symbol) {
|
|
77273
|
+
this.composerStore.replaceComposerCursorSelection(symbol);
|
|
77274
|
+
this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
77275
|
+
focusMode: "contentFocus",
|
|
77276
|
+
});
|
|
77277
|
+
}
|
|
77278
|
+
toggleRibbon() {
|
|
77279
|
+
this.composerStore.cancelEdition();
|
|
77280
|
+
this.menuState.isOpen = !this.menuState.isOpen;
|
|
77281
|
+
}
|
|
77282
|
+
}
|
|
77283
|
+
|
|
76683
77284
|
const COMPOSER_MAX_HEIGHT = 100;
|
|
76684
77285
|
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
76685
77286
|
const FX_SVG = /*xml*/ `
|
|
@@ -76689,7 +77290,7 @@ const FX_SVG = /*xml*/ `
|
|
|
76689
77290
|
`;
|
|
76690
77291
|
css /* scss */ `
|
|
76691
77292
|
.o-topbar-composer-container {
|
|
76692
|
-
height: ${
|
|
77293
|
+
height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
76693
77294
|
}
|
|
76694
77295
|
|
|
76695
77296
|
.o-topbar-composer {
|
|
@@ -76744,7 +77345,7 @@ class TopBarComposer extends owl.Component {
|
|
|
76744
77345
|
"max-height": `${COMPOSER_MAX_HEIGHT}px`,
|
|
76745
77346
|
"line-height": "24px",
|
|
76746
77347
|
};
|
|
76747
|
-
style.height = this.focus === "inactive" ? `${
|
|
77348
|
+
style.height = this.focus === "inactive" ? `${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px` : "fit-content";
|
|
76748
77349
|
return cssPropertiesToCss(style);
|
|
76749
77350
|
}
|
|
76750
77351
|
get containerStyle() {
|
|
@@ -77247,7 +77848,7 @@ class TopBarFontSizeEditor extends owl.Component {
|
|
|
77247
77848
|
|
|
77248
77849
|
class NumberFormatsTool extends owl.Component {
|
|
77249
77850
|
static template = "o-spreadsheet-NumberFormatsTool";
|
|
77250
|
-
static components = {
|
|
77851
|
+
static components = { MenuPopover, ActionButton };
|
|
77251
77852
|
static props = { class: String };
|
|
77252
77853
|
formatNumberMenuItemSpec = formatNumberMenuItemSpec;
|
|
77253
77854
|
topBarToolStore;
|
|
@@ -77297,7 +77898,7 @@ topBarToolBarRegistry
|
|
|
77297
77898
|
.addChild("edit", {
|
|
77298
77899
|
component: PaintFormatButton,
|
|
77299
77900
|
props: {
|
|
77300
|
-
class: "o-hoverable-button o-toolbar-button",
|
|
77901
|
+
class: "o-hoverable-button o-toolbar-button o-mobile-disabled",
|
|
77301
77902
|
},
|
|
77302
77903
|
sequence: 3,
|
|
77303
77904
|
})
|
|
@@ -77456,7 +78057,7 @@ topBarToolBarRegistry
|
|
|
77456
78057
|
.add("misc")
|
|
77457
78058
|
.addChild("misc", {
|
|
77458
78059
|
component: TableDropdownButton,
|
|
77459
|
-
props: { class: "o-toolbar-button o-hoverable-button o-menu-item-button" },
|
|
78060
|
+
props: { class: "o-toolbar-button o-hoverable-button o-menu-item-button o-mobile-disabled" },
|
|
77460
78061
|
sequence: 1,
|
|
77461
78062
|
})
|
|
77462
78063
|
.addChild("misc", {
|
|
@@ -77476,6 +78077,7 @@ css /* scss */ `
|
|
|
77476
78077
|
border-right: 1px solid ${SEPARATOR_COLOR};
|
|
77477
78078
|
width: 0;
|
|
77478
78079
|
margin: 0 6px;
|
|
78080
|
+
height: 30px;
|
|
77479
78081
|
}
|
|
77480
78082
|
|
|
77481
78083
|
.o-toolbar-button {
|
|
@@ -77484,7 +78086,7 @@ css /* scss */ `
|
|
|
77484
78086
|
|
|
77485
78087
|
.o-spreadsheet-topbar {
|
|
77486
78088
|
line-height: 1.2;
|
|
77487
|
-
font-size:
|
|
78089
|
+
font-size: 14px;
|
|
77488
78090
|
font-weight: 500;
|
|
77489
78091
|
background-color: #fff;
|
|
77490
78092
|
|
|
@@ -77508,7 +78110,7 @@ css /* scss */ `
|
|
|
77508
78110
|
|
|
77509
78111
|
.irregularity-map {
|
|
77510
78112
|
border-top: 1px solid ${SEPARATOR_COLOR};
|
|
77511
|
-
height: ${
|
|
78113
|
+
height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
77512
78114
|
|
|
77513
78115
|
.alert-info {
|
|
77514
78116
|
border-left: 3px solid ${ALERT_INFO_BORDER};
|
|
@@ -77521,7 +78123,7 @@ css /* scss */ `
|
|
|
77521
78123
|
|
|
77522
78124
|
/* Toolbar */
|
|
77523
78125
|
.o-topbar-toolbar {
|
|
77524
|
-
height: ${
|
|
78126
|
+
height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
77525
78127
|
|
|
77526
78128
|
.o-readonly-toolbar {
|
|
77527
78129
|
background-color: ${BACKGROUND_HEADER_COLOR};
|
|
@@ -77535,6 +78137,24 @@ css /* scss */ `
|
|
|
77535
78137
|
}
|
|
77536
78138
|
}
|
|
77537
78139
|
}
|
|
78140
|
+
|
|
78141
|
+
.o-spreadsheet-mobile {
|
|
78142
|
+
.o-topbar-toolbar {
|
|
78143
|
+
height: ${MOBILE_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
78144
|
+
}
|
|
78145
|
+
.o-topbar-divider {
|
|
78146
|
+
border-width: 2px;
|
|
78147
|
+
border-radius: 4px;
|
|
78148
|
+
}
|
|
78149
|
+
|
|
78150
|
+
.o-toolbar-button {
|
|
78151
|
+
height: 35px;
|
|
78152
|
+
width: 31px;
|
|
78153
|
+
.o-toolbar-button.o-mobile-disabled * {
|
|
78154
|
+
color: ${DISABLED_TEXT_COLOR};
|
|
78155
|
+
cursor: not-allowed;
|
|
78156
|
+
}
|
|
78157
|
+
}
|
|
77538
78158
|
`;
|
|
77539
78159
|
class TopBar extends owl.Component {
|
|
77540
78160
|
static template = "o-spreadsheet-TopBar";
|
|
@@ -77543,7 +78163,7 @@ class TopBar extends owl.Component {
|
|
|
77543
78163
|
dropdownMaxHeight: Number,
|
|
77544
78164
|
};
|
|
77545
78165
|
static components = {
|
|
77546
|
-
|
|
78166
|
+
MenuPopover,
|
|
77547
78167
|
TopBarComposer,
|
|
77548
78168
|
Popover,
|
|
77549
78169
|
};
|
|
@@ -77623,7 +78243,7 @@ class TopBar extends owl.Component {
|
|
|
77623
78243
|
// TODO : manage click events better. We need this piece of code
|
|
77624
78244
|
// otherwise the event opening the menu would close it on the same frame.
|
|
77625
78245
|
// And we cannot stop the event propagation because it's used in an
|
|
77626
|
-
// external listener of the
|
|
78246
|
+
// external listener of the MenuPopover component to close the context menu when
|
|
77627
78247
|
// clicking on the top bar
|
|
77628
78248
|
if (this.openedEl === ev.target) {
|
|
77629
78249
|
return;
|
|
@@ -78049,6 +78669,11 @@ css /* scss */ `
|
|
|
78049
78669
|
color: ${TEXT_BODY};
|
|
78050
78670
|
}
|
|
78051
78671
|
}
|
|
78672
|
+
|
|
78673
|
+
.o-spreadsheet-topbar-wrapper,
|
|
78674
|
+
.o-spreadsheet-bottombar-wrapper {
|
|
78675
|
+
z-index: ${ComponentsImportance.ScrollBar + 1};
|
|
78676
|
+
}
|
|
78052
78677
|
`;
|
|
78053
78678
|
class Spreadsheet extends owl.Component {
|
|
78054
78679
|
static template = "o-spreadsheet-Spreadsheet";
|
|
@@ -78062,6 +78687,7 @@ class Spreadsheet extends owl.Component {
|
|
|
78062
78687
|
TopBar,
|
|
78063
78688
|
Grid,
|
|
78064
78689
|
BottomBar,
|
|
78690
|
+
SmallBottomBar,
|
|
78065
78691
|
SidePanel,
|
|
78066
78692
|
SpreadsheetDashboard,
|
|
78067
78693
|
HeaderGroupContainer,
|
|
@@ -78085,12 +78711,25 @@ class Spreadsheet extends owl.Component {
|
|
|
78085
78711
|
else {
|
|
78086
78712
|
properties["grid-template-rows"] = `min-content auto min-content`;
|
|
78087
78713
|
}
|
|
78088
|
-
|
|
78714
|
+
const columnWidth = this.sidePanel.isOpen ? `${this.sidePanel.panelSize}px` : "auto";
|
|
78715
|
+
properties["grid-template-columns"] = `auto ${columnWidth}`;
|
|
78089
78716
|
return cssPropertiesToCss(properties);
|
|
78090
78717
|
}
|
|
78091
78718
|
setup() {
|
|
78719
|
+
if (!("isSmall" in this.env)) {
|
|
78720
|
+
const screenSize = useScreenWidth();
|
|
78721
|
+
owl.useSubEnv({
|
|
78722
|
+
get isSmall() {
|
|
78723
|
+
return screenSize.isSmall;
|
|
78724
|
+
},
|
|
78725
|
+
});
|
|
78726
|
+
}
|
|
78092
78727
|
const stores = useStoreProvider();
|
|
78093
78728
|
stores.inject(ModelStore, this.model);
|
|
78729
|
+
const env = this.env;
|
|
78730
|
+
stores.get(ScreenWidthStore).setSmallThreshhold(() => {
|
|
78731
|
+
return env.isSmall;
|
|
78732
|
+
});
|
|
78094
78733
|
this.notificationStore = useStore(NotificationStore);
|
|
78095
78734
|
this.composerFocusStore = useStore(ComposerFocusStore);
|
|
78096
78735
|
this.sidePanel = useStore(SidePanelStore);
|
|
@@ -78108,15 +78747,8 @@ class Spreadsheet extends owl.Component {
|
|
|
78108
78747
|
notifyUser: (notification) => this.notificationStore.notifyUser(notification),
|
|
78109
78748
|
askConfirmation: (text, confirm, cancel) => this.notificationStore.askConfirmation(text, confirm, cancel),
|
|
78110
78749
|
raiseError: (text, cb) => this.notificationStore.raiseError(text, cb),
|
|
78750
|
+
isMobile: isMobileOS,
|
|
78111
78751
|
});
|
|
78112
|
-
if (!("isSmall" in this.env)) {
|
|
78113
|
-
const screenSize = useScreenWidth();
|
|
78114
|
-
owl.useSubEnv({
|
|
78115
|
-
get isSmall() {
|
|
78116
|
-
return screenSize.isSmall;
|
|
78117
|
-
},
|
|
78118
|
-
});
|
|
78119
|
-
}
|
|
78120
78752
|
this.notificationStore.updateNotificationCallbacks({ ...this.props });
|
|
78121
78753
|
owl.useEffect(() => {
|
|
78122
78754
|
/**
|
|
@@ -78222,6 +78854,24 @@ class Spreadsheet extends owl.Component {
|
|
|
78222
78854
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
78223
78855
|
return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
|
|
78224
78856
|
}
|
|
78857
|
+
getGridSize() {
|
|
78858
|
+
const topBarHeight = this.spreadsheetRef.el
|
|
78859
|
+
?.querySelector(".o-spreadsheet-topbar-wrapper")
|
|
78860
|
+
?.getBoundingClientRect().height || 0;
|
|
78861
|
+
const bottomBarHeight = this.spreadsheetRef.el
|
|
78862
|
+
?.querySelector(".o-spreadsheet-bottombar-wrapper")
|
|
78863
|
+
?.getBoundingClientRect().height || 0;
|
|
78864
|
+
const gridWidth = this.spreadsheetRef.el?.querySelector(".o-grid")?.getBoundingClientRect().width || 0;
|
|
78865
|
+
const gridHeight = (this.spreadsheetRef.el?.getBoundingClientRect().height || 0) -
|
|
78866
|
+
(this.spreadsheetRef.el?.querySelector(".o-column-groups")?.getBoundingClientRect().height ||
|
|
78867
|
+
0) -
|
|
78868
|
+
topBarHeight -
|
|
78869
|
+
bottomBarHeight;
|
|
78870
|
+
return {
|
|
78871
|
+
width: Math.max(gridWidth - SCROLLBAR_WIDTH, 0),
|
|
78872
|
+
height: Math.max(gridHeight - SCROLLBAR_WIDTH, 0),
|
|
78873
|
+
};
|
|
78874
|
+
}
|
|
78225
78875
|
}
|
|
78226
78876
|
|
|
78227
78877
|
function inverseCommand(cmd) {
|
|
@@ -82484,7 +83134,7 @@ const SPREADSHEET_DIMENSIONS = {
|
|
|
82484
83134
|
MIN_COL_WIDTH,
|
|
82485
83135
|
HEADER_HEIGHT,
|
|
82486
83136
|
HEADER_WIDTH,
|
|
82487
|
-
|
|
83137
|
+
DESKTOP_BOTTOMBAR_HEIGHT,
|
|
82488
83138
|
DEFAULT_CELL_WIDTH,
|
|
82489
83139
|
DEFAULT_CELL_HEIGHT,
|
|
82490
83140
|
SCROLLBAR_WIDTH,
|
|
@@ -82630,7 +83280,7 @@ const components = {
|
|
|
82630
83280
|
FunnelChartDesignPanel,
|
|
82631
83281
|
ChartTypePicker,
|
|
82632
83282
|
FigureComponent,
|
|
82633
|
-
|
|
83283
|
+
MenuPopover,
|
|
82634
83284
|
Popover,
|
|
82635
83285
|
SelectionInput,
|
|
82636
83286
|
ValidationMessages,
|
|
@@ -82695,6 +83345,7 @@ exports.AbstractCellClipboardHandler = AbstractCellClipboardHandler;
|
|
|
82695
83345
|
exports.AbstractChart = AbstractChart;
|
|
82696
83346
|
exports.AbstractFigureClipboardHandler = AbstractFigureClipboardHandler;
|
|
82697
83347
|
exports.CellErrorType = CellErrorType;
|
|
83348
|
+
exports.ClientDisconnectedError = ClientDisconnectedError;
|
|
82698
83349
|
exports.CorePlugin = CorePlugin;
|
|
82699
83350
|
exports.CoreViewPlugin = CoreViewPlugin;
|
|
82700
83351
|
exports.DispatchResult = DispatchResult;
|
|
@@ -82741,6 +83392,6 @@ exports.tokenColors = tokenColors;
|
|
|
82741
83392
|
exports.tokenize = tokenize;
|
|
82742
83393
|
|
|
82743
83394
|
|
|
82744
|
-
__info__.version = "18.4.0-alpha.
|
|
82745
|
-
__info__.date = "2025-
|
|
82746
|
-
__info__.hash = "
|
|
83395
|
+
__info__.version = "18.4.0-alpha.8";
|
|
83396
|
+
__info__.date = "2025-06-12T09:53:48.133Z";
|
|
83397
|
+
__info__.hash = "9b7a8d0";
|