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