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