@odoo/o-spreadsheet 18.4.0-alpha.6 → 18.4.0-alpha.7
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 +1163 -598
- package/dist/o-spreadsheet.d.ts +323 -161
- package/dist/o-spreadsheet.esm.js +1163 -598
- package/dist/o-spreadsheet.iife.js +1163 -598
- package/dist/o-spreadsheet.iife.min.js +482 -502
- package/dist/o_spreadsheet.xml +201 -153
- 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.7
|
|
6
|
+
* @date 2025-06-06T09:32:44.285Z
|
|
7
|
+
* @hash 2bfbe64
|
|
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';
|
|
@@ -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",
|
|
@@ -20556,7 +20560,7 @@ const TEXT = {
|
|
|
20556
20560
|
description: _t("Converts a number to text according to a specified format."),
|
|
20557
20561
|
args: [
|
|
20558
20562
|
arg("number (number)", _t("The number, date or time to format.")),
|
|
20559
|
-
arg("format (string)", _t(
|
|
20563
|
+
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
20564
|
],
|
|
20561
20565
|
compute: function (number, format) {
|
|
20562
20566
|
const _number = toNumber(number, this.locale);
|
|
@@ -21663,8 +21667,6 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
|
|
|
21663
21667
|
if (isNaN(value)) {
|
|
21664
21668
|
continue;
|
|
21665
21669
|
}
|
|
21666
|
-
const axisId = chart.config.type === "radar" ? dataset.rAxisID : dataset.yAxisID;
|
|
21667
|
-
const displayValue = options.callback(Number(value), axisId);
|
|
21668
21670
|
const point = dataset.data[i];
|
|
21669
21671
|
const xPosition = point.x;
|
|
21670
21672
|
let yPosition = 0;
|
|
@@ -21688,7 +21690,8 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
|
|
|
21688
21690
|
textsPositions[xPosition].push(yPosition);
|
|
21689
21691
|
ctx.fillStyle = point.options.backgroundColor;
|
|
21690
21692
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
21691
|
-
|
|
21693
|
+
const valueToDisplay = options.callback(Number(value), dataset, i);
|
|
21694
|
+
drawTextWithBackground(valueToDisplay, xPosition, yPosition, ctx);
|
|
21692
21695
|
}
|
|
21693
21696
|
}
|
|
21694
21697
|
}
|
|
@@ -21705,7 +21708,7 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
|
|
|
21705
21708
|
if (isNaN(value)) {
|
|
21706
21709
|
continue;
|
|
21707
21710
|
}
|
|
21708
|
-
const displayValue = options.callback(value, dataset
|
|
21711
|
+
const displayValue = options.callback(value, dataset, i);
|
|
21709
21712
|
const point = dataset.data[i];
|
|
21710
21713
|
const yPosition = point.y;
|
|
21711
21714
|
let xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
@@ -21743,7 +21746,7 @@ function drawPieChartValues(chart, options, ctx) {
|
|
|
21743
21746
|
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
21744
21747
|
ctx.fillStyle = chartFontColor(options.background);
|
|
21745
21748
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
21746
|
-
const displayValue = options.callback(value,
|
|
21749
|
+
const displayValue = options.callback(value, dataset, i);
|
|
21747
21750
|
drawTextWithBackground(displayValue, x, y, ctx);
|
|
21748
21751
|
}
|
|
21749
21752
|
}
|
|
@@ -23490,7 +23493,7 @@ function isMacOS() {
|
|
|
23490
23493
|
* On Mac, this is the "meta" or "command" key.
|
|
23491
23494
|
*/
|
|
23492
23495
|
function isCtrlKey(ev) {
|
|
23493
|
-
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
23496
|
+
return isMacOS() || isIOS() ? ev.metaKey : ev.ctrlKey;
|
|
23494
23497
|
}
|
|
23495
23498
|
/**
|
|
23496
23499
|
* @param {MouseEvent} ev - The mouse event.
|
|
@@ -23529,6 +23532,23 @@ function downloadFile(dataUrl, fileName) {
|
|
|
23529
23532
|
function isBrowserFirefox() {
|
|
23530
23533
|
return /Firefox/i.test(navigator.userAgent);
|
|
23531
23534
|
}
|
|
23535
|
+
// Mobile detection
|
|
23536
|
+
function maxTouchPoints() {
|
|
23537
|
+
return navigator.maxTouchPoints || 1;
|
|
23538
|
+
}
|
|
23539
|
+
function isAndroid() {
|
|
23540
|
+
return /Android/i.test(navigator.userAgent);
|
|
23541
|
+
}
|
|
23542
|
+
function isIOS() {
|
|
23543
|
+
return (/(iPad|iPhone|iPod)/i.test(navigator.userAgent) ||
|
|
23544
|
+
(navigator.platform === "MacIntel" && maxTouchPoints() > 1));
|
|
23545
|
+
}
|
|
23546
|
+
function isOtherMobileOS() {
|
|
23547
|
+
return /(webOS|BlackBerry|Windows Phone)/i.test(navigator.userAgent);
|
|
23548
|
+
}
|
|
23549
|
+
function isMobileOS() {
|
|
23550
|
+
return isAndroid() || isIOS() || isOtherMobileOS();
|
|
23551
|
+
}
|
|
23532
23552
|
|
|
23533
23553
|
/**
|
|
23534
23554
|
* Convert a JS color hexadecimal to an excel compatible color.
|
|
@@ -25049,14 +25069,14 @@ function getPieChartLegend(definition, args) {
|
|
|
25049
25069
|
...getLegendDisplayOptions(definition),
|
|
25050
25070
|
labels: {
|
|
25051
25071
|
usePointStyle: true,
|
|
25052
|
-
generateLabels: (c) => c.data.labels?.map((label, index) => ({
|
|
25072
|
+
generateLabels: (c) => (c.data.labels?.map((label, index) => ({
|
|
25053
25073
|
text: truncateLabel(String(label)),
|
|
25054
25074
|
strokeStyle: colors[index],
|
|
25055
25075
|
fillStyle: colors[index],
|
|
25056
25076
|
pointStyle: "rect",
|
|
25057
25077
|
lineWidth: 2,
|
|
25058
25078
|
fontColor,
|
|
25059
|
-
})) || [],
|
|
25079
|
+
})) || []).filter((label) => label.text),
|
|
25060
25080
|
filter: (legendItem, data) => {
|
|
25061
25081
|
return "datasetIndex" in legendItem
|
|
25062
25082
|
? !data.datasets[legendItem.datasetIndex].hidden
|
|
@@ -25216,7 +25236,8 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
|
|
|
25216
25236
|
labels: {
|
|
25217
25237
|
color: fontColor,
|
|
25218
25238
|
usePointStyle: true,
|
|
25219
|
-
generateLabels: (chart) => chart.data.datasets
|
|
25239
|
+
generateLabels: (chart) => chart.data.datasets
|
|
25240
|
+
.map((dataset, index) => {
|
|
25220
25241
|
if (isTrendLineAxis(dataset["xAxisID"])) {
|
|
25221
25242
|
return {
|
|
25222
25243
|
text: truncateLabel(dataset.label),
|
|
@@ -25238,7 +25259,8 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
|
|
|
25238
25259
|
datasetIndex: index,
|
|
25239
25260
|
...legendLabelConfig,
|
|
25240
25261
|
};
|
|
25241
|
-
})
|
|
25262
|
+
})
|
|
25263
|
+
.filter((label) => label.text),
|
|
25242
25264
|
filter: (legendItem, data) => {
|
|
25243
25265
|
return "datasetIndex" in legendItem
|
|
25244
25266
|
? !data.datasets[legendItem.datasetIndex].hidden
|
|
@@ -25592,7 +25614,10 @@ function getChartShowValues(definition, args) {
|
|
|
25592
25614
|
horizontal: "horizontal" in definition && definition.horizontal,
|
|
25593
25615
|
showValues: "showValues" in definition ? !!definition.showValues : false,
|
|
25594
25616
|
background: definition.background,
|
|
25595
|
-
callback:
|
|
25617
|
+
callback: (value, dataset) => {
|
|
25618
|
+
const axisId = getDatasetAxisId(definition, dataset);
|
|
25619
|
+
return formatChartDatasetValue(axisFormats, locale)(value, axisId);
|
|
25620
|
+
},
|
|
25596
25621
|
};
|
|
25597
25622
|
}
|
|
25598
25623
|
function getSunburstShowValues(definition, args) {
|
|
@@ -25610,6 +25635,45 @@ function getSunburstShowValues(definition, args) {
|
|
|
25610
25635
|
},
|
|
25611
25636
|
};
|
|
25612
25637
|
}
|
|
25638
|
+
function getPyramidChartShowValues(definition, args) {
|
|
25639
|
+
const { axisFormats, locale } = args;
|
|
25640
|
+
return {
|
|
25641
|
+
horizontal: true,
|
|
25642
|
+
showValues: "showValues" in definition ? !!definition.showValues : false,
|
|
25643
|
+
background: definition.background,
|
|
25644
|
+
callback: (value, dataset) => {
|
|
25645
|
+
value = Math.abs(Number(value));
|
|
25646
|
+
return formatChartDatasetValue(axisFormats, locale)(value, dataset.xAxisID || "x");
|
|
25647
|
+
},
|
|
25648
|
+
};
|
|
25649
|
+
}
|
|
25650
|
+
function getWaterfallChartShowValues(definition, args) {
|
|
25651
|
+
const { axisFormats, locale, dataSetsValues } = args;
|
|
25652
|
+
const subtotalIndexes = dataSetsValues.reduce((subtotalIndexes, ds) => {
|
|
25653
|
+
subtotalIndexes.push((subtotalIndexes.at(-1) || -1) + ds.data.length + 1);
|
|
25654
|
+
return subtotalIndexes;
|
|
25655
|
+
}, []);
|
|
25656
|
+
return {
|
|
25657
|
+
showValues: "showValues" in definition ? !!definition.showValues : false,
|
|
25658
|
+
background: definition.background,
|
|
25659
|
+
callback: (value, dataset, index) => {
|
|
25660
|
+
const raw = dataset._dataset.data[index];
|
|
25661
|
+
const delta = raw[1] - raw[0];
|
|
25662
|
+
let sign = delta >= 0 ? "+" : "";
|
|
25663
|
+
if (definition.showSubTotals && subtotalIndexes.includes(index) && sign === "+") {
|
|
25664
|
+
sign = "";
|
|
25665
|
+
}
|
|
25666
|
+
return `${sign}${formatChartDatasetValue(axisFormats, locale)(delta, dataset.yAxisID)}`;
|
|
25667
|
+
},
|
|
25668
|
+
};
|
|
25669
|
+
}
|
|
25670
|
+
function getDatasetAxisId(definition, dataset) {
|
|
25671
|
+
if (dataset.rAxisID) {
|
|
25672
|
+
return dataset.rAxisID;
|
|
25673
|
+
}
|
|
25674
|
+
const axisId = "horizontal" in definition && definition.horizontal ? dataset.xAxisID : dataset.yAxisID;
|
|
25675
|
+
return axisId || "y";
|
|
25676
|
+
}
|
|
25613
25677
|
|
|
25614
25678
|
function getChartTitle(definition) {
|
|
25615
25679
|
const chartTitle = definition.title;
|
|
@@ -26012,6 +26076,7 @@ var CHART_RUNTIME_HELPERS = /*#__PURE__*/Object.freeze({
|
|
|
26012
26076
|
getPieChartTooltip: getPieChartTooltip,
|
|
26013
26077
|
getPyramidChartData: getPyramidChartData,
|
|
26014
26078
|
getPyramidChartScales: getPyramidChartScales,
|
|
26079
|
+
getPyramidChartShowValues: getPyramidChartShowValues,
|
|
26015
26080
|
getPyramidChartTooltip: getPyramidChartTooltip,
|
|
26016
26081
|
getRadarChartData: getRadarChartData,
|
|
26017
26082
|
getRadarChartDatasets: getRadarChartDatasets,
|
|
@@ -26032,6 +26097,7 @@ var CHART_RUNTIME_HELPERS = /*#__PURE__*/Object.freeze({
|
|
|
26032
26097
|
getTrendDatasetForLineChart: getTrendDatasetForLineChart,
|
|
26033
26098
|
getWaterfallChartLegend: getWaterfallChartLegend,
|
|
26034
26099
|
getWaterfallChartScales: getWaterfallChartScales,
|
|
26100
|
+
getWaterfallChartShowValues: getWaterfallChartShowValues,
|
|
26035
26101
|
getWaterfallChartTooltip: getWaterfallChartTooltip,
|
|
26036
26102
|
getWaterfallDatasetAndLabels: getWaterfallDatasetAndLabels,
|
|
26037
26103
|
makeDatasetsCumulative: makeDatasetsCumulative
|
|
@@ -27344,7 +27410,7 @@ function createPyramidChartRuntime(chart, getters) {
|
|
|
27344
27410
|
title: getChartTitle(definition),
|
|
27345
27411
|
legend: getBarChartLegend(definition),
|
|
27346
27412
|
tooltip: getPyramidChartTooltip(definition, chartData),
|
|
27347
|
-
chartShowValuesPlugin:
|
|
27413
|
+
chartShowValuesPlugin: getPyramidChartShowValues(definition, chartData),
|
|
27348
27414
|
},
|
|
27349
27415
|
},
|
|
27350
27416
|
};
|
|
@@ -28092,7 +28158,7 @@ function createWaterfallChartRuntime(chart, getters) {
|
|
|
28092
28158
|
title: getChartTitle(definition),
|
|
28093
28159
|
legend: getWaterfallChartLegend(definition),
|
|
28094
28160
|
tooltip: getWaterfallChartTooltip(definition, chartData),
|
|
28095
|
-
chartShowValuesPlugin:
|
|
28161
|
+
chartShowValuesPlugin: getWaterfallChartShowValues(definition, chartData),
|
|
28096
28162
|
waterfallLinesPlugin: { showConnectorLines: definition.showConnectorLines },
|
|
28097
28163
|
},
|
|
28098
28164
|
},
|
|
@@ -28884,6 +28950,7 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
|
|
|
28884
28950
|
env.openSidePanel("ChartPanel");
|
|
28885
28951
|
},
|
|
28886
28952
|
icon: "o-spreadsheet-Icon.EDIT",
|
|
28953
|
+
isEnabled: (env) => !env.isSmall,
|
|
28887
28954
|
},
|
|
28888
28955
|
getCopyMenuItem(figureId, env),
|
|
28889
28956
|
getCutMenuItem(figureId, env),
|
|
@@ -29098,6 +29165,147 @@ function useTimeOut() {
|
|
|
29098
29165
|
};
|
|
29099
29166
|
}
|
|
29100
29167
|
|
|
29168
|
+
//------------------------------------------------------------------------------
|
|
29169
|
+
// Context Menu Component
|
|
29170
|
+
//------------------------------------------------------------------------------
|
|
29171
|
+
css /* scss */ `
|
|
29172
|
+
.o-menu {
|
|
29173
|
+
background-color: white;
|
|
29174
|
+
user-select: none;
|
|
29175
|
+
|
|
29176
|
+
.o-menu-item {
|
|
29177
|
+
height: ${DESKTOP_MENU_ITEM_HEIGHT}px;
|
|
29178
|
+
padding: ${MENU_ITEM_PADDING_VERTICAL}px ${MENU_ITEM_PADDING_HORIZONTAL}px;
|
|
29179
|
+
cursor: pointer;
|
|
29180
|
+
user-select: none;
|
|
29181
|
+
|
|
29182
|
+
.o-menu-item-name {
|
|
29183
|
+
min-width: 40%;
|
|
29184
|
+
}
|
|
29185
|
+
|
|
29186
|
+
.o-menu-item-icon {
|
|
29187
|
+
display: inline-block;
|
|
29188
|
+
margin: 0px 8px 0px 0px;
|
|
29189
|
+
width: ${DESKTOP_MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
29190
|
+
line-height: ${DESKTOP_MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
29191
|
+
}
|
|
29192
|
+
|
|
29193
|
+
&:not(.disabled) {
|
|
29194
|
+
&:hover,
|
|
29195
|
+
&.o-menu-item-active {
|
|
29196
|
+
background-color: ${BUTTON_ACTIVE_BG};
|
|
29197
|
+
color: ${BUTTON_ACTIVE_TEXT_COLOR};
|
|
29198
|
+
}
|
|
29199
|
+
.o-menu-item-description {
|
|
29200
|
+
color: grey;
|
|
29201
|
+
}
|
|
29202
|
+
.o-menu-item-icon {
|
|
29203
|
+
.o-icon {
|
|
29204
|
+
color: ${ICONS_COLOR};
|
|
29205
|
+
}
|
|
29206
|
+
}
|
|
29207
|
+
}
|
|
29208
|
+
&.disabled {
|
|
29209
|
+
color: ${DISABLED_TEXT_COLOR};
|
|
29210
|
+
cursor: not-allowed;
|
|
29211
|
+
}
|
|
29212
|
+
}
|
|
29213
|
+
}
|
|
29214
|
+
|
|
29215
|
+
.o-spreadsheet-mobile {
|
|
29216
|
+
.o-menu-item {
|
|
29217
|
+
height: ${MOBILE_MENU_ITEM_HEIGHT}px;
|
|
29218
|
+
}
|
|
29219
|
+
}
|
|
29220
|
+
`;
|
|
29221
|
+
class Menu extends Component {
|
|
29222
|
+
static template = "o-spreadsheet-Menu";
|
|
29223
|
+
static props = {
|
|
29224
|
+
menuItems: Array,
|
|
29225
|
+
onClose: Function,
|
|
29226
|
+
onClickMenu: { type: Function, optional: true },
|
|
29227
|
+
onMouseEnter: { type: Function, optional: true },
|
|
29228
|
+
onMouseOver: { type: Function, optional: true },
|
|
29229
|
+
onMouseLeave: { type: Function, optional: true },
|
|
29230
|
+
width: { type: Number, optional: true },
|
|
29231
|
+
isActive: { type: Function, optional: true },
|
|
29232
|
+
onScroll: { type: Function, optional: true },
|
|
29233
|
+
};
|
|
29234
|
+
static components = {};
|
|
29235
|
+
static defaultProps = {};
|
|
29236
|
+
hoveredMenu = undefined;
|
|
29237
|
+
setup() {
|
|
29238
|
+
onWillUnmount(() => {
|
|
29239
|
+
this.hoveredMenu?.onStopHover?.(this.env);
|
|
29240
|
+
});
|
|
29241
|
+
}
|
|
29242
|
+
get menuItemsAndSeparators() {
|
|
29243
|
+
const menuItemsAndSeparators = [];
|
|
29244
|
+
for (let i = 0; i < this.props.menuItems.length; i++) {
|
|
29245
|
+
const menuItem = this.props.menuItems[i];
|
|
29246
|
+
if (menuItem.isVisible(this.env)) {
|
|
29247
|
+
menuItemsAndSeparators.push(menuItem);
|
|
29248
|
+
}
|
|
29249
|
+
if (menuItem.separator &&
|
|
29250
|
+
i !== this.props.menuItems.length - 1 && // no separator at the end
|
|
29251
|
+
menuItemsAndSeparators[menuItemsAndSeparators.length - 1] !== "separator" // no double separator
|
|
29252
|
+
) {
|
|
29253
|
+
menuItemsAndSeparators.push("separator");
|
|
29254
|
+
}
|
|
29255
|
+
}
|
|
29256
|
+
if (menuItemsAndSeparators[menuItemsAndSeparators.length - 1] === "separator") {
|
|
29257
|
+
menuItemsAndSeparators.pop();
|
|
29258
|
+
}
|
|
29259
|
+
if (menuItemsAndSeparators.length === 1 && menuItemsAndSeparators[0] === "separator") {
|
|
29260
|
+
return [];
|
|
29261
|
+
}
|
|
29262
|
+
return menuItemsAndSeparators;
|
|
29263
|
+
}
|
|
29264
|
+
get childrenHaveIcon() {
|
|
29265
|
+
return this.props.menuItems.some((menuItem) => !!this.getIconName(menuItem));
|
|
29266
|
+
}
|
|
29267
|
+
getIconName(menu) {
|
|
29268
|
+
if (menu.icon(this.env)) {
|
|
29269
|
+
return menu.icon(this.env);
|
|
29270
|
+
}
|
|
29271
|
+
if (menu.isActive?.(this.env)) {
|
|
29272
|
+
return "o-spreadsheet-Icon.CHECK";
|
|
29273
|
+
}
|
|
29274
|
+
return "";
|
|
29275
|
+
}
|
|
29276
|
+
getColor(menu) {
|
|
29277
|
+
return cssPropertiesToCss({ color: menu.textColor });
|
|
29278
|
+
}
|
|
29279
|
+
getIconColor(menu) {
|
|
29280
|
+
return cssPropertiesToCss({ color: menu.iconColor });
|
|
29281
|
+
}
|
|
29282
|
+
getName(menu) {
|
|
29283
|
+
return menu.name(this.env);
|
|
29284
|
+
}
|
|
29285
|
+
isRoot(menu) {
|
|
29286
|
+
return !menu.execute;
|
|
29287
|
+
}
|
|
29288
|
+
isEnabled(menu) {
|
|
29289
|
+
if (menu.isEnabled(this.env)) {
|
|
29290
|
+
return this.env.model.getters.isReadonly() ? menu.isReadonlyAllowed : true;
|
|
29291
|
+
}
|
|
29292
|
+
return false;
|
|
29293
|
+
}
|
|
29294
|
+
get menuStyle() {
|
|
29295
|
+
return this.props.width ? cssPropertiesToCss({ width: this.props.width + "px" }) : "";
|
|
29296
|
+
}
|
|
29297
|
+
onMouseEnter(menu, ev) {
|
|
29298
|
+
this.hoveredMenu = menu;
|
|
29299
|
+
menu.onStartHover?.(this.env);
|
|
29300
|
+
this.props.onMouseEnter?.(menu, ev);
|
|
29301
|
+
}
|
|
29302
|
+
onMouseLeave(menu, ev) {
|
|
29303
|
+
this.hoveredMenu = undefined;
|
|
29304
|
+
menu.onStopHover?.(this.env);
|
|
29305
|
+
this.props.onMouseLeave?.(menu, ev);
|
|
29306
|
+
}
|
|
29307
|
+
}
|
|
29308
|
+
|
|
29101
29309
|
/**
|
|
29102
29310
|
* Compute the intersection of two rectangles. Returns nothing if the two rectangles don't overlap
|
|
29103
29311
|
*/
|
|
@@ -29126,6 +29334,9 @@ function zoneToRect(zone) {
|
|
|
29126
29334
|
height: zone.bottom - zone.top,
|
|
29127
29335
|
};
|
|
29128
29336
|
}
|
|
29337
|
+
function isPointInsideRect(x, y, rect) {
|
|
29338
|
+
return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
|
|
29339
|
+
}
|
|
29129
29340
|
|
|
29130
29341
|
/**
|
|
29131
29342
|
* Return the o-spreadsheet element position relative
|
|
@@ -29423,57 +29634,17 @@ class TopRightPopoverContext extends PopoverPositionContext {
|
|
|
29423
29634
|
}
|
|
29424
29635
|
|
|
29425
29636
|
//------------------------------------------------------------------------------
|
|
29426
|
-
// Context
|
|
29637
|
+
// Context MenuPopover Component
|
|
29427
29638
|
//------------------------------------------------------------------------------
|
|
29428
29639
|
css /* scss */ `
|
|
29429
|
-
.o-menu {
|
|
29430
|
-
background-color: white;
|
|
29640
|
+
.o-menu-wrapper {
|
|
29431
29641
|
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
|
-
}
|
|
29642
|
+
background-color: white;
|
|
29472
29643
|
}
|
|
29473
29644
|
`;
|
|
29474
29645
|
const TIMEOUT_DELAY = 250;
|
|
29475
|
-
class
|
|
29476
|
-
static template = "o-spreadsheet-Menu";
|
|
29646
|
+
class MenuPopover extends Component {
|
|
29647
|
+
static template = "o-spreadsheet-Menu-Popover";
|
|
29477
29648
|
static props = {
|
|
29478
29649
|
anchorRect: Object,
|
|
29479
29650
|
popoverPositioning: { type: String, optional: true },
|
|
@@ -29486,7 +29657,7 @@ class Menu extends Component {
|
|
|
29486
29657
|
onMouseOver: { type: Function, optional: true },
|
|
29487
29658
|
width: { type: Number, optional: true },
|
|
29488
29659
|
};
|
|
29489
|
-
static components = { Menu, Popover };
|
|
29660
|
+
static components = { MenuPopover, Menu, Popover };
|
|
29490
29661
|
static defaultProps = {
|
|
29491
29662
|
depth: 1,
|
|
29492
29663
|
popoverPositioning: "top-right",
|
|
@@ -29513,27 +29684,18 @@ class Menu extends Component {
|
|
|
29513
29684
|
this.hoveredMenu?.onStopHover?.(this.env);
|
|
29514
29685
|
});
|
|
29515
29686
|
}
|
|
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;
|
|
29687
|
+
get menuProps() {
|
|
29688
|
+
return {
|
|
29689
|
+
menuItems: this.props.menuItems,
|
|
29690
|
+
onClose: this.close.bind(this),
|
|
29691
|
+
// @ts-ignore
|
|
29692
|
+
onClickMenu: this.onClickMenu.bind(this),
|
|
29693
|
+
onMouseOver: this.onMouseOver.bind(this),
|
|
29694
|
+
onMouseLeave: this.onMouseLeave.bind(this),
|
|
29695
|
+
width: this.props.width || MENU_WIDTH,
|
|
29696
|
+
isActive: this.isActive.bind(this),
|
|
29697
|
+
onScroll: this.onScroll.bind(this),
|
|
29698
|
+
};
|
|
29537
29699
|
}
|
|
29538
29700
|
get subMenuAnchorRect() {
|
|
29539
29701
|
const anchorRect = Object.assign({}, this.subMenu.anchorRect);
|
|
@@ -29547,12 +29709,13 @@ class Menu extends Component {
|
|
|
29547
29709
|
x: this.props.anchorRect.x,
|
|
29548
29710
|
y: this.props.anchorRect.y,
|
|
29549
29711
|
width: isRoot ? this.props.anchorRect.width : this.props.width || MENU_WIDTH,
|
|
29550
|
-
height: isRoot ? this.props.anchorRect.height :
|
|
29712
|
+
height: isRoot ? this.props.anchorRect.height : DESKTOP_MENU_ITEM_HEIGHT,
|
|
29551
29713
|
},
|
|
29552
29714
|
positioning: this.props.popoverPositioning,
|
|
29553
29715
|
verticalOffset: isRoot ? 0 : MENU_VERTICAL_PADDING,
|
|
29554
29716
|
onPopoverHidden: () => this.closeSubMenu(),
|
|
29555
29717
|
onPopoverMoved: () => this.closeSubMenu(),
|
|
29718
|
+
maxHeight: this.props.maxHeight,
|
|
29556
29719
|
};
|
|
29557
29720
|
}
|
|
29558
29721
|
get childrenHaveIcon() {
|
|
@@ -29622,7 +29785,7 @@ class Menu extends Component {
|
|
|
29622
29785
|
x: getRefBoundingRect(this.menuRef).x,
|
|
29623
29786
|
y: y - (this.subMenu.scrollOffset || 0),
|
|
29624
29787
|
width: this.props.width || MENU_WIDTH,
|
|
29625
|
-
height:
|
|
29788
|
+
height: DESKTOP_MENU_ITEM_HEIGHT,
|
|
29626
29789
|
};
|
|
29627
29790
|
this.subMenu.menuItems = menu.children(this.env);
|
|
29628
29791
|
this.subMenu.isOpen = true;
|
|
@@ -29671,14 +29834,8 @@ class Menu extends Component {
|
|
|
29671
29834
|
this.subMenu.isHoveringChild = true;
|
|
29672
29835
|
this.openingTimeOut.clear();
|
|
29673
29836
|
}
|
|
29674
|
-
onMouseEnter(menu, ev) {
|
|
29675
|
-
this.hoveredMenu = menu;
|
|
29676
|
-
menu.onStartHover?.(this.env);
|
|
29677
|
-
}
|
|
29678
29837
|
onMouseLeave(menu) {
|
|
29679
29838
|
this.openingTimeOut.schedule(this.closeSubMenu.bind(this), TIMEOUT_DELAY);
|
|
29680
|
-
this.hoveredMenu = undefined;
|
|
29681
|
-
menu.onStopHover?.(this.env);
|
|
29682
29839
|
}
|
|
29683
29840
|
get menuStyle() {
|
|
29684
29841
|
return this.props.width ? cssPropertiesToCss({ width: this.props.width + "px" }) : "";
|
|
@@ -29687,7 +29844,7 @@ class Menu extends Component {
|
|
|
29687
29844
|
|
|
29688
29845
|
class ChartDashboardMenu extends Component {
|
|
29689
29846
|
static template = "spreadsheet.ChartDashboardMenu";
|
|
29690
|
-
static components = {
|
|
29847
|
+
static components = { MenuPopover };
|
|
29691
29848
|
static props = { figureUI: Object };
|
|
29692
29849
|
originalChartDefinition;
|
|
29693
29850
|
fullScreenFigureStore;
|
|
@@ -29951,7 +30108,7 @@ class FigureComponent extends Component {
|
|
|
29951
30108
|
onMouseDown: { type: Function, optional: true },
|
|
29952
30109
|
onClickAnchor: { type: Function, optional: true },
|
|
29953
30110
|
};
|
|
29954
|
-
static components = {
|
|
30111
|
+
static components = { MenuPopover };
|
|
29955
30112
|
static defaultProps = {
|
|
29956
30113
|
onFigureDeleted: () => { },
|
|
29957
30114
|
onMouseDown: () => { },
|
|
@@ -30038,7 +30195,14 @@ class FigureComponent extends Component {
|
|
|
30038
30195
|
this.props.onClickAnchor(dirX, dirY, ev);
|
|
30039
30196
|
}
|
|
30040
30197
|
onMouseDown(ev) {
|
|
30041
|
-
this.
|
|
30198
|
+
if (!this.env.isMobile()) {
|
|
30199
|
+
this.props.onMouseDown(ev);
|
|
30200
|
+
}
|
|
30201
|
+
}
|
|
30202
|
+
onClick(ev) {
|
|
30203
|
+
if (this.env.isMobile()) {
|
|
30204
|
+
this.props.onMouseDown(ev);
|
|
30205
|
+
}
|
|
30042
30206
|
}
|
|
30043
30207
|
onKeyDown(ev) {
|
|
30044
30208
|
const keyDownShortcut = keyboardEventToShortcutString(ev);
|
|
@@ -31505,15 +31669,15 @@ class HighlightStore extends SpreadsheetStore {
|
|
|
31505
31669
|
const activeSheetId = this.getters.getActiveSheetId();
|
|
31506
31670
|
return this.providers
|
|
31507
31671
|
.flatMap((h) => h.highlights)
|
|
31508
|
-
.filter((h) => h.sheetId === activeSheetId)
|
|
31672
|
+
.filter((h) => h.range.sheetId === activeSheetId)
|
|
31509
31673
|
.map((highlight) => {
|
|
31510
|
-
const { numberOfRows, numberOfCols } = zoneToDimension(highlight.zone);
|
|
31674
|
+
const { numberOfRows, numberOfCols } = zoneToDimension(highlight.range.zone);
|
|
31511
31675
|
const zone = numberOfRows * numberOfCols === 1
|
|
31512
|
-
? this.getters.expandZone(highlight.sheetId, highlight.zone)
|
|
31513
|
-
: highlight.
|
|
31676
|
+
? this.getters.expandZone(highlight.range.sheetId, highlight.range.zone)
|
|
31677
|
+
: highlight.range.unboundedZone;
|
|
31514
31678
|
return {
|
|
31515
31679
|
...highlight,
|
|
31516
|
-
zone,
|
|
31680
|
+
range: this.model.getters.getRangeFromZone(highlight.range.sheetId, zone),
|
|
31517
31681
|
};
|
|
31518
31682
|
});
|
|
31519
31683
|
}
|
|
@@ -31526,7 +31690,7 @@ class HighlightStore extends SpreadsheetStore {
|
|
|
31526
31690
|
drawLayer(ctx, layer) {
|
|
31527
31691
|
if (layer === "Highlights") {
|
|
31528
31692
|
for (const highlight of this.highlights) {
|
|
31529
|
-
const rect = this.getters.getVisibleRect(highlight.zone);
|
|
31693
|
+
const rect = this.getters.getVisibleRect(highlight.range.zone);
|
|
31530
31694
|
drawHighlight(ctx, highlight, rect);
|
|
31531
31695
|
}
|
|
31532
31696
|
}
|
|
@@ -32154,12 +32318,12 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
32154
32318
|
rangeColor(xc, sheetName) {
|
|
32155
32319
|
const refSheet = sheetName ? this.model.getters.getSheetIdByName(sheetName) : this.sheetId;
|
|
32156
32320
|
const highlight = this.highlights.find((highlight) => {
|
|
32157
|
-
if (highlight.sheetId !== refSheet)
|
|
32321
|
+
if (highlight.range.sheetId !== refSheet)
|
|
32158
32322
|
return false;
|
|
32159
32323
|
const range = this.model.getters.getRangeFromSheetXC(refSheet, xc);
|
|
32160
32324
|
let zone = range.zone;
|
|
32161
32325
|
zone = getZoneArea(zone) === 1 ? this.model.getters.expandZone(refSheet, zone) : zone;
|
|
32162
|
-
return isEqual(zone, highlight.zone);
|
|
32326
|
+
return isEqual(zone, highlight.range.zone);
|
|
32163
32327
|
});
|
|
32164
32328
|
return highlight && highlight.color ? highlight.color : undefined;
|
|
32165
32329
|
}
|
|
@@ -32269,11 +32433,10 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
32269
32433
|
const { numberOfRows, numberOfCols } = zoneToDimension(range.zone);
|
|
32270
32434
|
const zone = numberOfRows * numberOfCols === 1
|
|
32271
32435
|
? this.getters.expandZone(range.sheetId, range.zone)
|
|
32272
|
-
: range.
|
|
32436
|
+
: range.unboundedZone;
|
|
32273
32437
|
return {
|
|
32274
|
-
zone,
|
|
32438
|
+
range: this.model.getters.getRangeFromZone(range.sheetId, zone),
|
|
32275
32439
|
color: rangeColor(rangeString),
|
|
32276
|
-
sheetId: range.sheetId,
|
|
32277
32440
|
interactive: true,
|
|
32278
32441
|
};
|
|
32279
32442
|
});
|
|
@@ -32526,11 +32689,15 @@ class Composer extends Component {
|
|
|
32526
32689
|
onInputContextMenu: { type: Function, optional: true },
|
|
32527
32690
|
composerStore: Object,
|
|
32528
32691
|
placeholder: { type: String, optional: true },
|
|
32692
|
+
inputMode: { type: String, optional: true },
|
|
32693
|
+
showAssistant: { type: Boolean, optional: true },
|
|
32529
32694
|
};
|
|
32530
32695
|
static components = { TextValueProvider, FunctionDescriptionProvider, SpeechBubble };
|
|
32531
32696
|
static defaultProps = {
|
|
32532
32697
|
inputStyle: "",
|
|
32533
32698
|
isDefaultFocus: false,
|
|
32699
|
+
inputMode: "text",
|
|
32700
|
+
showAssistant: true,
|
|
32534
32701
|
};
|
|
32535
32702
|
DOMFocusableElementStore;
|
|
32536
32703
|
composerRef = useRef("o_composer");
|
|
@@ -32581,8 +32748,7 @@ class Composer extends Component {
|
|
|
32581
32748
|
assistantStyle["max-height"] = `${availableSpaceAbove - CLOSE_ICON_RADIUS}px`;
|
|
32582
32749
|
// render top
|
|
32583
32750
|
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
32584
|
-
assistantStyle.
|
|
32585
|
-
assistantStyle.transform = `translate(0, -100%)`;
|
|
32751
|
+
assistantStyle.transform = `translate(0, calc(-100% - ${cellHeight + 3}px))`;
|
|
32586
32752
|
}
|
|
32587
32753
|
if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) {
|
|
32588
32754
|
// render left
|
|
@@ -32861,6 +33027,9 @@ class Composer extends Component {
|
|
|
32861
33027
|
// not main button, probably a context menu
|
|
32862
33028
|
return;
|
|
32863
33029
|
}
|
|
33030
|
+
if (this.env.isMobile() && !isIOS()) {
|
|
33031
|
+
return;
|
|
33032
|
+
}
|
|
32864
33033
|
this.contentHelper.removeSelection();
|
|
32865
33034
|
}
|
|
32866
33035
|
onMouseup() {
|
|
@@ -33484,7 +33653,7 @@ class ListCriterionForm extends CriterionForm {
|
|
|
33484
33653
|
*/
|
|
33485
33654
|
function startDnd(onPointerMove, onPointerUp) {
|
|
33486
33655
|
const removeListeners = () => {
|
|
33487
|
-
window.removeEventListener("pointerup", _onPointerUp);
|
|
33656
|
+
window.removeEventListener("pointerup", _onPointerUp, { capture: true });
|
|
33488
33657
|
window.removeEventListener("dragstart", _onDragStart);
|
|
33489
33658
|
window.removeEventListener("pointermove", onPointerMove);
|
|
33490
33659
|
window.removeEventListener("wheel", onPointerMove);
|
|
@@ -33496,7 +33665,7 @@ function startDnd(onPointerMove, onPointerUp) {
|
|
|
33496
33665
|
function _onDragStart(ev) {
|
|
33497
33666
|
ev.preventDefault();
|
|
33498
33667
|
}
|
|
33499
|
-
window.addEventListener("pointerup", _onPointerUp);
|
|
33668
|
+
window.addEventListener("pointerup", _onPointerUp, { capture: true });
|
|
33500
33669
|
window.addEventListener("dragstart", _onDragStart);
|
|
33501
33670
|
window.addEventListener("pointermove", onPointerMove);
|
|
33502
33671
|
// mouse wheel on window is by default a passive event.
|
|
@@ -34118,9 +34287,9 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
34118
34287
|
.filter((reference) => this.shouldBeHighlighted(this.inputSheetId, reference));
|
|
34119
34288
|
return XCs.map((xc) => {
|
|
34120
34289
|
const { sheetName } = splitReference(xc);
|
|
34290
|
+
const sheetId = (sheetName && this.getters.getSheetIdByName(sheetName)) || this.inputSheetId;
|
|
34121
34291
|
return {
|
|
34122
|
-
|
|
34123
|
-
sheetId: (sheetName && this.getters.getSheetIdByName(sheetName)) || this.inputSheetId,
|
|
34292
|
+
range: this.getters.getRangeFromSheetXC(sheetId, xc),
|
|
34124
34293
|
color,
|
|
34125
34294
|
interactive: true,
|
|
34126
34295
|
};
|
|
@@ -34589,7 +34758,7 @@ function getCriterionMenuItems(callback, availableTypes) {
|
|
|
34589
34758
|
return createActions(actionSpecs);
|
|
34590
34759
|
}
|
|
34591
34760
|
|
|
34592
|
-
/** This component looks like a select input, but on click it opens a
|
|
34761
|
+
/** 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
34762
|
class SelectMenu extends Component {
|
|
34594
34763
|
static template = "o-spreadsheet-SelectMenu";
|
|
34595
34764
|
static props = {
|
|
@@ -34597,7 +34766,7 @@ class SelectMenu extends Component {
|
|
|
34597
34766
|
selectedValue: String,
|
|
34598
34767
|
class: { type: String, optional: true },
|
|
34599
34768
|
};
|
|
34600
|
-
static components = {
|
|
34769
|
+
static components = { MenuPopover };
|
|
34601
34770
|
menuId = new UuidGenerator().uuidv4();
|
|
34602
34771
|
selectRef = useRef("select");
|
|
34603
34772
|
state = useState({
|
|
@@ -35345,7 +35514,7 @@ class MenuItemRegistry extends Registry {
|
|
|
35345
35514
|
}
|
|
35346
35515
|
|
|
35347
35516
|
//------------------------------------------------------------------------------
|
|
35348
|
-
// Link
|
|
35517
|
+
// Link MenuPopover Registry
|
|
35349
35518
|
//------------------------------------------------------------------------------
|
|
35350
35519
|
const linkMenuRegistry = new MenuItemRegistry();
|
|
35351
35520
|
linkMenuRegistry.add("sheet", {
|
|
@@ -35407,7 +35576,7 @@ class LinkEditor extends Component {
|
|
|
35407
35576
|
cellPosition: Object,
|
|
35408
35577
|
onClosed: { type: Function, optional: true },
|
|
35409
35578
|
};
|
|
35410
|
-
static components = {
|
|
35579
|
+
static components = { MenuPopover };
|
|
35411
35580
|
menuItems = linkMenuRegistry.getMenuItems();
|
|
35412
35581
|
link = useState(this.defaultState);
|
|
35413
35582
|
menu = useState({
|
|
@@ -35864,58 +36033,149 @@ css /* scss */ `
|
|
|
35864
36033
|
const ARROW_DOWN = {
|
|
35865
36034
|
width: 448,
|
|
35866
36035
|
height: 512,
|
|
35867
|
-
|
|
35868
|
-
|
|
36036
|
+
paths: [
|
|
36037
|
+
{
|
|
36038
|
+
fillColor: "#E06666",
|
|
36039
|
+
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",
|
|
36040
|
+
},
|
|
36041
|
+
],
|
|
35869
36042
|
};
|
|
35870
36043
|
const ARROW_UP = {
|
|
35871
36044
|
width: 448,
|
|
35872
36045
|
height: 512,
|
|
35873
|
-
|
|
35874
|
-
|
|
36046
|
+
paths: [
|
|
36047
|
+
{
|
|
36048
|
+
fillColor: "#6AA84F",
|
|
36049
|
+
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",
|
|
36050
|
+
},
|
|
36051
|
+
],
|
|
35875
36052
|
};
|
|
35876
36053
|
const ARROW_RIGHT = {
|
|
35877
36054
|
width: 448,
|
|
35878
36055
|
height: 512,
|
|
35879
|
-
|
|
35880
|
-
|
|
36056
|
+
paths: [
|
|
36057
|
+
{
|
|
36058
|
+
fillColor: "#F0AD4E",
|
|
36059
|
+
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",
|
|
36060
|
+
},
|
|
36061
|
+
],
|
|
35881
36062
|
};
|
|
35882
36063
|
const SMILE = {
|
|
35883
36064
|
width: 496,
|
|
35884
36065
|
height: 512,
|
|
35885
|
-
|
|
35886
|
-
|
|
36066
|
+
paths: [
|
|
36067
|
+
{
|
|
36068
|
+
fillColor: "#6AA84F",
|
|
36069
|
+
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",
|
|
36070
|
+
},
|
|
36071
|
+
],
|
|
35887
36072
|
};
|
|
35888
36073
|
const MEH = {
|
|
35889
36074
|
width: 496,
|
|
35890
36075
|
height: 512,
|
|
35891
|
-
|
|
35892
|
-
|
|
36076
|
+
paths: [
|
|
36077
|
+
{
|
|
36078
|
+
fillColor: "#F0AD4E",
|
|
36079
|
+
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",
|
|
36080
|
+
},
|
|
36081
|
+
],
|
|
35893
36082
|
};
|
|
35894
36083
|
const FROWN = {
|
|
35895
36084
|
width: 496,
|
|
35896
36085
|
height: 512,
|
|
35897
|
-
|
|
35898
|
-
|
|
36086
|
+
paths: [
|
|
36087
|
+
{
|
|
36088
|
+
fillColor: "#E06666",
|
|
36089
|
+
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",
|
|
36090
|
+
},
|
|
36091
|
+
],
|
|
35899
36092
|
};
|
|
35900
36093
|
const DOT_PATH = "M256 9 a247 247 0 1 0.1 0 0";
|
|
35901
36094
|
const GREEN_DOT = {
|
|
35902
36095
|
width: 512,
|
|
35903
36096
|
height: 512,
|
|
35904
|
-
fillColor: "#6AA84F",
|
|
35905
|
-
path: DOT_PATH,
|
|
36097
|
+
paths: [{ fillColor: "#6AA84F", path: DOT_PATH }],
|
|
35906
36098
|
};
|
|
35907
36099
|
const YELLOW_DOT = {
|
|
35908
36100
|
width: 512,
|
|
35909
36101
|
height: 512,
|
|
35910
|
-
fillColor: "#F0AD4E",
|
|
35911
|
-
path: DOT_PATH,
|
|
36102
|
+
paths: [{ fillColor: "#F0AD4E", path: DOT_PATH }],
|
|
35912
36103
|
};
|
|
35913
36104
|
const RED_DOT = {
|
|
35914
36105
|
width: 512,
|
|
35915
36106
|
height: 512,
|
|
35916
|
-
fillColor: "#E06666",
|
|
35917
|
-
|
|
36107
|
+
paths: [{ fillColor: "#E06666", path: DOT_PATH }],
|
|
36108
|
+
};
|
|
36109
|
+
const CARET_DOWN = {
|
|
36110
|
+
width: 512,
|
|
36111
|
+
height: 512,
|
|
36112
|
+
paths: [{ fillColor: TEXT_BODY_MUTED, path: "M120 195 h270 l-135 130" }],
|
|
36113
|
+
};
|
|
36114
|
+
const HOVERED_CARET_DOWN = {
|
|
36115
|
+
width: 512,
|
|
36116
|
+
height: 512,
|
|
36117
|
+
paths: [
|
|
36118
|
+
{ fillColor: TEXT_BODY_MUTED, path: "M15 15 h482 v482 h-482" },
|
|
36119
|
+
{ fillColor: "#fff", path: "M120 195 h270 l-135 130" },
|
|
36120
|
+
],
|
|
36121
|
+
};
|
|
36122
|
+
const CHECKBOX_UNCHECKED = {
|
|
36123
|
+
width: 512,
|
|
36124
|
+
height: 512,
|
|
36125
|
+
paths: [{ fillColor: GRAY_300, path: "M45,45 h422 v422 h-422 v-422 m30,30 v362 h362 v-362" }],
|
|
36126
|
+
};
|
|
36127
|
+
const CHECKBOX_UNCHECKED_HOVERED = {
|
|
36128
|
+
width: 512,
|
|
36129
|
+
height: 512,
|
|
36130
|
+
paths: [{ fillColor: ACTION_COLOR, path: "M45,45 h422 v422 h-422 v-422 m30,30 v362 h362 v-362" }],
|
|
35918
36131
|
};
|
|
36132
|
+
const CHECKBOX_CHECKED = {
|
|
36133
|
+
width: 512,
|
|
36134
|
+
height: 512,
|
|
36135
|
+
paths: [
|
|
36136
|
+
{ fillColor: ACTION_COLOR, path: "M45,45 h422 v422 h-422 v-422" },
|
|
36137
|
+
{ fillColor: "#FFF", path: "M165,240 l45,45 l135,-135 h60 l-195,195 l-105,-105" },
|
|
36138
|
+
],
|
|
36139
|
+
};
|
|
36140
|
+
function getPivotIconSvg(isCollapsed, isHovered) {
|
|
36141
|
+
const symbolPath = isCollapsed
|
|
36142
|
+
? "M149,235 h213 v43 h-213 M235,149 h43 v213 h-43" // +
|
|
36143
|
+
: "M149,235 h213 v43 h-213"; // -
|
|
36144
|
+
return {
|
|
36145
|
+
width: 512,
|
|
36146
|
+
height: 512,
|
|
36147
|
+
paths: [
|
|
36148
|
+
{ path: "M21,21 h469 v469 h-469", fillColor: isHovered ? GRAY_900 : "#777" }, // borders
|
|
36149
|
+
{ path: "M64,64 v384 h384 v-384", fillColor: isHovered ? GRAY_200 : "#eee" }, // background
|
|
36150
|
+
{ path: symbolPath, fillColor: isHovered ? GRAY_900 : "#777" },
|
|
36151
|
+
],
|
|
36152
|
+
};
|
|
36153
|
+
}
|
|
36154
|
+
function getDataFilterIcon(isActive, isHighContrast, isHovered) {
|
|
36155
|
+
const symbolPath = isActive
|
|
36156
|
+
? "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"
|
|
36157
|
+
: "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";
|
|
36158
|
+
const hoverBackgroundPath = isActive ? "M0,0 h24 v24 h-24" : "M0,0 h850 v850 h-850";
|
|
36159
|
+
const colors = { iconColor: FILTERS_COLOR, hoverBackgroundColor: FILTERS_COLOR };
|
|
36160
|
+
if (isHovered && !isHighContrast) {
|
|
36161
|
+
colors.iconColor = "#fff";
|
|
36162
|
+
}
|
|
36163
|
+
else if (!isHovered && isHighContrast) {
|
|
36164
|
+
colors.iconColor = "#defade";
|
|
36165
|
+
}
|
|
36166
|
+
else if (isHovered && isHighContrast) {
|
|
36167
|
+
colors.iconColor = FILTERS_COLOR;
|
|
36168
|
+
colors.hoverBackgroundColor = "#fff";
|
|
36169
|
+
}
|
|
36170
|
+
return {
|
|
36171
|
+
width: isActive ? 24 : 850,
|
|
36172
|
+
height: isActive ? 24 : 850,
|
|
36173
|
+
paths: [
|
|
36174
|
+
isHovered ? { path: hoverBackgroundPath, fillColor: colors.hoverBackgroundColor } : undefined,
|
|
36175
|
+
{ path: symbolPath, fillColor: colors.iconColor },
|
|
36176
|
+
].filter(isDefined),
|
|
36177
|
+
};
|
|
36178
|
+
}
|
|
35919
36179
|
const ICONS = {
|
|
35920
36180
|
arrowGood: {
|
|
35921
36181
|
template: "ARROW_UP",
|
|
@@ -35971,6 +36231,15 @@ const ICON_SETS = {
|
|
|
35971
36231
|
bad: "dotBad",
|
|
35972
36232
|
},
|
|
35973
36233
|
};
|
|
36234
|
+
const path2DCache = {};
|
|
36235
|
+
function getPath2D(svgPath) {
|
|
36236
|
+
if (path2DCache[svgPath]) {
|
|
36237
|
+
return path2DCache[svgPath];
|
|
36238
|
+
}
|
|
36239
|
+
const path2D = new Path2D(svgPath);
|
|
36240
|
+
path2DCache[svgPath] = path2D;
|
|
36241
|
+
return path2D;
|
|
36242
|
+
}
|
|
35974
36243
|
|
|
35975
36244
|
/**
|
|
35976
36245
|
* Map of the different types of conversions warnings and their name in error messages
|
|
@@ -41942,6 +42211,7 @@ const findAndReplace = {
|
|
|
41942
42211
|
execute: (env) => {
|
|
41943
42212
|
env.openSidePanel("FindAndReplace", {});
|
|
41944
42213
|
},
|
|
42214
|
+
isEnabled: (env) => !env.isSmall,
|
|
41945
42215
|
icon: "o-spreadsheet-Icon.SEARCH",
|
|
41946
42216
|
};
|
|
41947
42217
|
const deleteValues = {
|
|
@@ -42198,11 +42468,13 @@ const insertCellShiftRight = {
|
|
|
42198
42468
|
const insertChart = {
|
|
42199
42469
|
name: _t("Chart"),
|
|
42200
42470
|
execute: CREATE_CHART,
|
|
42471
|
+
isEnabled: (env) => !env.isSmall,
|
|
42201
42472
|
icon: "o-spreadsheet-Icon.INSERT_CHART",
|
|
42202
42473
|
};
|
|
42203
42474
|
const insertPivot = {
|
|
42204
42475
|
name: _t("Pivot table"),
|
|
42205
42476
|
execute: CREATE_PIVOT,
|
|
42477
|
+
isEnabled: (env) => !env.isSmall,
|
|
42206
42478
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
42207
42479
|
};
|
|
42208
42480
|
const insertImage = {
|
|
@@ -42210,12 +42482,14 @@ const insertImage = {
|
|
|
42210
42482
|
description: "Ctrl+O",
|
|
42211
42483
|
execute: CREATE_IMAGE,
|
|
42212
42484
|
isVisible: (env) => env.imageProvider !== undefined,
|
|
42485
|
+
isEnabled: (env) => !env.isSmall,
|
|
42213
42486
|
icon: "o-spreadsheet-Icon.INSERT_IMAGE",
|
|
42214
42487
|
};
|
|
42215
42488
|
const insertTable = {
|
|
42216
42489
|
name: () => _t("Table"),
|
|
42217
42490
|
execute: INSERT_TABLE,
|
|
42218
42491
|
isVisible: (env) => IS_SELECTION_CONTINUOUS(env) && !env.model.getters.getFirstTableInSelection(),
|
|
42492
|
+
isEnabled: (env) => !env.isSmall,
|
|
42219
42493
|
icon: "o-spreadsheet-Icon.PAINT_TABLE",
|
|
42220
42494
|
};
|
|
42221
42495
|
const insertFunction = {
|
|
@@ -42321,6 +42595,7 @@ const insertDropdown = {
|
|
|
42321
42595
|
},
|
|
42322
42596
|
});
|
|
42323
42597
|
},
|
|
42598
|
+
isEnabled: (env) => !env.isSmall,
|
|
42324
42599
|
icon: "o-spreadsheet-Icon.INSERT_DROPDOWN",
|
|
42325
42600
|
};
|
|
42326
42601
|
const insertSheet = {
|
|
@@ -42590,7 +42865,7 @@ const pivotProperties = {
|
|
|
42590
42865
|
isVisible: (env) => {
|
|
42591
42866
|
const position = env.model.getters.getActivePosition();
|
|
42592
42867
|
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
42593
|
-
return (pivotId && env.model.getters.isExistingPivot(pivotId)) || false;
|
|
42868
|
+
return (!env.isSmall && pivotId && env.model.getters.isExistingPivot(pivotId)) || false;
|
|
42594
42869
|
},
|
|
42595
42870
|
isReadonlyAllowed: true,
|
|
42596
42871
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
@@ -42708,7 +42983,7 @@ function isPivotSortMenuItemActive(env, order) {
|
|
|
42708
42983
|
}
|
|
42709
42984
|
|
|
42710
42985
|
//------------------------------------------------------------------------------
|
|
42711
|
-
// Context
|
|
42986
|
+
// Context MenuPopover Registry
|
|
42712
42987
|
//------------------------------------------------------------------------------
|
|
42713
42988
|
const cellMenuRegistry = new MenuItemRegistry();
|
|
42714
42989
|
cellMenuRegistry
|
|
@@ -42791,6 +43066,7 @@ cellMenuRegistry
|
|
|
42791
43066
|
.add("edit_table", {
|
|
42792
43067
|
...editTable,
|
|
42793
43068
|
isVisible: SELECTION_CONTAINS_SINGLE_TABLE,
|
|
43069
|
+
isEnabled: (env) => !env.isSmall,
|
|
42794
43070
|
sequence: 140,
|
|
42795
43071
|
})
|
|
42796
43072
|
.add("delete_table", {
|
|
@@ -42859,6 +43135,7 @@ const removeDuplicates = {
|
|
|
42859
43135
|
}
|
|
42860
43136
|
env.openSidePanel("RemoveDuplicates", {});
|
|
42861
43137
|
},
|
|
43138
|
+
isEnabled: (env) => !env.isSmall,
|
|
42862
43139
|
};
|
|
42863
43140
|
const trimWhitespace = {
|
|
42864
43141
|
name: _t("Trim whitespace"),
|
|
@@ -42886,7 +43163,7 @@ const splitToColumns = {
|
|
|
42886
43163
|
name: _t("Split text to columns"),
|
|
42887
43164
|
sequence: 1,
|
|
42888
43165
|
execute: (env) => env.openSidePanel("SplitToColumns", {}),
|
|
42889
|
-
isEnabled: (env) => env.model.getters.isSingleColSelected(),
|
|
43166
|
+
isEnabled: (env) => !env.isSmall && env.model.getters.isSingleColSelected(),
|
|
42890
43167
|
icon: "o-spreadsheet-Icon.SPLIT_TEXT",
|
|
42891
43168
|
};
|
|
42892
43169
|
const reinsertDynamicPivotMenu = {
|
|
@@ -42973,7 +43250,7 @@ const formatNumberAccounting = createFormatActionSpec({
|
|
|
42973
43250
|
const EXAMPLE_DATE = parseLiteral("2023/09/26 10:43:00 PM", DEFAULT_LOCALE);
|
|
42974
43251
|
const formatCustomCurrency = {
|
|
42975
43252
|
name: _t("Custom currency"),
|
|
42976
|
-
isVisible: (env) => env.loadCurrencies !== undefined,
|
|
43253
|
+
isVisible: (env) => env.loadCurrencies !== undefined && !env.isSmall,
|
|
42977
43254
|
execute: (env) => env.openSidePanel("CustomCurrency", {}),
|
|
42978
43255
|
};
|
|
42979
43256
|
const formatNumberDate = createFormatActionSpec({
|
|
@@ -43196,6 +43473,7 @@ const formatWrappingClip = {
|
|
|
43196
43473
|
const formatCF = {
|
|
43197
43474
|
name: _t("Conditional formatting"),
|
|
43198
43475
|
execute: OPEN_CF_SIDEPANEL_ACTION,
|
|
43476
|
+
isEnabled: (env) => !env.isSmall,
|
|
43199
43477
|
icon: "o-spreadsheet-Icon.CONDITIONAL_FORMAT",
|
|
43200
43478
|
};
|
|
43201
43479
|
const clearFormat = {
|
|
@@ -43579,8 +43857,7 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
|
|
|
43579
43857
|
}
|
|
43580
43858
|
return [
|
|
43581
43859
|
{
|
|
43582
|
-
|
|
43583
|
-
zone,
|
|
43860
|
+
range: this.model.getters.getRangeFromZone(position.sheetId, zone),
|
|
43584
43861
|
dashed: cell.value === CellErrorType.SpilledBlocked,
|
|
43585
43862
|
color: "#17A2B8",
|
|
43586
43863
|
noFill: true,
|
|
@@ -43665,6 +43942,7 @@ function useDragAndDropBeyondTheViewport(env) {
|
|
|
43665
43942
|
let previousEvClientPosition;
|
|
43666
43943
|
let startingX;
|
|
43667
43944
|
let startingY;
|
|
43945
|
+
let scrollDirection = "all";
|
|
43668
43946
|
const getters = env.model.getters;
|
|
43669
43947
|
let cleanUpFns = [];
|
|
43670
43948
|
const cleanUp = () => {
|
|
@@ -43690,55 +43968,59 @@ function useDragAndDropBeyondTheViewport(env) {
|
|
|
43690
43968
|
let timeoutDelay = MAX_DELAY;
|
|
43691
43969
|
const x = currentEv.clientX - position.left;
|
|
43692
43970
|
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
|
-
|
|
43971
|
+
if (scrollDirection !== "vertical") {
|
|
43972
|
+
const previousX = previousEvClientPosition.clientX - position.left;
|
|
43973
|
+
const edgeScrollInfoX = getters.getEdgeScrollCol(x, previousX, startingX);
|
|
43974
|
+
if (edgeScrollInfoX.canEdgeScroll) {
|
|
43975
|
+
canEdgeScroll = true;
|
|
43976
|
+
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoX.delay);
|
|
43977
|
+
let newTarget = colIndex;
|
|
43978
|
+
switch (edgeScrollInfoX.direction) {
|
|
43979
|
+
case "reset":
|
|
43980
|
+
colIndex = newTarget = xSplit;
|
|
43981
|
+
break;
|
|
43982
|
+
case 1:
|
|
43983
|
+
colIndex = right;
|
|
43984
|
+
newTarget = left + 1;
|
|
43985
|
+
break;
|
|
43986
|
+
case -1:
|
|
43987
|
+
colIndex = left - 1;
|
|
43988
|
+
while (env.model.getters.isColHidden(sheetId, colIndex)) {
|
|
43989
|
+
colIndex--;
|
|
43990
|
+
}
|
|
43991
|
+
newTarget = colIndex;
|
|
43992
|
+
break;
|
|
43993
|
+
}
|
|
43994
|
+
scrollX = getters.getColDimensions(sheetId, newTarget).start - offsetCorrectionX;
|
|
43714
43995
|
}
|
|
43715
|
-
scrollX = getters.getColDimensions(sheetId, newTarget).start - offsetCorrectionX;
|
|
43716
43996
|
}
|
|
43717
43997
|
const y = currentEv.clientY - position.top;
|
|
43718
43998
|
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
|
-
|
|
43999
|
+
if (scrollDirection !== "horizontal") {
|
|
44000
|
+
const previousY = previousEvClientPosition.clientY - position.top;
|
|
44001
|
+
const edgeScrollInfoY = getters.getEdgeScrollRow(y, previousY, startingY);
|
|
44002
|
+
if (edgeScrollInfoY.canEdgeScroll) {
|
|
44003
|
+
canEdgeScroll = true;
|
|
44004
|
+
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoY.delay);
|
|
44005
|
+
let newTarget = rowIndex;
|
|
44006
|
+
switch (edgeScrollInfoY.direction) {
|
|
44007
|
+
case "reset":
|
|
44008
|
+
rowIndex = newTarget = ySplit;
|
|
44009
|
+
break;
|
|
44010
|
+
case 1:
|
|
44011
|
+
rowIndex = bottom;
|
|
44012
|
+
newTarget = top + 1;
|
|
44013
|
+
break;
|
|
44014
|
+
case -1:
|
|
44015
|
+
rowIndex = top - 1;
|
|
44016
|
+
while (env.model.getters.isRowHidden(sheetId, rowIndex)) {
|
|
44017
|
+
rowIndex--;
|
|
44018
|
+
}
|
|
44019
|
+
newTarget = rowIndex;
|
|
44020
|
+
break;
|
|
44021
|
+
}
|
|
44022
|
+
scrollY = env.model.getters.getRowDimensions(sheetId, newTarget).start - offsetCorrectionY;
|
|
43740
44023
|
}
|
|
43741
|
-
scrollY = env.model.getters.getRowDimensions(sheetId, newTarget).start - offsetCorrectionY;
|
|
43742
44024
|
}
|
|
43743
44025
|
if (!canEdgeScroll) {
|
|
43744
44026
|
colIndex = adjustIndexWithinBounds(colIndex, x, getters.getNumberCols(sheetId) - 1);
|
|
@@ -43758,9 +44040,10 @@ function useDragAndDropBeyondTheViewport(env) {
|
|
|
43758
44040
|
pointerUpCallback?.();
|
|
43759
44041
|
cleanUp();
|
|
43760
44042
|
};
|
|
43761
|
-
const startFn = (initialPointerCoordinates, onPointerMove, onPointerUp) => {
|
|
44043
|
+
const startFn = (initialPointerCoordinates, onPointerMove, onPointerUp, startScrollDirection = "all") => {
|
|
43762
44044
|
cleanUp();
|
|
43763
44045
|
const position = gridOverlayPosition();
|
|
44046
|
+
scrollDirection = startScrollDirection;
|
|
43764
44047
|
startingX = initialPointerCoordinates.clientX - position.left;
|
|
43765
44048
|
startingY = initialPointerCoordinates.clientY - position.top;
|
|
43766
44049
|
previousEvClientPosition = {
|
|
@@ -44238,7 +44521,7 @@ class GridComposer extends Component {
|
|
|
44238
44521
|
});
|
|
44239
44522
|
}
|
|
44240
44523
|
get shouldDisplayCellReference() {
|
|
44241
|
-
return this.isCellReferenceVisible;
|
|
44524
|
+
return !this.env.isMobile() && this.isCellReferenceVisible;
|
|
44242
44525
|
}
|
|
44243
44526
|
get cellReference() {
|
|
44244
44527
|
const { col, row, sheetId } = this.composerStore.currentEditedCell;
|
|
@@ -44279,11 +44562,12 @@ class GridComposer extends Component {
|
|
|
44279
44562
|
onInputContextMenu: this.props.onInputContextMenu,
|
|
44280
44563
|
composerStore: this.composerStore,
|
|
44281
44564
|
inputStyle: `max-height: ${maxHeight}px;`,
|
|
44565
|
+
inputMode: this.composerStore.editionMode === "inactive" ? "none" : undefined,
|
|
44282
44566
|
};
|
|
44283
44567
|
}
|
|
44284
44568
|
get containerStyle() {
|
|
44285
|
-
if (this.composerStore.editionMode === "inactive") {
|
|
44286
|
-
return `z-index: -1000;`;
|
|
44569
|
+
if (this.composerStore.editionMode === "inactive" || this.env.isMobile()) {
|
|
44570
|
+
return `z-index: -1000; opacity: 0;`; // opacity 0 for safari on ios
|
|
44287
44571
|
}
|
|
44288
44572
|
const _isFormula = isFormula(this.composerStore.currentContent);
|
|
44289
44573
|
const cell = this.env.model.getters.getActiveCell();
|
|
@@ -44312,11 +44596,13 @@ class GridComposer extends Component {
|
|
|
44312
44596
|
*
|
|
44313
44597
|
* The +-1 are there to include cell borders in the composer sizing/positioning
|
|
44314
44598
|
*/
|
|
44599
|
+
const minHeight = Math.min(height + 1, maxHeight);
|
|
44600
|
+
const minWidth = Math.min(width + 1, maxWidth);
|
|
44315
44601
|
return cssPropertiesToCss({
|
|
44316
44602
|
left: `${left - 1}px`,
|
|
44317
44603
|
top: `${top}px`,
|
|
44318
|
-
"min-width": `${
|
|
44319
|
-
"min-height": `${
|
|
44604
|
+
"min-width": `${minWidth}px`,
|
|
44605
|
+
"min-height": `${minHeight}px`,
|
|
44320
44606
|
"max-width": `${maxWidth}px`,
|
|
44321
44607
|
"max-height": `${maxHeight}px`,
|
|
44322
44608
|
background,
|
|
@@ -44813,6 +45099,9 @@ class FiguresContainer extends Component {
|
|
|
44813
45099
|
if (!selectResult.isSuccessful) {
|
|
44814
45100
|
return;
|
|
44815
45101
|
}
|
|
45102
|
+
if (this.env.isMobile()) {
|
|
45103
|
+
return;
|
|
45104
|
+
}
|
|
44816
45105
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
44817
45106
|
const initialMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
44818
45107
|
const initialScrollPosition = this.env.model.getters.getActiveSheetScrollInfo();
|
|
@@ -45105,78 +45394,6 @@ class GridAddRowsFooter extends Component {
|
|
|
45105
45394
|
}
|
|
45106
45395
|
}
|
|
45107
45396
|
|
|
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
45397
|
/**
|
|
45181
45398
|
* Manages an event listener on a ref. Useful for hooks that want to manage
|
|
45182
45399
|
* event listeners, especially more than one. Prefer using t-on directly in
|
|
@@ -45265,7 +45482,7 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
45265
45482
|
return [];
|
|
45266
45483
|
}
|
|
45267
45484
|
return data.zones.map((zone) => ({
|
|
45268
|
-
zone,
|
|
45485
|
+
range: this.model.getters.getRangeFromZone(data.sheetId, zone),
|
|
45269
45486
|
color: SELECTION_BORDER_COLOR,
|
|
45270
45487
|
dashed: true,
|
|
45271
45488
|
sheetId: data.sheetId,
|
|
@@ -45288,7 +45505,7 @@ class HoveredTableStore extends SpreadsheetStore {
|
|
|
45288
45505
|
}
|
|
45289
45506
|
}
|
|
45290
45507
|
hover(position) {
|
|
45291
|
-
if (position.col === this.col && position.row === this.row) {
|
|
45508
|
+
if (!this.getters.isDashboard() || (position.col === this.col && position.row === this.row)) {
|
|
45292
45509
|
return "noStateChange";
|
|
45293
45510
|
}
|
|
45294
45511
|
this.col = position.col;
|
|
@@ -45322,6 +45539,14 @@ class HoveredTableStore extends SpreadsheetStore {
|
|
|
45322
45539
|
}
|
|
45323
45540
|
}
|
|
45324
45541
|
|
|
45542
|
+
class HoveredIconStore extends SpreadsheetStore {
|
|
45543
|
+
mutators = ["setHoveredIcon"];
|
|
45544
|
+
hoveredIcon = undefined;
|
|
45545
|
+
setHoveredIcon(icon) {
|
|
45546
|
+
this.hoveredIcon = icon;
|
|
45547
|
+
}
|
|
45548
|
+
}
|
|
45549
|
+
|
|
45325
45550
|
const CURSOR_SVG = /*xml*/ `
|
|
45326
45551
|
<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
45552
|
`;
|
|
@@ -45393,10 +45618,11 @@ function useCellHovered(env, gridRef) {
|
|
|
45393
45618
|
return pause();
|
|
45394
45619
|
}
|
|
45395
45620
|
}
|
|
45396
|
-
useRefListener(gridRef, "pointermove", updateMousePosition);
|
|
45621
|
+
useRefListener(gridRef, "pointermove", (ev) => !env.isMobile() && updateMousePosition(ev));
|
|
45397
45622
|
useRefListener(gridRef, "mouseleave", onMouseLeave);
|
|
45398
45623
|
useRefListener(gridRef, "mouseenter", resume);
|
|
45399
45624
|
useRefListener(gridRef, "pointerdown", recompute);
|
|
45625
|
+
useRefListener(gridRef, "pointerdown", (ev) => env.isMobile() && updateMousePosition(ev));
|
|
45400
45626
|
useExternalListener(window, "click", handleGlobalClick);
|
|
45401
45627
|
function handleGlobalClick(e) {
|
|
45402
45628
|
const target = e.target;
|
|
@@ -45425,11 +45651,11 @@ class GridOverlay extends Component {
|
|
|
45425
45651
|
onGridMoved: Function,
|
|
45426
45652
|
gridOverlayDimensions: String,
|
|
45427
45653
|
slots: { type: Object, optional: true },
|
|
45654
|
+
getGridSize: Function,
|
|
45428
45655
|
};
|
|
45429
45656
|
static components = {
|
|
45430
45657
|
FiguresContainer,
|
|
45431
45658
|
GridAddRowsFooter,
|
|
45432
|
-
GridCellIconOverlay,
|
|
45433
45659
|
};
|
|
45434
45660
|
static defaultProps = {
|
|
45435
45661
|
onCellDoubleClicked: () => { },
|
|
@@ -45441,15 +45667,17 @@ class GridOverlay extends Component {
|
|
|
45441
45667
|
gridOverlay = useRef("gridOverlay");
|
|
45442
45668
|
cellPopovers;
|
|
45443
45669
|
paintFormatStore;
|
|
45670
|
+
hoveredIconStore;
|
|
45444
45671
|
setup() {
|
|
45445
45672
|
useCellHovered(this.env, this.gridOverlay);
|
|
45446
45673
|
const resizeObserver = new ResizeObserver(() => {
|
|
45447
45674
|
const boundingRect = this.gridOverlayEl.getBoundingClientRect();
|
|
45675
|
+
const { width, height } = this.props.getGridSize();
|
|
45448
45676
|
this.props.onGridResized({
|
|
45449
45677
|
x: boundingRect.left,
|
|
45450
45678
|
y: boundingRect.top,
|
|
45451
|
-
height:
|
|
45452
|
-
width:
|
|
45679
|
+
height: height,
|
|
45680
|
+
width: width,
|
|
45453
45681
|
});
|
|
45454
45682
|
});
|
|
45455
45683
|
onMounted(() => {
|
|
@@ -45460,6 +45688,7 @@ class GridOverlay extends Component {
|
|
|
45460
45688
|
});
|
|
45461
45689
|
this.cellPopovers = useStore(CellPopoverStore);
|
|
45462
45690
|
this.paintFormatStore = useStore(PaintFormatStore);
|
|
45691
|
+
this.hoveredIconStore = useStore(HoveredIconStore);
|
|
45463
45692
|
}
|
|
45464
45693
|
get gridOverlayEl() {
|
|
45465
45694
|
if (!this.gridOverlay.el) {
|
|
@@ -45468,26 +45697,59 @@ class GridOverlay extends Component {
|
|
|
45468
45697
|
return this.gridOverlay.el;
|
|
45469
45698
|
}
|
|
45470
45699
|
get style() {
|
|
45471
|
-
return this.props.gridOverlayDimensions
|
|
45700
|
+
return (this.props.gridOverlayDimensions +
|
|
45701
|
+
cssPropertiesToCss({ cursor: this.hoveredIconStore.hoveredIcon ? "pointer" : "default" }));
|
|
45472
45702
|
}
|
|
45473
45703
|
get isPaintingFormat() {
|
|
45474
45704
|
return this.paintFormatStore.isActive;
|
|
45475
45705
|
}
|
|
45476
|
-
|
|
45477
|
-
if (
|
|
45706
|
+
onPointerMove(ev) {
|
|
45707
|
+
if (this.env.isMobile()) {
|
|
45708
|
+
return;
|
|
45709
|
+
}
|
|
45710
|
+
const icon = this.getInteractiveIconAtEvent(ev);
|
|
45711
|
+
const hoveredIcon = icon?.type ? { id: icon.type, position: icon.position } : undefined;
|
|
45712
|
+
if (!deepEquals(hoveredIcon, this.hoveredIconStore.hoveredIcon)) {
|
|
45713
|
+
this.hoveredIconStore.setHoveredIcon(hoveredIcon);
|
|
45714
|
+
}
|
|
45715
|
+
}
|
|
45716
|
+
onPointerDown(ev) {
|
|
45717
|
+
if (ev.button > 0 || this.env.isMobile()) {
|
|
45478
45718
|
// not main button, probably a context menu
|
|
45479
45719
|
return;
|
|
45480
45720
|
}
|
|
45481
|
-
|
|
45482
|
-
|
|
45721
|
+
this.onCellClicked(ev);
|
|
45722
|
+
}
|
|
45723
|
+
onClick(ev) {
|
|
45724
|
+
if (ev.button > 0 || !this.env.isMobile()) {
|
|
45725
|
+
// not main button, probably a context menu
|
|
45726
|
+
return;
|
|
45483
45727
|
}
|
|
45728
|
+
this.onCellClicked(ev);
|
|
45729
|
+
}
|
|
45730
|
+
onCellClicked(ev) {
|
|
45731
|
+
const openedPopover = this.cellPopovers.persistentCellPopover;
|
|
45484
45732
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
45485
45733
|
this.props.onCellClicked(col, row, {
|
|
45486
45734
|
expandZone: ev.shiftKey,
|
|
45487
45735
|
addZone: isCtrlKey(ev),
|
|
45488
45736
|
}, ev);
|
|
45737
|
+
const clickedIcon = this.getInteractiveIconAtEvent(ev);
|
|
45738
|
+
if (clickedIcon?.onClick) {
|
|
45739
|
+
clickedIcon.onClick(clickedIcon.position, this.env);
|
|
45740
|
+
}
|
|
45741
|
+
if (ev.target === this.gridOverlay.el &&
|
|
45742
|
+
this.cellPopovers.isOpen &&
|
|
45743
|
+
deepEquals(openedPopover, this.cellPopovers.persistentCellPopover)) {
|
|
45744
|
+
// Only close the popover if props.click/icon.click didn't open a new one
|
|
45745
|
+
this.cellPopovers.close();
|
|
45746
|
+
return;
|
|
45747
|
+
}
|
|
45489
45748
|
}
|
|
45490
45749
|
onDoubleClick(ev) {
|
|
45750
|
+
if (this.getInteractiveIconAtEvent(ev)) {
|
|
45751
|
+
return;
|
|
45752
|
+
}
|
|
45491
45753
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
45492
45754
|
this.props.onCellDoubleClicked(col, row);
|
|
45493
45755
|
}
|
|
@@ -45503,6 +45765,24 @@ class GridOverlay extends Component {
|
|
|
45503
45765
|
const rowIndex = this.env.model.getters.getRowIndex(y);
|
|
45504
45766
|
return [colIndex, rowIndex];
|
|
45505
45767
|
}
|
|
45768
|
+
getInteractiveIconAtEvent(ev) {
|
|
45769
|
+
const gridOverLayRect = getRefBoundingRect(this.gridOverlay);
|
|
45770
|
+
const gridOffset = this.env.model.getters.getGridOffset();
|
|
45771
|
+
const x = ev.clientX - gridOverLayRect.x + gridOffset.x;
|
|
45772
|
+
const y = ev.clientY - gridOverLayRect.y + gridOffset.y;
|
|
45773
|
+
const [col, row] = this.getCartesianCoordinates(ev);
|
|
45774
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
45775
|
+
let position = { col, row, sheetId };
|
|
45776
|
+
const merge = this.env.model.getters.getMerge(position);
|
|
45777
|
+
if (merge) {
|
|
45778
|
+
position = { col: merge.left, row: merge.top, sheetId };
|
|
45779
|
+
}
|
|
45780
|
+
const icons = this.env.model.getters.getCellIcons(position);
|
|
45781
|
+
const icon = icons.find((icon) => {
|
|
45782
|
+
return isPointInsideRect(x, y, this.env.model.getters.getCellIconRect(icon));
|
|
45783
|
+
});
|
|
45784
|
+
return icon?.onClick ? icon : undefined;
|
|
45785
|
+
}
|
|
45506
45786
|
}
|
|
45507
45787
|
|
|
45508
45788
|
class GridPopover extends Component {
|
|
@@ -45663,6 +45943,9 @@ class AbstractResizer extends Component {
|
|
|
45663
45943
|
this.state.waitingForMove = false;
|
|
45664
45944
|
}
|
|
45665
45945
|
onMouseMove(ev) {
|
|
45946
|
+
if (this.env.isMobile()) {
|
|
45947
|
+
return;
|
|
45948
|
+
}
|
|
45666
45949
|
if (this.state.isResizing || this.state.isMoving || this.state.isSelecting) {
|
|
45667
45950
|
return;
|
|
45668
45951
|
}
|
|
@@ -45707,7 +45990,21 @@ class AbstractResizer extends Component {
|
|
|
45707
45990
|
};
|
|
45708
45991
|
startDnd(onMouseMove, onMouseUp);
|
|
45709
45992
|
}
|
|
45993
|
+
onClick(ev) {
|
|
45994
|
+
if (!this.env.isMobile()) {
|
|
45995
|
+
return;
|
|
45996
|
+
}
|
|
45997
|
+
if (ev.button > 0) {
|
|
45998
|
+
// not main button, probably a context menu
|
|
45999
|
+
return;
|
|
46000
|
+
}
|
|
46001
|
+
const index = this._getElementIndex(this._getEvOffset(ev));
|
|
46002
|
+
this._selectElement(index, false);
|
|
46003
|
+
}
|
|
45710
46004
|
select(ev) {
|
|
46005
|
+
if (this.env.isMobile()) {
|
|
46006
|
+
return;
|
|
46007
|
+
}
|
|
45711
46008
|
if (ev.button > 0) {
|
|
45712
46009
|
// not main button, probably a context menu
|
|
45713
46010
|
return;
|
|
@@ -45776,6 +46073,9 @@ class AbstractResizer extends Component {
|
|
|
45776
46073
|
this.dragNDropGrid.start(ev, mouseMoveMovement, mouseUpMovement);
|
|
45777
46074
|
}
|
|
45778
46075
|
startSelection(ev, index) {
|
|
46076
|
+
if (this.env.isMobile()) {
|
|
46077
|
+
return;
|
|
46078
|
+
}
|
|
45779
46079
|
this.state.isSelecting = true;
|
|
45780
46080
|
if (ev.shiftKey) {
|
|
45781
46081
|
this._increaseSelection(index);
|
|
@@ -46221,11 +46521,13 @@ class GridRenderer {
|
|
|
46221
46521
|
renderer;
|
|
46222
46522
|
fingerprints;
|
|
46223
46523
|
hoveredTables;
|
|
46524
|
+
hoveredIcon;
|
|
46224
46525
|
constructor(get) {
|
|
46225
46526
|
this.getters = get(ModelStore).getters;
|
|
46226
46527
|
this.renderer = get(RendererStore);
|
|
46227
46528
|
this.fingerprints = get(FormulaFingerprintStore);
|
|
46228
46529
|
this.hoveredTables = get(HoveredTableStore);
|
|
46530
|
+
this.hoveredIcon = get(HoveredIconStore);
|
|
46229
46531
|
this.renderer.register(this);
|
|
46230
46532
|
}
|
|
46231
46533
|
get renderingLayers() {
|
|
@@ -46462,7 +46764,7 @@ class GridRenderer {
|
|
|
46462
46764
|
// compute vertical align start point parameter:
|
|
46463
46765
|
const textLineHeight = computeTextFontSizeInPixels(style);
|
|
46464
46766
|
const numberOfLines = box.content.textLines.length;
|
|
46465
|
-
let y = this.computeTextYCoordinate(box, textLineHeight, numberOfLines);
|
|
46767
|
+
let y = this.getters.computeTextYCoordinate(box, textLineHeight, style.verticalAlign, numberOfLines);
|
|
46466
46768
|
// use the horizontal and the vertical start points to:
|
|
46467
46769
|
// fill text / fill strikethrough / fill underline
|
|
46468
46770
|
for (const brokenLine of box.content.textLines) {
|
|
@@ -46479,7 +46781,12 @@ class GridRenderer {
|
|
|
46479
46781
|
const { ctx } = renderingContext;
|
|
46480
46782
|
for (const box of boxes) {
|
|
46481
46783
|
for (const icon of Object.values(box.icons)) {
|
|
46482
|
-
if (!icon
|
|
46784
|
+
if (!icon) {
|
|
46785
|
+
continue;
|
|
46786
|
+
}
|
|
46787
|
+
const isHovered = deepEquals({ id: icon.type, position: icon.position }, this.hoveredIcon.hoveredIcon);
|
|
46788
|
+
const svg = isHovered ? icon.hoverSvg || icon.svg : icon.svg;
|
|
46789
|
+
if (!svg) {
|
|
46483
46790
|
continue;
|
|
46484
46791
|
}
|
|
46485
46792
|
ctx.save();
|
|
@@ -46487,46 +46794,17 @@ class GridRenderer {
|
|
|
46487
46794
|
ctx.rect(box.x, box.y, box.width, box.height);
|
|
46488
46795
|
ctx.clip();
|
|
46489
46796
|
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);
|
|
46797
|
+
const { x, y } = this.getters.getCellIconRect(icon);
|
|
46798
|
+
ctx.translate(x, y);
|
|
46503
46799
|
ctx.scale(iconSize / svg.width, iconSize / svg.height);
|
|
46504
|
-
|
|
46505
|
-
|
|
46800
|
+
for (const path of svg.paths) {
|
|
46801
|
+
ctx.fillStyle = path.fillColor;
|
|
46802
|
+
ctx.fill(getPath2D(path.path));
|
|
46803
|
+
}
|
|
46506
46804
|
ctx.restore();
|
|
46507
46805
|
}
|
|
46508
46806
|
}
|
|
46509
46807
|
}
|
|
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
46808
|
drawHeaders(renderingContext) {
|
|
46531
46809
|
const { ctx, thinLineWidth } = renderingContext;
|
|
46532
46810
|
const visibleCols = this.getters.getSheetViewVisibleCols();
|
|
@@ -46963,6 +47241,9 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
|
46963
47241
|
const deltaX = lastX - clientX;
|
|
46964
47242
|
const deltaY = lastY - clientY;
|
|
46965
47243
|
const elapsedTime = currentTime - lastTime;
|
|
47244
|
+
if (!elapsedTime) {
|
|
47245
|
+
return;
|
|
47246
|
+
}
|
|
46966
47247
|
velocityX = deltaX / elapsedTime;
|
|
46967
47248
|
velocityY = deltaY / elapsedTime;
|
|
46968
47249
|
lastX = clientX;
|
|
@@ -46983,6 +47264,11 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
|
46983
47264
|
function onTouchEnd(ev) {
|
|
46984
47265
|
isMouseDown = false;
|
|
46985
47266
|
lastX = lastY = 0;
|
|
47267
|
+
if (resetTimeout) {
|
|
47268
|
+
clearTimeout(resetTimeout);
|
|
47269
|
+
}
|
|
47270
|
+
velocityX *= 1.2;
|
|
47271
|
+
velocityY *= 1.2;
|
|
46986
47272
|
requestAnimationFrame(scroll);
|
|
46987
47273
|
}
|
|
46988
47274
|
function scroll() {
|
|
@@ -47067,12 +47353,16 @@ class Border extends Component {
|
|
|
47067
47353
|
}
|
|
47068
47354
|
}
|
|
47069
47355
|
|
|
47356
|
+
const MOBILE_HANDLER_WIDTH = 40;
|
|
47070
47357
|
css /* scss */ `
|
|
47071
47358
|
.o-corner {
|
|
47072
47359
|
position: absolute;
|
|
47073
|
-
|
|
47074
|
-
|
|
47360
|
+
}
|
|
47361
|
+
|
|
47362
|
+
.o-corner-button {
|
|
47075
47363
|
border: 1px solid white;
|
|
47364
|
+
height: ${AUTOFILL_EDGE_LENGTH}px;
|
|
47365
|
+
width: ${AUTOFILL_EDGE_LENGTH}px;
|
|
47076
47366
|
}
|
|
47077
47367
|
.o-corner-nw,
|
|
47078
47368
|
.o-corner-se {
|
|
@@ -47099,34 +47389,61 @@ class Corner extends Component {
|
|
|
47099
47389
|
isResizing: Boolean,
|
|
47100
47390
|
onResizeHighlight: Function,
|
|
47101
47391
|
};
|
|
47102
|
-
|
|
47103
|
-
|
|
47104
|
-
|
|
47392
|
+
dirX;
|
|
47393
|
+
dirY;
|
|
47394
|
+
setup() {
|
|
47395
|
+
const { dirX, dirY } = orientationToDir(this.props.orientation);
|
|
47396
|
+
this.dirX = dirX;
|
|
47397
|
+
this.dirY = dirY;
|
|
47398
|
+
}
|
|
47399
|
+
get handlerStyle() {
|
|
47105
47400
|
const z = this.props.zone;
|
|
47106
|
-
const col = this.isLeft ? z.left : z.right;
|
|
47107
|
-
const row = this.isTop ? z.top : z.bottom;
|
|
47108
47401
|
const rect = this.env.model.getters.getVisibleRect({
|
|
47109
|
-
left:
|
|
47110
|
-
right:
|
|
47111
|
-
top:
|
|
47112
|
-
bottom:
|
|
47402
|
+
left: this.dirX === 1 ? z.right : z.left,
|
|
47403
|
+
right: this.dirX === -1 ? z.left : z.right,
|
|
47404
|
+
top: this.dirY === 1 ? z.bottom : z.top,
|
|
47405
|
+
bottom: this.dirY === -1 ? z.top : z.bottom,
|
|
47113
47406
|
});
|
|
47114
47407
|
// Don't show if not visible in the viewport
|
|
47115
47408
|
if (rect.width * rect.height === 0) {
|
|
47116
|
-
return `display:none
|
|
47409
|
+
return `display: none !important;`;
|
|
47410
|
+
}
|
|
47411
|
+
const leftValue = rect.x + rect.width / 2 + (this.dirX * rect.width) / 2;
|
|
47412
|
+
const topValue = rect.y + rect.height / 2 + (this.dirY * rect.height) / 2;
|
|
47413
|
+
const edgeLength = this.getHandlerEdgeLength();
|
|
47414
|
+
const css = {
|
|
47415
|
+
left: `${leftValue - edgeLength / 2}px`,
|
|
47416
|
+
top: `${topValue - edgeLength / 2}px`,
|
|
47417
|
+
height: `${edgeLength}px`,
|
|
47418
|
+
width: `${edgeLength}px`,
|
|
47419
|
+
};
|
|
47420
|
+
if (this.env.isMobile()) {
|
|
47421
|
+
css["border-radius"] = `${edgeLength / 2}px`;
|
|
47117
47422
|
}
|
|
47118
|
-
|
|
47119
|
-
|
|
47120
|
-
|
|
47121
|
-
|
|
47122
|
-
|
|
47423
|
+
return cssPropertiesToCss(css);
|
|
47424
|
+
}
|
|
47425
|
+
getHandlerEdgeLength() {
|
|
47426
|
+
return this.env.isMobile() ? MOBILE_HANDLER_WIDTH : AUTOFILL_EDGE_LENGTH;
|
|
47427
|
+
}
|
|
47428
|
+
get buttonLook() {
|
|
47429
|
+
const css = {
|
|
47123
47430
|
"background-color": this.props.color,
|
|
47124
|
-
|
|
47431
|
+
cursor: `${this.props.orientation}-resize`,
|
|
47432
|
+
};
|
|
47433
|
+
if (this.env.isMobile()) {
|
|
47434
|
+
css["border-radius"] = `${AUTOFILL_EDGE_LENGTH / 2}px`;
|
|
47435
|
+
}
|
|
47436
|
+
return cssPropertiesToCss(css);
|
|
47125
47437
|
}
|
|
47126
47438
|
onMouseDown(ev) {
|
|
47127
|
-
this.props.onResizeHighlight(ev, this.
|
|
47439
|
+
this.props.onResizeHighlight(ev, this.dirX, this.dirY);
|
|
47128
47440
|
}
|
|
47129
47441
|
}
|
|
47442
|
+
function orientationToDir(or) {
|
|
47443
|
+
const dirX = or.includes("w") ? -1 : or.includes("e") ? 1 : 0;
|
|
47444
|
+
const dirY = or.includes("n") ? -1 : or.includes("s") ? 1 : 0;
|
|
47445
|
+
return { dirX, dirY };
|
|
47446
|
+
}
|
|
47130
47447
|
|
|
47131
47448
|
css /*SCSS*/ `
|
|
47132
47449
|
.o-highlight {
|
|
@@ -47136,7 +47453,7 @@ css /*SCSS*/ `
|
|
|
47136
47453
|
class Highlight extends Component {
|
|
47137
47454
|
static template = "o-spreadsheet-Highlight";
|
|
47138
47455
|
static props = {
|
|
47139
|
-
|
|
47456
|
+
range: Object,
|
|
47140
47457
|
color: String,
|
|
47141
47458
|
};
|
|
47142
47459
|
static components = {
|
|
@@ -47147,26 +47464,49 @@ class Highlight extends Component {
|
|
|
47147
47464
|
shiftingMode: "none",
|
|
47148
47465
|
});
|
|
47149
47466
|
dragNDropGrid = useDragAndDropBeyondTheViewport(this.env);
|
|
47150
|
-
|
|
47467
|
+
get cornerOrientations() {
|
|
47468
|
+
if (!this.env.isMobile()) {
|
|
47469
|
+
return ["nw", "ne", "sw", "se"];
|
|
47470
|
+
}
|
|
47471
|
+
const z = this.props.range.unboundedZone;
|
|
47472
|
+
if (z.bottom === undefined) {
|
|
47473
|
+
return ["w", "e"];
|
|
47474
|
+
}
|
|
47475
|
+
else if (z.right === undefined) {
|
|
47476
|
+
return ["n", "s"];
|
|
47477
|
+
}
|
|
47478
|
+
else {
|
|
47479
|
+
return ["nw", "se"];
|
|
47480
|
+
}
|
|
47481
|
+
}
|
|
47482
|
+
onResizeHighlight(ev, dirX, dirY) {
|
|
47151
47483
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
47152
47484
|
this.highlightState.shiftingMode = "isResizing";
|
|
47153
|
-
const z = this.props.zone;
|
|
47154
|
-
const pivotCol =
|
|
47155
|
-
const pivotRow =
|
|
47156
|
-
let lastCol =
|
|
47157
|
-
let lastRow =
|
|
47485
|
+
const z = this.props.range.zone;
|
|
47486
|
+
const pivotCol = dirX === 1 ? z.left : z.right;
|
|
47487
|
+
const pivotRow = dirY === 1 ? z.top : z.bottom;
|
|
47488
|
+
let lastCol = dirX === 1 ? z.right : z.left;
|
|
47489
|
+
let lastRow = dirY === 1 ? z.bottom : z.top;
|
|
47158
47490
|
let currentZone = z;
|
|
47491
|
+
let scrollDirection = "all";
|
|
47492
|
+
if (this.env.isMobile()) {
|
|
47493
|
+
scrollDirection = dirX === 0 ? "vertical" : dirY === 0 ? "horizontal" : "all";
|
|
47494
|
+
}
|
|
47159
47495
|
this.env.model.dispatch("START_CHANGE_HIGHLIGHT", { zone: currentZone });
|
|
47160
47496
|
const mouseMove = (col, row) => {
|
|
47161
47497
|
if (lastCol !== col || lastRow !== row) {
|
|
47162
|
-
|
|
47163
|
-
|
|
47164
|
-
|
|
47165
|
-
|
|
47166
|
-
|
|
47167
|
-
|
|
47168
|
-
|
|
47169
|
-
|
|
47498
|
+
let { left, right, top, bottom } = currentZone;
|
|
47499
|
+
if (scrollDirection !== "horizontal") {
|
|
47500
|
+
lastRow = lastRow = clip(row === -1 ? lastRow : row, 0, this.env.model.getters.getNumberRows(activeSheetId) - 1);
|
|
47501
|
+
top = Math.min(pivotRow, lastRow);
|
|
47502
|
+
bottom = Math.max(pivotRow, lastRow);
|
|
47503
|
+
}
|
|
47504
|
+
if (scrollDirection !== "vertical") {
|
|
47505
|
+
lastCol = clip(col === -1 ? lastCol : col, 0, this.env.model.getters.getNumberCols(activeSheetId) - 1);
|
|
47506
|
+
left = Math.min(pivotCol, lastCol);
|
|
47507
|
+
right = Math.max(pivotCol, lastCol);
|
|
47508
|
+
}
|
|
47509
|
+
const newZone = { left, right, top, bottom };
|
|
47170
47510
|
if (!isEqual(newZone, currentZone)) {
|
|
47171
47511
|
this.env.model.selection.selectZone({
|
|
47172
47512
|
cell: { col: newZone.left, row: newZone.top },
|
|
@@ -47179,11 +47519,11 @@ class Highlight extends Component {
|
|
|
47179
47519
|
const mouseUp = () => {
|
|
47180
47520
|
this.highlightState.shiftingMode = "none";
|
|
47181
47521
|
};
|
|
47182
|
-
this.dragNDropGrid.start(ev, mouseMove, mouseUp);
|
|
47522
|
+
this.dragNDropGrid.start(ev, mouseMove, mouseUp, scrollDirection);
|
|
47183
47523
|
}
|
|
47184
47524
|
onMoveHighlight(ev) {
|
|
47185
47525
|
this.highlightState.shiftingMode = "isMoving";
|
|
47186
|
-
const z = this.props.zone;
|
|
47526
|
+
const z = this.props.range.zone;
|
|
47187
47527
|
const position = gridOverlayPosition();
|
|
47188
47528
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
47189
47529
|
const initCol = this.env.model.getters.getColIndex(ev.clientX - position.left);
|
|
@@ -47405,6 +47745,18 @@ class VerticalScrollBar extends Component {
|
|
|
47405
47745
|
}
|
|
47406
47746
|
}
|
|
47407
47747
|
|
|
47748
|
+
class Selection extends Component {
|
|
47749
|
+
static template = "o-spreadsheet-Selection";
|
|
47750
|
+
static props = {};
|
|
47751
|
+
static components = { Highlight };
|
|
47752
|
+
get highlightProps() {
|
|
47753
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
47754
|
+
const zone = this.env.model.getters.getUnboundedZone(sheetId, this.env.model.getters.getSelectedZone());
|
|
47755
|
+
const range = this.env.model.getters.getRangeFromZone(sheetId, zone);
|
|
47756
|
+
return { range, color: SELECTION_BORDER_COLOR };
|
|
47757
|
+
}
|
|
47758
|
+
}
|
|
47759
|
+
|
|
47408
47760
|
class Section extends Component {
|
|
47409
47761
|
static template = "o_spreadsheet.Section";
|
|
47410
47762
|
static props = {
|
|
@@ -48350,6 +48702,7 @@ class ColorPickerWidget extends Component {
|
|
|
48350
48702
|
|
|
48351
48703
|
css /* scss */ `
|
|
48352
48704
|
.o-font-size-editor {
|
|
48705
|
+
width: max-content !important;
|
|
48353
48706
|
height: calc(100% - 4px);
|
|
48354
48707
|
input.o-font-size {
|
|
48355
48708
|
outline: none;
|
|
@@ -50498,8 +50851,7 @@ class ConditionalFormatPreview extends Component {
|
|
|
50498
50851
|
get highlights() {
|
|
50499
50852
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
50500
50853
|
return this.props.conditionalFormat.ranges.map((range) => ({
|
|
50501
|
-
sheetId,
|
|
50502
|
-
zone: this.env.model.getters.getRangeFromSheetXC(sheetId, range).zone,
|
|
50854
|
+
range: this.env.model.getters.getRangeFromSheetXC(sheetId, range),
|
|
50503
50855
|
color: HIGHLIGHT_COLOR,
|
|
50504
50856
|
fillAlpha: 0.06,
|
|
50505
50857
|
}));
|
|
@@ -51457,8 +51809,7 @@ class DataValidationPreview extends Component {
|
|
|
51457
51809
|
}
|
|
51458
51810
|
get highlights() {
|
|
51459
51811
|
return this.props.rule.ranges.map((range) => ({
|
|
51460
|
-
|
|
51461
|
-
zone: range.zone,
|
|
51812
|
+
range,
|
|
51462
51813
|
color: HIGHLIGHT_COLOR,
|
|
51463
51814
|
fillAlpha: 0.06,
|
|
51464
51815
|
}));
|
|
@@ -51787,13 +52138,15 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
51787
52138
|
if (this.selectedMatchIndex === null) {
|
|
51788
52139
|
return;
|
|
51789
52140
|
}
|
|
52141
|
+
this.preserveSelectedMatchIndex = true;
|
|
52142
|
+
this.shouldFinalizeUpdateSelection = true;
|
|
51790
52143
|
this.model.dispatch("REPLACE_SEARCH", {
|
|
51791
52144
|
searchString: this.toSearch,
|
|
51792
52145
|
replaceWith: this.toReplace,
|
|
51793
52146
|
matches: [this.searchMatches[this.selectedMatchIndex]],
|
|
51794
52147
|
searchOptions: this.searchOptions,
|
|
51795
52148
|
});
|
|
51796
|
-
this.
|
|
52149
|
+
this.preserveSelectedMatchIndex = false;
|
|
51797
52150
|
}
|
|
51798
52151
|
/**
|
|
51799
52152
|
* Apply the replace function to all the matches one time.
|
|
@@ -51865,8 +52218,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
51865
52218
|
const { width, height } = this.getters.getVisibleRect(zoneWithMerge);
|
|
51866
52219
|
if (width > 0 && height > 0) {
|
|
51867
52220
|
highlights.push({
|
|
51868
|
-
sheetId,
|
|
51869
|
-
zone: zoneWithMerge,
|
|
52221
|
+
range: this.model.getters.getRangeFromZone(sheetId, zoneWithMerge),
|
|
51870
52222
|
color: FIND_AND_REPLACE_HIGHLIGHT_COLOR,
|
|
51871
52223
|
noBorder: index !== this.selectedMatchIndex,
|
|
51872
52224
|
thinLine: true,
|
|
@@ -51878,8 +52230,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
51878
52230
|
const range = this.searchOptions.specificRange;
|
|
51879
52231
|
if (range && range.sheetId === sheetId) {
|
|
51880
52232
|
highlights.push({
|
|
51881
|
-
|
|
51882
|
-
zone: range.zone,
|
|
52233
|
+
range,
|
|
51883
52234
|
color: FIND_AND_REPLACE_HIGHLIGHT_COLOR,
|
|
51884
52235
|
noFill: true,
|
|
51885
52236
|
thinLine: true,
|
|
@@ -52253,7 +52604,11 @@ function getPivotHighlights(getters, pivotId) {
|
|
|
52253
52604
|
const sheetId = getters.getActiveSheetId();
|
|
52254
52605
|
const pivotCellPositions = getVisiblePivotCellPositions(getters, pivotId);
|
|
52255
52606
|
const mergedZones = mergeContiguousZones(pivotCellPositions.map(positionToZone));
|
|
52256
|
-
return mergedZones.map((zone) => ({
|
|
52607
|
+
return mergedZones.map((zone) => ({
|
|
52608
|
+
range: getters.getRangeFromZone(sheetId, zone),
|
|
52609
|
+
noFill: true,
|
|
52610
|
+
color: HIGHLIGHT_COLOR,
|
|
52611
|
+
}));
|
|
52257
52612
|
}
|
|
52258
52613
|
function getVisiblePivotCellPositions(getters, pivotId) {
|
|
52259
52614
|
const positions = [];
|
|
@@ -52522,7 +52877,7 @@ class TextInput extends Component {
|
|
|
52522
52877
|
|
|
52523
52878
|
class CogWheelMenu extends Component {
|
|
52524
52879
|
static template = "o-spreadsheet-CogWheelMenu";
|
|
52525
|
-
static components = {
|
|
52880
|
+
static components = { MenuPopover };
|
|
52526
52881
|
static props = {
|
|
52527
52882
|
items: Array,
|
|
52528
52883
|
};
|
|
@@ -55092,6 +55447,7 @@ function createTableStyleContextMenuActions(env, styleId) {
|
|
|
55092
55447
|
id: "editTableStyle",
|
|
55093
55448
|
name: _t("Edit table style"),
|
|
55094
55449
|
execute: (env) => env.openSidePanel("TableStyleEditorPanel", { styleId }),
|
|
55450
|
+
isEnabled: (env) => !env.isSmall,
|
|
55095
55451
|
icon: "o-spreadsheet-Icon.EDIT",
|
|
55096
55452
|
},
|
|
55097
55453
|
{
|
|
@@ -55213,7 +55569,7 @@ css /* scss */ `
|
|
|
55213
55569
|
`;
|
|
55214
55570
|
class TableStylePreview extends Component {
|
|
55215
55571
|
static template = "o-spreadsheet-TableStylePreview";
|
|
55216
|
-
static components = {
|
|
55572
|
+
static components = { MenuPopover };
|
|
55217
55573
|
static props = {
|
|
55218
55574
|
tableConfig: Object,
|
|
55219
55575
|
tableStyle: Object,
|
|
@@ -55784,6 +56140,17 @@ sidePanelRegistry.add("PivotMeasureDisplayPanel", {
|
|
|
55784
56140
|
},
|
|
55785
56141
|
});
|
|
55786
56142
|
|
|
56143
|
+
class ScreenWidthStore {
|
|
56144
|
+
mutators = ["setSmallThreshhold"];
|
|
56145
|
+
_isSmallCallback = () => false;
|
|
56146
|
+
get isSmall() {
|
|
56147
|
+
return this._isSmallCallback();
|
|
56148
|
+
}
|
|
56149
|
+
setSmallThreshhold(isSmall) {
|
|
56150
|
+
this._isSmallCallback = isSmall;
|
|
56151
|
+
}
|
|
56152
|
+
}
|
|
56153
|
+
|
|
55787
56154
|
const DEFAULT_SIDE_PANEL_SIZE = 350;
|
|
55788
56155
|
const MIN_SHEET_VIEW_WIDTH = 150;
|
|
55789
56156
|
class SidePanelStore extends SpreadsheetStore {
|
|
@@ -55791,6 +56158,7 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
55791
56158
|
initialPanelProps = {};
|
|
55792
56159
|
componentTag = "";
|
|
55793
56160
|
panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
56161
|
+
screenWidthStore = this.get(ScreenWidthStore);
|
|
55794
56162
|
get isOpen() {
|
|
55795
56163
|
if (!this.componentTag) {
|
|
55796
56164
|
return false;
|
|
@@ -55812,6 +56180,9 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
55812
56180
|
return undefined;
|
|
55813
56181
|
}
|
|
55814
56182
|
open(componentTag, panelProps = {}) {
|
|
56183
|
+
if (this.screenWidthStore.isSmall) {
|
|
56184
|
+
return;
|
|
56185
|
+
}
|
|
55815
56186
|
const state = this.computeState(componentTag, panelProps);
|
|
55816
56187
|
if (!state.isOpen) {
|
|
55817
56188
|
return;
|
|
@@ -55926,8 +56297,7 @@ class TableResizer extends Component {
|
|
|
55926
56297
|
return [];
|
|
55927
56298
|
return [
|
|
55928
56299
|
{
|
|
55929
|
-
|
|
55930
|
-
sheetId: this.props.table.range.sheetId,
|
|
56300
|
+
range: this.env.model.getters.getRangeFromZone(this.props.table.range.sheetId, this.state.highlightZone),
|
|
55931
56301
|
color: COLOR,
|
|
55932
56302
|
noFill: true,
|
|
55933
56303
|
},
|
|
@@ -55949,13 +56319,14 @@ class Grid extends Component {
|
|
|
55949
56319
|
static template = "o-spreadsheet-Grid";
|
|
55950
56320
|
static props = {
|
|
55951
56321
|
exposeFocus: Function,
|
|
56322
|
+
getGridSize: Function,
|
|
55952
56323
|
};
|
|
55953
56324
|
static components = {
|
|
55954
56325
|
GridComposer,
|
|
55955
56326
|
GridOverlay,
|
|
55956
56327
|
GridPopover,
|
|
55957
56328
|
HeadersOverlay,
|
|
55958
|
-
|
|
56329
|
+
MenuPopover,
|
|
55959
56330
|
Autofill,
|
|
55960
56331
|
ClientTag,
|
|
55961
56332
|
Highlight,
|
|
@@ -55963,6 +56334,7 @@ class Grid extends Component {
|
|
|
55963
56334
|
VerticalScrollBar,
|
|
55964
56335
|
HorizontalScrollBar,
|
|
55965
56336
|
TableResizer,
|
|
56337
|
+
Selection,
|
|
55966
56338
|
};
|
|
55967
56339
|
HEADER_HEIGHT = HEADER_HEIGHT;
|
|
55968
56340
|
HEADER_WIDTH = HEADER_WIDTH;
|
|
@@ -56245,8 +56617,8 @@ class Grid extends Component {
|
|
|
56245
56617
|
}
|
|
56246
56618
|
onGridResized({ height, width }) {
|
|
56247
56619
|
this.env.model.dispatch("RESIZE_SHEETVIEW", {
|
|
56248
|
-
width: width,
|
|
56249
|
-
height: height,
|
|
56620
|
+
width: width - HEADER_WIDTH,
|
|
56621
|
+
height: height - HEADER_HEIGHT,
|
|
56250
56622
|
gridOffsetX: HEADER_WIDTH,
|
|
56251
56623
|
gridOffsetY: HEADER_HEIGHT,
|
|
56252
56624
|
});
|
|
@@ -56300,6 +56672,9 @@ class Grid extends Component {
|
|
|
56300
56672
|
else {
|
|
56301
56673
|
this.env.model.selection.selectCell(col, row);
|
|
56302
56674
|
}
|
|
56675
|
+
if (this.env.isMobile()) {
|
|
56676
|
+
return;
|
|
56677
|
+
}
|
|
56303
56678
|
let prevCol = col;
|
|
56304
56679
|
let prevRow = row;
|
|
56305
56680
|
const onMouseMove = (col, row, ev) => {
|
|
@@ -56585,6 +56960,9 @@ class Grid extends Component {
|
|
|
56585
56960
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
56586
56961
|
return this.env.model.getters.getCoreTables(sheetId).filter(isStaticTable);
|
|
56587
56962
|
}
|
|
56963
|
+
get displaySelectionHandler() {
|
|
56964
|
+
return this.env.isMobile() && this.composerFocusStore.activeComposer.editionMode === "inactive";
|
|
56965
|
+
}
|
|
56588
56966
|
}
|
|
56589
56967
|
|
|
56590
56968
|
/**
|
|
@@ -62511,7 +62889,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62511
62889
|
break;
|
|
62512
62890
|
}
|
|
62513
62891
|
case "UPDATE_PIVOT": {
|
|
62514
|
-
this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
|
|
62892
|
+
this.history.update("pivots", cmd.pivotId, "definition", this.repairSortedColumn(deepCopy(cmd.pivot)));
|
|
62515
62893
|
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
62516
62894
|
break;
|
|
62517
62895
|
}
|
|
@@ -62582,7 +62960,10 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62582
62960
|
// Private
|
|
62583
62961
|
// -------------------------------------------------------------------------
|
|
62584
62962
|
addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
|
|
62585
|
-
this.history.update("pivots", pivotId, {
|
|
62963
|
+
this.history.update("pivots", pivotId, {
|
|
62964
|
+
definition: this.repairSortedColumn(deepCopy(pivot)),
|
|
62965
|
+
formulaId,
|
|
62966
|
+
});
|
|
62586
62967
|
this.compileCalculatedMeasures(pivot.measures);
|
|
62587
62968
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
62588
62969
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
@@ -62671,6 +63052,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62671
63052
|
}
|
|
62672
63053
|
}
|
|
62673
63054
|
checkSortedColumnInMeasures(definition) {
|
|
63055
|
+
definition = this.repairSortedColumn(definition);
|
|
62674
63056
|
const measures = definition.measures.map((measure) => measure.id);
|
|
62675
63057
|
if (definition.sortedColumn && !measures.includes(definition.sortedColumn.measure)) {
|
|
62676
63058
|
return "InvalidDefinition" /* CommandResult.InvalidDefinition */;
|
|
@@ -62684,6 +63066,26 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
62684
63066
|
}
|
|
62685
63067
|
return "Success" /* CommandResult.Success */;
|
|
62686
63068
|
}
|
|
63069
|
+
repairSortedColumn(definition) {
|
|
63070
|
+
if (definition.sortedColumn) {
|
|
63071
|
+
// Fix for an upgrade issue: the sortedColumn measure was not updated
|
|
63072
|
+
// from using fieldName to using id. If the sortedColumn measure matches
|
|
63073
|
+
// a measure fieldName in the definition, update it to use the measure's id instead
|
|
63074
|
+
// of its fieldName.
|
|
63075
|
+
// TODO: add an upgrade step to fix this in master and remove this code
|
|
63076
|
+
const sortedMeasure = definition.measures.find((measure) => measure.fieldName === definition.sortedColumn?.measure);
|
|
63077
|
+
if (sortedMeasure) {
|
|
63078
|
+
return {
|
|
63079
|
+
...definition,
|
|
63080
|
+
sortedColumn: {
|
|
63081
|
+
...definition.sortedColumn,
|
|
63082
|
+
measure: sortedMeasure.id,
|
|
63083
|
+
},
|
|
63084
|
+
};
|
|
63085
|
+
}
|
|
63086
|
+
}
|
|
63087
|
+
return definition;
|
|
63088
|
+
}
|
|
62687
63089
|
// ---------------------------------------------------------------------
|
|
62688
63090
|
// Import/Export
|
|
62689
63091
|
// ---------------------------------------------------------------------
|
|
@@ -65551,186 +65953,6 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
|
|
|
65551
65953
|
}
|
|
65552
65954
|
}
|
|
65553
65955
|
|
|
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
65956
|
/**
|
|
65735
65957
|
* Registry to draw icons on cells
|
|
65736
65958
|
*/
|
|
@@ -65738,14 +65960,25 @@ const iconsOnCellRegistry = new Registry();
|
|
|
65738
65960
|
iconsOnCellRegistry.add("data_validation_checkbox", (getters, position) => {
|
|
65739
65961
|
const hasIcon = getters.isCellValidCheckbox(position);
|
|
65740
65962
|
if (hasIcon) {
|
|
65963
|
+
const value = !!getters.getEvaluatedCell(position).value;
|
|
65741
65964
|
return {
|
|
65742
|
-
svg:
|
|
65965
|
+
svg: value ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED,
|
|
65966
|
+
hoverSvg: value ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED_HOVERED,
|
|
65743
65967
|
priority: 2,
|
|
65744
65968
|
horizontalAlign: "center",
|
|
65745
65969
|
size: GRID_ICON_EDGE_LENGTH,
|
|
65746
65970
|
margin: GRID_ICON_MARGIN,
|
|
65747
|
-
component: DataValidationCheckbox,
|
|
65748
65971
|
position,
|
|
65972
|
+
type: "data_validation_checkbox",
|
|
65973
|
+
onClick: (position, env) => {
|
|
65974
|
+
const cell = env.model.getters.getCell(position);
|
|
65975
|
+
const isDisabled = env.model.getters.isReadonly() || !!cell?.isFormula;
|
|
65976
|
+
if (isDisabled) {
|
|
65977
|
+
return;
|
|
65978
|
+
}
|
|
65979
|
+
const cellContent = value ? "FALSE" : "TRUE";
|
|
65980
|
+
env.model.dispatch("UPDATE_CELL", { ...position, content: cellContent });
|
|
65981
|
+
},
|
|
65749
65982
|
};
|
|
65750
65983
|
}
|
|
65751
65984
|
return undefined;
|
|
@@ -65754,13 +65987,19 @@ iconsOnCellRegistry.add("data_validation_list_icon", (getters, position) => {
|
|
|
65754
65987
|
const hasIcon = !getters.isReadonly() && getters.cellHasListDataValidationIcon(position);
|
|
65755
65988
|
if (hasIcon) {
|
|
65756
65989
|
return {
|
|
65757
|
-
svg:
|
|
65990
|
+
svg: CARET_DOWN,
|
|
65991
|
+
hoverSvg: HOVERED_CARET_DOWN,
|
|
65758
65992
|
priority: 2,
|
|
65759
65993
|
horizontalAlign: "right",
|
|
65760
65994
|
size: GRID_ICON_EDGE_LENGTH,
|
|
65761
65995
|
margin: GRID_ICON_MARGIN,
|
|
65762
|
-
component: DataValidationListIcon,
|
|
65763
65996
|
position,
|
|
65997
|
+
onClick: (position, env) => {
|
|
65998
|
+
const { col, row } = position;
|
|
65999
|
+
env.model.selection.selectCell(col, row);
|
|
66000
|
+
env.startCellEdition();
|
|
66001
|
+
},
|
|
66002
|
+
type: "data_validation_list_icon",
|
|
65764
66003
|
};
|
|
65765
66004
|
}
|
|
65766
66005
|
return undefined;
|
|
@@ -65768,14 +66007,30 @@ iconsOnCellRegistry.add("data_validation_list_icon", (getters, position) => {
|
|
|
65768
66007
|
iconsOnCellRegistry.add("filter_icon", (getters, position) => {
|
|
65769
66008
|
const hasIcon = getters.isFilterHeader(position);
|
|
65770
66009
|
if (hasIcon) {
|
|
66010
|
+
const isFilterActive = getters.isFilterActive(position);
|
|
66011
|
+
const cellStyle = getters.getCellComputedStyle(position);
|
|
66012
|
+
const isHighContrast = relativeLuminance(cellStyle.fillColor || "#fff") < 0.45;
|
|
65771
66013
|
return {
|
|
65772
|
-
|
|
66014
|
+
type: "filter_icon",
|
|
66015
|
+
svg: getDataFilterIcon(isFilterActive, isHighContrast, false),
|
|
66016
|
+
hoverSvg: getDataFilterIcon(isFilterActive, isHighContrast, true),
|
|
65773
66017
|
priority: 3,
|
|
65774
66018
|
horizontalAlign: "right",
|
|
65775
66019
|
size: GRID_ICON_EDGE_LENGTH,
|
|
65776
66020
|
margin: GRID_ICON_MARGIN,
|
|
65777
|
-
component: FilterIcon,
|
|
65778
66021
|
position,
|
|
66022
|
+
onClick: (position, env) => {
|
|
66023
|
+
const cellPopovers = env.getStore(CellPopoverStore);
|
|
66024
|
+
const activePopover = cellPopovers.persistentCellPopover;
|
|
66025
|
+
if (activePopover.isOpen &&
|
|
66026
|
+
activePopover.col === position.col &&
|
|
66027
|
+
activePopover.row === position.row &&
|
|
66028
|
+
activePopover.type === "FilterMenu") {
|
|
66029
|
+
cellPopovers.close();
|
|
66030
|
+
return;
|
|
66031
|
+
}
|
|
66032
|
+
cellPopovers.open(position, "FilterMenu");
|
|
66033
|
+
},
|
|
65779
66034
|
};
|
|
65780
66035
|
}
|
|
65781
66036
|
return undefined;
|
|
@@ -65785,6 +66040,7 @@ iconsOnCellRegistry.add("conditional_formatting", (getters, position) => {
|
|
|
65785
66040
|
if (icon) {
|
|
65786
66041
|
const style = getters.getCellStyle(position);
|
|
65787
66042
|
return {
|
|
66043
|
+
type: "conditional_formatting",
|
|
65788
66044
|
svg: ICONS[icon].svg,
|
|
65789
66045
|
priority: 1,
|
|
65790
66046
|
horizontalAlign: "left",
|
|
@@ -65805,23 +66061,55 @@ iconsOnCellRegistry.add("pivot_collapse", (getters, position) => {
|
|
|
65805
66061
|
const definition = getters.getPivotCoreDefinition(pivotId);
|
|
65806
66062
|
const isDashboard = getters.isDashboard();
|
|
65807
66063
|
const fields = pivotCell.dimension === "COL" ? definition.columns : definition.rows;
|
|
65808
|
-
const
|
|
66064
|
+
const hasIcon = !isDashboard && pivotCell.domain.length !== fields.length;
|
|
66065
|
+
const domains = definition.collapsedDomains?.[pivotCell.dimension] ?? [];
|
|
66066
|
+
const isCollapsed = domains.some((domain) => deepEquals(domain, pivotCell.domain));
|
|
66067
|
+
const indent = pivotCell.dimension === "ROW" ? (pivotCell.domain.length - 1) * PIVOT_INDENT : 0;
|
|
65809
66068
|
return {
|
|
66069
|
+
type: "pivot_collapse",
|
|
65810
66070
|
priority: 4,
|
|
65811
66071
|
horizontalAlign: "left",
|
|
65812
|
-
size:
|
|
65813
|
-
?
|
|
66072
|
+
size: hasIcon || (!isDashboard && pivotCell.dimension === "ROW" && definition.rows.length > 1)
|
|
66073
|
+
? PIVOT_COLLAPSE_ICON_SIZE
|
|
65814
66074
|
: 0,
|
|
65815
|
-
margin:
|
|
65816
|
-
|
|
66075
|
+
margin: hasIcon ? GRID_ICON_MARGIN * 2 + indent : indent,
|
|
66076
|
+
svg: hasIcon ? getPivotIconSvg(isCollapsed, false) : undefined,
|
|
66077
|
+
hoverSvg: hasIcon ? getPivotIconSvg(isCollapsed, true) : undefined,
|
|
65817
66078
|
position,
|
|
66079
|
+
onClick: togglePivotCollapse,
|
|
65818
66080
|
};
|
|
65819
66081
|
}
|
|
65820
66082
|
return undefined;
|
|
65821
66083
|
});
|
|
66084
|
+
function togglePivotCollapse(position, env) {
|
|
66085
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
66086
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
66087
|
+
if (!pivotId || pivotCell.type !== "HEADER") {
|
|
66088
|
+
return;
|
|
66089
|
+
}
|
|
66090
|
+
const definition = env.model.getters.getPivotCoreDefinition(pivotId);
|
|
66091
|
+
const collapsedDomains = definition.collapsedDomains?.[pivotCell.dimension]
|
|
66092
|
+
? [...definition.collapsedDomains[pivotCell.dimension]]
|
|
66093
|
+
: [];
|
|
66094
|
+
const index = collapsedDomains.findIndex((domain) => deepEquals(domain, pivotCell.domain));
|
|
66095
|
+
if (index !== -1) {
|
|
66096
|
+
collapsedDomains.splice(index, 1);
|
|
66097
|
+
}
|
|
66098
|
+
else {
|
|
66099
|
+
collapsedDomains.push(pivotCell.domain);
|
|
66100
|
+
}
|
|
66101
|
+
const newDomains = definition.collapsedDomains
|
|
66102
|
+
? { ...definition.collapsedDomains }
|
|
66103
|
+
: { COL: [], ROW: [] };
|
|
66104
|
+
newDomains[pivotCell.dimension] = collapsedDomains;
|
|
66105
|
+
env.model.dispatch("UPDATE_PIVOT", {
|
|
66106
|
+
pivotId,
|
|
66107
|
+
pivot: { ...definition, collapsedDomains: newDomains },
|
|
66108
|
+
});
|
|
66109
|
+
}
|
|
65822
66110
|
|
|
65823
66111
|
class CellIconPlugin extends CoreViewPlugin {
|
|
65824
|
-
static getters = ["doesCellHaveGridIcon", "getCellIcons"];
|
|
66112
|
+
static getters = ["doesCellHaveGridIcon", "getCellIcons", "getCellIconRect"];
|
|
65825
66113
|
cellIconsCache = {};
|
|
65826
66114
|
handle(cmd) {
|
|
65827
66115
|
if (cmd.type !== "SET_VIEWPORT_OFFSET") {
|
|
@@ -65841,6 +66129,29 @@ class CellIconPlugin extends CoreViewPlugin {
|
|
|
65841
66129
|
}
|
|
65842
66130
|
return this.cellIconsCache[position.sheetId][position.col][position.row];
|
|
65843
66131
|
}
|
|
66132
|
+
getCellIconRect(icon) {
|
|
66133
|
+
const cellPosition = icon.position;
|
|
66134
|
+
const merge = this.getters.getMerge(cellPosition);
|
|
66135
|
+
const zone = merge || positionToZone(cellPosition);
|
|
66136
|
+
const cellRect = this.getters.getRect(zone);
|
|
66137
|
+
const cell = this.getters.getCell(cellPosition);
|
|
66138
|
+
const x = this.getIconHorizontalPosition(cellRect, icon.horizontalAlign, icon);
|
|
66139
|
+
const y = this.getters.computeTextYCoordinate(cellRect, icon.size, cell?.style?.verticalAlign);
|
|
66140
|
+
return { x: x, y: y, width: icon.size, height: icon.size };
|
|
66141
|
+
}
|
|
66142
|
+
getIconHorizontalPosition(rect, align, icon) {
|
|
66143
|
+
const start = rect.x;
|
|
66144
|
+
const end = rect.x + rect.width;
|
|
66145
|
+
switch (align) {
|
|
66146
|
+
case "right":
|
|
66147
|
+
return end - icon.margin - icon.size;
|
|
66148
|
+
case "left":
|
|
66149
|
+
return start + icon.margin;
|
|
66150
|
+
default:
|
|
66151
|
+
const centeringOffset = Math.floor((end - start - icon.size) / 2);
|
|
66152
|
+
return end - icon.size - centeringOffset;
|
|
66153
|
+
}
|
|
66154
|
+
}
|
|
65844
66155
|
computeCellIcons(position) {
|
|
65845
66156
|
const icons = { left: undefined, right: undefined, center: undefined };
|
|
65846
66157
|
const callbacks = iconsOnCellRegistry.getAll();
|
|
@@ -70067,6 +70378,7 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
70067
70378
|
"getCellText",
|
|
70068
70379
|
"getCellMultiLineText",
|
|
70069
70380
|
"getContiguousZone",
|
|
70381
|
+
"computeTextYCoordinate",
|
|
70070
70382
|
];
|
|
70071
70383
|
ctx = document.createElement("canvas").getContext("2d");
|
|
70072
70384
|
// ---------------------------------------------------------------------------
|
|
@@ -70169,6 +70481,25 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
70169
70481
|
});
|
|
70170
70482
|
return splitTextToWidth(this.ctx, text, style, args.wrapText ? args.maxWidth : undefined);
|
|
70171
70483
|
}
|
|
70484
|
+
/** Computes the vertical start point from which a text line should be draw in a cell.
|
|
70485
|
+
*
|
|
70486
|
+
* Note that in case the cell does not have enough spaces to display its text lines,
|
|
70487
|
+
* (wrapping cell case) then the vertical align should be at the top.
|
|
70488
|
+
* */
|
|
70489
|
+
computeTextYCoordinate(cellRect, textLineHeight, verticalAlign = DEFAULT_VERTICAL_ALIGN, numberOfLines = 1) {
|
|
70490
|
+
const y = cellRect.y + 1; // +1 to skip the cell grid line at the top
|
|
70491
|
+
const textHeight = computeTextLinesHeight(textLineHeight, numberOfLines);
|
|
70492
|
+
const hasEnoughSpaces = cellRect.height > textHeight + MIN_CELL_TEXT_MARGIN * 2;
|
|
70493
|
+
if (hasEnoughSpaces) {
|
|
70494
|
+
if (verticalAlign === "middle") {
|
|
70495
|
+
return Math.ceil(y + (cellRect.height - textHeight) / 2);
|
|
70496
|
+
}
|
|
70497
|
+
if (verticalAlign === "bottom") {
|
|
70498
|
+
return y + cellRect.height - textHeight - MIN_CELL_TEXT_MARGIN;
|
|
70499
|
+
}
|
|
70500
|
+
}
|
|
70501
|
+
return y + MIN_CELL_TEXT_MARGIN;
|
|
70502
|
+
}
|
|
70172
70503
|
/**
|
|
70173
70504
|
* Expands the given zone until bordered by empty cells or reached the sheet boundaries.
|
|
70174
70505
|
*/
|
|
@@ -72194,6 +72525,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72194
72525
|
"getElementsFromSelection",
|
|
72195
72526
|
"tryGetActiveSheetId",
|
|
72196
72527
|
"isGridSelectionActive",
|
|
72528
|
+
"getSelectecUnboundedZone",
|
|
72197
72529
|
];
|
|
72198
72530
|
gridSelection = {
|
|
72199
72531
|
anchor: {
|
|
@@ -72205,12 +72537,14 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72205
72537
|
selectedFigureId = null;
|
|
72206
72538
|
sheetsData = {};
|
|
72207
72539
|
moveClient;
|
|
72540
|
+
isUnbounded;
|
|
72208
72541
|
// This flag is used to avoid to historize the ACTIVE_SHEET command when it's
|
|
72209
72542
|
// the main command.
|
|
72210
72543
|
activeSheet = null;
|
|
72211
72544
|
constructor(config) {
|
|
72212
72545
|
super(config);
|
|
72213
72546
|
this.moveClient = config.moveClient;
|
|
72547
|
+
this.isUnbounded = false;
|
|
72214
72548
|
}
|
|
72215
72549
|
// ---------------------------------------------------------------------------
|
|
72216
72550
|
// Command Handling
|
|
@@ -72236,6 +72570,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72236
72570
|
handleEvent(event) {
|
|
72237
72571
|
const anchor = event.anchor;
|
|
72238
72572
|
let zones = [];
|
|
72573
|
+
this.isUnbounded = event.options?.unbounded || false;
|
|
72239
72574
|
switch (event.mode) {
|
|
72240
72575
|
case "overrideSelection":
|
|
72241
72576
|
zones = [anchor.zone];
|
|
@@ -72425,6 +72760,12 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72425
72760
|
getSelectedZone() {
|
|
72426
72761
|
return deepCopy(this.gridSelection.anchor.zone);
|
|
72427
72762
|
}
|
|
72763
|
+
getSelectecUnboundedZone() {
|
|
72764
|
+
const zone = this.isUnbounded
|
|
72765
|
+
? this.getters.getUnboundedZone(this.activeSheet.id, this.gridSelection.anchor.zone)
|
|
72766
|
+
: this.gridSelection.anchor.zone;
|
|
72767
|
+
return deepCopy(zone);
|
|
72768
|
+
}
|
|
72428
72769
|
getSelection() {
|
|
72429
72770
|
return deepCopy(this.gridSelection);
|
|
72430
72771
|
}
|
|
@@ -72618,11 +72959,6 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72618
72959
|
},
|
|
72619
72960
|
];
|
|
72620
72961
|
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
72962
|
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
72627
72963
|
const pasteTarget = [
|
|
72628
72964
|
{
|
|
@@ -72632,7 +72968,14 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
72632
72968
|
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
72633
72969
|
},
|
|
72634
72970
|
];
|
|
72635
|
-
|
|
72971
|
+
for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
|
|
72972
|
+
const handler = new Handler(this.getters, this.dispatch);
|
|
72973
|
+
const data = handler.copy(getClipboardDataPositions(sheetId, target));
|
|
72974
|
+
if (!data) {
|
|
72975
|
+
continue;
|
|
72976
|
+
}
|
|
72977
|
+
handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
|
|
72978
|
+
}
|
|
72636
72979
|
const selection = pasteTarget[0];
|
|
72637
72980
|
const col = selection.left;
|
|
72638
72981
|
const row = selection.top;
|
|
@@ -73178,6 +73521,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
73178
73521
|
"getRect",
|
|
73179
73522
|
"getFigureUI",
|
|
73180
73523
|
"getPositionAnchorOffset",
|
|
73524
|
+
"getGridOffset",
|
|
73181
73525
|
];
|
|
73182
73526
|
viewports = {};
|
|
73183
73527
|
/**
|
|
@@ -73367,6 +73711,9 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
73367
73711
|
height: this.sheetViewHeight,
|
|
73368
73712
|
};
|
|
73369
73713
|
}
|
|
73714
|
+
getGridOffset() {
|
|
73715
|
+
return { x: this.gridOffsetX, y: this.gridOffsetY };
|
|
73716
|
+
}
|
|
73370
73717
|
/** type as pane, not viewport but basically pane extends viewport */
|
|
73371
73718
|
getActiveMainViewport() {
|
|
73372
73719
|
const sheetId = this.getters.getActiveSheetId();
|
|
@@ -74745,6 +75092,7 @@ topbarMenuRegistry
|
|
|
74745
75092
|
name: _t("Settings"),
|
|
74746
75093
|
sequence: 100,
|
|
74747
75094
|
execute: (env) => env.openSidePanel("Settings"),
|
|
75095
|
+
isEnabled: (env) => !env.isSmall,
|
|
74748
75096
|
icon: "o-spreadsheet-Icon.COG",
|
|
74749
75097
|
})
|
|
74750
75098
|
// ---------------------------------------------------------------------
|
|
@@ -75162,6 +75510,7 @@ topbarMenuRegistry
|
|
|
75162
75510
|
execute: (env) => {
|
|
75163
75511
|
env.openSidePanel("DataValidation");
|
|
75164
75512
|
},
|
|
75513
|
+
isEnabled: (env) => !env.isSmall,
|
|
75165
75514
|
icon: "o-spreadsheet-Icon.DATA_VALIDATION",
|
|
75166
75515
|
sequence: 30,
|
|
75167
75516
|
separator: true,
|
|
@@ -75185,6 +75534,7 @@ topbarMenuRegistry
|
|
|
75185
75534
|
sequence: sequence + index,
|
|
75186
75535
|
isReadonlyAllowed: true,
|
|
75187
75536
|
execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
|
|
75537
|
+
isEnabled: (env) => !env.isSmall,
|
|
75188
75538
|
onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
|
|
75189
75539
|
onStopHover: (env) => env.getStore(HighlightStore).unRegister(highlightProvider),
|
|
75190
75540
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
@@ -75456,7 +75806,7 @@ css /* scss */ `
|
|
|
75456
75806
|
.o-sheet {
|
|
75457
75807
|
padding: 0 15px;
|
|
75458
75808
|
padding-right: 10px;
|
|
75459
|
-
height: ${
|
|
75809
|
+
height: ${DESKTOP_BOTTOMBAR_HEIGHT}px;
|
|
75460
75810
|
border-left: 1px solid #c1c1c1;
|
|
75461
75811
|
border-right: 1px solid #c1c1c1;
|
|
75462
75812
|
margin-left: -1px;
|
|
@@ -75500,6 +75850,10 @@ css /* scss */ `
|
|
|
75500
75850
|
width: calc(100% - 1px);
|
|
75501
75851
|
}
|
|
75502
75852
|
}
|
|
75853
|
+
|
|
75854
|
+
.o-spreadshet-mobile .o-sheet {
|
|
75855
|
+
height: ${MOBILE_BOTTOMBAR_HEIGHT}px;
|
|
75856
|
+
}
|
|
75503
75857
|
`;
|
|
75504
75858
|
class BottomBarSheet extends Component {
|
|
75505
75859
|
static template = "o-spreadsheet-BottomBarSheet";
|
|
@@ -75554,7 +75908,16 @@ class BottomBarSheet extends Component {
|
|
|
75554
75908
|
this.stopEdition();
|
|
75555
75909
|
}
|
|
75556
75910
|
}
|
|
75911
|
+
onClick() {
|
|
75912
|
+
if (!this.env.isMobile()) {
|
|
75913
|
+
return;
|
|
75914
|
+
}
|
|
75915
|
+
this.activateSheet();
|
|
75916
|
+
}
|
|
75557
75917
|
onMouseDown(ev) {
|
|
75918
|
+
if (this.env.isMobile()) {
|
|
75919
|
+
return;
|
|
75920
|
+
}
|
|
75558
75921
|
this.activateSheet();
|
|
75559
75922
|
this.props.onMouseDown(ev);
|
|
75560
75923
|
}
|
|
@@ -75898,8 +76261,8 @@ css /* scss */ `
|
|
|
75898
76261
|
}
|
|
75899
76262
|
}
|
|
75900
76263
|
|
|
75901
|
-
.mobile.o-spreadsheet-bottom-bar {
|
|
75902
|
-
padding-left:
|
|
76264
|
+
.o-spreadsheet-mobile .o-spreadsheet-bottom-bar {
|
|
76265
|
+
padding-left: 0;
|
|
75903
76266
|
|
|
75904
76267
|
.add-sheet-container {
|
|
75905
76268
|
order: 2;
|
|
@@ -75916,10 +76279,8 @@ css /* scss */ `
|
|
|
75916
76279
|
`;
|
|
75917
76280
|
class BottomBar extends Component {
|
|
75918
76281
|
static template = "o-spreadsheet-BottomBar";
|
|
75919
|
-
static props = {
|
|
75920
|
-
|
|
75921
|
-
};
|
|
75922
|
-
static components = { Menu, Ripple, BottomBarSheet, BottomBarStatistic };
|
|
76282
|
+
static props = { onClick: Function };
|
|
76283
|
+
static components = { MenuPopover, Ripple, BottomBarSheet, BottomBarStatistic };
|
|
75923
76284
|
bottomBarRef = useRef("bottomBar");
|
|
75924
76285
|
sheetListRef = useRef("sheetList");
|
|
75925
76286
|
dragAndDrop = useDragAndDropListItems();
|
|
@@ -76056,6 +76417,9 @@ class BottomBar extends Component {
|
|
|
76056
76417
|
if (event.button !== 0 || this.env.model.getters.isReadonly())
|
|
76057
76418
|
return;
|
|
76058
76419
|
this.closeMenu();
|
|
76420
|
+
if (this.env.isMobile()) {
|
|
76421
|
+
return;
|
|
76422
|
+
}
|
|
76059
76423
|
const visibleSheets = this.getVisibleSheets();
|
|
76060
76424
|
const sheetRects = this.getSheetItemRects();
|
|
76061
76425
|
const sheets = visibleSheets.map((sheet, index) => ({
|
|
@@ -76175,7 +76539,7 @@ css /* scss */ `
|
|
|
76175
76539
|
`;
|
|
76176
76540
|
class SpreadsheetDashboard extends Component {
|
|
76177
76541
|
static template = "o-spreadsheet-SpreadsheetDashboard";
|
|
76178
|
-
static props = {};
|
|
76542
|
+
static props = { getGridSize: Function };
|
|
76179
76543
|
static components = {
|
|
76180
76544
|
GridOverlay,
|
|
76181
76545
|
GridPopover,
|
|
@@ -76462,7 +76826,7 @@ class HeaderGroupContainer extends Component {
|
|
|
76462
76826
|
dimension: String,
|
|
76463
76827
|
layers: Array,
|
|
76464
76828
|
};
|
|
76465
|
-
static components = { RowGroup, ColGroup,
|
|
76829
|
+
static components = { RowGroup, ColGroup, MenuPopover };
|
|
76466
76830
|
menu = useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
76467
76831
|
getLayerOffset(layerIndex) {
|
|
76468
76832
|
return layerIndex * GROUP_LAYER_WIDTH;
|
|
@@ -76678,6 +77042,158 @@ class SidePanel extends Component {
|
|
|
76678
77042
|
}
|
|
76679
77043
|
}
|
|
76680
77044
|
|
|
77045
|
+
class RibbonMenu extends Component {
|
|
77046
|
+
static template = "o-spreadsheet-RibbonMenu";
|
|
77047
|
+
static props = {
|
|
77048
|
+
onClose: Function,
|
|
77049
|
+
};
|
|
77050
|
+
static components = { Menu };
|
|
77051
|
+
rootItems = topbarMenuRegistry.getMenuItems();
|
|
77052
|
+
menuRef = useRef("menu");
|
|
77053
|
+
state = useState({
|
|
77054
|
+
menuItems: this.rootItems,
|
|
77055
|
+
title: _t("Menu Bar"),
|
|
77056
|
+
parentState: undefined,
|
|
77057
|
+
});
|
|
77058
|
+
setup() {
|
|
77059
|
+
useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
77060
|
+
}
|
|
77061
|
+
onExternalClick(ev) {
|
|
77062
|
+
if (!this.menuRef.el?.contains(ev.target)) {
|
|
77063
|
+
this.props.onClose();
|
|
77064
|
+
}
|
|
77065
|
+
}
|
|
77066
|
+
onClickMenu(menu) {
|
|
77067
|
+
const children = menu.children(this.env);
|
|
77068
|
+
if (children.length) {
|
|
77069
|
+
this.state.parentState = { ...this.state };
|
|
77070
|
+
this.state.menuItems = children;
|
|
77071
|
+
this.state.title = menu.name(this.env);
|
|
77072
|
+
}
|
|
77073
|
+
else {
|
|
77074
|
+
this.state.menuItems = this.rootItems;
|
|
77075
|
+
this.state.title = undefined;
|
|
77076
|
+
this.state.parentState = undefined;
|
|
77077
|
+
menu.execute?.(this.env);
|
|
77078
|
+
this.props.onClose();
|
|
77079
|
+
}
|
|
77080
|
+
}
|
|
77081
|
+
get menuProps() {
|
|
77082
|
+
return {
|
|
77083
|
+
menuItems: this.state.menuItems,
|
|
77084
|
+
onClose: this.props.onClose,
|
|
77085
|
+
onClickMenu: this.onClickMenu.bind(this),
|
|
77086
|
+
};
|
|
77087
|
+
}
|
|
77088
|
+
get style() {
|
|
77089
|
+
return cssPropertiesToCss({
|
|
77090
|
+
height: `${this.props.height}px`,
|
|
77091
|
+
});
|
|
77092
|
+
}
|
|
77093
|
+
onClickBack() {
|
|
77094
|
+
if (!this.state.parentState) {
|
|
77095
|
+
this.props.onClose();
|
|
77096
|
+
return;
|
|
77097
|
+
}
|
|
77098
|
+
this.state.menuItems = this.state.parentState.menuItems;
|
|
77099
|
+
this.state.title = this.state.parentState.title;
|
|
77100
|
+
this.state.parentState = this.state.parentState.parentState;
|
|
77101
|
+
}
|
|
77102
|
+
get backTitle() {
|
|
77103
|
+
return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
|
|
77104
|
+
}
|
|
77105
|
+
}
|
|
77106
|
+
|
|
77107
|
+
css `
|
|
77108
|
+
.o-small-composer {
|
|
77109
|
+
z-index: ${ComponentsImportance.TopBarComposer};
|
|
77110
|
+
}
|
|
77111
|
+
`;
|
|
77112
|
+
class SmallBottomBar extends Component {
|
|
77113
|
+
static components = { Composer, BottomBar, Ripple, RibbonMenu };
|
|
77114
|
+
static template = "o-spreadsheet-SmallBottomBar";
|
|
77115
|
+
static props = {
|
|
77116
|
+
onClick: Function,
|
|
77117
|
+
};
|
|
77118
|
+
composerFocusStore;
|
|
77119
|
+
composerStore;
|
|
77120
|
+
composerInterface;
|
|
77121
|
+
composerRef = useRef("bottombarComposer");
|
|
77122
|
+
menuState = useState({
|
|
77123
|
+
isOpen: false,
|
|
77124
|
+
});
|
|
77125
|
+
setup() {
|
|
77126
|
+
this.composerFocusStore = useStore(ComposerFocusStore);
|
|
77127
|
+
const composerStore = useStore(CellComposerStore);
|
|
77128
|
+
this.composerStore = composerStore;
|
|
77129
|
+
this.composerInterface = {
|
|
77130
|
+
id: "bottombarComposer",
|
|
77131
|
+
get editionMode() {
|
|
77132
|
+
return composerStore.editionMode;
|
|
77133
|
+
},
|
|
77134
|
+
startEdition: this.composerStore.startEdition,
|
|
77135
|
+
setCurrentContent: this.composerStore.setCurrentContent,
|
|
77136
|
+
stopEdition: this.composerStore.stopEdition,
|
|
77137
|
+
};
|
|
77138
|
+
useEffect(() => {
|
|
77139
|
+
if (
|
|
77140
|
+
// we hide the grid composer on mobile so we need to autofocus this composer
|
|
77141
|
+
this.env.isMobile() &&
|
|
77142
|
+
!this.menuState.isOpen &&
|
|
77143
|
+
this.composerStore.editionMode !== "inactive" &&
|
|
77144
|
+
this.composerFocusStore.activeComposer !== this.composerInterface) {
|
|
77145
|
+
this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
77146
|
+
focusMode: "contentFocus",
|
|
77147
|
+
});
|
|
77148
|
+
}
|
|
77149
|
+
});
|
|
77150
|
+
}
|
|
77151
|
+
get focus() {
|
|
77152
|
+
return this.composerFocusStore.activeComposer === this.composerInterface
|
|
77153
|
+
? this.composerFocusStore.focusMode
|
|
77154
|
+
: "inactive";
|
|
77155
|
+
}
|
|
77156
|
+
get rect() {
|
|
77157
|
+
return this.composerRef.el
|
|
77158
|
+
? getBoundingRectAsPOJO(this.composerRef.el)
|
|
77159
|
+
: { x: 0, y: 0, width: 0, height: 0 };
|
|
77160
|
+
}
|
|
77161
|
+
get composerProps() {
|
|
77162
|
+
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
77163
|
+
return {
|
|
77164
|
+
rect: { ...this.rect },
|
|
77165
|
+
delimitation: {
|
|
77166
|
+
width,
|
|
77167
|
+
height,
|
|
77168
|
+
},
|
|
77169
|
+
focus: this.focus,
|
|
77170
|
+
composerStore: this.composerStore,
|
|
77171
|
+
onComposerContentFocused: () => this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
77172
|
+
focusMode: "contentFocus",
|
|
77173
|
+
}),
|
|
77174
|
+
isDefaultFocus: false,
|
|
77175
|
+
inputStyle: cssPropertiesToCss({
|
|
77176
|
+
height: this.focus === "inactive" ? "26px" : "fit-content",
|
|
77177
|
+
"max-height": `130px`,
|
|
77178
|
+
}),
|
|
77179
|
+
showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
|
|
77180
|
+
};
|
|
77181
|
+
}
|
|
77182
|
+
get symbols() {
|
|
77183
|
+
return ["=", "(", ")", ":", "-", "/", "*", ",", "+", "$", "."];
|
|
77184
|
+
}
|
|
77185
|
+
insertSymbol(symbol) {
|
|
77186
|
+
this.composerStore.replaceComposerCursorSelection(symbol);
|
|
77187
|
+
this.composerFocusStore.focusComposer(this.composerInterface, {
|
|
77188
|
+
focusMode: "contentFocus",
|
|
77189
|
+
});
|
|
77190
|
+
}
|
|
77191
|
+
toggleRibbon() {
|
|
77192
|
+
this.composerStore.cancelEdition();
|
|
77193
|
+
this.menuState.isOpen = !this.menuState.isOpen;
|
|
77194
|
+
}
|
|
77195
|
+
}
|
|
77196
|
+
|
|
76681
77197
|
const COMPOSER_MAX_HEIGHT = 100;
|
|
76682
77198
|
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
76683
77199
|
const FX_SVG = /*xml*/ `
|
|
@@ -76687,7 +77203,7 @@ const FX_SVG = /*xml*/ `
|
|
|
76687
77203
|
`;
|
|
76688
77204
|
css /* scss */ `
|
|
76689
77205
|
.o-topbar-composer-container {
|
|
76690
|
-
height: ${
|
|
77206
|
+
height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
76691
77207
|
}
|
|
76692
77208
|
|
|
76693
77209
|
.o-topbar-composer {
|
|
@@ -76742,7 +77258,7 @@ class TopBarComposer extends Component {
|
|
|
76742
77258
|
"max-height": `${COMPOSER_MAX_HEIGHT}px`,
|
|
76743
77259
|
"line-height": "24px",
|
|
76744
77260
|
};
|
|
76745
|
-
style.height = this.focus === "inactive" ? `${
|
|
77261
|
+
style.height = this.focus === "inactive" ? `${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px` : "fit-content";
|
|
76746
77262
|
return cssPropertiesToCss(style);
|
|
76747
77263
|
}
|
|
76748
77264
|
get containerStyle() {
|
|
@@ -77245,7 +77761,7 @@ class TopBarFontSizeEditor extends Component {
|
|
|
77245
77761
|
|
|
77246
77762
|
class NumberFormatsTool extends Component {
|
|
77247
77763
|
static template = "o-spreadsheet-NumberFormatsTool";
|
|
77248
|
-
static components = {
|
|
77764
|
+
static components = { MenuPopover, ActionButton };
|
|
77249
77765
|
static props = { class: String };
|
|
77250
77766
|
formatNumberMenuItemSpec = formatNumberMenuItemSpec;
|
|
77251
77767
|
topBarToolStore;
|
|
@@ -77295,7 +77811,7 @@ topBarToolBarRegistry
|
|
|
77295
77811
|
.addChild("edit", {
|
|
77296
77812
|
component: PaintFormatButton,
|
|
77297
77813
|
props: {
|
|
77298
|
-
class: "o-hoverable-button o-toolbar-button",
|
|
77814
|
+
class: "o-hoverable-button o-toolbar-button o-mobile-disabled",
|
|
77299
77815
|
},
|
|
77300
77816
|
sequence: 3,
|
|
77301
77817
|
})
|
|
@@ -77454,7 +77970,7 @@ topBarToolBarRegistry
|
|
|
77454
77970
|
.add("misc")
|
|
77455
77971
|
.addChild("misc", {
|
|
77456
77972
|
component: TableDropdownButton,
|
|
77457
|
-
props: { class: "o-toolbar-button o-hoverable-button o-menu-item-button" },
|
|
77973
|
+
props: { class: "o-toolbar-button o-hoverable-button o-menu-item-button o-mobile-disabled" },
|
|
77458
77974
|
sequence: 1,
|
|
77459
77975
|
})
|
|
77460
77976
|
.addChild("misc", {
|
|
@@ -77474,6 +77990,7 @@ css /* scss */ `
|
|
|
77474
77990
|
border-right: 1px solid ${SEPARATOR_COLOR};
|
|
77475
77991
|
width: 0;
|
|
77476
77992
|
margin: 0 6px;
|
|
77993
|
+
height: 30px;
|
|
77477
77994
|
}
|
|
77478
77995
|
|
|
77479
77996
|
.o-toolbar-button {
|
|
@@ -77506,7 +78023,7 @@ css /* scss */ `
|
|
|
77506
78023
|
|
|
77507
78024
|
.irregularity-map {
|
|
77508
78025
|
border-top: 1px solid ${SEPARATOR_COLOR};
|
|
77509
|
-
height: ${
|
|
78026
|
+
height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
77510
78027
|
|
|
77511
78028
|
.alert-info {
|
|
77512
78029
|
border-left: 3px solid ${ALERT_INFO_BORDER};
|
|
@@ -77519,7 +78036,7 @@ css /* scss */ `
|
|
|
77519
78036
|
|
|
77520
78037
|
/* Toolbar */
|
|
77521
78038
|
.o-topbar-toolbar {
|
|
77522
|
-
height: ${
|
|
78039
|
+
height: ${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
77523
78040
|
|
|
77524
78041
|
.o-readonly-toolbar {
|
|
77525
78042
|
background-color: ${BACKGROUND_HEADER_COLOR};
|
|
@@ -77533,6 +78050,24 @@ css /* scss */ `
|
|
|
77533
78050
|
}
|
|
77534
78051
|
}
|
|
77535
78052
|
}
|
|
78053
|
+
|
|
78054
|
+
.o-spreadsheet-mobile {
|
|
78055
|
+
.o-topbar-toolbar {
|
|
78056
|
+
height: ${MOBILE_TOPBAR_TOOLBAR_HEIGHT}px;
|
|
78057
|
+
}
|
|
78058
|
+
.o-topbar-divider {
|
|
78059
|
+
border-width: 2px;
|
|
78060
|
+
border-radius: 4px;
|
|
78061
|
+
}
|
|
78062
|
+
|
|
78063
|
+
.o-toolbar-button {
|
|
78064
|
+
height: 35px;
|
|
78065
|
+
width: 31px;
|
|
78066
|
+
.o-toolbar-button.o-mobile-disabled * {
|
|
78067
|
+
color: ${DISABLED_TEXT_COLOR};
|
|
78068
|
+
cursor: not-allowed;
|
|
78069
|
+
}
|
|
78070
|
+
}
|
|
77536
78071
|
`;
|
|
77537
78072
|
class TopBar extends Component {
|
|
77538
78073
|
static template = "o-spreadsheet-TopBar";
|
|
@@ -77541,7 +78076,7 @@ class TopBar extends Component {
|
|
|
77541
78076
|
dropdownMaxHeight: Number,
|
|
77542
78077
|
};
|
|
77543
78078
|
static components = {
|
|
77544
|
-
|
|
78079
|
+
MenuPopover,
|
|
77545
78080
|
TopBarComposer,
|
|
77546
78081
|
Popover,
|
|
77547
78082
|
};
|
|
@@ -77621,7 +78156,7 @@ class TopBar extends Component {
|
|
|
77621
78156
|
// TODO : manage click events better. We need this piece of code
|
|
77622
78157
|
// otherwise the event opening the menu would close it on the same frame.
|
|
77623
78158
|
// And we cannot stop the event propagation because it's used in an
|
|
77624
|
-
// external listener of the
|
|
78159
|
+
// external listener of the MenuPopover component to close the context menu when
|
|
77625
78160
|
// clicking on the top bar
|
|
77626
78161
|
if (this.openedEl === ev.target) {
|
|
77627
78162
|
return;
|
|
@@ -78047,6 +78582,11 @@ css /* scss */ `
|
|
|
78047
78582
|
color: ${TEXT_BODY};
|
|
78048
78583
|
}
|
|
78049
78584
|
}
|
|
78585
|
+
|
|
78586
|
+
.o-spreadsheet-topbar-wrapper,
|
|
78587
|
+
.o-spreadsheet-bottombar-wrapper {
|
|
78588
|
+
z-index: ${ComponentsImportance.ScrollBar + 1};
|
|
78589
|
+
}
|
|
78050
78590
|
`;
|
|
78051
78591
|
class Spreadsheet extends Component {
|
|
78052
78592
|
static template = "o-spreadsheet-Spreadsheet";
|
|
@@ -78060,6 +78600,7 @@ class Spreadsheet extends Component {
|
|
|
78060
78600
|
TopBar,
|
|
78061
78601
|
Grid,
|
|
78062
78602
|
BottomBar,
|
|
78603
|
+
SmallBottomBar,
|
|
78063
78604
|
SidePanel,
|
|
78064
78605
|
SpreadsheetDashboard,
|
|
78065
78606
|
HeaderGroupContainer,
|
|
@@ -78083,12 +78624,25 @@ class Spreadsheet extends Component {
|
|
|
78083
78624
|
else {
|
|
78084
78625
|
properties["grid-template-rows"] = `min-content auto min-content`;
|
|
78085
78626
|
}
|
|
78086
|
-
|
|
78627
|
+
const columnWidth = this.sidePanel.isOpen ? `${this.sidePanel.panelSize}px` : "auto";
|
|
78628
|
+
properties["grid-template-columns"] = `auto ${columnWidth}`;
|
|
78087
78629
|
return cssPropertiesToCss(properties);
|
|
78088
78630
|
}
|
|
78089
78631
|
setup() {
|
|
78632
|
+
if (!("isSmall" in this.env)) {
|
|
78633
|
+
const screenSize = useScreenWidth();
|
|
78634
|
+
useSubEnv({
|
|
78635
|
+
get isSmall() {
|
|
78636
|
+
return screenSize.isSmall;
|
|
78637
|
+
},
|
|
78638
|
+
});
|
|
78639
|
+
}
|
|
78090
78640
|
const stores = useStoreProvider();
|
|
78091
78641
|
stores.inject(ModelStore, this.model);
|
|
78642
|
+
const env = this.env;
|
|
78643
|
+
stores.get(ScreenWidthStore).setSmallThreshhold(() => {
|
|
78644
|
+
return env.isSmall;
|
|
78645
|
+
});
|
|
78092
78646
|
this.notificationStore = useStore(NotificationStore);
|
|
78093
78647
|
this.composerFocusStore = useStore(ComposerFocusStore);
|
|
78094
78648
|
this.sidePanel = useStore(SidePanelStore);
|
|
@@ -78106,15 +78660,8 @@ class Spreadsheet extends Component {
|
|
|
78106
78660
|
notifyUser: (notification) => this.notificationStore.notifyUser(notification),
|
|
78107
78661
|
askConfirmation: (text, confirm, cancel) => this.notificationStore.askConfirmation(text, confirm, cancel),
|
|
78108
78662
|
raiseError: (text, cb) => this.notificationStore.raiseError(text, cb),
|
|
78663
|
+
isMobile: isMobileOS,
|
|
78109
78664
|
});
|
|
78110
|
-
if (!("isSmall" in this.env)) {
|
|
78111
|
-
const screenSize = useScreenWidth();
|
|
78112
|
-
useSubEnv({
|
|
78113
|
-
get isSmall() {
|
|
78114
|
-
return screenSize.isSmall;
|
|
78115
|
-
},
|
|
78116
|
-
});
|
|
78117
|
-
}
|
|
78118
78665
|
this.notificationStore.updateNotificationCallbacks({ ...this.props });
|
|
78119
78666
|
useEffect(() => {
|
|
78120
78667
|
/**
|
|
@@ -78220,6 +78767,24 @@ class Spreadsheet extends Component {
|
|
|
78220
78767
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
78221
78768
|
return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
|
|
78222
78769
|
}
|
|
78770
|
+
getGridSize() {
|
|
78771
|
+
const topBarHeight = this.spreadsheetRef.el
|
|
78772
|
+
?.querySelector(".o-spreadsheet-topbar-wrapper")
|
|
78773
|
+
?.getBoundingClientRect().height || 0;
|
|
78774
|
+
const bottomBarHeight = this.spreadsheetRef.el
|
|
78775
|
+
?.querySelector(".o-spreadsheet-bottombar-wrapper")
|
|
78776
|
+
?.getBoundingClientRect().height || 0;
|
|
78777
|
+
const gridWidth = this.spreadsheetRef.el?.querySelector(".o-grid")?.getBoundingClientRect().width || 0;
|
|
78778
|
+
const gridHeight = (this.spreadsheetRef.el?.getBoundingClientRect().height || 0) -
|
|
78779
|
+
(this.spreadsheetRef.el?.querySelector(".o-column-groups")?.getBoundingClientRect().height ||
|
|
78780
|
+
0) -
|
|
78781
|
+
topBarHeight -
|
|
78782
|
+
bottomBarHeight;
|
|
78783
|
+
return {
|
|
78784
|
+
width: Math.max(gridWidth - SCROLLBAR_WIDTH, 0),
|
|
78785
|
+
height: Math.max(gridHeight - SCROLLBAR_WIDTH, 0),
|
|
78786
|
+
};
|
|
78787
|
+
}
|
|
78223
78788
|
}
|
|
78224
78789
|
|
|
78225
78790
|
function inverseCommand(cmd) {
|
|
@@ -82482,7 +83047,7 @@ const SPREADSHEET_DIMENSIONS = {
|
|
|
82482
83047
|
MIN_COL_WIDTH,
|
|
82483
83048
|
HEADER_HEIGHT,
|
|
82484
83049
|
HEADER_WIDTH,
|
|
82485
|
-
|
|
83050
|
+
DESKTOP_BOTTOMBAR_HEIGHT,
|
|
82486
83051
|
DEFAULT_CELL_WIDTH,
|
|
82487
83052
|
DEFAULT_CELL_HEIGHT,
|
|
82488
83053
|
SCROLLBAR_WIDTH,
|
|
@@ -82628,7 +83193,7 @@ const components = {
|
|
|
82628
83193
|
FunnelChartDesignPanel,
|
|
82629
83194
|
ChartTypePicker,
|
|
82630
83195
|
FigureComponent,
|
|
82631
|
-
|
|
83196
|
+
MenuPopover,
|
|
82632
83197
|
Popover,
|
|
82633
83198
|
SelectionInput,
|
|
82634
83199
|
ValidationMessages,
|
|
@@ -82692,6 +83257,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
82692
83257
|
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 };
|
|
82693
83258
|
|
|
82694
83259
|
|
|
82695
|
-
__info__.version = "18.4.0-alpha.
|
|
82696
|
-
__info__.date = "2025-
|
|
82697
|
-
__info__.hash = "
|
|
83260
|
+
__info__.version = "18.4.0-alpha.7";
|
|
83261
|
+
__info__.date = "2025-06-06T09:32:44.285Z";
|
|
83262
|
+
__info__.hash = "2bfbe64";
|