@odoo/o-spreadsheet 17.1.0-alpha.5 → 17.1.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 +1749 -772
- package/dist/o-spreadsheet.d.ts +860 -47
- package/dist/o-spreadsheet.esm.js +1749 -772
- package/dist/o-spreadsheet.iife.js +1749 -772
- package/dist/o-spreadsheet.iife.min.js +292 -286
- package/dist/o_spreadsheet.xml +339 -468
- package/package.json +8 -4
|
@@ -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 17.1.0-alpha.
|
|
6
|
-
* @date
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.1.0-alpha.7
|
|
6
|
+
* @date 2024-01-12T13:45:00.505Z
|
|
7
|
+
* @hash cbce1ed
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
|
|
@@ -328,13 +328,6 @@ const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
|
|
|
328
328
|
//------------------------------------------------------------------------------
|
|
329
329
|
// Miscellaneous
|
|
330
330
|
//------------------------------------------------------------------------------
|
|
331
|
-
/**
|
|
332
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
333
|
-
* is ordered.
|
|
334
|
-
*/
|
|
335
|
-
function stringify(obj) {
|
|
336
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
337
|
-
}
|
|
338
331
|
/**
|
|
339
332
|
* Remove quotes from a quoted string
|
|
340
333
|
* ```js
|
|
@@ -557,7 +550,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
557
550
|
*/
|
|
558
551
|
function getItemId(item, itemsDic) {
|
|
559
552
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
560
|
-
if (
|
|
553
|
+
if (deepEquals(value, item)) {
|
|
561
554
|
return parseInt(key, 10);
|
|
562
555
|
}
|
|
563
556
|
}
|
|
@@ -1207,16 +1200,84 @@ function toXC(col, row, rangePart = { colFixed: false, rowFixed: false }) {
|
|
|
1207
1200
|
// -----------------------------------------------------------------------------
|
|
1208
1201
|
// Date Type
|
|
1209
1202
|
// -----------------------------------------------------------------------------
|
|
1203
|
+
/**
|
|
1204
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
1205
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
1206
|
+
* and it is timezone-agnostic.
|
|
1207
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
1208
|
+
*/
|
|
1209
|
+
class DateTime {
|
|
1210
|
+
jsDate;
|
|
1211
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
1212
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
1213
|
+
}
|
|
1214
|
+
static fromTimestamp(timestamp) {
|
|
1215
|
+
const date = new Date(timestamp);
|
|
1216
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
1217
|
+
}
|
|
1218
|
+
static now() {
|
|
1219
|
+
const now = new Date();
|
|
1220
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
1221
|
+
}
|
|
1222
|
+
toString() {
|
|
1223
|
+
return this.jsDate.toString();
|
|
1224
|
+
}
|
|
1225
|
+
toLocaleDateString() {
|
|
1226
|
+
return this.jsDate.toLocaleDateString();
|
|
1227
|
+
}
|
|
1228
|
+
getTime() {
|
|
1229
|
+
return this.jsDate.getTime();
|
|
1230
|
+
}
|
|
1231
|
+
getFullYear() {
|
|
1232
|
+
return this.jsDate.getUTCFullYear();
|
|
1233
|
+
}
|
|
1234
|
+
getMonth() {
|
|
1235
|
+
return this.jsDate.getUTCMonth();
|
|
1236
|
+
}
|
|
1237
|
+
getDate() {
|
|
1238
|
+
return this.jsDate.getUTCDate();
|
|
1239
|
+
}
|
|
1240
|
+
getDay() {
|
|
1241
|
+
return this.jsDate.getUTCDay();
|
|
1242
|
+
}
|
|
1243
|
+
getHours() {
|
|
1244
|
+
return this.jsDate.getUTCHours();
|
|
1245
|
+
}
|
|
1246
|
+
getMinutes() {
|
|
1247
|
+
return this.jsDate.getUTCMinutes();
|
|
1248
|
+
}
|
|
1249
|
+
getSeconds() {
|
|
1250
|
+
return this.jsDate.getUTCSeconds();
|
|
1251
|
+
}
|
|
1252
|
+
setFullYear(year) {
|
|
1253
|
+
return this.jsDate.setUTCFullYear(year);
|
|
1254
|
+
}
|
|
1255
|
+
setMonth(month) {
|
|
1256
|
+
return this.jsDate.setUTCMonth(month);
|
|
1257
|
+
}
|
|
1258
|
+
setDate(date) {
|
|
1259
|
+
return this.jsDate.setUTCDate(date);
|
|
1260
|
+
}
|
|
1261
|
+
setHours(hours) {
|
|
1262
|
+
return this.jsDate.setUTCHours(hours);
|
|
1263
|
+
}
|
|
1264
|
+
setMinutes(minutes) {
|
|
1265
|
+
return this.jsDate.setUTCMinutes(minutes);
|
|
1266
|
+
}
|
|
1267
|
+
setSeconds(seconds) {
|
|
1268
|
+
return this.jsDate.setUTCSeconds(seconds);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1210
1271
|
// -----------------------------------------------------------------------------
|
|
1211
1272
|
// Parsing
|
|
1212
1273
|
// -----------------------------------------------------------------------------
|
|
1213
|
-
const INITIAL_1900_DAY = new
|
|
1274
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
1214
1275
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
1215
1276
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
1216
|
-
const CURRENT_YEAR =
|
|
1217
|
-
const CURRENT_MONTH =
|
|
1218
|
-
const INITIAL_JS_DAY =
|
|
1219
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
1277
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
1278
|
+
const CURRENT_MONTH = DateTime.now().getMonth();
|
|
1279
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
1280
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
1220
1281
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
1221
1282
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
1222
1283
|
const dateSeparatorsRegex = /\/|-|\s/;
|
|
@@ -1277,7 +1338,7 @@ function _parseDateTime(str, locale) {
|
|
|
1277
1338
|
return {
|
|
1278
1339
|
value: date.value + time.value,
|
|
1279
1340
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
1280
|
-
jsDate: new
|
|
1341
|
+
jsDate: new DateTime(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
|
|
1281
1342
|
};
|
|
1282
1343
|
}
|
|
1283
1344
|
return date || time;
|
|
@@ -1353,12 +1414,12 @@ function parseDate(parts, separator) {
|
|
|
1353
1414
|
// month + 1: months are 0-indexed in JS
|
|
1354
1415
|
const leadingZero = (monthStr?.length === 2 && month + 1 < 10) || (dayStr?.length === 2 && day < 10);
|
|
1355
1416
|
const fullYear = yearStr?.length !== 2;
|
|
1356
|
-
const jsDate = new
|
|
1417
|
+
const jsDate = new DateTime(year, month, day);
|
|
1357
1418
|
if (jsDate.getMonth() !== month || jsDate.getDate() !== day) {
|
|
1358
1419
|
// invalid date
|
|
1359
1420
|
return null;
|
|
1360
1421
|
}
|
|
1361
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
1422
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
1362
1423
|
const format = getFormatFromDateParts(parts, separator, leadingZero, fullYear);
|
|
1363
1424
|
return {
|
|
1364
1425
|
value: Math.round(delta / MS_PER_DAY),
|
|
@@ -1449,7 +1510,7 @@ function parseTime(str) {
|
|
|
1449
1510
|
if (hours >= 24) {
|
|
1450
1511
|
format = "hhhh:mm:ss";
|
|
1451
1512
|
}
|
|
1452
|
-
const jsDate = new
|
|
1513
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
1453
1514
|
return {
|
|
1454
1515
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
1455
1516
|
format: format,
|
|
@@ -1463,7 +1524,7 @@ function parseTime(str) {
|
|
|
1463
1524
|
// -----------------------------------------------------------------------------
|
|
1464
1525
|
function numberToJsDate(value) {
|
|
1465
1526
|
const truncValue = Math.trunc(value);
|
|
1466
|
-
let date =
|
|
1527
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
1467
1528
|
let time = value - truncValue;
|
|
1468
1529
|
time = time < 0 ? 1 + time : time;
|
|
1469
1530
|
const hours = Math.round(time * 24);
|
|
@@ -1483,7 +1544,7 @@ function jsDateToNumber(date) {
|
|
|
1483
1544
|
}
|
|
1484
1545
|
/** Return the number of days in the current month of the given date */
|
|
1485
1546
|
function getDaysInMonth(date) {
|
|
1486
|
-
return new
|
|
1547
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
1487
1548
|
}
|
|
1488
1549
|
function isLastDayOfMonth(date) {
|
|
1489
1550
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -1501,7 +1562,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
1501
1562
|
const yStart = date.getFullYear();
|
|
1502
1563
|
const mStart = date.getMonth();
|
|
1503
1564
|
const dStart = date.getDate();
|
|
1504
|
-
const jsDate = new
|
|
1565
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
1505
1566
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
1506
1567
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
1507
1568
|
}
|
|
@@ -2060,6 +2121,8 @@ var CommandResult;
|
|
|
2060
2121
|
CommandResult["NoChanges"] = "NoChanges";
|
|
2061
2122
|
})(CommandResult || (CommandResult = {}));
|
|
2062
2123
|
|
|
2124
|
+
const PLAIN_TEXT_FORMAT = "@"; // see OpenXML spec §18.8.31
|
|
2125
|
+
|
|
2063
2126
|
const DEFAULT_LOCALES = [
|
|
2064
2127
|
{
|
|
2065
2128
|
name: "English (US)",
|
|
@@ -2724,20 +2787,20 @@ function flattenRowFirst(items, callback) {
|
|
|
2724
2787
|
}
|
|
2725
2788
|
|
|
2726
2789
|
function toCriterionDateNumber(dateValue) {
|
|
2727
|
-
const today =
|
|
2790
|
+
const today = DateTime.now();
|
|
2728
2791
|
switch (dateValue) {
|
|
2729
2792
|
case "today":
|
|
2730
2793
|
return jsDateToNumber(today);
|
|
2731
2794
|
case "yesterday":
|
|
2732
|
-
return jsDateToNumber(
|
|
2795
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
|
|
2733
2796
|
case "tomorrow":
|
|
2734
|
-
return jsDateToNumber(
|
|
2797
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
|
|
2735
2798
|
case "lastWeek":
|
|
2736
|
-
return jsDateToNumber(
|
|
2799
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
|
|
2737
2800
|
case "lastMonth":
|
|
2738
|
-
return jsDateToNumber(
|
|
2801
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
|
|
2739
2802
|
case "lastYear":
|
|
2740
|
-
return jsDateToNumber(
|
|
2803
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
|
|
2741
2804
|
}
|
|
2742
2805
|
}
|
|
2743
2806
|
/** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
|
|
@@ -2823,6 +2886,9 @@ function parseFormat(formatString) {
|
|
|
2823
2886
|
* Formats a cell value with its format.
|
|
2824
2887
|
*/
|
|
2825
2888
|
function formatValue(value, { format, locale }) {
|
|
2889
|
+
if (format === PLAIN_TEXT_FORMAT) {
|
|
2890
|
+
return toString(value) || "";
|
|
2891
|
+
}
|
|
2826
2892
|
switch (typeof value) {
|
|
2827
2893
|
case "string":
|
|
2828
2894
|
return value;
|
|
@@ -3095,7 +3161,7 @@ function formatJSTime(jsDate, format) {
|
|
|
3095
3161
|
.map((p) => {
|
|
3096
3162
|
switch (p) {
|
|
3097
3163
|
case "hhhh":
|
|
3098
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
3164
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
3099
3165
|
return helapsedHours.toString();
|
|
3100
3166
|
case "hh":
|
|
3101
3167
|
return hours.toString().padStart(2, "0");
|
|
@@ -4663,6 +4729,9 @@ function transformRangeData(range, executed) {
|
|
|
4663
4729
|
|
|
4664
4730
|
class ChartJsComponent extends Component {
|
|
4665
4731
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
4732
|
+
static props = {
|
|
4733
|
+
figure: Object,
|
|
4734
|
+
};
|
|
4666
4735
|
canvas = useRef("graphContainer");
|
|
4667
4736
|
chart;
|
|
4668
4737
|
get background() {
|
|
@@ -4715,9 +4784,6 @@ class ChartJsComponent extends Component {
|
|
|
4715
4784
|
this.chart.update("active");
|
|
4716
4785
|
}
|
|
4717
4786
|
}
|
|
4718
|
-
ChartJsComponent.props = {
|
|
4719
|
-
figure: Object,
|
|
4720
|
-
};
|
|
4721
4787
|
|
|
4722
4788
|
/**
|
|
4723
4789
|
* AbstractChart is the class from which every Chart should inherit.
|
|
@@ -5294,7 +5360,7 @@ function createScorecardChartRuntime(chart, getters) {
|
|
|
5294
5360
|
};
|
|
5295
5361
|
baselineCell = getters.getEvaluatedCell(baselinePosition);
|
|
5296
5362
|
}
|
|
5297
|
-
const background = getters.
|
|
5363
|
+
const { background, fontColor } = getters.getStyleOfSingleCellChart(chart.background, chart.keyValue);
|
|
5298
5364
|
const locale = getters.getLocale();
|
|
5299
5365
|
return {
|
|
5300
5366
|
title: _t(chart.title),
|
|
@@ -5303,7 +5369,7 @@ function createScorecardChartRuntime(chart, getters) {
|
|
|
5303
5369
|
baselineArrow: getBaselineArrowDirection(baselineCell, keyValueCell, chart.baselineMode),
|
|
5304
5370
|
baselineColor: getBaselineColor(baselineCell, chart.baselineMode, keyValueCell, chart.baselineColorUp, chart.baselineColorDown),
|
|
5305
5371
|
baselineDescr: chart.baselineDescr ? _t(chart.baselineDescr) : "",
|
|
5306
|
-
fontColor
|
|
5372
|
+
fontColor,
|
|
5307
5373
|
background,
|
|
5308
5374
|
baselineStyle: chart.baselineMode !== "percentage" && baseline
|
|
5309
5375
|
? getters.getCellStyle({
|
|
@@ -5568,6 +5634,9 @@ class KeyValueElement extends ScorecardScalableElement {
|
|
|
5568
5634
|
|
|
5569
5635
|
class ScorecardChart extends Component {
|
|
5570
5636
|
static template = "o-spreadsheet-ScorecardChart";
|
|
5637
|
+
static props = {
|
|
5638
|
+
figure: Object,
|
|
5639
|
+
};
|
|
5571
5640
|
canvas = useRef("chartContainer");
|
|
5572
5641
|
get runtime() {
|
|
5573
5642
|
return this.env.model.getters.getChartRuntime(this.props.figure.id);
|
|
@@ -5585,9 +5654,6 @@ class ScorecardChart extends Component {
|
|
|
5585
5654
|
drawScoreChart(config, canvas);
|
|
5586
5655
|
}
|
|
5587
5656
|
}
|
|
5588
|
-
ScorecardChart.props = {
|
|
5589
|
-
figure: Object,
|
|
5590
|
-
};
|
|
5591
5657
|
|
|
5592
5658
|
/**
|
|
5593
5659
|
* Registry
|
|
@@ -5729,6 +5795,9 @@ function detectLink(value) {
|
|
|
5729
5795
|
}
|
|
5730
5796
|
|
|
5731
5797
|
function evaluateLiteral(content, localeFormat) {
|
|
5798
|
+
if (localeFormat.format === PLAIN_TEXT_FORMAT) {
|
|
5799
|
+
return textCell(content || "", localeFormat);
|
|
5800
|
+
}
|
|
5732
5801
|
return createEvaluatedCell(parseLiteral(content || "", localeFormat.locale), localeFormat);
|
|
5733
5802
|
}
|
|
5734
5803
|
function parseLiteral(content, locale) {
|
|
@@ -5763,6 +5832,9 @@ function createEvaluatedCell(value, localeFormat) {
|
|
|
5763
5832
|
}
|
|
5764
5833
|
function _createEvaluatedCell(value, localeFormat) {
|
|
5765
5834
|
try {
|
|
5835
|
+
if (localeFormat.format === PLAIN_TEXT_FORMAT) {
|
|
5836
|
+
return textCell(toString(value), localeFormat);
|
|
5837
|
+
}
|
|
5766
5838
|
for (const builder of builders) {
|
|
5767
5839
|
const evaluateCell = builder(value, localeFormat);
|
|
5768
5840
|
if (evaluateCell) {
|
|
@@ -6260,11 +6332,11 @@ css /* scss */ `
|
|
|
6260
6332
|
class ErrorToolTip extends Component {
|
|
6261
6333
|
static maxSize = { maxHeight: ERROR_TOOLTIP_MAX_HEIGHT };
|
|
6262
6334
|
static template = "o-spreadsheet-ErrorToolTip";
|
|
6335
|
+
static props = {
|
|
6336
|
+
errors: Array,
|
|
6337
|
+
onClosed: { type: Function, optional: true },
|
|
6338
|
+
};
|
|
6263
6339
|
}
|
|
6264
|
-
ErrorToolTip.props = {
|
|
6265
|
-
errors: Array,
|
|
6266
|
-
onClosed: { type: Function, optional: true },
|
|
6267
|
-
};
|
|
6268
6340
|
const ErrorToolTipPopoverBuilder = {
|
|
6269
6341
|
onHover: (position, getters) => {
|
|
6270
6342
|
const cell = getters.getEvaluatedCell(position);
|
|
@@ -6306,6 +6378,14 @@ css /*SCSS*/ `
|
|
|
6306
6378
|
`;
|
|
6307
6379
|
class FilterMenuValueItem extends Component {
|
|
6308
6380
|
static template = "o-spreadsheet-FilterMenuValueItem";
|
|
6381
|
+
static props = {
|
|
6382
|
+
value: String,
|
|
6383
|
+
isChecked: Boolean,
|
|
6384
|
+
isSelected: Boolean,
|
|
6385
|
+
onMouseMove: Function,
|
|
6386
|
+
onClick: Function,
|
|
6387
|
+
scrolledTo: { type: String, optional: true },
|
|
6388
|
+
};
|
|
6309
6389
|
itemRef = useRef("menuValueItem");
|
|
6310
6390
|
setup() {
|
|
6311
6391
|
onWillPatch(() => {
|
|
@@ -6323,17 +6403,9 @@ class FilterMenuValueItem extends Component {
|
|
|
6323
6403
|
});
|
|
6324
6404
|
}
|
|
6325
6405
|
}
|
|
6326
|
-
FilterMenuValueItem.props = {
|
|
6327
|
-
value: String,
|
|
6328
|
-
isChecked: Boolean,
|
|
6329
|
-
isSelected: Boolean,
|
|
6330
|
-
onMouseMove: Function,
|
|
6331
|
-
onClick: Function,
|
|
6332
|
-
scrolledTo: { type: String, optional: true },
|
|
6333
|
-
};
|
|
6334
6406
|
|
|
6335
6407
|
const FILTER_MENU_HEIGHT = 295;
|
|
6336
|
-
const CSS
|
|
6408
|
+
const CSS = css /* scss */ `
|
|
6337
6409
|
.o-filter-menu {
|
|
6338
6410
|
box-sizing: border-box;
|
|
6339
6411
|
padding: 8px 16px;
|
|
@@ -6429,9 +6501,12 @@ const CSS$2 = css /* scss */ `
|
|
|
6429
6501
|
}
|
|
6430
6502
|
`;
|
|
6431
6503
|
class FilterMenu extends Component {
|
|
6432
|
-
static size = { width: MENU_WIDTH, height: FILTER_MENU_HEIGHT };
|
|
6433
6504
|
static template = "o-spreadsheet-FilterMenu";
|
|
6434
|
-
static
|
|
6505
|
+
static props = {
|
|
6506
|
+
filterPosition: Object,
|
|
6507
|
+
onClosed: { type: Function, optional: true },
|
|
6508
|
+
};
|
|
6509
|
+
static style = CSS;
|
|
6435
6510
|
static components = { FilterMenuValueItem };
|
|
6436
6511
|
state = useState({
|
|
6437
6512
|
values: [],
|
|
@@ -6583,10 +6658,6 @@ class FilterMenu extends Component {
|
|
|
6583
6658
|
this.props.onClosed?.();
|
|
6584
6659
|
}
|
|
6585
6660
|
}
|
|
6586
|
-
FilterMenu.props = {
|
|
6587
|
-
filterPosition: Object,
|
|
6588
|
-
onClosed: { type: Function, optional: true },
|
|
6589
|
-
};
|
|
6590
6661
|
const FilterMenuPopoverBuilder = {
|
|
6591
6662
|
onOpen: (position, getters) => {
|
|
6592
6663
|
return {
|
|
@@ -6598,6 +6669,7 @@ const FilterMenuPopoverBuilder = {
|
|
|
6598
6669
|
},
|
|
6599
6670
|
};
|
|
6600
6671
|
|
|
6672
|
+
const macRegex = /Mac/i;
|
|
6601
6673
|
/**
|
|
6602
6674
|
* Return true if the event was triggered from
|
|
6603
6675
|
* a child element.
|
|
@@ -6649,7 +6721,7 @@ const letterRegex = /^[a-zA-Z]$/;
|
|
|
6649
6721
|
*/
|
|
6650
6722
|
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
6651
6723
|
let keyDownString = "";
|
|
6652
|
-
if (ev
|
|
6724
|
+
if (isCtrlKey(ev) && ev.key !== "Ctrl")
|
|
6653
6725
|
keyDownString += "Ctrl+";
|
|
6654
6726
|
if (ev.metaKey)
|
|
6655
6727
|
keyDownString += "Ctrl+";
|
|
@@ -6662,7 +6734,15 @@ function keyboardEventToShortcutString(ev, mode = "key") {
|
|
|
6662
6734
|
return keyDownString;
|
|
6663
6735
|
}
|
|
6664
6736
|
function isMacOS() {
|
|
6665
|
-
return navigator.userAgent
|
|
6737
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
6738
|
+
}
|
|
6739
|
+
/**
|
|
6740
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
6741
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
6742
|
+
* On Mac, this is the "meta" or "command" key.
|
|
6743
|
+
*/
|
|
6744
|
+
function isCtrlKey(ev) {
|
|
6745
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
6666
6746
|
}
|
|
6667
6747
|
|
|
6668
6748
|
/**
|
|
@@ -6779,6 +6859,19 @@ css /* scss */ `
|
|
|
6779
6859
|
`;
|
|
6780
6860
|
class Popover extends Component {
|
|
6781
6861
|
static template = "o-spreadsheet-Popover";
|
|
6862
|
+
static props = {
|
|
6863
|
+
anchorRect: Object,
|
|
6864
|
+
containerRect: { type: Object, optional: true },
|
|
6865
|
+
positioning: { type: String, optional: true },
|
|
6866
|
+
maxWidth: { type: Number, optional: true },
|
|
6867
|
+
maxHeight: { type: Number, optional: true },
|
|
6868
|
+
verticalOffset: { type: Number, optional: true },
|
|
6869
|
+
onMouseWheel: { type: Function, optional: true },
|
|
6870
|
+
onPopoverHidden: { type: Function, optional: true },
|
|
6871
|
+
onPopoverMoved: { type: Function, optional: true },
|
|
6872
|
+
zIndex: { type: Number, optional: true },
|
|
6873
|
+
slots: Object,
|
|
6874
|
+
};
|
|
6782
6875
|
static defaultProps = {
|
|
6783
6876
|
positioning: "BottomLeft",
|
|
6784
6877
|
verticalOffset: 0,
|
|
@@ -6835,19 +6928,6 @@ class Popover extends Component {
|
|
|
6835
6928
|
});
|
|
6836
6929
|
}
|
|
6837
6930
|
}
|
|
6838
|
-
Popover.props = {
|
|
6839
|
-
anchorRect: Object,
|
|
6840
|
-
containerRect: { type: Object, optional: true },
|
|
6841
|
-
positioning: { type: String, optional: true },
|
|
6842
|
-
maxWidth: { type: Number, optional: true },
|
|
6843
|
-
maxHeight: { type: Number, optional: true },
|
|
6844
|
-
verticalOffset: { type: Number, optional: true },
|
|
6845
|
-
onMouseWheel: { type: Function, optional: true },
|
|
6846
|
-
onPopoverHidden: { type: Function, optional: true },
|
|
6847
|
-
onPopoverMoved: { type: Function, optional: true },
|
|
6848
|
-
zIndex: { type: Number, optional: true },
|
|
6849
|
-
slots: Object,
|
|
6850
|
-
};
|
|
6851
6931
|
class PopoverPositionContext {
|
|
6852
6932
|
anchorRect;
|
|
6853
6933
|
containerRect;
|
|
@@ -7029,6 +7109,15 @@ css /* scss */ `
|
|
|
7029
7109
|
`;
|
|
7030
7110
|
class Menu extends Component {
|
|
7031
7111
|
static template = "o-spreadsheet-Menu";
|
|
7112
|
+
static props = {
|
|
7113
|
+
position: Object,
|
|
7114
|
+
menuItems: Array,
|
|
7115
|
+
depth: { type: Number, optional: true },
|
|
7116
|
+
maxHeight: { type: Number, optional: true },
|
|
7117
|
+
onClose: Function,
|
|
7118
|
+
onMenuClicked: { type: Function, optional: true },
|
|
7119
|
+
menuId: { type: String, optional: true },
|
|
7120
|
+
};
|
|
7032
7121
|
static components = { Menu, Popover };
|
|
7033
7122
|
static defaultProps = {
|
|
7034
7123
|
depth: 1,
|
|
@@ -7185,15 +7274,6 @@ class Menu extends Component {
|
|
|
7185
7274
|
}
|
|
7186
7275
|
}
|
|
7187
7276
|
}
|
|
7188
|
-
Menu.props = {
|
|
7189
|
-
position: Object,
|
|
7190
|
-
menuItems: Array,
|
|
7191
|
-
depth: { type: Number, optional: true },
|
|
7192
|
-
maxHeight: { type: Number, optional: true },
|
|
7193
|
-
onClose: Function,
|
|
7194
|
-
onMenuClicked: { type: Function, optional: true },
|
|
7195
|
-
menuId: { type: String, optional: true },
|
|
7196
|
-
};
|
|
7197
7277
|
|
|
7198
7278
|
const LINK_TOOLTIP_HEIGHT = 32;
|
|
7199
7279
|
const LINK_TOOLTIP_WIDTH = 220;
|
|
@@ -7246,8 +7326,12 @@ css /* scss */ `
|
|
|
7246
7326
|
}
|
|
7247
7327
|
`;
|
|
7248
7328
|
class LinkDisplay extends Component {
|
|
7249
|
-
static components = { Menu };
|
|
7250
7329
|
static template = "o-spreadsheet-LinkDisplay";
|
|
7330
|
+
static props = {
|
|
7331
|
+
cellPosition: Object,
|
|
7332
|
+
onClosed: { type: Function, optional: true },
|
|
7333
|
+
};
|
|
7334
|
+
static components = { Menu };
|
|
7251
7335
|
get cell() {
|
|
7252
7336
|
const { col, row } = this.props.cellPosition;
|
|
7253
7337
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -7302,10 +7386,6 @@ const LinkCellPopoverBuilder = {
|
|
|
7302
7386
|
};
|
|
7303
7387
|
},
|
|
7304
7388
|
};
|
|
7305
|
-
LinkDisplay.props = {
|
|
7306
|
-
cellPosition: Object,
|
|
7307
|
-
onClosed: { type: Function, optional: true },
|
|
7308
|
-
};
|
|
7309
7389
|
|
|
7310
7390
|
/**
|
|
7311
7391
|
* Tokenizer
|
|
@@ -7939,6 +8019,10 @@ css /* scss */ `
|
|
|
7939
8019
|
`;
|
|
7940
8020
|
class LinkEditor extends Component {
|
|
7941
8021
|
static template = "o-spreadsheet-LinkEditor";
|
|
8022
|
+
static props = {
|
|
8023
|
+
cellPosition: Object,
|
|
8024
|
+
onClosed: { type: Function, optional: true },
|
|
8025
|
+
};
|
|
7942
8026
|
static components = { Menu };
|
|
7943
8027
|
menuItems = linkMenuRegistry.getMenuItems();
|
|
7944
8028
|
link = useState(this.defaultState);
|
|
@@ -8036,10 +8120,6 @@ const LinkEditorPopoverBuilder = {
|
|
|
8036
8120
|
};
|
|
8037
8121
|
},
|
|
8038
8122
|
};
|
|
8039
|
-
LinkEditor.props = {
|
|
8040
|
-
cellPosition: Object,
|
|
8041
|
-
onClosed: { type: Function, optional: true },
|
|
8042
|
-
};
|
|
8043
8123
|
|
|
8044
8124
|
const cellPopoverRegistry = new Registry();
|
|
8045
8125
|
cellPopoverRegistry
|
|
@@ -8322,6 +8402,7 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale })
|
|
|
8322
8402
|
labels: labels.map(truncateLabel),
|
|
8323
8403
|
datasets: [],
|
|
8324
8404
|
},
|
|
8405
|
+
platform: undefined,
|
|
8325
8406
|
plugins: [],
|
|
8326
8407
|
};
|
|
8327
8408
|
}
|
|
@@ -8901,7 +8982,7 @@ function createGaugeChartRuntime(chart, getters) {
|
|
|
8901
8982
|
});
|
|
8902
8983
|
return {
|
|
8903
8984
|
chartJsConfig: config,
|
|
8904
|
-
background: getters.
|
|
8985
|
+
background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
|
|
8905
8986
|
};
|
|
8906
8987
|
}
|
|
8907
8988
|
|
|
@@ -8982,7 +9063,7 @@ function getFormatMinDisplayUnit(format) {
|
|
|
8982
9063
|
else if (format.includes("h") || format.includes("H")) {
|
|
8983
9064
|
return "hour";
|
|
8984
9065
|
}
|
|
8985
|
-
else if (format.includes("
|
|
9066
|
+
else if (format.includes("d")) {
|
|
8986
9067
|
return "day";
|
|
8987
9068
|
}
|
|
8988
9069
|
else if (format.includes("M")) {
|
|
@@ -9494,6 +9575,27 @@ function calculatePercentage(dataset, dataIndex) {
|
|
|
9494
9575
|
const percentage = (dataset[dataIndex] / total) * 100;
|
|
9495
9576
|
return percentage.toFixed(2);
|
|
9496
9577
|
}
|
|
9578
|
+
function filterNegativeValues(labels, datasets) {
|
|
9579
|
+
const dataPointsIndexes = labels.reduce((indexes, label, i) => {
|
|
9580
|
+
const shouldKeep = datasets.some((dataset) => {
|
|
9581
|
+
const dataPoint = dataset.data[i];
|
|
9582
|
+
return typeof dataPoint !== "number" || dataPoint >= 0;
|
|
9583
|
+
});
|
|
9584
|
+
if (shouldKeep) {
|
|
9585
|
+
indexes.push(i);
|
|
9586
|
+
}
|
|
9587
|
+
return indexes;
|
|
9588
|
+
}, []);
|
|
9589
|
+
const filteredLabels = dataPointsIndexes.map((i) => labels[i] || "");
|
|
9590
|
+
const filteredDatasets = datasets.map((dataset) => ({
|
|
9591
|
+
...dataset,
|
|
9592
|
+
data: dataPointsIndexes.map((i) => {
|
|
9593
|
+
const dataPoint = dataset.data[i];
|
|
9594
|
+
return typeof dataPoint !== "number" || dataPoint >= 0 ? dataPoint : 0;
|
|
9595
|
+
}),
|
|
9596
|
+
}));
|
|
9597
|
+
return { labels: filteredLabels, dataSetsValues: filteredDatasets };
|
|
9598
|
+
}
|
|
9497
9599
|
function createPieChartRuntime(chart, getters) {
|
|
9498
9600
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
9499
9601
|
let labels = labelValues.formattedValues;
|
|
@@ -9507,6 +9609,7 @@ function createPieChartRuntime(chart, getters) {
|
|
|
9507
9609
|
if (chart.aggregated) {
|
|
9508
9610
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
9509
9611
|
}
|
|
9612
|
+
({ dataSetsValues, labels } = filterNegativeValues(labels, dataSetsValues));
|
|
9510
9613
|
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
9511
9614
|
const locale = getters.getLocale();
|
|
9512
9615
|
const config = getPieConfiguration(chart, labels, { format: dataSetFormat, locale });
|
|
@@ -9604,6 +9707,10 @@ css /* scss */ `
|
|
|
9604
9707
|
`;
|
|
9605
9708
|
class ChartFigure extends Component {
|
|
9606
9709
|
static template = "o-spreadsheet-ChartFigure";
|
|
9710
|
+
static props = {
|
|
9711
|
+
figure: Object,
|
|
9712
|
+
onFigureDeleted: Function,
|
|
9713
|
+
};
|
|
9607
9714
|
static components = {};
|
|
9608
9715
|
onDoubleClick() {
|
|
9609
9716
|
this.env.model.dispatch("SELECT_FIGURE", { id: this.props.figure.id });
|
|
@@ -9621,13 +9728,13 @@ class ChartFigure extends Component {
|
|
|
9621
9728
|
return component;
|
|
9622
9729
|
}
|
|
9623
9730
|
}
|
|
9624
|
-
ChartFigure.props = {
|
|
9625
|
-
figure: Object,
|
|
9626
|
-
onFigureDeleted: Function,
|
|
9627
|
-
};
|
|
9628
9731
|
|
|
9629
9732
|
class ImageFigure extends Component {
|
|
9630
9733
|
static template = "o-spreadsheet-ImageFigure";
|
|
9734
|
+
static props = {
|
|
9735
|
+
figure: Object,
|
|
9736
|
+
onFigureDeleted: Function,
|
|
9737
|
+
};
|
|
9631
9738
|
static components = {};
|
|
9632
9739
|
// ---------------------------------------------------------------------------
|
|
9633
9740
|
// Getters
|
|
@@ -9639,10 +9746,6 @@ class ImageFigure extends Component {
|
|
|
9639
9746
|
return this.env.model.getters.getImagePath(this.figureId);
|
|
9640
9747
|
}
|
|
9641
9748
|
}
|
|
9642
|
-
ImageFigure.props = {
|
|
9643
|
-
figure: Object,
|
|
9644
|
-
onFigureDeleted: Function,
|
|
9645
|
-
};
|
|
9646
9749
|
|
|
9647
9750
|
function centerFigurePosition(getters, size) {
|
|
9648
9751
|
const { x: offsetCorrectionX, y: offsetCorrectionY } = getters.getMainViewportCoordinates();
|
|
@@ -10344,7 +10447,7 @@ function setStyle(env, style) {
|
|
|
10344
10447
|
// Simple actions
|
|
10345
10448
|
//------------------------------------------------------------------------------
|
|
10346
10449
|
const PASTE_ACTION = async (env) => paste$1(env);
|
|
10347
|
-
const
|
|
10450
|
+
const PASTE_AS_VALUE_ACTION = async (env) => paste$1(env, "asValue");
|
|
10348
10451
|
async function paste$1(env, pasteOption) {
|
|
10349
10452
|
const spreadsheetClipboard = env.model.getters.getClipboardTextContent();
|
|
10350
10453
|
const osClipboard = await env.clipboard.readText();
|
|
@@ -10357,7 +10460,7 @@ async function paste$1(env, pasteOption) {
|
|
|
10357
10460
|
else {
|
|
10358
10461
|
interactivePaste(env, target, pasteOption);
|
|
10359
10462
|
}
|
|
10360
|
-
if (env.model.getters.isCutOperation() && pasteOption !== "
|
|
10463
|
+
if (env.model.getters.isCutOperation() && pasteOption !== "asValue") {
|
|
10361
10464
|
await env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
10362
10465
|
}
|
|
10363
10466
|
break;
|
|
@@ -10772,9 +10875,9 @@ const pasteSpecial = {
|
|
|
10772
10875
|
icon: "o-spreadsheet-Icon.PASTE",
|
|
10773
10876
|
};
|
|
10774
10877
|
const pasteSpecialValue = {
|
|
10775
|
-
name: _t("Paste value
|
|
10878
|
+
name: _t("Paste as value"),
|
|
10776
10879
|
description: "Ctrl+Shift+V",
|
|
10777
|
-
execute:
|
|
10880
|
+
execute: PASTE_AS_VALUE_ACTION,
|
|
10778
10881
|
};
|
|
10779
10882
|
const pasteSpecialFormat = {
|
|
10780
10883
|
name: _t("Paste format only"),
|
|
@@ -10930,6 +11033,9 @@ function arg(definition, description = "") {
|
|
|
10930
11033
|
function makeArg(str, description) {
|
|
10931
11034
|
let parts = str.match(ARG_REGEXP);
|
|
10932
11035
|
let name = parts[1].trim();
|
|
11036
|
+
if (!name) {
|
|
11037
|
+
throw new Error(`Function argument definition is missing a name: '${str}'.`);
|
|
11038
|
+
}
|
|
10933
11039
|
let types = [];
|
|
10934
11040
|
let isOptional = false;
|
|
10935
11041
|
let isRepeating = false;
|
|
@@ -14652,7 +14758,7 @@ const DATE = {
|
|
|
14652
14758
|
if (_year < 1900) {
|
|
14653
14759
|
_year += 1900;
|
|
14654
14760
|
}
|
|
14655
|
-
const jsDate = new
|
|
14761
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
14656
14762
|
const result = jsDateToRoundNumber(jsDate);
|
|
14657
14763
|
assert(() => result >= 0, _t("The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900."));
|
|
14658
14764
|
return result;
|
|
@@ -14695,7 +14801,7 @@ const DATEDIF = {
|
|
|
14695
14801
|
// See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
|
|
14696
14802
|
let days = jsEndDate.getDate() - jsStartDate.getDate();
|
|
14697
14803
|
if (days < 0) {
|
|
14698
|
-
const monthBeforeEndMonth = new
|
|
14804
|
+
const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
|
|
14699
14805
|
const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
|
|
14700
14806
|
days = daysInMonthBeforeEndMonth - Math.abs(days);
|
|
14701
14807
|
}
|
|
@@ -14704,7 +14810,7 @@ const DATEDIF = {
|
|
|
14704
14810
|
if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
|
|
14705
14811
|
return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
|
|
14706
14812
|
}
|
|
14707
|
-
const endDateWithinOneYear = new
|
|
14813
|
+
const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
|
|
14708
14814
|
let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
|
|
14709
14815
|
if (days < 0) {
|
|
14710
14816
|
endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
|
|
@@ -14821,7 +14927,7 @@ const EOMONTH = {
|
|
|
14821
14927
|
const _months = Math.trunc(toNumber(months, this.locale));
|
|
14822
14928
|
const yStart = _startDate.getFullYear();
|
|
14823
14929
|
const mStart = _startDate.getMonth();
|
|
14824
|
-
const jsDate = new
|
|
14930
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
14825
14931
|
return jsDateToRoundNumber(jsDate);
|
|
14826
14932
|
},
|
|
14827
14933
|
isExported: true,
|
|
@@ -14858,17 +14964,17 @@ const ISOWEEKNUM = {
|
|
|
14858
14964
|
// The first week of the year is the week that contains the first
|
|
14859
14965
|
// Thursday of the year.
|
|
14860
14966
|
let firstThursday = 1;
|
|
14861
|
-
while (new
|
|
14967
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
14862
14968
|
firstThursday += 1;
|
|
14863
14969
|
}
|
|
14864
|
-
const firstDayOfFirstWeek = new
|
|
14970
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
14865
14971
|
// The last week of the year is the week that contains the last Thursday of
|
|
14866
14972
|
// the year.
|
|
14867
14973
|
let lastThursday = 31;
|
|
14868
|
-
while (new
|
|
14974
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
14869
14975
|
lastThursday -= 1;
|
|
14870
14976
|
}
|
|
14871
|
-
const lastDayOfLastWeek = new
|
|
14977
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
14872
14978
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
14873
14979
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
14874
14980
|
let offsetYear;
|
|
@@ -14894,17 +15000,17 @@ const ISOWEEKNUM = {
|
|
|
14894
15000
|
case 1:
|
|
14895
15001
|
// firstDay is the 1st day of the 1st week of the year after
|
|
14896
15002
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
14897
|
-
firstDay = new
|
|
15003
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
14898
15004
|
break;
|
|
14899
15005
|
case -1:
|
|
14900
15006
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
14901
15007
|
// The first week of the previous year is the week that contains the
|
|
14902
15008
|
// first Thursday of the previous year.
|
|
14903
15009
|
let firstThursdayPreviousYear = 1;
|
|
14904
|
-
while (new
|
|
15010
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
14905
15011
|
firstThursdayPreviousYear += 1;
|
|
14906
15012
|
}
|
|
14907
|
-
firstDay = new
|
|
15013
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
14908
15014
|
break;
|
|
14909
15015
|
}
|
|
14910
15016
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -15039,8 +15145,8 @@ const NETWORKDAYS_INTL = {
|
|
|
15039
15145
|
});
|
|
15040
15146
|
}
|
|
15041
15147
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
15042
|
-
const stopDate =
|
|
15043
|
-
let stepDate =
|
|
15148
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
15149
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
15044
15150
|
const timeStopDate = stopDate.getTime();
|
|
15045
15151
|
let timeStepDate = stepDate.getTime();
|
|
15046
15152
|
let netWorkingDay = 0;
|
|
@@ -15066,8 +15172,7 @@ const NOW = {
|
|
|
15066
15172
|
return getDateTimeFormat(this.locale);
|
|
15067
15173
|
},
|
|
15068
15174
|
compute: function () {
|
|
15069
|
-
let today =
|
|
15070
|
-
today.setMilliseconds(0);
|
|
15175
|
+
let today = DateTime.now();
|
|
15071
15176
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
15072
15177
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
15073
15178
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -15141,8 +15246,8 @@ const TODAY = {
|
|
|
15141
15246
|
return this.locale.dateFormat;
|
|
15142
15247
|
},
|
|
15143
15248
|
compute: function () {
|
|
15144
|
-
const today =
|
|
15145
|
-
const jsDate = new
|
|
15249
|
+
const today = DateTime.now();
|
|
15250
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
15146
15251
|
return jsDateToRoundNumber(jsDate);
|
|
15147
15252
|
},
|
|
15148
15253
|
isExported: true,
|
|
@@ -15197,10 +15302,10 @@ const WEEKNUM = {
|
|
|
15197
15302
|
}
|
|
15198
15303
|
const y = _date.getFullYear();
|
|
15199
15304
|
let dayStart = 1;
|
|
15200
|
-
let startDayOfFirstWeek = new
|
|
15305
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
15201
15306
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
15202
15307
|
dayStart += 1;
|
|
15203
|
-
startDayOfFirstWeek = new
|
|
15308
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
15204
15309
|
}
|
|
15205
15310
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
15206
15311
|
if (dif < 0) {
|
|
@@ -15258,7 +15363,7 @@ const WORKDAY_INTL = {
|
|
|
15258
15363
|
timesHoliday.add(holiday.getTime());
|
|
15259
15364
|
});
|
|
15260
15365
|
}
|
|
15261
|
-
let stepDate =
|
|
15366
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
15262
15367
|
let timeStepDate = stepDate.getTime();
|
|
15263
15368
|
const unitDay = Math.sign(_numDays);
|
|
15264
15369
|
let stepDay = Math.abs(_numDays);
|
|
@@ -15322,7 +15427,7 @@ const MONTH_START = {
|
|
|
15322
15427
|
const _startDate = toJsDate(date, this.locale);
|
|
15323
15428
|
const yStart = _startDate.getFullYear();
|
|
15324
15429
|
const mStart = _startDate.getMonth();
|
|
15325
|
-
const jsDate = new
|
|
15430
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
15326
15431
|
return jsDateToRoundNumber(jsDate);
|
|
15327
15432
|
},
|
|
15328
15433
|
};
|
|
@@ -15364,7 +15469,7 @@ const QUARTER_START = {
|
|
|
15364
15469
|
compute: function (date) {
|
|
15365
15470
|
const quarter = QUARTER.compute.bind(this)(date);
|
|
15366
15471
|
const year = YEAR.compute.bind(this)(date);
|
|
15367
|
-
const jsDate = new
|
|
15472
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
15368
15473
|
return jsDateToRoundNumber(jsDate);
|
|
15369
15474
|
},
|
|
15370
15475
|
};
|
|
@@ -15381,7 +15486,7 @@ const QUARTER_END = {
|
|
|
15381
15486
|
compute: function (date) {
|
|
15382
15487
|
const quarter = QUARTER.compute.bind(this)(date);
|
|
15383
15488
|
const year = YEAR.compute.bind(this)(date);
|
|
15384
|
-
const jsDate = new
|
|
15489
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
15385
15490
|
return jsDateToRoundNumber(jsDate);
|
|
15386
15491
|
},
|
|
15387
15492
|
};
|
|
@@ -15397,7 +15502,7 @@ const YEAR_START = {
|
|
|
15397
15502
|
},
|
|
15398
15503
|
compute: function (date) {
|
|
15399
15504
|
const year = YEAR.compute.bind(this)(date);
|
|
15400
|
-
const jsDate = new
|
|
15505
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
15401
15506
|
return jsDateToRoundNumber(jsDate);
|
|
15402
15507
|
},
|
|
15403
15508
|
};
|
|
@@ -15413,7 +15518,7 @@ const YEAR_END = {
|
|
|
15413
15518
|
},
|
|
15414
15519
|
compute: function (date) {
|
|
15415
15520
|
const year = YEAR.compute.bind(this)(date);
|
|
15416
|
-
const jsDate = new
|
|
15521
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
15417
15522
|
return jsDateToRoundNumber(jsDate);
|
|
15418
15523
|
},
|
|
15419
15524
|
};
|
|
@@ -15461,8 +15566,8 @@ const DEFAULT_DELTA_ARG = 0;
|
|
|
15461
15566
|
const DELTA = {
|
|
15462
15567
|
description: _t("Compare two numeric values, returning 1 if they're equal."),
|
|
15463
15568
|
args: [
|
|
15464
|
-
arg(" (number)", _t("The first number to compare.")),
|
|
15465
|
-
arg(` (number, default=${DEFAULT_DELTA_ARG})`, _t("The second number to compare.")),
|
|
15569
|
+
arg("number1 (number)", _t("The first number to compare.")),
|
|
15570
|
+
arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _t("The second number to compare.")),
|
|
15466
15571
|
],
|
|
15467
15572
|
returns: ["NUMBER"],
|
|
15468
15573
|
compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
|
|
@@ -15889,7 +15994,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
15889
15994
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity, locale) {
|
|
15890
15995
|
const startDate = toJsDate(settlement, locale);
|
|
15891
15996
|
const endDate = toJsDate(maturity, locale);
|
|
15892
|
-
const startDatePlusOneYear =
|
|
15997
|
+
const startDatePlusOneYear = toJsDate(settlement, locale);
|
|
15893
15998
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
15894
15999
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _t("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
15895
16000
|
}
|
|
@@ -16024,7 +16129,7 @@ const AMORLINC = {
|
|
|
16024
16129
|
arg("salvage (number)", _t("The value of the asset at the end of depreciation.")),
|
|
16025
16130
|
arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
|
|
16026
16131
|
arg("rate (number)", _t("The deprecation rate.")),
|
|
16027
|
-
arg(" (number, optional)", _t("An indicator of what day count method to use.")),
|
|
16132
|
+
arg("day_count_convention (number, optional)", _t("An indicator of what day count method to use.")),
|
|
16028
16133
|
],
|
|
16029
16134
|
returns: ["NUMBER"],
|
|
16030
16135
|
compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
|
|
@@ -19196,8 +19301,8 @@ const MID = {
|
|
|
19196
19301
|
description: _t("A segment of a string."),
|
|
19197
19302
|
args: [
|
|
19198
19303
|
arg("text (string)", _t("The string to extract a segment from.")),
|
|
19199
|
-
arg(" (number)", _t("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
19200
|
-
arg(" (number)", _t("The length of the segment to extract.")),
|
|
19304
|
+
arg("starting_at (number)", _t("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
19305
|
+
arg("extract_length (number)", _t("The length of the segment to extract.")),
|
|
19201
19306
|
],
|
|
19202
19307
|
returns: ["STRING"],
|
|
19203
19308
|
compute: function (text, starting_at, extract_length) {
|
|
@@ -20013,6 +20118,11 @@ const formatNumberAutomatic = {
|
|
|
20013
20118
|
execute: (env) => setFormatter(env, ""),
|
|
20014
20119
|
isActive: (env) => isAutomaticFormatSelected(env),
|
|
20015
20120
|
};
|
|
20121
|
+
const formatNumberPlainText = {
|
|
20122
|
+
name: _t("Plain text"),
|
|
20123
|
+
execute: (env) => setFormatter(env, PLAIN_TEXT_FORMAT),
|
|
20124
|
+
isActive: (env) => isFormatSelected(env, PLAIN_TEXT_FORMAT),
|
|
20125
|
+
};
|
|
20016
20126
|
const formatNumberNumber = createFormatActionSpec({
|
|
20017
20127
|
name: _t("Number"),
|
|
20018
20128
|
descriptionValue: 1000.12,
|
|
@@ -20372,6 +20482,7 @@ var ACTION_FORMAT = /*#__PURE__*/Object.freeze({
|
|
|
20372
20482
|
formatNumberFullWeekDayAndMonth: formatNumberFullWeekDayAndMonth,
|
|
20373
20483
|
formatNumberNumber: formatNumberNumber,
|
|
20374
20484
|
formatNumberPercent: formatNumberPercent,
|
|
20485
|
+
formatNumberPlainText: formatNumberPlainText,
|
|
20375
20486
|
formatNumberShortMonth: formatNumberShortMonth,
|
|
20376
20487
|
formatNumberShortWeekDay: formatNumberShortWeekDay,
|
|
20377
20488
|
formatNumberTime: formatNumberTime,
|
|
@@ -20802,6 +20913,10 @@ numberFormatMenuRegistry
|
|
|
20802
20913
|
.add("format_number_automatic", {
|
|
20803
20914
|
...formatNumberAutomatic,
|
|
20804
20915
|
sequence: 10,
|
|
20916
|
+
})
|
|
20917
|
+
.add("format_number_plain_text", {
|
|
20918
|
+
...formatNumberPlainText,
|
|
20919
|
+
sequence: 15,
|
|
20805
20920
|
separator: true,
|
|
20806
20921
|
})
|
|
20807
20922
|
.add("format_number_number", {
|
|
@@ -21400,10 +21515,10 @@ const arrowMap = {
|
|
|
21400
21515
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
21401
21516
|
const direction = arrowMap[ev.key];
|
|
21402
21517
|
if (ev.shiftKey) {
|
|
21403
|
-
selection.resizeAnchorZone(direction, ev
|
|
21518
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
21404
21519
|
}
|
|
21405
21520
|
else {
|
|
21406
|
-
selection.moveAnchorCell(direction, ev
|
|
21521
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
21407
21522
|
}
|
|
21408
21523
|
}
|
|
21409
21524
|
|
|
@@ -21470,6 +21585,15 @@ css /* scss */ `
|
|
|
21470
21585
|
*/
|
|
21471
21586
|
class SelectionInput extends Component {
|
|
21472
21587
|
static template = "o-spreadsheet-SelectionInput";
|
|
21588
|
+
static props = {
|
|
21589
|
+
ranges: Function,
|
|
21590
|
+
hasSingleRange: { type: Boolean, optional: true },
|
|
21591
|
+
required: { type: Boolean, optional: true },
|
|
21592
|
+
isInvalid: { type: Boolean, optional: true },
|
|
21593
|
+
class: { type: String, optional: true },
|
|
21594
|
+
onSelectionChanged: { type: Function, optional: true },
|
|
21595
|
+
onSelectionConfirmed: { type: Function, optional: true },
|
|
21596
|
+
};
|
|
21473
21597
|
id = uuidGenerator$1.uuidv4();
|
|
21474
21598
|
previousRanges = this.props.ranges() || [];
|
|
21475
21599
|
originSheet = this.env.model.getters.getActiveSheetId();
|
|
@@ -21632,15 +21756,6 @@ class SelectionInput extends Component {
|
|
|
21632
21756
|
this.env.model.dispatch("UNFOCUS_SELECTION_INPUT");
|
|
21633
21757
|
}
|
|
21634
21758
|
}
|
|
21635
|
-
SelectionInput.props = {
|
|
21636
|
-
ranges: Function,
|
|
21637
|
-
hasSingleRange: { type: Boolean, optional: true },
|
|
21638
|
-
required: { type: Boolean, optional: true },
|
|
21639
|
-
isInvalid: { type: Boolean, optional: true },
|
|
21640
|
-
class: { type: String, optional: true },
|
|
21641
|
-
onSelectionChanged: { type: Function, optional: true },
|
|
21642
|
-
onSelectionConfirmed: { type: Function, optional: true },
|
|
21643
|
-
};
|
|
21644
21759
|
|
|
21645
21760
|
css /* scss */ `
|
|
21646
21761
|
.o-validation-error,
|
|
@@ -21656,6 +21771,10 @@ css /* scss */ `
|
|
|
21656
21771
|
`;
|
|
21657
21772
|
class ValidationMessages extends Component {
|
|
21658
21773
|
static template = "o-spreadsheet-ValidationMessages";
|
|
21774
|
+
static props = {
|
|
21775
|
+
messages: Array,
|
|
21776
|
+
msgType: String,
|
|
21777
|
+
};
|
|
21659
21778
|
get divClasses() {
|
|
21660
21779
|
if (this.props.msgType === "warning") {
|
|
21661
21780
|
return "o-validation-warning text-warning";
|
|
@@ -21663,14 +21782,96 @@ class ValidationMessages extends Component {
|
|
|
21663
21782
|
return "o-validation-error text-danger";
|
|
21664
21783
|
}
|
|
21665
21784
|
}
|
|
21666
|
-
|
|
21667
|
-
|
|
21668
|
-
|
|
21669
|
-
|
|
21785
|
+
|
|
21786
|
+
css /* scss */ `
|
|
21787
|
+
.o-checkbox {
|
|
21788
|
+
display: flex;
|
|
21789
|
+
justify-items: center;
|
|
21790
|
+
input {
|
|
21791
|
+
margin-right: 5px;
|
|
21792
|
+
}
|
|
21793
|
+
}
|
|
21794
|
+
`;
|
|
21795
|
+
class Checkbox extends Component {
|
|
21796
|
+
static template = "o-spreadsheet.Checkbox";
|
|
21797
|
+
static props = {
|
|
21798
|
+
label: { type: String, optional: true },
|
|
21799
|
+
value: { type: Boolean, optional: true },
|
|
21800
|
+
className: { type: String, optional: true },
|
|
21801
|
+
name: { type: String, optional: true },
|
|
21802
|
+
onChange: Function,
|
|
21803
|
+
};
|
|
21804
|
+
static defaultProps = { value: false };
|
|
21805
|
+
onChange(ev) {
|
|
21806
|
+
const value = ev.target.checked;
|
|
21807
|
+
this.props.onChange(value);
|
|
21808
|
+
}
|
|
21809
|
+
}
|
|
21810
|
+
|
|
21811
|
+
class Section extends Component {
|
|
21812
|
+
static template = "o_spreadsheet.Section";
|
|
21813
|
+
static props = {
|
|
21814
|
+
class: { type: String, optional: true },
|
|
21815
|
+
slots: Object,
|
|
21816
|
+
};
|
|
21817
|
+
}
|
|
21818
|
+
|
|
21819
|
+
class ChartDataSeries extends Component {
|
|
21820
|
+
static template = "o-spreadsheet.ChartDataSeries";
|
|
21821
|
+
static components = { SelectionInput, Section };
|
|
21822
|
+
static props = {
|
|
21823
|
+
ranges: Function,
|
|
21824
|
+
hasSingleRange: { type: Boolean, optional: true },
|
|
21825
|
+
onSelectionChanged: Function,
|
|
21826
|
+
onSelectionConfirmed: Function,
|
|
21827
|
+
};
|
|
21828
|
+
get title() {
|
|
21829
|
+
return this.props.hasSingleRange ? _t("Data range") : _t("Data series");
|
|
21830
|
+
}
|
|
21831
|
+
}
|
|
21832
|
+
|
|
21833
|
+
class ChartErrorSection extends Component {
|
|
21834
|
+
static template = "o-spreadsheet.ChartErrorSection";
|
|
21835
|
+
static components = { Section, ValidationMessages };
|
|
21836
|
+
static props = { messages: { type: Array, element: String } };
|
|
21837
|
+
}
|
|
21838
|
+
|
|
21839
|
+
class ChartLabelRange extends Component {
|
|
21840
|
+
static template = "o-spreadsheet.ChartLabelRange";
|
|
21841
|
+
static components = { SelectionInput, Checkbox, Section };
|
|
21842
|
+
static props = {
|
|
21843
|
+
title: { type: String, optional: true },
|
|
21844
|
+
range: Function,
|
|
21845
|
+
isInvalid: Boolean,
|
|
21846
|
+
required: { type: Boolean, optional: true },
|
|
21847
|
+
onSelectionChanged: Function,
|
|
21848
|
+
onSelectionConfirmed: Function,
|
|
21849
|
+
options: { type: Array, optional: true },
|
|
21850
|
+
};
|
|
21851
|
+
static defaultProps = {
|
|
21852
|
+
title: _t("Categories / Labels"),
|
|
21853
|
+
options: [],
|
|
21854
|
+
required: false,
|
|
21855
|
+
};
|
|
21856
|
+
}
|
|
21670
21857
|
|
|
21671
21858
|
class LineBarPieConfigPanel extends Component {
|
|
21672
21859
|
static template = "o-spreadsheet-LineBarPieConfigPanel";
|
|
21673
|
-
static components = {
|
|
21860
|
+
static components = {
|
|
21861
|
+
SelectionInput,
|
|
21862
|
+
ValidationMessages,
|
|
21863
|
+
ChartDataSeries,
|
|
21864
|
+
ChartLabelRange,
|
|
21865
|
+
Section,
|
|
21866
|
+
Checkbox,
|
|
21867
|
+
ChartErrorSection,
|
|
21868
|
+
};
|
|
21869
|
+
static props = {
|
|
21870
|
+
figureId: String,
|
|
21871
|
+
definition: Object,
|
|
21872
|
+
updateChart: Function,
|
|
21873
|
+
canUpdateChart: Function,
|
|
21874
|
+
};
|
|
21674
21875
|
state = useState({
|
|
21675
21876
|
datasetDispatchResult: undefined,
|
|
21676
21877
|
labelsDispatchResult: undefined,
|
|
@@ -21694,9 +21895,22 @@ class LineBarPieConfigPanel extends Component {
|
|
|
21694
21895
|
get isLabelInvalid() {
|
|
21695
21896
|
return !!this.state.labelsDispatchResult?.isCancelledBecause("InvalidLabelRange" /* CommandResult.InvalidLabelRange */);
|
|
21696
21897
|
}
|
|
21697
|
-
|
|
21898
|
+
get dataSetsHaveTitleLabel() {
|
|
21899
|
+
return _t("Use row %s as headers", this.calculateHeaderPosition() || "");
|
|
21900
|
+
}
|
|
21901
|
+
getLabelRangeOptions() {
|
|
21902
|
+
return [
|
|
21903
|
+
{
|
|
21904
|
+
name: "aggregated",
|
|
21905
|
+
label: _t("Aggregate"),
|
|
21906
|
+
value: this.props.definition.aggregated,
|
|
21907
|
+
onChange: this.onUpdateAggregated.bind(this),
|
|
21908
|
+
},
|
|
21909
|
+
];
|
|
21910
|
+
}
|
|
21911
|
+
onUpdateDataSetsHaveTitle(dataSetsHaveTitle) {
|
|
21698
21912
|
this.props.updateChart(this.props.figureId, {
|
|
21699
|
-
dataSetsHaveTitle
|
|
21913
|
+
dataSetsHaveTitle,
|
|
21700
21914
|
});
|
|
21701
21915
|
}
|
|
21702
21916
|
/**
|
|
@@ -21736,9 +21950,9 @@ class LineBarPieConfigPanel extends Component {
|
|
|
21736
21950
|
getLabelRange() {
|
|
21737
21951
|
return this.labelRange || "";
|
|
21738
21952
|
}
|
|
21739
|
-
onUpdateAggregated(
|
|
21953
|
+
onUpdateAggregated(aggregated) {
|
|
21740
21954
|
this.props.updateChart(this.props.figureId, {
|
|
21741
|
-
aggregated
|
|
21955
|
+
aggregated,
|
|
21742
21956
|
});
|
|
21743
21957
|
}
|
|
21744
21958
|
calculateHeaderPosition() {
|
|
@@ -21758,23 +21972,20 @@ class LineBarPieConfigPanel extends Component {
|
|
|
21758
21972
|
return undefined;
|
|
21759
21973
|
}
|
|
21760
21974
|
}
|
|
21761
|
-
LineBarPieConfigPanel.props = {
|
|
21762
|
-
figureId: String,
|
|
21763
|
-
definition: Object,
|
|
21764
|
-
updateChart: Function,
|
|
21765
|
-
canUpdateChart: Function,
|
|
21766
|
-
};
|
|
21767
21975
|
|
|
21768
21976
|
class BarConfigPanel extends LineBarPieConfigPanel {
|
|
21769
21977
|
static template = "o-spreadsheet-BarConfigPanel";
|
|
21770
|
-
|
|
21978
|
+
get stackedLabel() {
|
|
21979
|
+
return _t("Stacked barchart");
|
|
21980
|
+
}
|
|
21981
|
+
onUpdateStacked(stacked) {
|
|
21771
21982
|
this.props.updateChart(this.props.figureId, {
|
|
21772
|
-
stacked
|
|
21983
|
+
stacked,
|
|
21773
21984
|
});
|
|
21774
21985
|
}
|
|
21775
|
-
onUpdateAggregated(
|
|
21986
|
+
onUpdateAggregated(aggregated) {
|
|
21776
21987
|
this.props.updateChart(this.props.figureId, {
|
|
21777
|
-
aggregated
|
|
21988
|
+
aggregated,
|
|
21778
21989
|
});
|
|
21779
21990
|
}
|
|
21780
21991
|
}
|
|
@@ -22102,6 +22313,12 @@ css /* scss */ `
|
|
|
22102
22313
|
`;
|
|
22103
22314
|
class ColorPicker extends Component {
|
|
22104
22315
|
static template = "o-spreadsheet-ColorPicker";
|
|
22316
|
+
static props = {
|
|
22317
|
+
onColorPicked: Function,
|
|
22318
|
+
currentColor: { type: String, optional: true },
|
|
22319
|
+
maxHeight: { type: Number, optional: true },
|
|
22320
|
+
anchorRect: Object,
|
|
22321
|
+
};
|
|
22105
22322
|
static defaultProps = { currentColor: "" };
|
|
22106
22323
|
static components = { Popover };
|
|
22107
22324
|
COLORS = COLOR_PICKER_DEFAULTS;
|
|
@@ -22237,12 +22454,6 @@ class ColorPicker extends Component {
|
|
|
22237
22454
|
return isSameColor(color1, color2);
|
|
22238
22455
|
}
|
|
22239
22456
|
}
|
|
22240
|
-
ColorPicker.props = {
|
|
22241
|
-
onColorPicked: Function,
|
|
22242
|
-
currentColor: { type: String, optional: true },
|
|
22243
|
-
maxHeight: { type: Number, optional: true },
|
|
22244
|
-
anchorRect: Object,
|
|
22245
|
-
};
|
|
22246
22457
|
|
|
22247
22458
|
css /* scss */ `
|
|
22248
22459
|
.o-color-picker-widget {
|
|
@@ -22280,6 +22491,17 @@ css /* scss */ `
|
|
|
22280
22491
|
`;
|
|
22281
22492
|
class ColorPickerWidget extends Component {
|
|
22282
22493
|
static template = "o-spreadsheet-ColorPickerWidget";
|
|
22494
|
+
static props = {
|
|
22495
|
+
currentColor: { type: String, optional: true },
|
|
22496
|
+
toggleColorPicker: Function,
|
|
22497
|
+
showColorPicker: Boolean,
|
|
22498
|
+
onColorPicked: Function,
|
|
22499
|
+
icon: String,
|
|
22500
|
+
title: { type: String, optional: true },
|
|
22501
|
+
disabled: { type: Boolean, optional: true },
|
|
22502
|
+
dropdownMaxHeight: { type: Number, optional: true },
|
|
22503
|
+
class: { type: String, optional: true },
|
|
22504
|
+
};
|
|
22283
22505
|
static components = { ColorPicker };
|
|
22284
22506
|
colorPickerButtonRef = useRef("colorPickerButton");
|
|
22285
22507
|
get iconStyle() {
|
|
@@ -22298,44 +22520,55 @@ class ColorPickerWidget extends Component {
|
|
|
22298
22520
|
};
|
|
22299
22521
|
}
|
|
22300
22522
|
}
|
|
22301
|
-
ColorPickerWidget.props = {
|
|
22302
|
-
currentColor: { type: String, optional: true },
|
|
22303
|
-
toggleColorPicker: Function,
|
|
22304
|
-
showColorPicker: Boolean,
|
|
22305
|
-
onColorPicked: Function,
|
|
22306
|
-
icon: String,
|
|
22307
|
-
title: { type: String, optional: true },
|
|
22308
|
-
disabled: { type: Boolean, optional: true },
|
|
22309
|
-
dropdownMaxHeight: { type: Number, optional: true },
|
|
22310
|
-
class: { type: String, optional: true },
|
|
22311
|
-
};
|
|
22312
22523
|
|
|
22313
|
-
class
|
|
22314
|
-
static template = "o-spreadsheet
|
|
22315
|
-
static components = { ColorPickerWidget };
|
|
22316
|
-
|
|
22317
|
-
|
|
22318
|
-
|
|
22319
|
-
}
|
|
22320
|
-
|
|
22321
|
-
this.state.fillColorTool = false;
|
|
22322
|
-
}
|
|
22524
|
+
class ChartColor extends Component {
|
|
22525
|
+
static template = "o-spreadsheet.ChartColor";
|
|
22526
|
+
static components = { ColorPickerWidget, Section };
|
|
22527
|
+
static props = {
|
|
22528
|
+
currentColor: { type: String, optional: true },
|
|
22529
|
+
onColorPicked: Function,
|
|
22530
|
+
};
|
|
22531
|
+
state;
|
|
22323
22532
|
setup() {
|
|
22324
|
-
this.state
|
|
22325
|
-
useExternalListener(window, "click", this.
|
|
22533
|
+
this.state = useState({ pickerOpened: false });
|
|
22534
|
+
useExternalListener(window, "click", this.closePicker);
|
|
22326
22535
|
}
|
|
22327
|
-
|
|
22328
|
-
this.state.
|
|
22536
|
+
closePicker() {
|
|
22537
|
+
this.state.pickerOpened = false;
|
|
22538
|
+
}
|
|
22539
|
+
togglePicker() {
|
|
22540
|
+
this.state.pickerOpened = !this.state.pickerOpened;
|
|
22541
|
+
}
|
|
22542
|
+
}
|
|
22543
|
+
|
|
22544
|
+
class ChartTitle extends Component {
|
|
22545
|
+
static template = "o-spreadsheet.ChartTitle";
|
|
22546
|
+
static components = { ColorPickerWidget, Section };
|
|
22547
|
+
static props = { title: String, update: Function };
|
|
22548
|
+
updateTitle(ev) {
|
|
22549
|
+
this.props.update(ev.target.value);
|
|
22550
|
+
}
|
|
22551
|
+
}
|
|
22552
|
+
|
|
22553
|
+
class LineBarPieDesignPanel extends Component {
|
|
22554
|
+
static template = "o-spreadsheet-LineBarPieDesignPanel";
|
|
22555
|
+
static components = { ChartColor, ColorPickerWidget, ChartTitle, Section };
|
|
22556
|
+
static props = {
|
|
22557
|
+
figureId: String,
|
|
22558
|
+
definition: Object,
|
|
22559
|
+
updateChart: Function,
|
|
22560
|
+
canUpdateChart: Function,
|
|
22561
|
+
};
|
|
22562
|
+
get title() {
|
|
22563
|
+
return _t(this.props.definition.title);
|
|
22329
22564
|
}
|
|
22330
22565
|
updateBackgroundColor(color) {
|
|
22331
22566
|
this.props.updateChart(this.props.figureId, {
|
|
22332
22567
|
background: color,
|
|
22333
22568
|
});
|
|
22334
22569
|
}
|
|
22335
|
-
updateTitle() {
|
|
22336
|
-
this.props.updateChart(this.props.figureId, {
|
|
22337
|
-
title: this.state.title,
|
|
22338
|
-
});
|
|
22570
|
+
updateTitle(title) {
|
|
22571
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
22339
22572
|
}
|
|
22340
22573
|
updateSelect(attr, ev) {
|
|
22341
22574
|
this.props.updateChart(this.props.figureId, {
|
|
@@ -22343,12 +22576,6 @@ class LineBarPieDesignPanel extends Component {
|
|
|
22343
22576
|
});
|
|
22344
22577
|
}
|
|
22345
22578
|
}
|
|
22346
|
-
LineBarPieDesignPanel.props = {
|
|
22347
|
-
figureId: String,
|
|
22348
|
-
definition: Object,
|
|
22349
|
-
updateChart: Function,
|
|
22350
|
-
canUpdateChart: Function,
|
|
22351
|
-
};
|
|
22352
22579
|
|
|
22353
22580
|
class BarChartDesignPanel extends LineBarPieDesignPanel {
|
|
22354
22581
|
static template = "o-spreadsheet-BarChartDesignPanel";
|
|
@@ -22356,7 +22583,13 @@ class BarChartDesignPanel extends LineBarPieDesignPanel {
|
|
|
22356
22583
|
|
|
22357
22584
|
class GaugeChartConfigPanel extends Component {
|
|
22358
22585
|
static template = "o-spreadsheet-GaugeChartConfigPanel";
|
|
22359
|
-
static components = { SelectionInput,
|
|
22586
|
+
static components = { SelectionInput, ChartErrorSection, ChartDataSeries };
|
|
22587
|
+
static props = {
|
|
22588
|
+
figureId: String,
|
|
22589
|
+
definition: Object,
|
|
22590
|
+
updateChart: Function,
|
|
22591
|
+
canUpdateChart: Function,
|
|
22592
|
+
};
|
|
22360
22593
|
state = useState({
|
|
22361
22594
|
dataRangeDispatchResult: undefined,
|
|
22362
22595
|
});
|
|
@@ -22383,12 +22616,6 @@ class GaugeChartConfigPanel extends Component {
|
|
|
22383
22616
|
return this.dataRange || "";
|
|
22384
22617
|
}
|
|
22385
22618
|
}
|
|
22386
|
-
GaugeChartConfigPanel.props = {
|
|
22387
|
-
figureId: String,
|
|
22388
|
-
definition: Object,
|
|
22389
|
-
updateChart: Function,
|
|
22390
|
-
canUpdateChart: Function,
|
|
22391
|
-
};
|
|
22392
22619
|
|
|
22393
22620
|
css /* scss */ `
|
|
22394
22621
|
.o-gauge-color-set {
|
|
@@ -22423,31 +22650,35 @@ css /* scss */ `
|
|
|
22423
22650
|
`;
|
|
22424
22651
|
class GaugeChartDesignPanel extends Component {
|
|
22425
22652
|
static template = "o-spreadsheet-GaugeChartDesignPanel";
|
|
22426
|
-
static components = { ColorPickerWidget,
|
|
22653
|
+
static components = { ColorPickerWidget, ChartErrorSection, ChartColor, ChartTitle, Section };
|
|
22654
|
+
static props = {
|
|
22655
|
+
figureId: String,
|
|
22656
|
+
definition: Object,
|
|
22657
|
+
updateChart: Function,
|
|
22658
|
+
canUpdateChart: Function,
|
|
22659
|
+
};
|
|
22427
22660
|
state = useState({
|
|
22428
|
-
title: "",
|
|
22429
22661
|
openedMenu: undefined,
|
|
22430
22662
|
sectionRuleDispatchResult: undefined,
|
|
22431
22663
|
sectionRule: deepCopy(this.props.definition.sectionRule),
|
|
22432
22664
|
});
|
|
22433
22665
|
setup() {
|
|
22434
|
-
this.state.title = _t(this.props.definition.title);
|
|
22435
22666
|
useExternalListener(window, "click", this.closeMenus);
|
|
22436
22667
|
}
|
|
22668
|
+
get title() {
|
|
22669
|
+
return _t(this.props.definition.title);
|
|
22670
|
+
}
|
|
22437
22671
|
get designErrorMessages() {
|
|
22438
22672
|
const cancelledReasons = [...(this.state.sectionRuleDispatchResult?.reasons || [])];
|
|
22439
22673
|
return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
|
|
22440
22674
|
}
|
|
22441
22675
|
updateBackgroundColor(color) {
|
|
22442
|
-
this.state.openedMenu = undefined;
|
|
22443
22676
|
this.props.updateChart(this.props.figureId, {
|
|
22444
22677
|
background: color,
|
|
22445
22678
|
});
|
|
22446
22679
|
}
|
|
22447
|
-
updateTitle() {
|
|
22448
|
-
this.props.updateChart(this.props.figureId, {
|
|
22449
|
-
title: this.state.title,
|
|
22450
|
-
});
|
|
22680
|
+
updateTitle(title) {
|
|
22681
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
22451
22682
|
}
|
|
22452
22683
|
isRangeMinInvalid() {
|
|
22453
22684
|
return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause("EmptyGaugeRangeMin" /* CommandResult.EmptyGaugeRangeMin */) ||
|
|
@@ -22497,12 +22728,6 @@ class GaugeChartDesignPanel extends Component {
|
|
|
22497
22728
|
this.state.openedMenu = undefined;
|
|
22498
22729
|
}
|
|
22499
22730
|
}
|
|
22500
|
-
GaugeChartDesignPanel.props = {
|
|
22501
|
-
figureId: String,
|
|
22502
|
-
definition: Object,
|
|
22503
|
-
updateChart: Function,
|
|
22504
|
-
canUpdateChart: Function,
|
|
22505
|
-
};
|
|
22506
22731
|
|
|
22507
22732
|
class LineConfigPanel extends LineBarPieConfigPanel {
|
|
22508
22733
|
static template = "o-spreadsheet-LineConfigPanel";
|
|
@@ -22513,24 +22738,42 @@ class LineConfigPanel extends LineBarPieConfigPanel {
|
|
|
22513
22738
|
}
|
|
22514
22739
|
return false;
|
|
22515
22740
|
}
|
|
22516
|
-
|
|
22741
|
+
get stackedLabel() {
|
|
22742
|
+
return _t("Stacked linechart");
|
|
22743
|
+
}
|
|
22744
|
+
get cumulativeLabel() {
|
|
22745
|
+
return _t("Cumulative data");
|
|
22746
|
+
}
|
|
22747
|
+
getLabelRangeOptions() {
|
|
22748
|
+
const options = super.getLabelRangeOptions();
|
|
22749
|
+
if (this.canTreatLabelsAsText) {
|
|
22750
|
+
options.push({
|
|
22751
|
+
name: "labelsAsText",
|
|
22752
|
+
value: this.props.definition.labelsAsText,
|
|
22753
|
+
label: _t("Treat labels as text"),
|
|
22754
|
+
onChange: this.onUpdateLabelsAsText.bind(this),
|
|
22755
|
+
});
|
|
22756
|
+
}
|
|
22757
|
+
return options;
|
|
22758
|
+
}
|
|
22759
|
+
onUpdateLabelsAsText(labelsAsText) {
|
|
22517
22760
|
this.props.updateChart(this.props.figureId, {
|
|
22518
|
-
labelsAsText
|
|
22761
|
+
labelsAsText,
|
|
22519
22762
|
});
|
|
22520
22763
|
}
|
|
22521
|
-
onUpdateStacked(
|
|
22764
|
+
onUpdateStacked(stacked) {
|
|
22522
22765
|
this.props.updateChart(this.props.figureId, {
|
|
22523
|
-
stacked
|
|
22766
|
+
stacked,
|
|
22524
22767
|
});
|
|
22525
22768
|
}
|
|
22526
|
-
onUpdateAggregated(
|
|
22769
|
+
onUpdateAggregated(aggregated) {
|
|
22527
22770
|
this.props.updateChart(this.props.figureId, {
|
|
22528
|
-
aggregated
|
|
22771
|
+
aggregated,
|
|
22529
22772
|
});
|
|
22530
22773
|
}
|
|
22531
|
-
onUpdateCumulative(
|
|
22774
|
+
onUpdateCumulative(cumulative) {
|
|
22532
22775
|
this.props.updateChart(this.props.figureId, {
|
|
22533
|
-
cumulative
|
|
22776
|
+
cumulative,
|
|
22534
22777
|
});
|
|
22535
22778
|
}
|
|
22536
22779
|
}
|
|
@@ -22541,7 +22784,13 @@ class LineChartDesignPanel extends LineBarPieDesignPanel {
|
|
|
22541
22784
|
|
|
22542
22785
|
class ScorecardChartConfigPanel extends Component {
|
|
22543
22786
|
static template = "o-spreadsheet-ScorecardChartConfigPanel";
|
|
22544
|
-
static components = { SelectionInput, ValidationMessages };
|
|
22787
|
+
static components = { SelectionInput, ValidationMessages, ChartErrorSection, Section };
|
|
22788
|
+
static props = {
|
|
22789
|
+
figureId: String,
|
|
22790
|
+
definition: Object,
|
|
22791
|
+
updateChart: Function,
|
|
22792
|
+
canUpdateChart: Function,
|
|
22793
|
+
};
|
|
22545
22794
|
state = useState({
|
|
22546
22795
|
keyValueDispatchResult: undefined,
|
|
22547
22796
|
baselineDispatchResult: undefined,
|
|
@@ -22593,28 +22842,27 @@ class ScorecardChartConfigPanel extends Component {
|
|
|
22593
22842
|
this.props.updateChart(this.props.figureId, { baselineMode: ev.target.value });
|
|
22594
22843
|
}
|
|
22595
22844
|
}
|
|
22596
|
-
ScorecardChartConfigPanel.props = {
|
|
22597
|
-
figureId: String,
|
|
22598
|
-
definition: Object,
|
|
22599
|
-
updateChart: Function,
|
|
22600
|
-
canUpdateChart: Function,
|
|
22601
|
-
};
|
|
22602
22845
|
|
|
22603
22846
|
class ScorecardChartDesignPanel extends Component {
|
|
22604
22847
|
static template = "o-spreadsheet-ScorecardChartDesignPanel";
|
|
22605
|
-
static components = { ColorPickerWidget };
|
|
22848
|
+
static components = { ColorPickerWidget, ChartColor, ChartTitle, Section };
|
|
22849
|
+
static props = {
|
|
22850
|
+
figureId: String,
|
|
22851
|
+
definition: Object,
|
|
22852
|
+
updateChart: Function,
|
|
22853
|
+
canUpdateChart: Function,
|
|
22854
|
+
};
|
|
22606
22855
|
state = useState({
|
|
22607
|
-
title: "",
|
|
22608
22856
|
openedColorPicker: undefined,
|
|
22609
22857
|
});
|
|
22610
22858
|
setup() {
|
|
22611
|
-
this.state.title = _t(this.props.definition.title);
|
|
22612
22859
|
useExternalListener(window, "click", this.closeMenus);
|
|
22613
22860
|
}
|
|
22614
|
-
|
|
22615
|
-
this.props.
|
|
22616
|
-
|
|
22617
|
-
|
|
22861
|
+
get title() {
|
|
22862
|
+
return _t(this.props.definition.title);
|
|
22863
|
+
}
|
|
22864
|
+
updateTitle(title) {
|
|
22865
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
22618
22866
|
}
|
|
22619
22867
|
translate(term) {
|
|
22620
22868
|
return _t(term);
|
|
@@ -22648,12 +22896,6 @@ class ScorecardChartDesignPanel extends Component {
|
|
|
22648
22896
|
this.state.openedColorPicker = undefined;
|
|
22649
22897
|
}
|
|
22650
22898
|
}
|
|
22651
|
-
ScorecardChartDesignPanel.props = {
|
|
22652
|
-
figureId: String,
|
|
22653
|
-
definition: Object,
|
|
22654
|
-
updateChart: Function,
|
|
22655
|
-
canUpdateChart: Function,
|
|
22656
|
-
};
|
|
22657
22899
|
|
|
22658
22900
|
const chartSidePanelComponentRegistry = new Registry();
|
|
22659
22901
|
chartSidePanelComponentRegistry
|
|
@@ -22704,6 +22946,8 @@ css /* scss */ `
|
|
|
22704
22946
|
`;
|
|
22705
22947
|
class ChartPanel extends Component {
|
|
22706
22948
|
static template = "o-spreadsheet-ChartPanel";
|
|
22949
|
+
static components = { Section };
|
|
22950
|
+
static props = { onCloseSidePanel: Function };
|
|
22707
22951
|
state;
|
|
22708
22952
|
get figureId() {
|
|
22709
22953
|
return this.state.figureId;
|
|
@@ -22790,9 +23034,6 @@ class ChartPanel extends Component {
|
|
|
22790
23034
|
this.state.panel = panel;
|
|
22791
23035
|
}
|
|
22792
23036
|
}
|
|
22793
|
-
ChartPanel.props = {
|
|
22794
|
-
onCloseSidePanel: Function,
|
|
22795
|
-
};
|
|
22796
23037
|
|
|
22797
23038
|
css /* scss */ `
|
|
22798
23039
|
.o-spreadsheet {
|
|
@@ -22903,6 +23144,9 @@ css /* scss */ `
|
|
|
22903
23144
|
`;
|
|
22904
23145
|
class IconPicker extends Component {
|
|
22905
23146
|
static template = "o-spreadsheet-IconPicker";
|
|
23147
|
+
static props = {
|
|
23148
|
+
onIconPicked: Function,
|
|
23149
|
+
};
|
|
22906
23150
|
icons = ICONS;
|
|
22907
23151
|
iconSets = ICON_SETS;
|
|
22908
23152
|
onIconClick(icon) {
|
|
@@ -22911,9 +23155,6 @@ class IconPicker extends Component {
|
|
|
22911
23155
|
}
|
|
22912
23156
|
}
|
|
22913
23157
|
}
|
|
22914
|
-
IconPicker.props = {
|
|
22915
|
-
onIconPicked: Function,
|
|
22916
|
-
};
|
|
22917
23158
|
|
|
22918
23159
|
function useDragAndDropListItems() {
|
|
22919
23160
|
let dndHelper;
|
|
@@ -23268,6 +23509,11 @@ css /* scss */ `
|
|
|
23268
23509
|
`;
|
|
23269
23510
|
class ConditionalFormatPreviewList extends Component {
|
|
23270
23511
|
static template = "o-spreadsheet-ConditionalFormatPreviewList";
|
|
23512
|
+
static props = {
|
|
23513
|
+
conditionalFormats: Array,
|
|
23514
|
+
onPreviewClick: Function,
|
|
23515
|
+
onAddConditionalFormat: Function,
|
|
23516
|
+
};
|
|
23271
23517
|
icons = ICONS;
|
|
23272
23518
|
dragAndDrop = useDragAndDropListItems();
|
|
23273
23519
|
cfListRef = useRef("cfList");
|
|
@@ -23348,11 +23594,6 @@ class ConditionalFormatPreviewList extends Component {
|
|
|
23348
23594
|
}
|
|
23349
23595
|
}
|
|
23350
23596
|
}
|
|
23351
|
-
ConditionalFormatPreviewList.props = {
|
|
23352
|
-
conditionalFormats: Array,
|
|
23353
|
-
onPreviewClick: Function,
|
|
23354
|
-
onAddConditionalFormat: Function,
|
|
23355
|
-
};
|
|
23356
23597
|
|
|
23357
23598
|
css /* scss */ `
|
|
23358
23599
|
label {
|
|
@@ -23525,11 +23766,16 @@ css /* scss */ `
|
|
|
23525
23766
|
`;
|
|
23526
23767
|
class ConditionalFormattingEditor extends Component {
|
|
23527
23768
|
static template = "o-spreadsheet-ConditionalFormattingEditor";
|
|
23769
|
+
static props = {
|
|
23770
|
+
editedCf: { type: Object, optional: true },
|
|
23771
|
+
onExitEdition: Function,
|
|
23772
|
+
};
|
|
23528
23773
|
static components = {
|
|
23529
23774
|
SelectionInput,
|
|
23530
23775
|
IconPicker,
|
|
23531
23776
|
ColorPickerWidget,
|
|
23532
23777
|
ConditionalFormatPreviewList,
|
|
23778
|
+
Section,
|
|
23533
23779
|
};
|
|
23534
23780
|
icons = ICONS;
|
|
23535
23781
|
cellIsOperators = CellIsOperators;
|
|
@@ -23789,13 +24035,13 @@ class ConditionalFormattingEditor extends Component {
|
|
|
23789
24035
|
this.state.rules.iconSet.icons[target] = icon;
|
|
23790
24036
|
}
|
|
23791
24037
|
}
|
|
23792
|
-
ConditionalFormattingEditor.props = {
|
|
23793
|
-
editedCf: { type: Object, optional: true },
|
|
23794
|
-
onExitEdition: Function,
|
|
23795
|
-
};
|
|
23796
24038
|
|
|
23797
24039
|
class ConditionalFormattingPanel extends Component {
|
|
23798
24040
|
static template = "o-spreadsheet-ConditionalFormattingPanel";
|
|
24041
|
+
static props = {
|
|
24042
|
+
selection: { type: Object, optional: true },
|
|
24043
|
+
onCloseSidePanel: Function,
|
|
24044
|
+
};
|
|
23799
24045
|
static components = {
|
|
23800
24046
|
ConditionalFormatPreviewList,
|
|
23801
24047
|
ConditionalFormattingEditor,
|
|
@@ -23854,10 +24100,6 @@ class ConditionalFormattingPanel extends Component {
|
|
|
23854
24100
|
this.state.editedCf = cf;
|
|
23855
24101
|
}
|
|
23856
24102
|
}
|
|
23857
|
-
ConditionalFormattingPanel.props = {
|
|
23858
|
-
selection: { type: Object, optional: true },
|
|
23859
|
-
onCloseSidePanel: Function,
|
|
23860
|
-
};
|
|
23861
24103
|
|
|
23862
24104
|
css /* scss */ `
|
|
23863
24105
|
.o-custom-currency {
|
|
@@ -23868,6 +24110,8 @@ css /* scss */ `
|
|
|
23868
24110
|
`;
|
|
23869
24111
|
class CustomCurrencyPanel extends Component {
|
|
23870
24112
|
static template = "o-spreadsheet-CustomCurrencyPanel";
|
|
24113
|
+
static components = { Section };
|
|
24114
|
+
static props = { onCloseSidePanel: Function };
|
|
23871
24115
|
availableCurrencies;
|
|
23872
24116
|
state;
|
|
23873
24117
|
setup() {
|
|
@@ -23990,9 +24234,6 @@ class CustomCurrencyPanel extends Component {
|
|
|
23990
24234
|
return currency.name + (currency.code ? ` (${currency.code})` : "");
|
|
23991
24235
|
}
|
|
23992
24236
|
}
|
|
23993
|
-
CustomCurrencyPanel.props = {
|
|
23994
|
-
onCloseSidePanel: Function,
|
|
23995
|
-
};
|
|
23996
24237
|
|
|
23997
24238
|
css /* scss */ `
|
|
23998
24239
|
.o-find-and-replace {
|
|
@@ -24012,11 +24253,20 @@ css /* scss */ `
|
|
|
24012
24253
|
padding: 4px 0 4px 4px;
|
|
24013
24254
|
}
|
|
24014
24255
|
}
|
|
24256
|
+
|
|
24257
|
+
.o-matches-count div {
|
|
24258
|
+
text-overflow: ellipsis;
|
|
24259
|
+
overflow: hidden;
|
|
24260
|
+
white-space: nowrap;
|
|
24261
|
+
}
|
|
24015
24262
|
}
|
|
24016
24263
|
`;
|
|
24017
24264
|
class FindAndReplacePanel extends Component {
|
|
24018
24265
|
static template = "o-spreadsheet-FindAndReplacePanel";
|
|
24019
|
-
static components = { SelectionInput };
|
|
24266
|
+
static components = { SelectionInput, Section, Checkbox };
|
|
24267
|
+
static props = {
|
|
24268
|
+
onCloseSidePanel: Function,
|
|
24269
|
+
};
|
|
24020
24270
|
debounceTimeoutId;
|
|
24021
24271
|
initialShowFormulaState = false;
|
|
24022
24272
|
dataRange = "";
|
|
@@ -24091,19 +24341,16 @@ class FindAndReplacePanel extends Component {
|
|
|
24091
24341
|
this.replace();
|
|
24092
24342
|
}
|
|
24093
24343
|
}
|
|
24094
|
-
searchFormulas(
|
|
24095
|
-
const showFormula = ev.target.checked;
|
|
24344
|
+
searchFormulas(showFormula) {
|
|
24096
24345
|
this.env.model.dispatch("SET_FORMULA_VISIBILITY", {
|
|
24097
24346
|
show: showFormula,
|
|
24098
24347
|
});
|
|
24099
24348
|
this.updateSearch({ searchFormulas: showFormula });
|
|
24100
24349
|
}
|
|
24101
|
-
searchExactMatch(
|
|
24102
|
-
const exactMatch = ev.target.checked;
|
|
24350
|
+
searchExactMatch(exactMatch) {
|
|
24103
24351
|
this.updateSearch({ exactMatch });
|
|
24104
24352
|
}
|
|
24105
|
-
searchMatchCase(
|
|
24106
|
-
const matchCase = ev.target.checked;
|
|
24353
|
+
searchMatchCase(matchCase) {
|
|
24107
24354
|
this.updateSearch({ matchCase });
|
|
24108
24355
|
}
|
|
24109
24356
|
changeSearchScope(ev) {
|
|
@@ -24156,9 +24403,6 @@ class FindAndReplacePanel extends Component {
|
|
|
24156
24403
|
});
|
|
24157
24404
|
}
|
|
24158
24405
|
}
|
|
24159
|
-
FindAndReplacePanel.props = {
|
|
24160
|
-
onCloseSidePanel: Function,
|
|
24161
|
-
};
|
|
24162
24406
|
|
|
24163
24407
|
css /* scss */ `
|
|
24164
24408
|
.o-more-formats-panel {
|
|
@@ -24190,13 +24434,13 @@ const DATE_FORMAT_ACTIONS = createActions([
|
|
|
24190
24434
|
]);
|
|
24191
24435
|
class MoreFormatsPanel extends Component {
|
|
24192
24436
|
static template = "o-spreadsheet-MoreFormatsPanel";
|
|
24437
|
+
static props = {
|
|
24438
|
+
onCloseSidePanel: Function,
|
|
24439
|
+
};
|
|
24193
24440
|
get dateFormatsActions() {
|
|
24194
24441
|
return DATE_FORMAT_ACTIONS;
|
|
24195
24442
|
}
|
|
24196
24443
|
}
|
|
24197
|
-
MoreFormatsPanel.props = {
|
|
24198
|
-
onCloseSidePanel: Function,
|
|
24199
|
-
};
|
|
24200
24444
|
|
|
24201
24445
|
css /* scss */ `
|
|
24202
24446
|
.o-checkbox-selection {
|
|
@@ -24205,7 +24449,7 @@ css /* scss */ `
|
|
|
24205
24449
|
`;
|
|
24206
24450
|
class RemoveDuplicatesPanel extends Component {
|
|
24207
24451
|
static template = "o-spreadsheet-RemoveDuplicatesPanel";
|
|
24208
|
-
static components = { ValidationMessages };
|
|
24452
|
+
static components = { ValidationMessages, Section, Checkbox };
|
|
24209
24453
|
state = useState({
|
|
24210
24454
|
hasHeader: false,
|
|
24211
24455
|
columns: {},
|
|
@@ -24294,6 +24538,8 @@ css /* scss */ `
|
|
|
24294
24538
|
`;
|
|
24295
24539
|
class SettingsPanel extends Component {
|
|
24296
24540
|
static template = "o-spreadsheet-SettingsPanel";
|
|
24541
|
+
static components = { Section };
|
|
24542
|
+
static props = { onCloseSidePanel: Function };
|
|
24297
24543
|
loadedLocales = [];
|
|
24298
24544
|
setup() {
|
|
24299
24545
|
onWillStart(() => this.loadLocales());
|
|
@@ -24342,9 +24588,6 @@ class SettingsPanel extends Component {
|
|
|
24342
24588
|
return this.loadedLocales;
|
|
24343
24589
|
}
|
|
24344
24590
|
}
|
|
24345
|
-
SettingsPanel.props = {
|
|
24346
|
-
onCloseSidePanel: Function,
|
|
24347
|
-
};
|
|
24348
24591
|
|
|
24349
24592
|
const SplitToColumnsInteractiveContent = {
|
|
24350
24593
|
SplitIsDestructive: _t("This will overwrite data in the subsequent columns. Split anyway?"),
|
|
@@ -24440,7 +24683,7 @@ dataValidationEvaluatorRegistry.add("dateIs", {
|
|
|
24440
24683
|
return false;
|
|
24441
24684
|
}
|
|
24442
24685
|
if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
|
|
24443
|
-
const today = jsDateToRoundNumber(
|
|
24686
|
+
const today = jsDateToRoundNumber(DateTime.now());
|
|
24444
24687
|
return isDateBetween(dateValue, today, criterionValue);
|
|
24445
24688
|
}
|
|
24446
24689
|
return areDatesSameDay(dateValue, criterionValue);
|
|
@@ -24932,7 +25175,8 @@ const SEPARATORS = [
|
|
|
24932
25175
|
];
|
|
24933
25176
|
class SplitIntoColumnsPanel extends Component {
|
|
24934
25177
|
static template = "o-spreadsheet-SplitIntoColumnsPanel";
|
|
24935
|
-
static components = { ValidationMessages };
|
|
25178
|
+
static components = { ValidationMessages, Section, Checkbox };
|
|
25179
|
+
static props = { onCloseSidePanel: Function };
|
|
24936
25180
|
state = useState({ separatorValue: "auto", addNewColumns: false, customSeparator: "" });
|
|
24937
25181
|
setup() {
|
|
24938
25182
|
onWillUpdateProps(() => {
|
|
@@ -24954,10 +25198,8 @@ class SplitIntoColumnsPanel extends Component {
|
|
|
24954
25198
|
return;
|
|
24955
25199
|
this.state.customSeparator = ev.target.value;
|
|
24956
25200
|
}
|
|
24957
|
-
updateAddNewColumnsCheckbox(
|
|
24958
|
-
|
|
24959
|
-
return;
|
|
24960
|
-
this.state.addNewColumns = ev.target.checked;
|
|
25201
|
+
updateAddNewColumnsCheckbox(addNewColumns) {
|
|
25202
|
+
this.state.addNewColumns = addNewColumns;
|
|
24961
25203
|
}
|
|
24962
25204
|
confirm() {
|
|
24963
25205
|
const result = interactiveSplitToColumns(this.env, this.separatorValue, this.state.addNewColumns);
|
|
@@ -25011,13 +25253,15 @@ class SplitIntoColumnsPanel extends Component {
|
|
|
25011
25253
|
return !this.separatorValue || this.errorMessages.length > 0;
|
|
25012
25254
|
}
|
|
25013
25255
|
}
|
|
25014
|
-
SplitIntoColumnsPanel.props = {
|
|
25015
|
-
onCloseSidePanel: Function,
|
|
25016
|
-
};
|
|
25017
25256
|
|
|
25018
25257
|
/** This component looks like a select input, but on click it opens a Menu with the items given as props instead of a dropdown */
|
|
25019
25258
|
class SelectMenu extends Component {
|
|
25020
25259
|
static template = "o-spreadsheet-SelectMenu";
|
|
25260
|
+
static props = {
|
|
25261
|
+
menuItems: Array,
|
|
25262
|
+
selectedValue: String,
|
|
25263
|
+
class: { type: String, optional: true },
|
|
25264
|
+
};
|
|
25021
25265
|
static components = { Menu };
|
|
25022
25266
|
selectRef = useRef("select");
|
|
25023
25267
|
selectRect = useAbsoluteBoundingRect(this.selectRef);
|
|
@@ -25037,13 +25281,12 @@ class SelectMenu extends Component {
|
|
|
25037
25281
|
};
|
|
25038
25282
|
}
|
|
25039
25283
|
}
|
|
25040
|
-
SelectMenu.props = {
|
|
25041
|
-
menuItems: Array,
|
|
25042
|
-
selectedValue: String,
|
|
25043
|
-
class: { type: String, optional: true },
|
|
25044
|
-
};
|
|
25045
25284
|
|
|
25046
25285
|
class DataValidationCriterionForm extends Component {
|
|
25286
|
+
static props = {
|
|
25287
|
+
criterion: Object,
|
|
25288
|
+
onCriterionChanged: Function,
|
|
25289
|
+
};
|
|
25047
25290
|
setup() {
|
|
25048
25291
|
onMounted(() => {
|
|
25049
25292
|
interactiveStopEdition(this.env);
|
|
@@ -25057,10 +25300,6 @@ class DataValidationCriterionForm extends Component {
|
|
|
25057
25300
|
this.props.onCriterionChanged(filteredCriterion);
|
|
25058
25301
|
}
|
|
25059
25302
|
}
|
|
25060
|
-
DataValidationCriterionForm.props = {
|
|
25061
|
-
criterion: Object,
|
|
25062
|
-
onCriterionChanged: Function,
|
|
25063
|
-
};
|
|
25064
25303
|
|
|
25065
25304
|
css /* scss */ `
|
|
25066
25305
|
.o-dv-input {
|
|
@@ -25075,6 +25314,15 @@ css /* scss */ `
|
|
|
25075
25314
|
`;
|
|
25076
25315
|
class DataValidationInput extends Component {
|
|
25077
25316
|
static template = "o-spreadsheet-DataValidationInput";
|
|
25317
|
+
static props = {
|
|
25318
|
+
value: { type: String, optional: true },
|
|
25319
|
+
criterionType: String,
|
|
25320
|
+
onValueChanged: Function,
|
|
25321
|
+
onKeyDown: { type: Function, optional: true },
|
|
25322
|
+
focused: { type: Boolean, optional: true },
|
|
25323
|
+
onBlur: { type: Function, optional: true },
|
|
25324
|
+
onFocus: { type: Function, optional: true },
|
|
25325
|
+
};
|
|
25078
25326
|
static defaultProps = {
|
|
25079
25327
|
value: "",
|
|
25080
25328
|
onKeyDown: () => { },
|
|
@@ -25113,15 +25361,6 @@ class DataValidationInput extends Component {
|
|
|
25113
25361
|
return this.env.model.getters.getDataValidationInvalidCriterionValueMessage(this.props.criterionType, canonicalizeContent(this.props.value, this.env.model.getters.getLocale()));
|
|
25114
25362
|
}
|
|
25115
25363
|
}
|
|
25116
|
-
DataValidationInput.props = {
|
|
25117
|
-
value: { type: String, optional: true },
|
|
25118
|
-
criterionType: String,
|
|
25119
|
-
onValueChanged: Function,
|
|
25120
|
-
onKeyDown: { type: Function, optional: true },
|
|
25121
|
-
focused: { type: Boolean, optional: true },
|
|
25122
|
-
onBlur: { type: Function, optional: true },
|
|
25123
|
-
onFocus: { type: Function, optional: true },
|
|
25124
|
-
};
|
|
25125
25364
|
|
|
25126
25365
|
const DATES_VALUES = {
|
|
25127
25366
|
today: _t("today"),
|
|
@@ -25457,7 +25696,11 @@ css /* scss */ `
|
|
|
25457
25696
|
`;
|
|
25458
25697
|
class DataValidationEditor extends Component {
|
|
25459
25698
|
static template = "o-spreadsheet-DataValidationEditor";
|
|
25460
|
-
static components = { SelectionInput, SelectMenu };
|
|
25699
|
+
static components = { SelectionInput, SelectMenu, Section };
|
|
25700
|
+
static props = {
|
|
25701
|
+
rule: { type: Object, optional: true },
|
|
25702
|
+
onExit: Function,
|
|
25703
|
+
};
|
|
25461
25704
|
state = useState({ rule: this.defaultDataValidationRule });
|
|
25462
25705
|
setup() {
|
|
25463
25706
|
if (this.props.rule) {
|
|
@@ -25533,10 +25776,6 @@ class DataValidationEditor extends Component {
|
|
|
25533
25776
|
return dataValidationPanelCriteriaRegistry.get(this.state.rule.criterion.type).component;
|
|
25534
25777
|
}
|
|
25535
25778
|
}
|
|
25536
|
-
DataValidationEditor.props = {
|
|
25537
|
-
rule: { type: Object, optional: true },
|
|
25538
|
-
onExit: Function,
|
|
25539
|
-
};
|
|
25540
25779
|
|
|
25541
25780
|
css /* scss */ `
|
|
25542
25781
|
.o-sidePanel {
|
|
@@ -25566,6 +25805,10 @@ css /* scss */ `
|
|
|
25566
25805
|
`;
|
|
25567
25806
|
class DataValidationPreview extends Component {
|
|
25568
25807
|
static template = "o-spreadsheet-DataValidationPreview";
|
|
25808
|
+
static props = {
|
|
25809
|
+
onClick: Function,
|
|
25810
|
+
rule: Object,
|
|
25811
|
+
};
|
|
25569
25812
|
deleteDataValidation() {
|
|
25570
25813
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
25571
25814
|
this.env.model.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: this.props.rule.id });
|
|
@@ -25582,13 +25825,12 @@ class DataValidationPreview extends Component {
|
|
|
25582
25825
|
.getPreview(this.props.rule.criterion, this.env.model.getters);
|
|
25583
25826
|
}
|
|
25584
25827
|
}
|
|
25585
|
-
DataValidationPreview.props = {
|
|
25586
|
-
onClick: Function,
|
|
25587
|
-
rule: Object,
|
|
25588
|
-
};
|
|
25589
25828
|
|
|
25590
25829
|
class DataValidationPanel extends Component {
|
|
25591
25830
|
static template = "o-spreadsheet-DataValidationPanel";
|
|
25831
|
+
static props = {
|
|
25832
|
+
onCloseSidePanel: Function,
|
|
25833
|
+
};
|
|
25592
25834
|
static components = { DataValidationPreview, DataValidationEditor };
|
|
25593
25835
|
state = useState({ mode: "list", activeRule: undefined });
|
|
25594
25836
|
onPreviewClick(id) {
|
|
@@ -25618,9 +25860,6 @@ class DataValidationPanel extends Component {
|
|
|
25618
25860
|
return this.env.model.getters.getDataValidationRules(sheetId);
|
|
25619
25861
|
}
|
|
25620
25862
|
}
|
|
25621
|
-
DataValidationPanel.props = {
|
|
25622
|
-
onCloseSidePanel: Function,
|
|
25623
|
-
};
|
|
25624
25863
|
|
|
25625
25864
|
const sidePanelRegistry = new Registry();
|
|
25626
25865
|
sidePanelRegistry.add("ConditionalFormatting", {
|
|
@@ -25752,6 +25991,13 @@ css /*SCSS*/ `
|
|
|
25752
25991
|
`;
|
|
25753
25992
|
class FigureComponent extends Component {
|
|
25754
25993
|
static template = "o-spreadsheet-FigureComponent";
|
|
25994
|
+
static props = {
|
|
25995
|
+
figure: Object,
|
|
25996
|
+
style: { type: String, optional: true },
|
|
25997
|
+
onFigureDeleted: { type: Function, optional: true },
|
|
25998
|
+
onMouseDown: { type: Function, optional: true },
|
|
25999
|
+
onClickAnchor: { type: Function, optional: true },
|
|
26000
|
+
};
|
|
25755
26001
|
static components = { Menu };
|
|
25756
26002
|
static defaultProps = {
|
|
25757
26003
|
onFigureDeleted: () => { },
|
|
@@ -25894,13 +26140,6 @@ class FigureComponent extends Component {
|
|
|
25894
26140
|
.menuBuilder(this.props.figure.id, this.props.onFigureDeleted, this.env);
|
|
25895
26141
|
}
|
|
25896
26142
|
}
|
|
25897
|
-
FigureComponent.props = {
|
|
25898
|
-
figure: Object,
|
|
25899
|
-
style: { type: String, optional: true },
|
|
25900
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
25901
|
-
onMouseDown: { type: Function, optional: true },
|
|
25902
|
-
onClickAnchor: { type: Function, optional: true },
|
|
25903
|
-
};
|
|
25904
26143
|
|
|
25905
26144
|
const ToggleGroupInteractiveContent = {
|
|
25906
26145
|
CannotHideAllRows: _t("Cannot hide all the rows of a sheet."),
|
|
@@ -26038,6 +26277,10 @@ css /* scss */ `
|
|
|
26038
26277
|
`;
|
|
26039
26278
|
class Autofill extends Component {
|
|
26040
26279
|
static template = "o-spreadsheet-Autofill";
|
|
26280
|
+
static props = {
|
|
26281
|
+
position: Object,
|
|
26282
|
+
isVisible: Boolean,
|
|
26283
|
+
};
|
|
26041
26284
|
state = useState({
|
|
26042
26285
|
position: { left: 0, top: 0 },
|
|
26043
26286
|
handler: false,
|
|
@@ -26106,18 +26349,14 @@ class Autofill extends Component {
|
|
|
26106
26349
|
this.env.model.dispatch("AUTOFILL_AUTO");
|
|
26107
26350
|
}
|
|
26108
26351
|
}
|
|
26109
|
-
Autofill.props = {
|
|
26110
|
-
position: Object,
|
|
26111
|
-
isVisible: Boolean,
|
|
26112
|
-
};
|
|
26113
26352
|
class TooltipComponent extends Component {
|
|
26353
|
+
static props = {
|
|
26354
|
+
content: String,
|
|
26355
|
+
};
|
|
26114
26356
|
static template = xml /* xml */ `
|
|
26115
26357
|
<div t-esc="props.content"/>
|
|
26116
26358
|
`;
|
|
26117
26359
|
}
|
|
26118
|
-
TooltipComponent.props = {
|
|
26119
|
-
content: String,
|
|
26120
|
-
};
|
|
26121
26360
|
|
|
26122
26361
|
css /* scss */ `
|
|
26123
26362
|
.o-client-tag {
|
|
@@ -26131,6 +26370,13 @@ css /* scss */ `
|
|
|
26131
26370
|
`;
|
|
26132
26371
|
class ClientTag extends Component {
|
|
26133
26372
|
static template = "o-spreadsheet-ClientTag";
|
|
26373
|
+
static props = {
|
|
26374
|
+
active: Boolean,
|
|
26375
|
+
name: String,
|
|
26376
|
+
color: String,
|
|
26377
|
+
col: Number,
|
|
26378
|
+
row: Number,
|
|
26379
|
+
};
|
|
26134
26380
|
get tagStyle() {
|
|
26135
26381
|
const { col, row, color } = this.props;
|
|
26136
26382
|
const { height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
@@ -26148,13 +26394,6 @@ class ClientTag extends Component {
|
|
|
26148
26394
|
});
|
|
26149
26395
|
}
|
|
26150
26396
|
}
|
|
26151
|
-
ClientTag.props = {
|
|
26152
|
-
active: Boolean,
|
|
26153
|
-
name: String,
|
|
26154
|
-
color: String,
|
|
26155
|
-
col: Number,
|
|
26156
|
-
row: Number,
|
|
26157
|
-
};
|
|
26158
26397
|
|
|
26159
26398
|
function getHtmlContentFromPattern(pattern, value, highlightColor, className) {
|
|
26160
26399
|
const pendingHtmlContent = [];
|
|
@@ -26194,14 +26433,14 @@ css /* scss */ `
|
|
|
26194
26433
|
`;
|
|
26195
26434
|
class TextValueProvider extends Component {
|
|
26196
26435
|
static template = "o-spreadsheet-TextValueProvider";
|
|
26436
|
+
static props = {
|
|
26437
|
+
values: Array,
|
|
26438
|
+
selectedIndex: { type: Number, optional: true },
|
|
26439
|
+
getHtmlContent: Function,
|
|
26440
|
+
onValueSelected: Function,
|
|
26441
|
+
onValueHovered: Function,
|
|
26442
|
+
};
|
|
26197
26443
|
}
|
|
26198
|
-
TextValueProvider.props = {
|
|
26199
|
-
values: Array,
|
|
26200
|
-
selectedIndex: { type: Number, optional: true },
|
|
26201
|
-
getHtmlContent: Function,
|
|
26202
|
-
onValueSelected: Function,
|
|
26203
|
-
onValueHovered: Function,
|
|
26204
|
-
};
|
|
26205
26444
|
|
|
26206
26445
|
class ContentEditableHelper {
|
|
26207
26446
|
// todo make el private and expose dedicated methods
|
|
@@ -26563,6 +26802,11 @@ css /* scss */ `
|
|
|
26563
26802
|
`;
|
|
26564
26803
|
class FunctionDescriptionProvider extends Component {
|
|
26565
26804
|
static template = "o-spreadsheet-FunctionDescriptionProvider";
|
|
26805
|
+
static props = {
|
|
26806
|
+
functionName: String,
|
|
26807
|
+
functionDescription: Object,
|
|
26808
|
+
argToFocus: Number,
|
|
26809
|
+
};
|
|
26566
26810
|
assistantState = useState({
|
|
26567
26811
|
allowCellSelectionBehind: false,
|
|
26568
26812
|
});
|
|
@@ -26587,11 +26831,6 @@ class FunctionDescriptionProvider extends Component {
|
|
|
26587
26831
|
}, 2000);
|
|
26588
26832
|
}
|
|
26589
26833
|
}
|
|
26590
|
-
FunctionDescriptionProvider.props = {
|
|
26591
|
-
functionName: String,
|
|
26592
|
-
functionDescription: Object,
|
|
26593
|
-
argToFocus: Number,
|
|
26594
|
-
};
|
|
26595
26834
|
|
|
26596
26835
|
const functions$2 = functionRegistry.content;
|
|
26597
26836
|
const ASSISTANT_WIDTH = 300;
|
|
@@ -26657,6 +26896,16 @@ css /* scss */ `
|
|
|
26657
26896
|
`;
|
|
26658
26897
|
class Composer extends Component {
|
|
26659
26898
|
static template = "o-spreadsheet-Composer";
|
|
26899
|
+
static props = {
|
|
26900
|
+
focus: {
|
|
26901
|
+
validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
|
|
26902
|
+
},
|
|
26903
|
+
onComposerContentFocused: Function,
|
|
26904
|
+
inputStyle: { type: String, optional: true },
|
|
26905
|
+
rect: { type: Object, optional: true },
|
|
26906
|
+
delimitation: { type: Object, optional: true },
|
|
26907
|
+
onComposerUnmounted: { type: Function, optional: true },
|
|
26908
|
+
};
|
|
26660
26909
|
static components = { TextValueProvider, FunctionDescriptionProvider };
|
|
26661
26910
|
static defaultProps = {
|
|
26662
26911
|
inputStyle: "",
|
|
@@ -27213,14 +27462,6 @@ class Composer extends Component {
|
|
|
27213
27462
|
this.autoCompleteState.getHtmlContent = (value) => [{ value }];
|
|
27214
27463
|
}
|
|
27215
27464
|
}
|
|
27216
|
-
Composer.props = {
|
|
27217
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27218
|
-
onComposerContentFocused: Function,
|
|
27219
|
-
inputStyle: { type: String, optional: true },
|
|
27220
|
-
rect: { type: Object, optional: true },
|
|
27221
|
-
delimitation: { type: Object, optional: true },
|
|
27222
|
-
onComposerUnmounted: { type: Function, optional: true },
|
|
27223
|
-
};
|
|
27224
27465
|
|
|
27225
27466
|
const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
|
|
27226
27467
|
const GRID_CELL_REFERENCE_TOP_OFFSET = 28;
|
|
@@ -27252,6 +27493,14 @@ css /* scss */ `
|
|
|
27252
27493
|
*/
|
|
27253
27494
|
class GridComposer extends Component {
|
|
27254
27495
|
static template = "o-spreadsheet-GridComposer";
|
|
27496
|
+
static props = {
|
|
27497
|
+
focus: {
|
|
27498
|
+
validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
|
|
27499
|
+
},
|
|
27500
|
+
onComposerUnmounted: Function,
|
|
27501
|
+
onComposerContentFocused: Function,
|
|
27502
|
+
gridDims: Object,
|
|
27503
|
+
};
|
|
27255
27504
|
static components = { Composer };
|
|
27256
27505
|
gridComposerRef;
|
|
27257
27506
|
zone;
|
|
@@ -27358,22 +27607,22 @@ class GridComposer extends Component {
|
|
|
27358
27607
|
});
|
|
27359
27608
|
}
|
|
27360
27609
|
}
|
|
27361
|
-
GridComposer.props = {
|
|
27362
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27363
|
-
onComposerUnmounted: Function,
|
|
27364
|
-
onComposerContentFocused: Function,
|
|
27365
|
-
gridDims: Object,
|
|
27366
|
-
};
|
|
27367
27610
|
|
|
27368
|
-
|
|
27611
|
+
css /* scss */ `
|
|
27369
27612
|
.o-grid-cell-icon {
|
|
27370
27613
|
width: ${GRID_ICON_EDGE_LENGTH}px;
|
|
27371
27614
|
height: ${GRID_ICON_EDGE_LENGTH}px;
|
|
27372
27615
|
}
|
|
27373
27616
|
`;
|
|
27374
27617
|
class GridCellIcon extends Component {
|
|
27375
|
-
static style = CSS$1;
|
|
27376
27618
|
static template = "o-spreadsheet-GridCellIcon";
|
|
27619
|
+
static props = {
|
|
27620
|
+
cellPosition: Object,
|
|
27621
|
+
horizontalAlign: { type: String, optional: true },
|
|
27622
|
+
verticalAlign: { type: String, optional: true },
|
|
27623
|
+
offset: { type: Object, optional: true },
|
|
27624
|
+
slots: Object,
|
|
27625
|
+
};
|
|
27377
27626
|
get iconStyle() {
|
|
27378
27627
|
const x = this.getIconHorizontalPosition();
|
|
27379
27628
|
const y = this.getIconVerticalPosition();
|
|
@@ -27422,15 +27671,8 @@ class GridCellIcon extends Component {
|
|
|
27422
27671
|
return !(rect.width === 0 || rect.height === 0);
|
|
27423
27672
|
}
|
|
27424
27673
|
}
|
|
27425
|
-
GridCellIcon.props = {
|
|
27426
|
-
cellPosition: Object,
|
|
27427
|
-
horizontalAlign: { type: String, optional: true },
|
|
27428
|
-
verticalAlign: { type: String, optional: true },
|
|
27429
|
-
offset: { type: Object, optional: true },
|
|
27430
|
-
slots: Object,
|
|
27431
|
-
};
|
|
27432
27674
|
|
|
27433
|
-
|
|
27675
|
+
css /* scss */ `
|
|
27434
27676
|
.o-filter-icon {
|
|
27435
27677
|
color: ${FILTERS_COLOR};
|
|
27436
27678
|
display: flex;
|
|
@@ -27445,8 +27687,10 @@ const CSS = css /* scss */ `
|
|
|
27445
27687
|
}
|
|
27446
27688
|
`;
|
|
27447
27689
|
class FilterIcon extends Component {
|
|
27448
|
-
static style = CSS;
|
|
27449
27690
|
static template = "o-spreadsheet-FilterIcon";
|
|
27691
|
+
static props = {
|
|
27692
|
+
cellPosition: Object,
|
|
27693
|
+
};
|
|
27450
27694
|
onClick() {
|
|
27451
27695
|
const position = this.props.cellPosition;
|
|
27452
27696
|
const activePopoverType = this.env.model.getters.getPersistentPopoverTypeAtPosition(position);
|
|
@@ -27465,12 +27709,12 @@ class FilterIcon extends Component {
|
|
|
27465
27709
|
return this.env.model.getters.isFilterActive(this.props.cellPosition);
|
|
27466
27710
|
}
|
|
27467
27711
|
}
|
|
27468
|
-
FilterIcon.props = {
|
|
27469
|
-
cellPosition: Object,
|
|
27470
|
-
};
|
|
27471
27712
|
|
|
27472
27713
|
class FilterIconsOverlay extends Component {
|
|
27473
27714
|
static template = "o-spreadsheet-FilterIconsOverlay";
|
|
27715
|
+
static props = {
|
|
27716
|
+
gridPosition: { type: Object, optional: true },
|
|
27717
|
+
};
|
|
27474
27718
|
static components = {
|
|
27475
27719
|
GridCellIcon,
|
|
27476
27720
|
FilterIcon,
|
|
@@ -27484,9 +27728,6 @@ class FilterIconsOverlay extends Component {
|
|
|
27484
27728
|
return headerPositions.map((position) => ({ sheetId, ...position }));
|
|
27485
27729
|
}
|
|
27486
27730
|
}
|
|
27487
|
-
FilterIconsOverlay.props = {
|
|
27488
|
-
gridPosition: { type: Object, optional: true },
|
|
27489
|
-
};
|
|
27490
27731
|
|
|
27491
27732
|
const CHECKBOX_WIDTH = 15;
|
|
27492
27733
|
const MARGIN = (GRID_ICON_EDGE_LENGTH - CHECKBOX_WIDTH) / 2;
|
|
@@ -27500,6 +27741,9 @@ css /* scss */ `
|
|
|
27500
27741
|
`;
|
|
27501
27742
|
class DataValidationCheckbox extends Component {
|
|
27502
27743
|
static template = "o-spreadsheet-DataValidationCheckbox";
|
|
27744
|
+
static props = {
|
|
27745
|
+
cellPosition: Object,
|
|
27746
|
+
};
|
|
27503
27747
|
onCheckboxChange(ev) {
|
|
27504
27748
|
const newValue = ev.target.checked;
|
|
27505
27749
|
const { sheetId, col, row } = this.props.cellPosition;
|
|
@@ -27514,9 +27758,6 @@ class DataValidationCheckbox extends Component {
|
|
|
27514
27758
|
return !!cell?.isFormula;
|
|
27515
27759
|
}
|
|
27516
27760
|
}
|
|
27517
|
-
DataValidationCheckbox.props = {
|
|
27518
|
-
cellPosition: Object,
|
|
27519
|
-
};
|
|
27520
27761
|
|
|
27521
27762
|
const ICON_WIDTH = 13;
|
|
27522
27763
|
css /* scss */ `
|
|
@@ -27539,18 +27780,19 @@ css /* scss */ `
|
|
|
27539
27780
|
`;
|
|
27540
27781
|
class DataValidationListIcon extends Component {
|
|
27541
27782
|
static template = "o-spreadsheet-DataValidationListIcon";
|
|
27783
|
+
static props = {
|
|
27784
|
+
cellPosition: Object,
|
|
27785
|
+
};
|
|
27542
27786
|
onClick() {
|
|
27543
27787
|
const { col, row } = this.props.cellPosition;
|
|
27544
27788
|
this.env.model.selection.selectCell(col, row);
|
|
27545
27789
|
this.env.startCellEdition();
|
|
27546
27790
|
}
|
|
27547
27791
|
}
|
|
27548
|
-
DataValidationListIcon.props = {
|
|
27549
|
-
cellPosition: Object,
|
|
27550
|
-
};
|
|
27551
27792
|
|
|
27552
27793
|
class DataValidationOverlay extends Component {
|
|
27553
27794
|
static template = "o-spreadsheet-DataValidationOverlay";
|
|
27795
|
+
static props = {};
|
|
27554
27796
|
static components = { GridCellIcon, DataValidationCheckbox, DataValidationListIcon };
|
|
27555
27797
|
get checkBoxCellPositions() {
|
|
27556
27798
|
return this.env.model.getters.getDataValidationCheckBoxCellPositions();
|
|
@@ -27561,7 +27803,6 @@ class DataValidationOverlay extends Component {
|
|
|
27561
27803
|
: this.env.model.getters.getDataValidationListCellsPositions();
|
|
27562
27804
|
}
|
|
27563
27805
|
}
|
|
27564
|
-
DataValidationOverlay.props = {};
|
|
27565
27806
|
|
|
27566
27807
|
/**
|
|
27567
27808
|
* Transform a figure with coordinates from the model, to coordinates as they are shown on the screen,
|
|
@@ -27897,6 +28138,9 @@ css /*SCSS*/ `
|
|
|
27897
28138
|
*/
|
|
27898
28139
|
class FiguresContainer extends Component {
|
|
27899
28140
|
static template = "o-spreadsheet-FiguresContainer";
|
|
28141
|
+
static props = {
|
|
28142
|
+
onFigureDeleted: Function,
|
|
28143
|
+
};
|
|
27900
28144
|
static components = { FigureComponent };
|
|
27901
28145
|
dnd = useState({
|
|
27902
28146
|
draggedFigure: undefined,
|
|
@@ -28146,9 +28390,6 @@ class FiguresContainer extends Component {
|
|
|
28146
28390
|
}
|
|
28147
28391
|
}
|
|
28148
28392
|
}
|
|
28149
|
-
FiguresContainer.props = {
|
|
28150
|
-
onFigureDeleted: Function,
|
|
28151
|
-
};
|
|
28152
28393
|
|
|
28153
28394
|
css /* scss */ `
|
|
28154
28395
|
.o-grid-add-rows {
|
|
@@ -28167,6 +28408,9 @@ css /* scss */ `
|
|
|
28167
28408
|
`;
|
|
28168
28409
|
class GridAddRowsFooter extends Component {
|
|
28169
28410
|
static template = "o-spreadsheet-GridAddRowsFooter";
|
|
28411
|
+
static props = {
|
|
28412
|
+
focusGrid: Function,
|
|
28413
|
+
};
|
|
28170
28414
|
static components = { ValidationMessages };
|
|
28171
28415
|
inputRef = useRef("inputRef");
|
|
28172
28416
|
state = useState({
|
|
@@ -28233,9 +28477,6 @@ class GridAddRowsFooter extends Component {
|
|
|
28233
28477
|
this.props.focusGrid();
|
|
28234
28478
|
}
|
|
28235
28479
|
}
|
|
28236
|
-
GridAddRowsFooter.props = {
|
|
28237
|
-
focusGrid: Function,
|
|
28238
|
-
};
|
|
28239
28480
|
|
|
28240
28481
|
/**
|
|
28241
28482
|
* Manages an event listener on a ref. Useful for hooks that want to manage
|
|
@@ -28391,6 +28632,16 @@ function useTouchMove(gridRef, handler, canMoveUp) {
|
|
|
28391
28632
|
}
|
|
28392
28633
|
class GridOverlay extends Component {
|
|
28393
28634
|
static template = "o-spreadsheet-GridOverlay";
|
|
28635
|
+
static props = {
|
|
28636
|
+
onCellHovered: { type: Function, optional: true },
|
|
28637
|
+
onCellDoubleClicked: { type: Function, optional: true },
|
|
28638
|
+
onCellClicked: { type: Function, optional: true },
|
|
28639
|
+
onCellRightClicked: { type: Function, optional: true },
|
|
28640
|
+
onGridResized: { type: Function, optional: true },
|
|
28641
|
+
onFigureDeleted: { type: Function, optional: true },
|
|
28642
|
+
onGridMoved: Function,
|
|
28643
|
+
gridOverlayDimensions: String,
|
|
28644
|
+
};
|
|
28394
28645
|
static components = { FiguresContainer, DataValidationOverlay, GridAddRowsFooter };
|
|
28395
28646
|
static defaultProps = {
|
|
28396
28647
|
onCellHovered: () => { },
|
|
@@ -28442,7 +28693,10 @@ class GridOverlay extends Component {
|
|
|
28442
28693
|
return;
|
|
28443
28694
|
}
|
|
28444
28695
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
28445
|
-
this.props.onCellClicked(col, row, {
|
|
28696
|
+
this.props.onCellClicked(col, row, {
|
|
28697
|
+
expandZone: ev.shiftKey,
|
|
28698
|
+
addZone: isCtrlKey(ev),
|
|
28699
|
+
});
|
|
28446
28700
|
}
|
|
28447
28701
|
onDoubleClick(ev) {
|
|
28448
28702
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -28461,19 +28715,15 @@ class GridOverlay extends Component {
|
|
|
28461
28715
|
return [colIndex, rowIndex];
|
|
28462
28716
|
}
|
|
28463
28717
|
}
|
|
28464
|
-
GridOverlay.props = {
|
|
28465
|
-
onCellHovered: { type: Function, optional: true },
|
|
28466
|
-
onCellDoubleClicked: { type: Function, optional: true },
|
|
28467
|
-
onCellClicked: { type: Function, optional: true },
|
|
28468
|
-
onCellRightClicked: { type: Function, optional: true },
|
|
28469
|
-
onGridResized: { type: Function, optional: true },
|
|
28470
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
28471
|
-
onGridMoved: Function,
|
|
28472
|
-
gridOverlayDimensions: String,
|
|
28473
|
-
};
|
|
28474
28718
|
|
|
28475
28719
|
class GridPopover extends Component {
|
|
28476
28720
|
static template = "o-spreadsheet-GridPopover";
|
|
28721
|
+
static props = {
|
|
28722
|
+
hoveredCell: Object,
|
|
28723
|
+
onClosePopover: Function,
|
|
28724
|
+
onMouseWheel: Function,
|
|
28725
|
+
gridRect: Object,
|
|
28726
|
+
};
|
|
28477
28727
|
static components = { Popover };
|
|
28478
28728
|
zIndex = ComponentsImportance.GridPopover;
|
|
28479
28729
|
get cellPopover() {
|
|
@@ -28493,14 +28743,11 @@ class GridPopover extends Component {
|
|
|
28493
28743
|
};
|
|
28494
28744
|
}
|
|
28495
28745
|
}
|
|
28496
|
-
GridPopover.props = {
|
|
28497
|
-
hoveredCell: Object,
|
|
28498
|
-
onClosePopover: Function,
|
|
28499
|
-
onMouseWheel: Function,
|
|
28500
|
-
gridRect: Object,
|
|
28501
|
-
};
|
|
28502
28746
|
|
|
28503
28747
|
class AbstractResizer extends Component {
|
|
28748
|
+
static props = {
|
|
28749
|
+
onOpenContextMenu: Function,
|
|
28750
|
+
};
|
|
28504
28751
|
PADDING = 0;
|
|
28505
28752
|
MAX_SIZE_MARGIN = 0;
|
|
28506
28753
|
MIN_ELEMENT_SIZE = 0;
|
|
@@ -28672,7 +28919,7 @@ class AbstractResizer extends Component {
|
|
|
28672
28919
|
this._increaseSelection(index);
|
|
28673
28920
|
}
|
|
28674
28921
|
else {
|
|
28675
|
-
this._selectElement(index, ev
|
|
28922
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
28676
28923
|
}
|
|
28677
28924
|
this.lastSelectedElementIndex = index;
|
|
28678
28925
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -28757,10 +29004,10 @@ css /* scss */ `
|
|
|
28757
29004
|
}
|
|
28758
29005
|
}
|
|
28759
29006
|
`;
|
|
28760
|
-
AbstractResizer.props = {
|
|
28761
|
-
onOpenContextMenu: Function,
|
|
28762
|
-
};
|
|
28763
29007
|
class ColResizer extends AbstractResizer {
|
|
29008
|
+
static props = {
|
|
29009
|
+
onOpenContextMenu: Function,
|
|
29010
|
+
};
|
|
28764
29011
|
static template = "o-spreadsheet-ColResizer";
|
|
28765
29012
|
colResizerRef;
|
|
28766
29013
|
setup() {
|
|
@@ -28829,8 +29076,8 @@ class ColResizer extends AbstractResizer {
|
|
|
28829
29076
|
this.env.raiseError(MergeErrorMessage);
|
|
28830
29077
|
}
|
|
28831
29078
|
}
|
|
28832
|
-
_selectElement(index,
|
|
28833
|
-
this.env.model.selection.selectColumn(index,
|
|
29079
|
+
_selectElement(index, addDistinctHeader) {
|
|
29080
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
28834
29081
|
}
|
|
28835
29082
|
_increaseSelection(index) {
|
|
28836
29083
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -28922,10 +29169,10 @@ css /* scss */ `
|
|
|
28922
29169
|
}
|
|
28923
29170
|
}
|
|
28924
29171
|
`;
|
|
28925
|
-
ColResizer.props = {
|
|
28926
|
-
onOpenContextMenu: Function,
|
|
28927
|
-
};
|
|
28928
29172
|
class RowResizer extends AbstractResizer {
|
|
29173
|
+
static props = {
|
|
29174
|
+
onOpenContextMenu: Function,
|
|
29175
|
+
};
|
|
28929
29176
|
static template = "o-spreadsheet-RowResizer";
|
|
28930
29177
|
setup() {
|
|
28931
29178
|
super.setup();
|
|
@@ -28994,8 +29241,8 @@ class RowResizer extends AbstractResizer {
|
|
|
28994
29241
|
this.env.raiseError(MergeErrorMessage);
|
|
28995
29242
|
}
|
|
28996
29243
|
}
|
|
28997
|
-
_selectElement(index,
|
|
28998
|
-
this.env.model.selection.selectRow(index,
|
|
29244
|
+
_selectElement(index, addDistinctHeader) {
|
|
29245
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
28999
29246
|
}
|
|
29000
29247
|
_increaseSelection(index) {
|
|
29001
29248
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -29046,19 +29293,16 @@ css /* scss */ `
|
|
|
29046
29293
|
}
|
|
29047
29294
|
}
|
|
29048
29295
|
`;
|
|
29049
|
-
RowResizer.props = {
|
|
29050
|
-
onOpenContextMenu: Function,
|
|
29051
|
-
};
|
|
29052
29296
|
class HeadersOverlay extends Component {
|
|
29297
|
+
static props = {
|
|
29298
|
+
onOpenContextMenu: Function,
|
|
29299
|
+
};
|
|
29053
29300
|
static template = "o-spreadsheet-HeadersOverlay";
|
|
29054
29301
|
static components = { ColResizer, RowResizer };
|
|
29055
29302
|
selectAll() {
|
|
29056
29303
|
this.env.model.selection.selectAll();
|
|
29057
29304
|
}
|
|
29058
29305
|
}
|
|
29059
|
-
HeadersOverlay.props = {
|
|
29060
|
-
onOpenContextMenu: Function,
|
|
29061
|
-
};
|
|
29062
29306
|
|
|
29063
29307
|
function useGridDrawing(refName, model, canvasSize) {
|
|
29064
29308
|
const canvasRef = useRef(refName);
|
|
@@ -29116,6 +29360,12 @@ css /* scss */ `
|
|
|
29116
29360
|
`;
|
|
29117
29361
|
class Border extends Component {
|
|
29118
29362
|
static template = "o-spreadsheet-Border";
|
|
29363
|
+
static props = {
|
|
29364
|
+
zone: Object,
|
|
29365
|
+
orientation: String,
|
|
29366
|
+
isMoving: Boolean,
|
|
29367
|
+
onMoveHighlight: Function,
|
|
29368
|
+
};
|
|
29119
29369
|
get style() {
|
|
29120
29370
|
const isTop = ["n", "w", "e"].includes(this.props.orientation);
|
|
29121
29371
|
const isLeft = ["n", "w", "s"].includes(this.props.orientation);
|
|
@@ -29144,12 +29394,6 @@ class Border extends Component {
|
|
|
29144
29394
|
this.props.onMoveHighlight(ev.clientX, ev.clientY);
|
|
29145
29395
|
}
|
|
29146
29396
|
}
|
|
29147
|
-
Border.props = {
|
|
29148
|
-
zone: Object,
|
|
29149
|
-
orientation: String,
|
|
29150
|
-
isMoving: Boolean,
|
|
29151
|
-
onMoveHighlight: Function,
|
|
29152
|
-
};
|
|
29153
29397
|
|
|
29154
29398
|
css /* scss */ `
|
|
29155
29399
|
.o-corner {
|
|
@@ -29176,6 +29420,13 @@ css /* scss */ `
|
|
|
29176
29420
|
`;
|
|
29177
29421
|
class Corner extends Component {
|
|
29178
29422
|
static template = "o-spreadsheet-Corner";
|
|
29423
|
+
static props = {
|
|
29424
|
+
zone: Object,
|
|
29425
|
+
color: String,
|
|
29426
|
+
orientation: String,
|
|
29427
|
+
isResizing: Boolean,
|
|
29428
|
+
onResizeHighlight: Function,
|
|
29429
|
+
};
|
|
29179
29430
|
isTop = this.props.orientation[0] === "n";
|
|
29180
29431
|
isLeft = this.props.orientation[1] === "w";
|
|
29181
29432
|
get style() {
|
|
@@ -29204,13 +29455,6 @@ class Corner extends Component {
|
|
|
29204
29455
|
this.props.onResizeHighlight(this.isLeft, this.isTop);
|
|
29205
29456
|
}
|
|
29206
29457
|
}
|
|
29207
|
-
Corner.props = {
|
|
29208
|
-
zone: Object,
|
|
29209
|
-
color: String,
|
|
29210
|
-
orientation: String,
|
|
29211
|
-
isResizing: Boolean,
|
|
29212
|
-
onResizeHighlight: Function,
|
|
29213
|
-
};
|
|
29214
29458
|
|
|
29215
29459
|
css /*SCSS*/ `
|
|
29216
29460
|
.o-highlight {
|
|
@@ -29219,6 +29463,10 @@ css /*SCSS*/ `
|
|
|
29219
29463
|
`;
|
|
29220
29464
|
class Highlight extends Component {
|
|
29221
29465
|
static template = "o-spreadsheet-Highlight";
|
|
29466
|
+
static props = {
|
|
29467
|
+
zone: Object,
|
|
29468
|
+
color: String,
|
|
29469
|
+
};
|
|
29222
29470
|
static components = {
|
|
29223
29471
|
Corner,
|
|
29224
29472
|
Border,
|
|
@@ -29302,10 +29550,6 @@ class Highlight extends Component {
|
|
|
29302
29550
|
dragAndDropBeyondTheViewport(this.env, mouseMove, mouseUp);
|
|
29303
29551
|
}
|
|
29304
29552
|
}
|
|
29305
|
-
Highlight.props = {
|
|
29306
|
-
zone: Object,
|
|
29307
|
-
color: String,
|
|
29308
|
-
};
|
|
29309
29553
|
|
|
29310
29554
|
let ScrollBar$1 = class ScrollBar {
|
|
29311
29555
|
direction;
|
|
@@ -29345,6 +29589,14 @@ css /* scss */ `
|
|
|
29345
29589
|
}
|
|
29346
29590
|
`;
|
|
29347
29591
|
class ScrollBar extends Component {
|
|
29592
|
+
static props = {
|
|
29593
|
+
width: { type: Number, optional: true },
|
|
29594
|
+
height: { type: Number, optional: true },
|
|
29595
|
+
direction: String,
|
|
29596
|
+
position: Object,
|
|
29597
|
+
offset: Number,
|
|
29598
|
+
onScroll: Function,
|
|
29599
|
+
};
|
|
29348
29600
|
static template = xml /*xml*/ `
|
|
29349
29601
|
<div
|
|
29350
29602
|
t-attf-class="o-scrollbar {{props.direction}}"
|
|
@@ -29388,16 +29640,11 @@ class ScrollBar extends Component {
|
|
|
29388
29640
|
}
|
|
29389
29641
|
}
|
|
29390
29642
|
}
|
|
29391
|
-
ScrollBar.props = {
|
|
29392
|
-
width: { type: Number, optional: true },
|
|
29393
|
-
height: { type: Number, optional: true },
|
|
29394
|
-
direction: String,
|
|
29395
|
-
position: Object,
|
|
29396
|
-
offset: Number,
|
|
29397
|
-
onScroll: Function,
|
|
29398
|
-
};
|
|
29399
29643
|
|
|
29400
29644
|
class HorizontalScrollBar extends Component {
|
|
29645
|
+
static props = {
|
|
29646
|
+
leftOffset: { type: Number, optional: true },
|
|
29647
|
+
};
|
|
29401
29648
|
static components = { ScrollBar };
|
|
29402
29649
|
static template = xml /*xml*/ `
|
|
29403
29650
|
<ScrollBar
|
|
@@ -29438,11 +29685,11 @@ class HorizontalScrollBar extends Component {
|
|
|
29438
29685
|
});
|
|
29439
29686
|
}
|
|
29440
29687
|
}
|
|
29441
|
-
HorizontalScrollBar.props = {
|
|
29442
|
-
leftOffset: { type: Number, optional: true },
|
|
29443
|
-
};
|
|
29444
29688
|
|
|
29445
29689
|
class VerticalScrollBar extends Component {
|
|
29690
|
+
static props = {
|
|
29691
|
+
topOffset: { type: Number, optional: true },
|
|
29692
|
+
};
|
|
29446
29693
|
static components = { ScrollBar };
|
|
29447
29694
|
static template = xml /*xml*/ `
|
|
29448
29695
|
<ScrollBar
|
|
@@ -29483,9 +29730,6 @@ class VerticalScrollBar extends Component {
|
|
|
29483
29730
|
});
|
|
29484
29731
|
}
|
|
29485
29732
|
}
|
|
29486
|
-
VerticalScrollBar.props = {
|
|
29487
|
-
topOffset: { type: Number, optional: true },
|
|
29488
|
-
};
|
|
29489
29733
|
|
|
29490
29734
|
const registries$1 = {
|
|
29491
29735
|
ROW: rowMenuRegistry,
|
|
@@ -29499,6 +29743,13 @@ const registries$1 = {
|
|
|
29499
29743
|
// -----------------------------------------------------------------------------
|
|
29500
29744
|
class Grid extends Component {
|
|
29501
29745
|
static template = "o-spreadsheet-Grid";
|
|
29746
|
+
static props = {
|
|
29747
|
+
sidePanelIsOpen: Boolean,
|
|
29748
|
+
exposeFocus: Function,
|
|
29749
|
+
focusComposer: String,
|
|
29750
|
+
onComposerContentFocused: Function,
|
|
29751
|
+
onGridComposerCellFocused: Function,
|
|
29752
|
+
};
|
|
29502
29753
|
static components = {
|
|
29503
29754
|
GridComposer,
|
|
29504
29755
|
GridOverlay,
|
|
@@ -29688,7 +29939,7 @@ class Grid extends Component {
|
|
|
29688
29939
|
"Ctrl+Shift+E": () => this.setHorizontalAlign("center"),
|
|
29689
29940
|
"Ctrl+Shift+L": () => this.setHorizontalAlign("left"),
|
|
29690
29941
|
"Ctrl+Shift+R": () => this.setHorizontalAlign("right"),
|
|
29691
|
-
"Ctrl+Shift+V": () =>
|
|
29942
|
+
"Ctrl+Shift+V": () => PASTE_AS_VALUE_ACTION(this.env),
|
|
29692
29943
|
"Ctrl+Shift+<": () => this.clearFormatting(),
|
|
29693
29944
|
"Ctrl+<": () => this.clearFormatting(),
|
|
29694
29945
|
"Ctrl+Shift+ ": () => {
|
|
@@ -29796,17 +30047,17 @@ class Grid extends Component {
|
|
|
29796
30047
|
// ---------------------------------------------------------------------------
|
|
29797
30048
|
// Zone selection with mouse
|
|
29798
30049
|
// ---------------------------------------------------------------------------
|
|
29799
|
-
onCellClicked(col, row, {
|
|
30050
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
29800
30051
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
29801
30052
|
this.closeOpenedPopover();
|
|
29802
30053
|
}
|
|
29803
30054
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
29804
30055
|
interactiveStopEdition(this.env);
|
|
29805
30056
|
}
|
|
29806
|
-
if (
|
|
30057
|
+
if (expandZone) {
|
|
29807
30058
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
29808
30059
|
}
|
|
29809
|
-
else if (
|
|
30060
|
+
else if (addZone) {
|
|
29810
30061
|
this.env.model.selection.addCellToSelection(col, row);
|
|
29811
30062
|
}
|
|
29812
30063
|
else {
|
|
@@ -30103,13 +30354,6 @@ class Grid extends Component {
|
|
|
30103
30354
|
}
|
|
30104
30355
|
}
|
|
30105
30356
|
}
|
|
30106
|
-
Grid.props = {
|
|
30107
|
-
sidePanelIsOpen: Boolean,
|
|
30108
|
-
exposeFocus: Function,
|
|
30109
|
-
focusComposer: String,
|
|
30110
|
-
onComposerContentFocused: Function,
|
|
30111
|
-
onGridComposerCellFocused: Function,
|
|
30112
|
-
};
|
|
30113
30357
|
|
|
30114
30358
|
/**
|
|
30115
30359
|
* Represent a raw XML string
|
|
@@ -30609,7 +30853,7 @@ const XLSX_FORMATS_CONVERSION_MAP = {
|
|
|
30609
30853
|
46: "hhhh:mm:ss",
|
|
30610
30854
|
47: "hhhh:mm:ss",
|
|
30611
30855
|
48: undefined,
|
|
30612
|
-
49:
|
|
30856
|
+
49: PLAIN_TEXT_FORMAT,
|
|
30613
30857
|
};
|
|
30614
30858
|
/**
|
|
30615
30859
|
* Mapping format index to format defined by default
|
|
@@ -31530,20 +31774,26 @@ function convertFigures(sheetData) {
|
|
|
31530
31774
|
.filter(isDefined$1);
|
|
31531
31775
|
}
|
|
31532
31776
|
function convertFigure(figure, id, sheetData) {
|
|
31533
|
-
|
|
31534
|
-
|
|
31535
|
-
|
|
31536
|
-
|
|
31537
|
-
|
|
31538
|
-
convertEMUToDotValue(figure.
|
|
31539
|
-
|
|
31540
|
-
|
|
31777
|
+
let x1, y1;
|
|
31778
|
+
let height, width;
|
|
31779
|
+
if (figure.anchors.length === 1) {
|
|
31780
|
+
// one cell anchor
|
|
31781
|
+
({ x: x1, y: y1 } = getPositionFromAnchor(figure.anchors[0], sheetData));
|
|
31782
|
+
width = convertEMUToDotValue(figure.figureSize.cx);
|
|
31783
|
+
height = convertEMUToDotValue(figure.figureSize.cy);
|
|
31784
|
+
}
|
|
31785
|
+
else {
|
|
31786
|
+
({ x: x1, y: y1 } = getPositionFromAnchor(figure.anchors[0], sheetData));
|
|
31787
|
+
const { x: x2, y: y2 } = getPositionFromAnchor(figure.anchors[1], sheetData);
|
|
31788
|
+
width = x2 - x1;
|
|
31789
|
+
height = y2 - y1;
|
|
31790
|
+
}
|
|
31541
31791
|
const figureData = { id, x: x1, y: y1 };
|
|
31542
31792
|
if (isChartData(figure.data)) {
|
|
31543
31793
|
return {
|
|
31544
31794
|
...figureData,
|
|
31545
|
-
width
|
|
31546
|
-
height
|
|
31795
|
+
width,
|
|
31796
|
+
height,
|
|
31547
31797
|
tag: "chart",
|
|
31548
31798
|
data: convertChartData(figure.data),
|
|
31549
31799
|
};
|
|
@@ -31609,6 +31859,12 @@ function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
|
31609
31859
|
const dataXC = zoneToXc(zone);
|
|
31610
31860
|
return getFullReference(sheetName, dataXC);
|
|
31611
31861
|
}
|
|
31862
|
+
function getPositionFromAnchor(anchor, sheetData) {
|
|
31863
|
+
return {
|
|
31864
|
+
x: getColPosition(anchor.col, sheetData) + convertEMUToDotValue(anchor.colOffset),
|
|
31865
|
+
y: getRowPosition(anchor.row, sheetData) + convertEMUToDotValue(anchor.rowOffset),
|
|
31866
|
+
};
|
|
31867
|
+
}
|
|
31612
31868
|
|
|
31613
31869
|
/**
|
|
31614
31870
|
* Match external reference (ex. '[1]Sheet 3'!$B$4)
|
|
@@ -32732,27 +32988,50 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
|
|
|
32732
32988
|
}
|
|
32733
32989
|
}
|
|
32734
32990
|
|
|
32991
|
+
const ONE_CELL_ANCHOR = "oneCellAnchor";
|
|
32992
|
+
const TWO_CELL_ANCHOR = "twoCellAnchor";
|
|
32735
32993
|
class XlsxFigureExtractor extends XlsxBaseExtractor {
|
|
32736
32994
|
extractFigures() {
|
|
32737
32995
|
return this.mapOnElements({ parent: this.rootFile.file.xml, query: "xdr:wsDr", children: true }, (figureElement) => {
|
|
32738
32996
|
const anchorType = removeTagEscapedNamespaces(figureElement.tagName);
|
|
32739
|
-
|
|
32740
|
-
throw new Error("Only twoCellAnchor are supported for xlsx drawings.");
|
|
32741
|
-
}
|
|
32997
|
+
const anchors = this.extractFigureAnchorsByType(figureElement, anchorType);
|
|
32742
32998
|
const chartElement = this.querySelector(figureElement, "c:chart");
|
|
32743
32999
|
const imageElement = this.querySelector(figureElement, "a:blip");
|
|
32744
33000
|
if (!chartElement && !imageElement) {
|
|
32745
33001
|
throw new Error("Only chart and image figures are currently supported.");
|
|
32746
33002
|
}
|
|
32747
33003
|
return {
|
|
32748
|
-
anchors
|
|
32749
|
-
this.extractFigureAnchor("xdr:from", figureElement),
|
|
32750
|
-
this.extractFigureAnchor("xdr:to", figureElement),
|
|
32751
|
-
],
|
|
33004
|
+
anchors,
|
|
32752
33005
|
data: chartElement ? this.extractChart(chartElement) : this.extractImage(figureElement),
|
|
33006
|
+
figureSize: anchorType === ONE_CELL_ANCHOR
|
|
33007
|
+
? this.extractFigureSizeFromSizeTag(figureElement, "xdr:ext")
|
|
33008
|
+
: undefined,
|
|
32753
33009
|
};
|
|
32754
33010
|
});
|
|
32755
33011
|
}
|
|
33012
|
+
extractFigureAnchorsByType(figureElement, anchorType) {
|
|
33013
|
+
switch (anchorType) {
|
|
33014
|
+
case ONE_CELL_ANCHOR:
|
|
33015
|
+
return [this.extractFigureAnchor("xdr:from", figureElement)];
|
|
33016
|
+
case TWO_CELL_ANCHOR:
|
|
33017
|
+
return [
|
|
33018
|
+
this.extractFigureAnchor("xdr:from", figureElement),
|
|
33019
|
+
this.extractFigureAnchor("xdr:to", figureElement),
|
|
33020
|
+
];
|
|
33021
|
+
default:
|
|
33022
|
+
throw new Error(`${anchorType} is not supported for xlsx drawings. `);
|
|
33023
|
+
}
|
|
33024
|
+
}
|
|
33025
|
+
extractFigureSizeFromSizeTag(figureElement, sizeTag) {
|
|
33026
|
+
const sizeElement = this.querySelector(figureElement, sizeTag);
|
|
33027
|
+
if (!sizeElement) {
|
|
33028
|
+
throw new Error(`Missing size element '${sizeTag}'`);
|
|
33029
|
+
}
|
|
33030
|
+
return {
|
|
33031
|
+
cx: this.extractAttr(sizeElement, "cx", { required: true }).asNum(),
|
|
33032
|
+
cy: this.extractAttr(sizeElement, "cy", { required: true }).asNum(),
|
|
33033
|
+
};
|
|
33034
|
+
}
|
|
32756
33035
|
extractFigureAnchor(anchorTag, figureElement) {
|
|
32757
33036
|
const anchor = this.querySelector(figureElement, anchorTag);
|
|
32758
33037
|
if (!anchor) {
|
|
@@ -32781,15 +33060,15 @@ class XlsxFigureExtractor extends XlsxBaseExtractor {
|
|
|
32781
33060
|
if (!image) {
|
|
32782
33061
|
throw new Error("Unable to extract image");
|
|
32783
33062
|
}
|
|
32784
|
-
const shapePropertyElement = this.querySelector(figureElement, "a:xfrm");
|
|
32785
33063
|
const extension = image.fileName.split(".").at(-1);
|
|
33064
|
+
const anchorType = removeTagEscapedNamespaces(figureElement.tagName);
|
|
33065
|
+
const sizeElement = anchorType === TWO_CELL_ANCHOR ? this.querySelector(figureElement, "a:xfrm") : figureElement;
|
|
33066
|
+
const sizeTag = anchorType === TWO_CELL_ANCHOR ? "a:ext" : "xdr:ext";
|
|
33067
|
+
const size = this.extractFigureSizeFromSizeTag(sizeElement, sizeTag);
|
|
32786
33068
|
return {
|
|
32787
33069
|
imageSrc: image.imageSrc,
|
|
32788
33070
|
mimetype: extension ? IMAGE_EXTENSION_TO_MIMETYPE_MAPPING[extension] : undefined,
|
|
32789
|
-
size
|
|
32790
|
-
cx: this.extractChildAttr(shapePropertyElement, "a:ext", "cx", { required: true }).asNum(),
|
|
32791
|
-
cy: this.extractChildAttr(shapePropertyElement, "a:ext", "cy", { required: true }).asNum(),
|
|
32792
|
-
},
|
|
33071
|
+
size,
|
|
32793
33072
|
};
|
|
32794
33073
|
}
|
|
32795
33074
|
}
|
|
@@ -34742,7 +35021,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
34742
35021
|
*/
|
|
34743
35022
|
function getBorderId(border) {
|
|
34744
35023
|
for (let [key, value] of Object.entries(borders)) {
|
|
34745
|
-
if (
|
|
35024
|
+
if (deepEquals(value, border)) {
|
|
34746
35025
|
return parseInt(key, 10);
|
|
34747
35026
|
}
|
|
34748
35027
|
}
|
|
@@ -35913,7 +36192,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35913
36192
|
}
|
|
35914
36193
|
createLiteralCell(id, content, format, style) {
|
|
35915
36194
|
const locale = this.getters.getLocale();
|
|
35916
|
-
|
|
36195
|
+
if (format !== PLAIN_TEXT_FORMAT) {
|
|
36196
|
+
content = toString(parseLiteral(content, locale));
|
|
36197
|
+
}
|
|
35917
36198
|
return {
|
|
35918
36199
|
id,
|
|
35919
36200
|
content,
|
|
@@ -40060,56 +40341,758 @@ class CompilationParametersBuilder {
|
|
|
40060
40341
|
}
|
|
40061
40342
|
}
|
|
40062
40343
|
|
|
40344
|
+
function quickselect(arr, k, left, right, compare) {
|
|
40345
|
+
quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
|
|
40346
|
+
}
|
|
40347
|
+
|
|
40348
|
+
function quickselectStep(arr, k, left, right, compare) {
|
|
40349
|
+
|
|
40350
|
+
while (right > left) {
|
|
40351
|
+
if (right - left > 600) {
|
|
40352
|
+
var n = right - left + 1;
|
|
40353
|
+
var m = k - left + 1;
|
|
40354
|
+
var z = Math.log(n);
|
|
40355
|
+
var s = 0.5 * Math.exp(2 * z / 3);
|
|
40356
|
+
var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
|
|
40357
|
+
var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
|
|
40358
|
+
var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
|
|
40359
|
+
quickselectStep(arr, k, newLeft, newRight, compare);
|
|
40360
|
+
}
|
|
40361
|
+
|
|
40362
|
+
var t = arr[k];
|
|
40363
|
+
var i = left;
|
|
40364
|
+
var j = right;
|
|
40365
|
+
|
|
40366
|
+
swap(arr, left, k);
|
|
40367
|
+
if (compare(arr[right], t) > 0) swap(arr, left, right);
|
|
40368
|
+
|
|
40369
|
+
while (i < j) {
|
|
40370
|
+
swap(arr, i, j);
|
|
40371
|
+
i++;
|
|
40372
|
+
j--;
|
|
40373
|
+
while (compare(arr[i], t) < 0) i++;
|
|
40374
|
+
while (compare(arr[j], t) > 0) j--;
|
|
40375
|
+
}
|
|
40376
|
+
|
|
40377
|
+
if (compare(arr[left], t) === 0) swap(arr, left, j);
|
|
40378
|
+
else {
|
|
40379
|
+
j++;
|
|
40380
|
+
swap(arr, j, right);
|
|
40381
|
+
}
|
|
40382
|
+
|
|
40383
|
+
if (j <= k) left = j + 1;
|
|
40384
|
+
if (k <= j) right = j - 1;
|
|
40385
|
+
}
|
|
40386
|
+
}
|
|
40387
|
+
|
|
40388
|
+
function swap(arr, i, j) {
|
|
40389
|
+
var tmp = arr[i];
|
|
40390
|
+
arr[i] = arr[j];
|
|
40391
|
+
arr[j] = tmp;
|
|
40392
|
+
}
|
|
40393
|
+
|
|
40394
|
+
function defaultCompare(a, b) {
|
|
40395
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
40396
|
+
}
|
|
40397
|
+
|
|
40398
|
+
class RBush {
|
|
40399
|
+
constructor(maxEntries = 9) {
|
|
40400
|
+
// max entries in a node is 9 by default; min node fill is 40% for best performance
|
|
40401
|
+
this._maxEntries = Math.max(4, maxEntries);
|
|
40402
|
+
this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
|
|
40403
|
+
this.clear();
|
|
40404
|
+
}
|
|
40405
|
+
|
|
40406
|
+
all() {
|
|
40407
|
+
return this._all(this.data, []);
|
|
40408
|
+
}
|
|
40409
|
+
|
|
40410
|
+
search(bbox) {
|
|
40411
|
+
let node = this.data;
|
|
40412
|
+
const result = [];
|
|
40413
|
+
|
|
40414
|
+
if (!intersects(bbox, node)) return result;
|
|
40415
|
+
|
|
40416
|
+
const toBBox = this.toBBox;
|
|
40417
|
+
const nodesToSearch = [];
|
|
40418
|
+
|
|
40419
|
+
while (node) {
|
|
40420
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
40421
|
+
const child = node.children[i];
|
|
40422
|
+
const childBBox = node.leaf ? toBBox(child) : child;
|
|
40423
|
+
|
|
40424
|
+
if (intersects(bbox, childBBox)) {
|
|
40425
|
+
if (node.leaf) result.push(child);
|
|
40426
|
+
else if (contains(bbox, childBBox)) this._all(child, result);
|
|
40427
|
+
else nodesToSearch.push(child);
|
|
40428
|
+
}
|
|
40429
|
+
}
|
|
40430
|
+
node = nodesToSearch.pop();
|
|
40431
|
+
}
|
|
40432
|
+
|
|
40433
|
+
return result;
|
|
40434
|
+
}
|
|
40435
|
+
|
|
40436
|
+
collides(bbox) {
|
|
40437
|
+
let node = this.data;
|
|
40438
|
+
|
|
40439
|
+
if (!intersects(bbox, node)) return false;
|
|
40440
|
+
|
|
40441
|
+
const nodesToSearch = [];
|
|
40442
|
+
while (node) {
|
|
40443
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
40444
|
+
const child = node.children[i];
|
|
40445
|
+
const childBBox = node.leaf ? this.toBBox(child) : child;
|
|
40446
|
+
|
|
40447
|
+
if (intersects(bbox, childBBox)) {
|
|
40448
|
+
if (node.leaf || contains(bbox, childBBox)) return true;
|
|
40449
|
+
nodesToSearch.push(child);
|
|
40450
|
+
}
|
|
40451
|
+
}
|
|
40452
|
+
node = nodesToSearch.pop();
|
|
40453
|
+
}
|
|
40454
|
+
|
|
40455
|
+
return false;
|
|
40456
|
+
}
|
|
40457
|
+
|
|
40458
|
+
load(data) {
|
|
40459
|
+
if (!(data && data.length)) return this;
|
|
40460
|
+
|
|
40461
|
+
if (data.length < this._minEntries) {
|
|
40462
|
+
for (let i = 0; i < data.length; i++) {
|
|
40463
|
+
this.insert(data[i]);
|
|
40464
|
+
}
|
|
40465
|
+
return this;
|
|
40466
|
+
}
|
|
40467
|
+
|
|
40468
|
+
// recursively build the tree with the given data from scratch using OMT algorithm
|
|
40469
|
+
let node = this._build(data.slice(), 0, data.length - 1, 0);
|
|
40470
|
+
|
|
40471
|
+
if (!this.data.children.length) {
|
|
40472
|
+
// save as is if tree is empty
|
|
40473
|
+
this.data = node;
|
|
40474
|
+
|
|
40475
|
+
} else if (this.data.height === node.height) {
|
|
40476
|
+
// split root if trees have the same height
|
|
40477
|
+
this._splitRoot(this.data, node);
|
|
40478
|
+
|
|
40479
|
+
} else {
|
|
40480
|
+
if (this.data.height < node.height) {
|
|
40481
|
+
// swap trees if inserted one is bigger
|
|
40482
|
+
const tmpNode = this.data;
|
|
40483
|
+
this.data = node;
|
|
40484
|
+
node = tmpNode;
|
|
40485
|
+
}
|
|
40486
|
+
|
|
40487
|
+
// insert the small tree into the large tree at appropriate level
|
|
40488
|
+
this._insert(node, this.data.height - node.height - 1, true);
|
|
40489
|
+
}
|
|
40490
|
+
|
|
40491
|
+
return this;
|
|
40492
|
+
}
|
|
40493
|
+
|
|
40494
|
+
insert(item) {
|
|
40495
|
+
if (item) this._insert(item, this.data.height - 1);
|
|
40496
|
+
return this;
|
|
40497
|
+
}
|
|
40498
|
+
|
|
40499
|
+
clear() {
|
|
40500
|
+
this.data = createNode([]);
|
|
40501
|
+
return this;
|
|
40502
|
+
}
|
|
40503
|
+
|
|
40504
|
+
remove(item, equalsFn) {
|
|
40505
|
+
if (!item) return this;
|
|
40506
|
+
|
|
40507
|
+
let node = this.data;
|
|
40508
|
+
const bbox = this.toBBox(item);
|
|
40509
|
+
const path = [];
|
|
40510
|
+
const indexes = [];
|
|
40511
|
+
let i, parent, goingUp;
|
|
40512
|
+
|
|
40513
|
+
// depth-first iterative tree traversal
|
|
40514
|
+
while (node || path.length) {
|
|
40515
|
+
|
|
40516
|
+
if (!node) { // go up
|
|
40517
|
+
node = path.pop();
|
|
40518
|
+
parent = path[path.length - 1];
|
|
40519
|
+
i = indexes.pop();
|
|
40520
|
+
goingUp = true;
|
|
40521
|
+
}
|
|
40522
|
+
|
|
40523
|
+
if (node.leaf) { // check current node
|
|
40524
|
+
const index = findItem(item, node.children, equalsFn);
|
|
40525
|
+
|
|
40526
|
+
if (index !== -1) {
|
|
40527
|
+
// item found, remove the item and condense tree upwards
|
|
40528
|
+
node.children.splice(index, 1);
|
|
40529
|
+
path.push(node);
|
|
40530
|
+
this._condense(path);
|
|
40531
|
+
return this;
|
|
40532
|
+
}
|
|
40533
|
+
}
|
|
40534
|
+
|
|
40535
|
+
if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
|
|
40536
|
+
path.push(node);
|
|
40537
|
+
indexes.push(i);
|
|
40538
|
+
i = 0;
|
|
40539
|
+
parent = node;
|
|
40540
|
+
node = node.children[0];
|
|
40541
|
+
|
|
40542
|
+
} else if (parent) { // go right
|
|
40543
|
+
i++;
|
|
40544
|
+
node = parent.children[i];
|
|
40545
|
+
goingUp = false;
|
|
40546
|
+
|
|
40547
|
+
} else node = null; // nothing found
|
|
40548
|
+
}
|
|
40549
|
+
|
|
40550
|
+
return this;
|
|
40551
|
+
}
|
|
40552
|
+
|
|
40553
|
+
toBBox(item) { return item; }
|
|
40554
|
+
|
|
40555
|
+
compareMinX(a, b) { return a.minX - b.minX; }
|
|
40556
|
+
compareMinY(a, b) { return a.minY - b.minY; }
|
|
40557
|
+
|
|
40558
|
+
toJSON() { return this.data; }
|
|
40559
|
+
|
|
40560
|
+
fromJSON(data) {
|
|
40561
|
+
this.data = data;
|
|
40562
|
+
return this;
|
|
40563
|
+
}
|
|
40564
|
+
|
|
40565
|
+
_all(node, result) {
|
|
40566
|
+
const nodesToSearch = [];
|
|
40567
|
+
while (node) {
|
|
40568
|
+
if (node.leaf) result.push(...node.children);
|
|
40569
|
+
else nodesToSearch.push(...node.children);
|
|
40570
|
+
|
|
40571
|
+
node = nodesToSearch.pop();
|
|
40572
|
+
}
|
|
40573
|
+
return result;
|
|
40574
|
+
}
|
|
40575
|
+
|
|
40576
|
+
_build(items, left, right, height) {
|
|
40577
|
+
|
|
40578
|
+
const N = right - left + 1;
|
|
40579
|
+
let M = this._maxEntries;
|
|
40580
|
+
let node;
|
|
40581
|
+
|
|
40582
|
+
if (N <= M) {
|
|
40583
|
+
// reached leaf level; return leaf
|
|
40584
|
+
node = createNode(items.slice(left, right + 1));
|
|
40585
|
+
calcBBox(node, this.toBBox);
|
|
40586
|
+
return node;
|
|
40587
|
+
}
|
|
40588
|
+
|
|
40589
|
+
if (!height) {
|
|
40590
|
+
// target height of the bulk-loaded tree
|
|
40591
|
+
height = Math.ceil(Math.log(N) / Math.log(M));
|
|
40592
|
+
|
|
40593
|
+
// target number of root entries to maximize storage utilization
|
|
40594
|
+
M = Math.ceil(N / Math.pow(M, height - 1));
|
|
40595
|
+
}
|
|
40596
|
+
|
|
40597
|
+
node = createNode([]);
|
|
40598
|
+
node.leaf = false;
|
|
40599
|
+
node.height = height;
|
|
40600
|
+
|
|
40601
|
+
// split the items into M mostly square tiles
|
|
40602
|
+
|
|
40603
|
+
const N2 = Math.ceil(N / M);
|
|
40604
|
+
const N1 = N2 * Math.ceil(Math.sqrt(M));
|
|
40605
|
+
|
|
40606
|
+
multiSelect(items, left, right, N1, this.compareMinX);
|
|
40607
|
+
|
|
40608
|
+
for (let i = left; i <= right; i += N1) {
|
|
40609
|
+
|
|
40610
|
+
const right2 = Math.min(i + N1 - 1, right);
|
|
40611
|
+
|
|
40612
|
+
multiSelect(items, i, right2, N2, this.compareMinY);
|
|
40613
|
+
|
|
40614
|
+
for (let j = i; j <= right2; j += N2) {
|
|
40615
|
+
|
|
40616
|
+
const right3 = Math.min(j + N2 - 1, right2);
|
|
40617
|
+
|
|
40618
|
+
// pack each entry recursively
|
|
40619
|
+
node.children.push(this._build(items, j, right3, height - 1));
|
|
40620
|
+
}
|
|
40621
|
+
}
|
|
40622
|
+
|
|
40623
|
+
calcBBox(node, this.toBBox);
|
|
40624
|
+
|
|
40625
|
+
return node;
|
|
40626
|
+
}
|
|
40627
|
+
|
|
40628
|
+
_chooseSubtree(bbox, node, level, path) {
|
|
40629
|
+
while (true) {
|
|
40630
|
+
path.push(node);
|
|
40631
|
+
|
|
40632
|
+
if (node.leaf || path.length - 1 === level) break;
|
|
40633
|
+
|
|
40634
|
+
let minArea = Infinity;
|
|
40635
|
+
let minEnlargement = Infinity;
|
|
40636
|
+
let targetNode;
|
|
40637
|
+
|
|
40638
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
40639
|
+
const child = node.children[i];
|
|
40640
|
+
const area = bboxArea(child);
|
|
40641
|
+
const enlargement = enlargedArea(bbox, child) - area;
|
|
40642
|
+
|
|
40643
|
+
// choose entry with the least area enlargement
|
|
40644
|
+
if (enlargement < minEnlargement) {
|
|
40645
|
+
minEnlargement = enlargement;
|
|
40646
|
+
minArea = area < minArea ? area : minArea;
|
|
40647
|
+
targetNode = child;
|
|
40648
|
+
|
|
40649
|
+
} else if (enlargement === minEnlargement) {
|
|
40650
|
+
// otherwise choose one with the smallest area
|
|
40651
|
+
if (area < minArea) {
|
|
40652
|
+
minArea = area;
|
|
40653
|
+
targetNode = child;
|
|
40654
|
+
}
|
|
40655
|
+
}
|
|
40656
|
+
}
|
|
40657
|
+
|
|
40658
|
+
node = targetNode || node.children[0];
|
|
40659
|
+
}
|
|
40660
|
+
|
|
40661
|
+
return node;
|
|
40662
|
+
}
|
|
40663
|
+
|
|
40664
|
+
_insert(item, level, isNode) {
|
|
40665
|
+
const bbox = isNode ? item : this.toBBox(item);
|
|
40666
|
+
const insertPath = [];
|
|
40667
|
+
|
|
40668
|
+
// find the best node for accommodating the item, saving all nodes along the path too
|
|
40669
|
+
const node = this._chooseSubtree(bbox, this.data, level, insertPath);
|
|
40670
|
+
|
|
40671
|
+
// put the item into the node
|
|
40672
|
+
node.children.push(item);
|
|
40673
|
+
extend(node, bbox);
|
|
40674
|
+
|
|
40675
|
+
// split on node overflow; propagate upwards if necessary
|
|
40676
|
+
while (level >= 0) {
|
|
40677
|
+
if (insertPath[level].children.length > this._maxEntries) {
|
|
40678
|
+
this._split(insertPath, level);
|
|
40679
|
+
level--;
|
|
40680
|
+
} else break;
|
|
40681
|
+
}
|
|
40682
|
+
|
|
40683
|
+
// adjust bboxes along the insertion path
|
|
40684
|
+
this._adjustParentBBoxes(bbox, insertPath, level);
|
|
40685
|
+
}
|
|
40686
|
+
|
|
40687
|
+
// split overflowed node into two
|
|
40688
|
+
_split(insertPath, level) {
|
|
40689
|
+
const node = insertPath[level];
|
|
40690
|
+
const M = node.children.length;
|
|
40691
|
+
const m = this._minEntries;
|
|
40692
|
+
|
|
40693
|
+
this._chooseSplitAxis(node, m, M);
|
|
40694
|
+
|
|
40695
|
+
const splitIndex = this._chooseSplitIndex(node, m, M);
|
|
40696
|
+
|
|
40697
|
+
const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
|
|
40698
|
+
newNode.height = node.height;
|
|
40699
|
+
newNode.leaf = node.leaf;
|
|
40700
|
+
|
|
40701
|
+
calcBBox(node, this.toBBox);
|
|
40702
|
+
calcBBox(newNode, this.toBBox);
|
|
40703
|
+
|
|
40704
|
+
if (level) insertPath[level - 1].children.push(newNode);
|
|
40705
|
+
else this._splitRoot(node, newNode);
|
|
40706
|
+
}
|
|
40707
|
+
|
|
40708
|
+
_splitRoot(node, newNode) {
|
|
40709
|
+
// split root node
|
|
40710
|
+
this.data = createNode([node, newNode]);
|
|
40711
|
+
this.data.height = node.height + 1;
|
|
40712
|
+
this.data.leaf = false;
|
|
40713
|
+
calcBBox(this.data, this.toBBox);
|
|
40714
|
+
}
|
|
40715
|
+
|
|
40716
|
+
_chooseSplitIndex(node, m, M) {
|
|
40717
|
+
let index;
|
|
40718
|
+
let minOverlap = Infinity;
|
|
40719
|
+
let minArea = Infinity;
|
|
40720
|
+
|
|
40721
|
+
for (let i = m; i <= M - m; i++) {
|
|
40722
|
+
const bbox1 = distBBox(node, 0, i, this.toBBox);
|
|
40723
|
+
const bbox2 = distBBox(node, i, M, this.toBBox);
|
|
40724
|
+
|
|
40725
|
+
const overlap = intersectionArea(bbox1, bbox2);
|
|
40726
|
+
const area = bboxArea(bbox1) + bboxArea(bbox2);
|
|
40727
|
+
|
|
40728
|
+
// choose distribution with minimum overlap
|
|
40729
|
+
if (overlap < minOverlap) {
|
|
40730
|
+
minOverlap = overlap;
|
|
40731
|
+
index = i;
|
|
40732
|
+
|
|
40733
|
+
minArea = area < minArea ? area : minArea;
|
|
40734
|
+
|
|
40735
|
+
} else if (overlap === minOverlap) {
|
|
40736
|
+
// otherwise choose distribution with minimum area
|
|
40737
|
+
if (area < minArea) {
|
|
40738
|
+
minArea = area;
|
|
40739
|
+
index = i;
|
|
40740
|
+
}
|
|
40741
|
+
}
|
|
40742
|
+
}
|
|
40743
|
+
|
|
40744
|
+
return index || M - m;
|
|
40745
|
+
}
|
|
40746
|
+
|
|
40747
|
+
// sorts node children by the best axis for split
|
|
40748
|
+
_chooseSplitAxis(node, m, M) {
|
|
40749
|
+
const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
|
|
40750
|
+
const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
|
|
40751
|
+
const xMargin = this._allDistMargin(node, m, M, compareMinX);
|
|
40752
|
+
const yMargin = this._allDistMargin(node, m, M, compareMinY);
|
|
40753
|
+
|
|
40754
|
+
// if total distributions margin value is minimal for x, sort by minX,
|
|
40755
|
+
// otherwise it's already sorted by minY
|
|
40756
|
+
if (xMargin < yMargin) node.children.sort(compareMinX);
|
|
40757
|
+
}
|
|
40758
|
+
|
|
40759
|
+
// total margin of all possible split distributions where each node is at least m full
|
|
40760
|
+
_allDistMargin(node, m, M, compare) {
|
|
40761
|
+
node.children.sort(compare);
|
|
40762
|
+
|
|
40763
|
+
const toBBox = this.toBBox;
|
|
40764
|
+
const leftBBox = distBBox(node, 0, m, toBBox);
|
|
40765
|
+
const rightBBox = distBBox(node, M - m, M, toBBox);
|
|
40766
|
+
let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
|
|
40767
|
+
|
|
40768
|
+
for (let i = m; i < M - m; i++) {
|
|
40769
|
+
const child = node.children[i];
|
|
40770
|
+
extend(leftBBox, node.leaf ? toBBox(child) : child);
|
|
40771
|
+
margin += bboxMargin(leftBBox);
|
|
40772
|
+
}
|
|
40773
|
+
|
|
40774
|
+
for (let i = M - m - 1; i >= m; i--) {
|
|
40775
|
+
const child = node.children[i];
|
|
40776
|
+
extend(rightBBox, node.leaf ? toBBox(child) : child);
|
|
40777
|
+
margin += bboxMargin(rightBBox);
|
|
40778
|
+
}
|
|
40779
|
+
|
|
40780
|
+
return margin;
|
|
40781
|
+
}
|
|
40782
|
+
|
|
40783
|
+
_adjustParentBBoxes(bbox, path, level) {
|
|
40784
|
+
// adjust bboxes along the given tree path
|
|
40785
|
+
for (let i = level; i >= 0; i--) {
|
|
40786
|
+
extend(path[i], bbox);
|
|
40787
|
+
}
|
|
40788
|
+
}
|
|
40789
|
+
|
|
40790
|
+
_condense(path) {
|
|
40791
|
+
// go through the path, removing empty nodes and updating bboxes
|
|
40792
|
+
for (let i = path.length - 1, siblings; i >= 0; i--) {
|
|
40793
|
+
if (path[i].children.length === 0) {
|
|
40794
|
+
if (i > 0) {
|
|
40795
|
+
siblings = path[i - 1].children;
|
|
40796
|
+
siblings.splice(siblings.indexOf(path[i]), 1);
|
|
40797
|
+
|
|
40798
|
+
} else this.clear();
|
|
40799
|
+
|
|
40800
|
+
} else calcBBox(path[i], this.toBBox);
|
|
40801
|
+
}
|
|
40802
|
+
}
|
|
40803
|
+
}
|
|
40804
|
+
|
|
40805
|
+
function findItem(item, items, equalsFn) {
|
|
40806
|
+
if (!equalsFn) return items.indexOf(item);
|
|
40807
|
+
|
|
40808
|
+
for (let i = 0; i < items.length; i++) {
|
|
40809
|
+
if (equalsFn(item, items[i])) return i;
|
|
40810
|
+
}
|
|
40811
|
+
return -1;
|
|
40812
|
+
}
|
|
40813
|
+
|
|
40814
|
+
// calculate node's bbox from bboxes of its children
|
|
40815
|
+
function calcBBox(node, toBBox) {
|
|
40816
|
+
distBBox(node, 0, node.children.length, toBBox, node);
|
|
40817
|
+
}
|
|
40818
|
+
|
|
40819
|
+
// min bounding rectangle of node children from k to p-1
|
|
40820
|
+
function distBBox(node, k, p, toBBox, destNode) {
|
|
40821
|
+
if (!destNode) destNode = createNode(null);
|
|
40822
|
+
destNode.minX = Infinity;
|
|
40823
|
+
destNode.minY = Infinity;
|
|
40824
|
+
destNode.maxX = -Infinity;
|
|
40825
|
+
destNode.maxY = -Infinity;
|
|
40826
|
+
|
|
40827
|
+
for (let i = k; i < p; i++) {
|
|
40828
|
+
const child = node.children[i];
|
|
40829
|
+
extend(destNode, node.leaf ? toBBox(child) : child);
|
|
40830
|
+
}
|
|
40831
|
+
|
|
40832
|
+
return destNode;
|
|
40833
|
+
}
|
|
40834
|
+
|
|
40835
|
+
function extend(a, b) {
|
|
40836
|
+
a.minX = Math.min(a.minX, b.minX);
|
|
40837
|
+
a.minY = Math.min(a.minY, b.minY);
|
|
40838
|
+
a.maxX = Math.max(a.maxX, b.maxX);
|
|
40839
|
+
a.maxY = Math.max(a.maxY, b.maxY);
|
|
40840
|
+
return a;
|
|
40841
|
+
}
|
|
40842
|
+
|
|
40843
|
+
function compareNodeMinX(a, b) { return a.minX - b.minX; }
|
|
40844
|
+
function compareNodeMinY(a, b) { return a.minY - b.minY; }
|
|
40845
|
+
|
|
40846
|
+
function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
|
|
40847
|
+
function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
|
|
40848
|
+
|
|
40849
|
+
function enlargedArea(a, b) {
|
|
40850
|
+
return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
|
|
40851
|
+
(Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
|
|
40852
|
+
}
|
|
40853
|
+
|
|
40854
|
+
function intersectionArea(a, b) {
|
|
40855
|
+
const minX = Math.max(a.minX, b.minX);
|
|
40856
|
+
const minY = Math.max(a.minY, b.minY);
|
|
40857
|
+
const maxX = Math.min(a.maxX, b.maxX);
|
|
40858
|
+
const maxY = Math.min(a.maxY, b.maxY);
|
|
40859
|
+
|
|
40860
|
+
return Math.max(0, maxX - minX) *
|
|
40861
|
+
Math.max(0, maxY - minY);
|
|
40862
|
+
}
|
|
40863
|
+
|
|
40864
|
+
function contains(a, b) {
|
|
40865
|
+
return a.minX <= b.minX &&
|
|
40866
|
+
a.minY <= b.minY &&
|
|
40867
|
+
b.maxX <= a.maxX &&
|
|
40868
|
+
b.maxY <= a.maxY;
|
|
40869
|
+
}
|
|
40870
|
+
|
|
40871
|
+
function intersects(a, b) {
|
|
40872
|
+
return b.minX <= a.maxX &&
|
|
40873
|
+
b.minY <= a.maxY &&
|
|
40874
|
+
b.maxX >= a.minX &&
|
|
40875
|
+
b.maxY >= a.minY;
|
|
40876
|
+
}
|
|
40877
|
+
|
|
40878
|
+
function createNode(children) {
|
|
40879
|
+
return {
|
|
40880
|
+
children,
|
|
40881
|
+
height: 1,
|
|
40882
|
+
leaf: true,
|
|
40883
|
+
minX: Infinity,
|
|
40884
|
+
minY: Infinity,
|
|
40885
|
+
maxX: -Infinity,
|
|
40886
|
+
maxY: -Infinity
|
|
40887
|
+
};
|
|
40888
|
+
}
|
|
40889
|
+
|
|
40890
|
+
// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
|
|
40891
|
+
// combines selection algorithm with binary divide & conquer approach
|
|
40892
|
+
|
|
40893
|
+
function multiSelect(arr, left, right, n, compare) {
|
|
40894
|
+
const stack = [left, right];
|
|
40895
|
+
|
|
40896
|
+
while (stack.length) {
|
|
40897
|
+
right = stack.pop();
|
|
40898
|
+
left = stack.pop();
|
|
40899
|
+
|
|
40900
|
+
if (right - left <= n) continue;
|
|
40901
|
+
|
|
40902
|
+
const mid = left + Math.ceil((right - left) / n / 2) * n;
|
|
40903
|
+
quickselect(arr, mid, left, right, compare);
|
|
40904
|
+
|
|
40905
|
+
stack.push(left, mid, mid, right);
|
|
40906
|
+
}
|
|
40907
|
+
}
|
|
40908
|
+
|
|
40063
40909
|
/**
|
|
40064
|
-
*
|
|
40910
|
+
* R-Tree Data Structure
|
|
40911
|
+
*
|
|
40912
|
+
* R-Tree is a spatial data structure used for efficient indexing and querying
|
|
40913
|
+
* of multi-dimensional objects, particularly in geometric and spatial applications.
|
|
40914
|
+
*
|
|
40915
|
+
* It organizes objects into a tree hierarchy, grouping nearby objects together
|
|
40916
|
+
* in bounding boxes. Each node in the tree represents a bounding box that
|
|
40917
|
+
* contains its child nodes or leaf objects. This hierarchical structure allows
|
|
40918
|
+
* for faster spatial queries.
|
|
40919
|
+
*
|
|
40920
|
+
* @see https://en.wikipedia.org/wiki/R-tree
|
|
40921
|
+
*
|
|
40922
|
+
* Consider a 2D Space with four zones: A, B, C, D
|
|
40923
|
+
* +--------------------------+
|
|
40924
|
+
* | |
|
|
40925
|
+
* | +---+ +-------+ |
|
|
40926
|
+
* | | A | | B | |
|
|
40927
|
+
* | +---+ +-------+ |
|
|
40928
|
+
* | |
|
|
40929
|
+
* | |
|
|
40930
|
+
* | +---+ |
|
|
40931
|
+
* | | C | |
|
|
40932
|
+
* | +---+ |
|
|
40933
|
+
* | +-----------+ |
|
|
40934
|
+
* | | D | |
|
|
40935
|
+
* | +-----------+ |
|
|
40936
|
+
* | |
|
|
40937
|
+
* +--------------------------+
|
|
40938
|
+
*
|
|
40939
|
+
* It groups together zones that are spatially close into a minimum bounding box.
|
|
40940
|
+
* For example, A and B are grouped together in rectangle R1, and C and D are grouped
|
|
40941
|
+
* in R2.
|
|
40942
|
+
*
|
|
40943
|
+
* R0
|
|
40944
|
+
* +--------------------------+
|
|
40945
|
+
* | R1 |
|
|
40946
|
+
* | +-----------------+ |
|
|
40947
|
+
* | | A | | B | |
|
|
40948
|
+
* | +-----------------+ |
|
|
40949
|
+
* | |
|
|
40950
|
+
* | R2 |
|
|
40951
|
+
* | +---+---+---+ |
|
|
40952
|
+
* | | | C | | |
|
|
40953
|
+
* | | +---+ | |
|
|
40954
|
+
* | +-----------+ |
|
|
40955
|
+
* | | D | |
|
|
40956
|
+
* | +-----------+ |
|
|
40957
|
+
* | |
|
|
40958
|
+
* +--------------------------+
|
|
40959
|
+
*
|
|
40960
|
+
* The tree would look like this:
|
|
40961
|
+
* R0
|
|
40962
|
+
* / \
|
|
40963
|
+
* / \
|
|
40964
|
+
* R1 R2
|
|
40965
|
+
* | |
|
|
40966
|
+
* A,B C,D
|
|
40967
|
+
|
|
40968
|
+
* Choosing how to group the zones is crucial for the performance of the tree.
|
|
40969
|
+
* Key considerations include avoiding excessive empty space coverage and minimizing overlap
|
|
40970
|
+
* to reduce the number of subtrees processed during searches.
|
|
40971
|
+
*
|
|
40972
|
+
* Various heuristics exist for determining the optimal grouping strategy, such as "least enlargement"
|
|
40973
|
+
* which prioritizes grouping nodes resulting in the smallest increase in bounding box size. In cases where
|
|
40974
|
+
* the choice cannot be made based on this criterion due to the same enlargement for different groupings,
|
|
40975
|
+
* we then evaluate "least area," aiming to minimize the overall area of bounding boxes.
|
|
40976
|
+
*
|
|
40977
|
+
* This implementation is tailored for spreadsheet use, indexing objects associated
|
|
40978
|
+
* with a zone and a sheet.
|
|
40979
|
+
*
|
|
40980
|
+
* It uses the RBush library under the hood. One 2D RBush R-tree per sheet.
|
|
40981
|
+
* @see https://github.com/mourner/rbush
|
|
40982
|
+
*/
|
|
40983
|
+
class SpreadsheetRTree {
|
|
40984
|
+
/**
|
|
40985
|
+
* One 2D R-tree per sheet
|
|
40986
|
+
*/
|
|
40987
|
+
rTrees = {};
|
|
40988
|
+
/**
|
|
40989
|
+
* Bulk-inserts the given items into the tree. Bulk insertion is usually ~2-3 times
|
|
40990
|
+
* faster than inserting items one by one. After bulk loading (bulk insertion into
|
|
40991
|
+
* an empty tree), subsequent query performance is also ~20-30% better.
|
|
40992
|
+
*/
|
|
40993
|
+
constructor(items = []) {
|
|
40994
|
+
const rangesPerSheet = {};
|
|
40995
|
+
for (const item of items) {
|
|
40996
|
+
const sheetId = item.boundingBox.sheetId;
|
|
40997
|
+
if (!rangesPerSheet[sheetId]) {
|
|
40998
|
+
rangesPerSheet[sheetId] = [];
|
|
40999
|
+
}
|
|
41000
|
+
rangesPerSheet[sheetId].push(item);
|
|
41001
|
+
}
|
|
41002
|
+
for (const sheetId in rangesPerSheet) {
|
|
41003
|
+
this.rTrees[sheetId] = new ZoneRBush();
|
|
41004
|
+
this.rTrees[sheetId].load(rangesPerSheet[sheetId]); // bulk-insert
|
|
41005
|
+
}
|
|
41006
|
+
}
|
|
41007
|
+
insert(item) {
|
|
41008
|
+
const sheetId = item.boundingBox.sheetId;
|
|
41009
|
+
if (!this.rTrees[sheetId]) {
|
|
41010
|
+
this.rTrees[sheetId] = new ZoneRBush();
|
|
41011
|
+
}
|
|
41012
|
+
this.rTrees[sheetId].insert(item);
|
|
41013
|
+
}
|
|
41014
|
+
search({ zone, sheetId }) {
|
|
41015
|
+
if (!this.rTrees[sheetId]) {
|
|
41016
|
+
return [];
|
|
41017
|
+
}
|
|
41018
|
+
return this.rTrees[sheetId].search({
|
|
41019
|
+
minX: zone.left,
|
|
41020
|
+
minY: zone.top,
|
|
41021
|
+
maxX: zone.right,
|
|
41022
|
+
maxY: zone.bottom,
|
|
41023
|
+
});
|
|
41024
|
+
}
|
|
41025
|
+
remove(item) {
|
|
41026
|
+
const sheetId = item.boundingBox.sheetId;
|
|
41027
|
+
if (!this.rTrees[sheetId]) {
|
|
41028
|
+
return;
|
|
41029
|
+
}
|
|
41030
|
+
this.rTrees[sheetId].remove(item, deepEquals);
|
|
41031
|
+
}
|
|
41032
|
+
}
|
|
41033
|
+
/**
|
|
41034
|
+
* RBush extension to use zones as bounding boxes
|
|
41035
|
+
*/
|
|
41036
|
+
class ZoneRBush extends RBush {
|
|
41037
|
+
toBBox({ boundingBox }) {
|
|
41038
|
+
const zone = boundingBox.zone;
|
|
41039
|
+
return {
|
|
41040
|
+
minX: zone.left,
|
|
41041
|
+
minY: zone.top,
|
|
41042
|
+
maxX: zone.right,
|
|
41043
|
+
maxY: zone.bottom,
|
|
41044
|
+
};
|
|
41045
|
+
}
|
|
41046
|
+
compareMinX(a, b) {
|
|
41047
|
+
return a.boundingBox.zone.left - b.boundingBox.zone.left;
|
|
41048
|
+
}
|
|
41049
|
+
compareMinY(a, b) {
|
|
41050
|
+
return a.boundingBox.zone.top - b.boundingBox.zone.top;
|
|
41051
|
+
}
|
|
41052
|
+
}
|
|
41053
|
+
|
|
41054
|
+
/**
|
|
41055
|
+
* Implementation of a dependency Graph.
|
|
40065
41056
|
* The graph is used to evaluate the cells in the correct
|
|
40066
41057
|
* order, and should be updated each time a cell's content is modified
|
|
40067
41058
|
*
|
|
41059
|
+
* It uses an R-Tree data structure to efficiently find dependent cells.
|
|
40068
41060
|
*/
|
|
40069
41061
|
class FormulaDependencyGraph {
|
|
40070
|
-
|
|
40071
|
-
* Internal structure:
|
|
40072
|
-
* - key: a cell position (encoded as an integer)
|
|
40073
|
-
* - value: a set of cell positions that depends on the key
|
|
40074
|
-
*
|
|
40075
|
-
* Given
|
|
40076
|
-
* - A1:"= B1 + SQRT(B2)"
|
|
40077
|
-
* - C1:"= B1";
|
|
40078
|
-
* - C2:"= C1"
|
|
40079
|
-
*
|
|
40080
|
-
* we will have something like:
|
|
40081
|
-
* - B1 ---> (A1, C1) meaning A1 and C1 depends on B1
|
|
40082
|
-
* - B2 ---> (A1) meaning A1 depends on B2
|
|
40083
|
-
* - C1 ---> (C2) meaning C2 depends on C1
|
|
40084
|
-
*/
|
|
40085
|
-
inverseDependencies = new Map();
|
|
41062
|
+
encoder;
|
|
40086
41063
|
dependencies = new Map();
|
|
41064
|
+
rTree;
|
|
41065
|
+
constructor(encoder, data = []) {
|
|
41066
|
+
this.encoder = encoder;
|
|
41067
|
+
this.rTree = new SpreadsheetRTree(data);
|
|
41068
|
+
}
|
|
40087
41069
|
removeAllDependencies(formulaPositionId) {
|
|
40088
|
-
const
|
|
40089
|
-
if (!
|
|
41070
|
+
const ranges = this.dependencies.get(formulaPositionId);
|
|
41071
|
+
if (!ranges) {
|
|
40090
41072
|
return;
|
|
40091
41073
|
}
|
|
40092
|
-
for (const
|
|
40093
|
-
this.
|
|
41074
|
+
for (const range of ranges) {
|
|
41075
|
+
this.rTree.remove(range);
|
|
40094
41076
|
}
|
|
40095
41077
|
this.dependencies.delete(formulaPositionId);
|
|
40096
41078
|
}
|
|
40097
41079
|
addDependencies(formulaPositionId, dependencies) {
|
|
40098
|
-
|
|
40099
|
-
|
|
40100
|
-
|
|
40101
|
-
|
|
40102
|
-
|
|
40103
|
-
|
|
40104
|
-
|
|
40105
|
-
|
|
41080
|
+
const rTreeItems = dependencies.map(({ sheetId, zone }) => ({
|
|
41081
|
+
data: formulaPositionId,
|
|
41082
|
+
boundingBox: {
|
|
41083
|
+
zone,
|
|
41084
|
+
sheetId,
|
|
41085
|
+
},
|
|
41086
|
+
}));
|
|
41087
|
+
for (const item of rTreeItems) {
|
|
41088
|
+
this.rTree.insert(item);
|
|
40106
41089
|
}
|
|
40107
41090
|
const existingDependencies = this.dependencies.get(formulaPositionId);
|
|
40108
41091
|
if (existingDependencies) {
|
|
40109
|
-
existingDependencies.push(...
|
|
41092
|
+
existingDependencies.push(...rTreeItems);
|
|
40110
41093
|
}
|
|
40111
41094
|
else {
|
|
40112
|
-
this.dependencies.set(formulaPositionId,
|
|
41095
|
+
this.dependencies.set(formulaPositionId, rTreeItems);
|
|
40113
41096
|
}
|
|
40114
41097
|
}
|
|
40115
41098
|
/**
|
|
@@ -40117,20 +41100,20 @@ class FormulaDependencyGraph {
|
|
|
40117
41100
|
* in the correct order they should be evaluated.
|
|
40118
41101
|
* This is called a topological ordering (excluding cycles)
|
|
40119
41102
|
*/
|
|
40120
|
-
getCellsDependingOn(
|
|
41103
|
+
getCellsDependingOn(ranges) {
|
|
40121
41104
|
const visited = new JetSet();
|
|
40122
|
-
const queue = Array.from(
|
|
41105
|
+
const queue = Array.from(ranges).reverse();
|
|
40123
41106
|
while (queue.length > 0) {
|
|
40124
|
-
const
|
|
40125
|
-
visited.add(
|
|
40126
|
-
const
|
|
40127
|
-
for (const
|
|
40128
|
-
if (!visited.has(
|
|
40129
|
-
queue.push(
|
|
41107
|
+
const range = queue.pop();
|
|
41108
|
+
visited.add(...this.encoder.encodeBoundingBox(range));
|
|
41109
|
+
const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
|
|
41110
|
+
for (const positionId of impactedPositionIds) {
|
|
41111
|
+
if (!visited.has(positionId)) {
|
|
41112
|
+
queue.push(this.encoder.decodeToBoundingBox(positionId));
|
|
40130
41113
|
}
|
|
40131
41114
|
}
|
|
40132
41115
|
}
|
|
40133
|
-
visited.delete(...
|
|
41116
|
+
visited.delete(...ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
|
|
40134
41117
|
return visited;
|
|
40135
41118
|
}
|
|
40136
41119
|
}
|
|
@@ -40218,9 +41201,9 @@ class Evaluator {
|
|
|
40218
41201
|
context;
|
|
40219
41202
|
getters;
|
|
40220
41203
|
compilationParams;
|
|
40221
|
-
|
|
41204
|
+
encoder = new PositionBitsEncoder();
|
|
40222
41205
|
evaluatedCells = new Map();
|
|
40223
|
-
formulaDependencies = lazy(new FormulaDependencyGraph());
|
|
41206
|
+
formulaDependencies = lazy(new FormulaDependencyGraph(this.encoder));
|
|
40224
41207
|
blockedArrayFormulas = new Set();
|
|
40225
41208
|
spreadingRelations = new SpreadingRelation();
|
|
40226
41209
|
constructor(context, getters) {
|
|
@@ -40229,23 +41212,23 @@ class Evaluator {
|
|
|
40229
41212
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40230
41213
|
}
|
|
40231
41214
|
getEvaluatedCell(position) {
|
|
40232
|
-
return (this.evaluatedCells.get(this.
|
|
41215
|
+
return (this.evaluatedCells.get(this.encoder.encode(position)) ||
|
|
40233
41216
|
createEvaluatedCell("", { locale: this.getters.getLocale() }));
|
|
40234
41217
|
}
|
|
40235
41218
|
getSpreadPositionsOf(position) {
|
|
40236
|
-
const positionId = this.
|
|
41219
|
+
const positionId = this.encoder.encode(position);
|
|
40237
41220
|
if (!this.spreadingRelations.isArrayFormula(positionId)) {
|
|
40238
41221
|
return [];
|
|
40239
41222
|
}
|
|
40240
|
-
return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map(this.
|
|
41223
|
+
return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map((positionId) => this.encoder.decode(positionId));
|
|
40241
41224
|
}
|
|
40242
41225
|
getArrayFormulaSpreadingOn(position) {
|
|
40243
|
-
const positionId = this.
|
|
41226
|
+
const positionId = this.encoder.encode(position);
|
|
40244
41227
|
const formulaPosition = this.getArrayFormulaSpreadingOnId(positionId);
|
|
40245
|
-
return formulaPosition !== undefined ? this.
|
|
41228
|
+
return formulaPosition !== undefined ? this.encoder.decode(formulaPosition) : undefined;
|
|
40246
41229
|
}
|
|
40247
41230
|
getEvaluatedPositions() {
|
|
40248
|
-
return [...this.evaluatedCells.keys()].map(this.
|
|
41231
|
+
return [...this.evaluatedCells.keys()].map((p) => this.encoder.decode(p));
|
|
40249
41232
|
}
|
|
40250
41233
|
getArrayFormulaSpreadingOnId(positionId) {
|
|
40251
41234
|
if (!this.spreadingRelations.hasArrayFormulaResult(positionId)) {
|
|
@@ -40255,7 +41238,7 @@ class Evaluator {
|
|
|
40255
41238
|
return Array.from(arrayFormulas).find((positionId) => !this.blockedArrayFormulas.has(positionId));
|
|
40256
41239
|
}
|
|
40257
41240
|
updateDependencies(position) {
|
|
40258
|
-
const positionId = this.
|
|
41241
|
+
const positionId = this.encoder.encode(position);
|
|
40259
41242
|
this.formulaDependencies().removeAllDependencies(positionId);
|
|
40260
41243
|
const dependencies = this.getDirectDependencies(positionId);
|
|
40261
41244
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
@@ -40265,12 +41248,12 @@ class Evaluator {
|
|
|
40265
41248
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40266
41249
|
}
|
|
40267
41250
|
evaluateCells(positions) {
|
|
40268
|
-
const cells = positions.map(this.
|
|
41251
|
+
const cells = positions.map((p) => this.encoder.encode(p));
|
|
40269
41252
|
const cellsToCompute = new JetSet(cells);
|
|
40270
|
-
const
|
|
41253
|
+
const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
|
|
40271
41254
|
cellsToCompute.add(...this.getCellsDependingOn(cells));
|
|
40272
|
-
cellsToCompute.add(...
|
|
40273
|
-
cellsToCompute.add(...this.getCellsDependingOn(
|
|
41255
|
+
cellsToCompute.add(...arrayFormulasPositionIds);
|
|
41256
|
+
cellsToCompute.add(...this.getCellsDependingOn(arrayFormulasPositionIds));
|
|
40274
41257
|
this.evaluate(cellsToCompute);
|
|
40275
41258
|
}
|
|
40276
41259
|
getArrayFormulasImpactedByChangesOf(positionIds) {
|
|
@@ -40293,12 +41276,14 @@ class Evaluator {
|
|
|
40293
41276
|
this.blockedArrayFormulas = new Set();
|
|
40294
41277
|
this.spreadingRelations = new SpreadingRelation();
|
|
40295
41278
|
this.formulaDependencies = lazy(() => {
|
|
40296
|
-
const
|
|
40297
|
-
|
|
40298
|
-
|
|
40299
|
-
|
|
40300
|
-
|
|
40301
|
-
|
|
41279
|
+
const dependencies = [...this.getAllCells()].flatMap((positionId) => this.getDirectDependencies(positionId).map((range) => ({
|
|
41280
|
+
data: positionId,
|
|
41281
|
+
boundingBox: {
|
|
41282
|
+
zone: range.zone,
|
|
41283
|
+
sheetId: range.sheetId,
|
|
41284
|
+
},
|
|
41285
|
+
})));
|
|
41286
|
+
return new FormulaDependencyGraph(this.encoder, dependencies);
|
|
40302
41287
|
});
|
|
40303
41288
|
}
|
|
40304
41289
|
evaluateAllCells() {
|
|
@@ -40320,7 +41305,7 @@ class Evaluator {
|
|
|
40320
41305
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
40321
41306
|
const cellIds = this.getters.getCells(sheetId);
|
|
40322
41307
|
for (const cellId in cellIds) {
|
|
40323
|
-
positionIds.add(this.
|
|
41308
|
+
positionIds.add(this.encoder.encode(this.getters.getCellPosition(cellId)));
|
|
40324
41309
|
}
|
|
40325
41310
|
}
|
|
40326
41311
|
return positionIds;
|
|
@@ -40365,7 +41350,7 @@ class Evaluator {
|
|
|
40365
41350
|
if (!this.blockedArrayFormulas.has(positionId)) {
|
|
40366
41351
|
this.invalidateSpreading(positionId);
|
|
40367
41352
|
}
|
|
40368
|
-
const cellPosition = this.
|
|
41353
|
+
const cellPosition = this.encoder.decode(positionId);
|
|
40369
41354
|
const cell = this.getters.getCell(cellPosition);
|
|
40370
41355
|
if (cell === undefined) {
|
|
40371
41356
|
return createEvaluatedCell("", { locale: this.getters.getLocale() });
|
|
@@ -40388,7 +41373,7 @@ class Evaluator {
|
|
|
40388
41373
|
}
|
|
40389
41374
|
}
|
|
40390
41375
|
computeAndSave(position) {
|
|
40391
|
-
const positionId = this.
|
|
41376
|
+
const positionId = this.encoder.encode(position);
|
|
40392
41377
|
const evaluatedCell = this.computeCell(positionId);
|
|
40393
41378
|
if (!this.evaluatedCells.has(positionId)) {
|
|
40394
41379
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
@@ -40443,15 +41428,15 @@ class Evaluator {
|
|
|
40443
41428
|
throw new Error(_t("Result couldn't be automatically expanded. Please insert more columns and rows."));
|
|
40444
41429
|
}
|
|
40445
41430
|
updateSpreadRelation({ sheetId, col, row, }) {
|
|
40446
|
-
const arrayFormulaPositionId = this.
|
|
41431
|
+
const arrayFormulaPositionId = this.encoder.encode({ sheetId, col, row });
|
|
40447
41432
|
return (i, j) => {
|
|
40448
41433
|
const position = { sheetId, col: i + col, row: j + row };
|
|
40449
|
-
const resultPositionId = this.
|
|
41434
|
+
const resultPositionId = this.encoder.encode(position);
|
|
40450
41435
|
this.spreadingRelations.addRelation({ resultPositionId, arrayFormulaPositionId });
|
|
40451
41436
|
};
|
|
40452
41437
|
}
|
|
40453
41438
|
checkCollision({ sheetId, col, row }) {
|
|
40454
|
-
const formulaPositionId = this.
|
|
41439
|
+
const formulaPositionId = this.encoder.encode({ sheetId, col, row });
|
|
40455
41440
|
return (i, j) => {
|
|
40456
41441
|
const position = { sheetId: sheetId, col: i + col, row: j + row };
|
|
40457
41442
|
const rawCell = this.getters.getCell(position);
|
|
@@ -40472,7 +41457,7 @@ class Evaluator {
|
|
|
40472
41457
|
format: format || matrixResult[i][j]?.format,
|
|
40473
41458
|
locale: this.getters.getLocale(),
|
|
40474
41459
|
});
|
|
40475
|
-
const positionId = this.
|
|
41460
|
+
const positionId = this.encoder.encode(position);
|
|
40476
41461
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
40477
41462
|
// check if formula dependencies present in the spread zone
|
|
40478
41463
|
// if so, they need to be recomputed
|
|
@@ -40504,29 +41489,17 @@ class Evaluator {
|
|
|
40504
41489
|
if (!cell?.isFormula) {
|
|
40505
41490
|
return [];
|
|
40506
41491
|
}
|
|
40507
|
-
|
|
40508
|
-
for (const range of cell.compiledFormula.dependencies) {
|
|
40509
|
-
if (range.invalidSheetName || range.invalidXc) {
|
|
40510
|
-
continue;
|
|
40511
|
-
}
|
|
40512
|
-
const sheetId = range.sheetId;
|
|
40513
|
-
forEachPositionsInZone(range.zone, (col, row) => {
|
|
40514
|
-
dependencies.push(this.encodePosition({ sheetId, col, row }));
|
|
40515
|
-
});
|
|
40516
|
-
}
|
|
40517
|
-
return dependencies;
|
|
41492
|
+
return cell.compiledFormula.dependencies;
|
|
40518
41493
|
}
|
|
40519
41494
|
getCellsDependingOn(positionIds) {
|
|
40520
|
-
|
|
41495
|
+
const ranges = [];
|
|
41496
|
+
for (const positionId of positionIds) {
|
|
41497
|
+
ranges.push(this.encoder.decodeToBoundingBox(positionId));
|
|
41498
|
+
}
|
|
41499
|
+
return this.formulaDependencies().getCellsDependingOn(ranges);
|
|
40521
41500
|
}
|
|
40522
41501
|
getCell(positionId) {
|
|
40523
|
-
return this.getters.getCell(this.
|
|
40524
|
-
}
|
|
40525
|
-
encodePosition(position) {
|
|
40526
|
-
return this.positionEncoder.encode(position);
|
|
40527
|
-
}
|
|
40528
|
-
decodePosition(positionId) {
|
|
40529
|
-
return this.positionEncoder.decode(positionId);
|
|
41502
|
+
return this.getters.getCell(this.encoder.decode(positionId));
|
|
40530
41503
|
}
|
|
40531
41504
|
}
|
|
40532
41505
|
function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
@@ -40582,6 +41555,13 @@ class PositionBitsEncoder {
|
|
|
40582
41555
|
encode({ sheetId, col, row }) {
|
|
40583
41556
|
return (this.encodeSheet(sheetId) << 42n) | (BigInt(col) << 21n) | BigInt(row);
|
|
40584
41557
|
}
|
|
41558
|
+
encodeBoundingBox({ sheetId, zone }) {
|
|
41559
|
+
const positions = [];
|
|
41560
|
+
forEachPositionsInZone(zone, (col, row) => {
|
|
41561
|
+
positions.push(this.encode({ sheetId, col, row }));
|
|
41562
|
+
});
|
|
41563
|
+
return positions;
|
|
41564
|
+
}
|
|
40585
41565
|
decode(id) {
|
|
40586
41566
|
// keep only the last 21 bits by AND-ing the bit sequence with 21 ones
|
|
40587
41567
|
const row = Number(id & 2097151n);
|
|
@@ -40589,6 +41569,10 @@ class PositionBitsEncoder {
|
|
|
40589
41569
|
const sheetId = this.decodeSheet(id >> 42n);
|
|
40590
41570
|
return { sheetId, col, row };
|
|
40591
41571
|
}
|
|
41572
|
+
decodeToBoundingBox(id) {
|
|
41573
|
+
const { sheetId, col, row } = this.decode(id);
|
|
41574
|
+
return { sheetId, zone: { left: col, top: row, right: col, bottom: row } };
|
|
41575
|
+
}
|
|
40592
41576
|
encodeSheet(sheetId) {
|
|
40593
41577
|
const sheetKey = this.sheetMapping[sheetId];
|
|
40594
41578
|
if (sheetKey === undefined) {
|
|
@@ -40771,7 +41755,12 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40771
41755
|
// Getters
|
|
40772
41756
|
// ---------------------------------------------------------------------------
|
|
40773
41757
|
evaluateFormula(sheetId, formulaString) {
|
|
40774
|
-
|
|
41758
|
+
try {
|
|
41759
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
41760
|
+
}
|
|
41761
|
+
catch (error) {
|
|
41762
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
41763
|
+
}
|
|
40775
41764
|
}
|
|
40776
41765
|
/**
|
|
40777
41766
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -41040,7 +42029,7 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
41040
42029
|
}
|
|
41041
42030
|
|
|
41042
42031
|
class EvaluationChartPlugin extends UIPlugin {
|
|
41043
|
-
static getters = ["getChartRuntime", "
|
|
42032
|
+
static getters = ["getChartRuntime", "getStyleOfSingleCellChart"];
|
|
41044
42033
|
charts = {};
|
|
41045
42034
|
createRuntimeChart = chartRuntimeFactory(this.getters);
|
|
41046
42035
|
handle(cmd) {
|
|
@@ -41078,25 +42067,26 @@ class EvaluationChartPlugin extends UIPlugin {
|
|
|
41078
42067
|
return this.charts[figureId];
|
|
41079
42068
|
}
|
|
41080
42069
|
/**
|
|
41081
|
-
* Get the background
|
|
41082
|
-
* of the chart. In order of priority, it will return :
|
|
41083
|
-
*
|
|
41084
|
-
* - the chart background color if one is defined
|
|
41085
|
-
* - the fill color of the cell if one is defined
|
|
41086
|
-
* - the fill color of the cell from conditional formats if one is defined
|
|
41087
|
-
* - the default chart color if no other color is defined
|
|
42070
|
+
* Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
|
|
41088
42071
|
*/
|
|
41089
|
-
|
|
42072
|
+
getStyleOfSingleCellChart(chartBackground, mainRange) {
|
|
41090
42073
|
if (chartBackground)
|
|
41091
|
-
return chartBackground;
|
|
42074
|
+
return { background: chartBackground, fontColor: chartFontColor(chartBackground) };
|
|
41092
42075
|
if (!mainRange) {
|
|
41093
|
-
return
|
|
42076
|
+
return {
|
|
42077
|
+
background: BACKGROUND_CHART_COLOR,
|
|
42078
|
+
fontColor: chartFontColor(BACKGROUND_CHART_COLOR),
|
|
42079
|
+
};
|
|
41094
42080
|
}
|
|
41095
42081
|
const col = mainRange.zone.left;
|
|
41096
42082
|
const row = mainRange.zone.top;
|
|
41097
42083
|
const sheetId = mainRange.sheetId;
|
|
41098
42084
|
const style = this.getters.getCellComputedStyle({ sheetId, col, row });
|
|
41099
|
-
|
|
42085
|
+
const background = style.fillColor || BACKGROUND_CHART_COLOR;
|
|
42086
|
+
return {
|
|
42087
|
+
background,
|
|
42088
|
+
fontColor: style.textColor || chartFontColor(background),
|
|
42089
|
+
};
|
|
41100
42090
|
}
|
|
41101
42091
|
exportForExcel(data) {
|
|
41102
42092
|
for (const sheet of data.sheets) {
|
|
@@ -41207,45 +42197,40 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
41207
42197
|
getComputedStyles(sheetId) {
|
|
41208
42198
|
const computedStyle = {};
|
|
41209
42199
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
41210
|
-
|
|
41211
|
-
|
|
41212
|
-
|
|
41213
|
-
|
|
41214
|
-
|
|
41215
|
-
|
|
41216
|
-
|
|
41217
|
-
|
|
41218
|
-
|
|
41219
|
-
|
|
41220
|
-
|
|
41221
|
-
for (let
|
|
41222
|
-
|
|
41223
|
-
|
|
41224
|
-
|
|
41225
|
-
const
|
|
41226
|
-
|
|
41227
|
-
|
|
41228
|
-
|
|
41229
|
-
|
|
41230
|
-
|
|
41231
|
-
});
|
|
41232
|
-
}
|
|
41233
|
-
return value;
|
|
41234
|
-
});
|
|
41235
|
-
if (predicate && predicate(target, { ...cf.rule, values })) {
|
|
41236
|
-
if (!computedStyle[col])
|
|
41237
|
-
computedStyle[col] = [];
|
|
41238
|
-
// we must combine all the properties of all the CF rules applied to the given cell
|
|
41239
|
-
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
42200
|
+
switch (cf.rule.type) {
|
|
42201
|
+
case "ColorScaleRule":
|
|
42202
|
+
for (let range of cf.ranges) {
|
|
42203
|
+
this.applyColorScale(sheetId, range, cf.rule, computedStyle);
|
|
42204
|
+
}
|
|
42205
|
+
break;
|
|
42206
|
+
case "CellIsRule":
|
|
42207
|
+
const formulas = cf.rule.values.map((value) => value.startsWith("=") ? compile(value) : undefined);
|
|
42208
|
+
for (let ref of cf.ranges) {
|
|
42209
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
42210
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
42211
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
42212
|
+
const predicate = this.rulePredicate[cf.rule.type];
|
|
42213
|
+
const target = { sheetId, col, row };
|
|
42214
|
+
const values = cf.rule.values.map((value, i) => {
|
|
42215
|
+
const compiledFormula = formulas[i];
|
|
42216
|
+
if (compiledFormula) {
|
|
42217
|
+
return this.getters.getTranslatedCellFormula(sheetId, col - zone.left, row - zone.top, {
|
|
42218
|
+
...compiledFormula,
|
|
42219
|
+
dependencies: compiledFormula.dependencies.map((d) => this.getters.getRangeFromSheetXC(sheetId, d)),
|
|
42220
|
+
});
|
|
41240
42221
|
}
|
|
42222
|
+
return value;
|
|
42223
|
+
});
|
|
42224
|
+
if (predicate && predicate(target, { ...cf.rule, values })) {
|
|
42225
|
+
if (!computedStyle[col])
|
|
42226
|
+
computedStyle[col] = [];
|
|
42227
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
42228
|
+
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
41241
42229
|
}
|
|
41242
42230
|
}
|
|
41243
42231
|
}
|
|
41244
|
-
|
|
41245
|
-
|
|
41246
|
-
}
|
|
41247
|
-
catch (_) {
|
|
41248
|
-
// we don't care about the errors within the evaluation of a rule
|
|
42232
|
+
}
|
|
42233
|
+
break;
|
|
41249
42234
|
}
|
|
41250
42235
|
}
|
|
41251
42236
|
return computedStyle;
|
|
@@ -41856,11 +42841,6 @@ class AutofillPlugin extends UIPlugin {
|
|
|
41856
42841
|
return "Success" /* CommandResult.Success */;
|
|
41857
42842
|
}
|
|
41858
42843
|
return "InvalidAutofillSelection" /* CommandResult.InvalidAutofillSelection */;
|
|
41859
|
-
case "AUTOFILL_AUTO":
|
|
41860
|
-
const zone = this.getters.getSelectedZone();
|
|
41861
|
-
return zone.top === zone.bottom
|
|
41862
|
-
? "Success" /* CommandResult.Success */
|
|
41863
|
-
: "CancelledForUnknownReason" /* CommandResult.CancelledForUnknownReason */;
|
|
41864
42844
|
}
|
|
41865
42845
|
return "Success" /* CommandResult.Success */;
|
|
41866
42846
|
}
|
|
@@ -42017,7 +42997,7 @@ class AutofillPlugin extends UIPlugin {
|
|
|
42017
42997
|
let row = zone.bottom;
|
|
42018
42998
|
if (col > 0) {
|
|
42019
42999
|
let leftPosition = { sheetId, col: col - 1, row };
|
|
42020
|
-
while (this.getters.
|
|
43000
|
+
while (this.getters.getCorrespondingFormulaCell(leftPosition) ||
|
|
42021
43001
|
this.getters.getCell(leftPosition)?.content) {
|
|
42022
43002
|
row += 1;
|
|
42023
43003
|
leftPosition = { sheetId, col: col - 1, row };
|
|
@@ -42027,7 +43007,7 @@ class AutofillPlugin extends UIPlugin {
|
|
|
42027
43007
|
col = zone.right;
|
|
42028
43008
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
42029
43009
|
let rightPosition = { sheetId, col: col + 1, row };
|
|
42030
|
-
while (this.getters.
|
|
43010
|
+
while (this.getters.getCorrespondingFormulaCell(rightPosition) ||
|
|
42031
43011
|
this.getters.getCell(rightPosition)?.content) {
|
|
42032
43012
|
row += 1;
|
|
42033
43013
|
rightPosition = { sheetId, col: col + 1, row };
|
|
@@ -43622,7 +44602,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43622
44602
|
isPasteAllowed(target, clipboardOption) {
|
|
43623
44603
|
const sheetId = this.getters.getActiveSheetId();
|
|
43624
44604
|
if (this.operation === "CUT" && clipboardOption?.pasteOption !== undefined) {
|
|
43625
|
-
// cannot paste only format or
|
|
44605
|
+
// cannot paste only format or as value if the previous operation is a CUT
|
|
43626
44606
|
return "WrongPasteOption" /* CommandResult.WrongPasteOption */;
|
|
43627
44607
|
}
|
|
43628
44608
|
if (target.length > 1) {
|
|
@@ -43804,7 +44784,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43804
44784
|
// This condition is used to determine if we have to paste the CF or not.
|
|
43805
44785
|
// We have to do it when the command handled is "PASTE", not "INSERT_CELL"
|
|
43806
44786
|
// or "DELETE_CELL". So, the state should be the local state
|
|
43807
|
-
const shouldPasteCF = clipboardOptions?.pasteOption !== "
|
|
44787
|
+
const shouldPasteCF = clipboardOptions?.pasteOption !== "asValue" && clipboardOptions?.shouldPasteCF;
|
|
43808
44788
|
const shouldPasteDV = !clipboardOptions?.pasteOption;
|
|
43809
44789
|
const sheetId = this.getters.getActiveSheetId();
|
|
43810
44790
|
// first, add missing cols/rows if needed
|
|
@@ -43840,10 +44820,11 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43840
44820
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43841
44821
|
const { sheetId, col, row } = target;
|
|
43842
44822
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43843
|
-
|
|
44823
|
+
const originFormat = origin.cell?.format ?? origin.evaluatedCell.format;
|
|
44824
|
+
if (clipboardOption?.pasteOption === "asValue") {
|
|
43844
44825
|
const locale = this.getters.getLocale();
|
|
43845
44826
|
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43846
|
-
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
44827
|
+
this.dispatch("UPDATE_CELL", { ...target, content, format: originFormat });
|
|
43847
44828
|
return;
|
|
43848
44829
|
}
|
|
43849
44830
|
const targetBorders = this.getters.getCellBorder(target);
|
|
@@ -43859,7 +44840,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43859
44840
|
this.dispatch("UPDATE_CELL", {
|
|
43860
44841
|
...target,
|
|
43861
44842
|
style: origin.cell?.style ?? null,
|
|
43862
|
-
format:
|
|
44843
|
+
format: originFormat ?? targetCell.format,
|
|
43863
44844
|
});
|
|
43864
44845
|
return;
|
|
43865
44846
|
}
|
|
@@ -50062,6 +51043,20 @@ css /* scss */ `
|
|
|
50062
51043
|
`;
|
|
50063
51044
|
class RippleEffect extends Component {
|
|
50064
51045
|
static template = "o-spreadsheet-RippleEffect";
|
|
51046
|
+
static props = {
|
|
51047
|
+
x: String,
|
|
51048
|
+
y: String,
|
|
51049
|
+
color: String,
|
|
51050
|
+
opacity: Number,
|
|
51051
|
+
duration: Number,
|
|
51052
|
+
width: Number,
|
|
51053
|
+
height: Number,
|
|
51054
|
+
offsetY: Number,
|
|
51055
|
+
offsetX: Number,
|
|
51056
|
+
allowOverflow: Boolean,
|
|
51057
|
+
onAnimationEnd: Function,
|
|
51058
|
+
style: String,
|
|
51059
|
+
};
|
|
50065
51060
|
rippleRef = useRef("ripple");
|
|
50066
51061
|
setup() {
|
|
50067
51062
|
let animation = undefined;
|
|
@@ -50097,22 +51092,23 @@ class RippleEffect extends Component {
|
|
|
50097
51092
|
});
|
|
50098
51093
|
}
|
|
50099
51094
|
}
|
|
50100
|
-
RippleEffect.props = {
|
|
50101
|
-
x: String,
|
|
50102
|
-
y: String,
|
|
50103
|
-
color: String,
|
|
50104
|
-
opacity: Number,
|
|
50105
|
-
duration: Number,
|
|
50106
|
-
width: Number,
|
|
50107
|
-
height: Number,
|
|
50108
|
-
offsetY: Number,
|
|
50109
|
-
offsetX: Number,
|
|
50110
|
-
allowOverflow: Boolean,
|
|
50111
|
-
onAnimationEnd: Function,
|
|
50112
|
-
style: String,
|
|
50113
|
-
};
|
|
50114
51095
|
class Ripple extends Component {
|
|
50115
51096
|
static template = "o-spreadsheet-Ripple";
|
|
51097
|
+
static props = {
|
|
51098
|
+
color: { type: String, optional: true },
|
|
51099
|
+
opacity: { type: Number, optional: true },
|
|
51100
|
+
duration: { type: Number, optional: true },
|
|
51101
|
+
ignoreClickPosition: { type: Boolean, optional: true },
|
|
51102
|
+
width: { type: Number, optional: true },
|
|
51103
|
+
height: { type: Number, optional: true },
|
|
51104
|
+
offsetY: { type: Number, optional: true },
|
|
51105
|
+
offsetX: { type: Number, optional: true },
|
|
51106
|
+
allowOverflow: { type: Boolean, optional: true },
|
|
51107
|
+
enabled: { type: Boolean, optional: true },
|
|
51108
|
+
onAnimationEnd: { type: Function, optional: true },
|
|
51109
|
+
slots: Object,
|
|
51110
|
+
class: { type: String, optional: true },
|
|
51111
|
+
};
|
|
50116
51112
|
static components = { RippleEffect };
|
|
50117
51113
|
static defaultProps = {
|
|
50118
51114
|
color: "#aaaaaa",
|
|
@@ -50198,21 +51194,6 @@ class Ripple extends Component {
|
|
|
50198
51194
|
};
|
|
50199
51195
|
}
|
|
50200
51196
|
}
|
|
50201
|
-
Ripple.props = {
|
|
50202
|
-
color: { type: String, optional: true },
|
|
50203
|
-
opacity: { type: Number, optional: true },
|
|
50204
|
-
duration: { type: Number, optional: true },
|
|
50205
|
-
ignoreClickPosition: { type: Boolean, optional: true },
|
|
50206
|
-
width: { type: Number, optional: true },
|
|
50207
|
-
height: { type: Number, optional: true },
|
|
50208
|
-
offsetY: { type: Number, optional: true },
|
|
50209
|
-
offsetX: { type: Number, optional: true },
|
|
50210
|
-
allowOverflow: { type: Boolean, optional: true },
|
|
50211
|
-
enabled: { type: Boolean, optional: true },
|
|
50212
|
-
onAnimationEnd: { type: Function, optional: true },
|
|
50213
|
-
slots: Object,
|
|
50214
|
-
class: { type: String, optional: true },
|
|
50215
|
-
};
|
|
50216
51197
|
|
|
50217
51198
|
function interactiveRenameSheet(env, sheetId, name, errorCallback) {
|
|
50218
51199
|
const result = env.model.dispatch("RENAME_SHEET", { sheetId, name });
|
|
@@ -50270,6 +51251,12 @@ css /* scss */ `
|
|
|
50270
51251
|
`;
|
|
50271
51252
|
class BottomBarSheet extends Component {
|
|
50272
51253
|
static template = "o-spreadsheet-BottomBarSheet";
|
|
51254
|
+
static props = {
|
|
51255
|
+
sheetId: String,
|
|
51256
|
+
openContextMenu: Function,
|
|
51257
|
+
style: { type: String, optional: true },
|
|
51258
|
+
onMouseDown: { type: Function, optional: true },
|
|
51259
|
+
};
|
|
50273
51260
|
static components = { Ripple };
|
|
50274
51261
|
static defaultProps = {
|
|
50275
51262
|
onMouseDown: () => { },
|
|
@@ -50391,12 +51378,6 @@ class BottomBarSheet extends Component {
|
|
|
50391
51378
|
return this.env.model.getters.getSheetName(this.props.sheetId);
|
|
50392
51379
|
}
|
|
50393
51380
|
}
|
|
50394
|
-
BottomBarSheet.props = {
|
|
50395
|
-
sheetId: String,
|
|
50396
|
-
openContextMenu: Function,
|
|
50397
|
-
style: { type: String, optional: true },
|
|
50398
|
-
onMouseDown: { type: Function, optional: true },
|
|
50399
|
-
};
|
|
50400
51381
|
|
|
50401
51382
|
// -----------------------------------------------------------------------------
|
|
50402
51383
|
// SpreadSheet
|
|
@@ -50414,6 +51395,10 @@ css /* scss */ `
|
|
|
50414
51395
|
`;
|
|
50415
51396
|
class BottomBarStatistic extends Component {
|
|
50416
51397
|
static template = "o-spreadsheet-BottomBarStatisic";
|
|
51398
|
+
static props = {
|
|
51399
|
+
openContextMenu: Function,
|
|
51400
|
+
closeContextMenu: Function,
|
|
51401
|
+
};
|
|
50417
51402
|
static components = { Ripple };
|
|
50418
51403
|
selectedStatisticFn = "";
|
|
50419
51404
|
statisticFnResults = {};
|
|
@@ -50460,10 +51445,6 @@ class BottomBarStatistic extends Component {
|
|
|
50460
51445
|
return fnName + ": " + (fnValue !== undefined ? formatValue(fnValue, { locale }) : "__");
|
|
50461
51446
|
}
|
|
50462
51447
|
}
|
|
50463
|
-
BottomBarStatistic.props = {
|
|
50464
|
-
openContextMenu: Function,
|
|
50465
|
-
closeContextMenu: Function,
|
|
50466
|
-
};
|
|
50467
51448
|
|
|
50468
51449
|
// -----------------------------------------------------------------------------
|
|
50469
51450
|
// SpreadSheet
|
|
@@ -50514,6 +51495,9 @@ css /* scss */ `
|
|
|
50514
51495
|
`;
|
|
50515
51496
|
class BottomBar extends Component {
|
|
50516
51497
|
static template = "o-spreadsheet-BottomBar";
|
|
51498
|
+
static props = {
|
|
51499
|
+
onClick: Function,
|
|
51500
|
+
};
|
|
50517
51501
|
static components = { Menu, Ripple, BottomBarSheet, BottomBarStatistic };
|
|
50518
51502
|
bottomBarRef = useRef("bottomBar");
|
|
50519
51503
|
sheetListRef = useRef("sheetList");
|
|
@@ -50699,9 +51683,6 @@ class BottomBar extends Component {
|
|
|
50699
51683
|
return this.sheetListRef.el.scrollWidth - this.sheetListRef.el.clientWidth;
|
|
50700
51684
|
}
|
|
50701
51685
|
}
|
|
50702
|
-
BottomBar.props = {
|
|
50703
|
-
onClick: Function,
|
|
50704
|
-
};
|
|
50705
51686
|
|
|
50706
51687
|
css /* scss */ `
|
|
50707
51688
|
.o-dashboard-clickable-cell {
|
|
@@ -50712,6 +51693,7 @@ css /* scss */ `
|
|
|
50712
51693
|
let tKey = 1;
|
|
50713
51694
|
class SpreadsheetDashboard extends Component {
|
|
50714
51695
|
static template = "o-spreadsheet-SpreadsheetDashboard";
|
|
51696
|
+
static props = {};
|
|
50715
51697
|
static components = {
|
|
50716
51698
|
GridOverlay,
|
|
50717
51699
|
GridPopover,
|
|
@@ -50830,7 +51812,6 @@ class SpreadsheetDashboard extends Component {
|
|
|
50830
51812
|
return { ...this.canvasPosition, ...this.env.model.getters.getSheetViewDimensionWithHeaders() };
|
|
50831
51813
|
}
|
|
50832
51814
|
}
|
|
50833
|
-
SpreadsheetDashboard.props = {};
|
|
50834
51815
|
|
|
50835
51816
|
css /* scss */ `
|
|
50836
51817
|
.o-header-group {
|
|
@@ -50858,6 +51839,11 @@ css /* scss */ `
|
|
|
50858
51839
|
`;
|
|
50859
51840
|
class AbstractHeaderGroup extends Component {
|
|
50860
51841
|
static template = "o-spreadsheet-HeaderGroup";
|
|
51842
|
+
static props = {
|
|
51843
|
+
group: Object,
|
|
51844
|
+
layerOffset: Number,
|
|
51845
|
+
openContextMenu: Function,
|
|
51846
|
+
};
|
|
50861
51847
|
toggleGroup() {
|
|
50862
51848
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
50863
51849
|
const { start, end } = this.props.group;
|
|
@@ -50894,11 +51880,6 @@ class AbstractHeaderGroup extends Component {
|
|
|
50894
51880
|
this.props.openContextMenu(position, menuItems);
|
|
50895
51881
|
}
|
|
50896
51882
|
}
|
|
50897
|
-
AbstractHeaderGroup.props = {
|
|
50898
|
-
group: Object,
|
|
50899
|
-
layerOffset: Number,
|
|
50900
|
-
openContextMenu: Function,
|
|
50901
|
-
};
|
|
50902
51883
|
class RowGroup extends AbstractHeaderGroup {
|
|
50903
51884
|
dimension = "ROW";
|
|
50904
51885
|
get groupBorderStyle() {
|
|
@@ -51029,6 +52010,10 @@ css /* scss */ `
|
|
|
51029
52010
|
`;
|
|
51030
52011
|
class HeaderGroupContainer extends Component {
|
|
51031
52012
|
static template = "o-spreadsheet-HeaderGroupContainer";
|
|
52013
|
+
static props = {
|
|
52014
|
+
dimension: String,
|
|
52015
|
+
layers: Array,
|
|
52016
|
+
};
|
|
51032
52017
|
static components = { RowGroup, ColGroup, Menu };
|
|
51033
52018
|
menu = useState({ isOpen: false, position: null, menuItems: [] });
|
|
51034
52019
|
getLayerOffset(layerIndex) {
|
|
@@ -51091,10 +52076,6 @@ class HeaderGroupContainer extends Component {
|
|
|
51091
52076
|
}
|
|
51092
52077
|
}
|
|
51093
52078
|
}
|
|
51094
|
-
HeaderGroupContainer.props = {
|
|
51095
|
-
dimension: String,
|
|
51096
|
-
layers: Array,
|
|
51097
|
-
};
|
|
51098
52079
|
|
|
51099
52080
|
css /* scss */ `
|
|
51100
52081
|
.o-sidePanel {
|
|
@@ -51205,14 +52186,6 @@ css /* scss */ `
|
|
|
51205
52186
|
text-align: left;
|
|
51206
52187
|
}
|
|
51207
52188
|
|
|
51208
|
-
.o-checkbox {
|
|
51209
|
-
display: flex;
|
|
51210
|
-
justify-items: center;
|
|
51211
|
-
input {
|
|
51212
|
-
margin-right: 5px;
|
|
51213
|
-
}
|
|
51214
|
-
}
|
|
51215
|
-
|
|
51216
52189
|
.o-inflection {
|
|
51217
52190
|
table {
|
|
51218
52191
|
table-layout: fixed;
|
|
@@ -51253,6 +52226,11 @@ css /* scss */ `
|
|
|
51253
52226
|
`;
|
|
51254
52227
|
class SidePanel extends Component {
|
|
51255
52228
|
static template = "o-spreadsheet-SidePanel";
|
|
52229
|
+
static props = {
|
|
52230
|
+
component: String,
|
|
52231
|
+
panelProps: { type: Object, optional: true },
|
|
52232
|
+
onCloseSidePanel: Function,
|
|
52233
|
+
};
|
|
51256
52234
|
state;
|
|
51257
52235
|
setup() {
|
|
51258
52236
|
this.state = useState({
|
|
@@ -51266,11 +52244,6 @@ class SidePanel extends Component {
|
|
|
51266
52244
|
: this.state.panel.title;
|
|
51267
52245
|
}
|
|
51268
52246
|
}
|
|
51269
|
-
SidePanel.props = {
|
|
51270
|
-
component: String,
|
|
51271
|
-
panelProps: { type: Object, optional: true },
|
|
51272
|
-
onCloseSidePanel: Function,
|
|
51273
|
-
};
|
|
51274
52247
|
|
|
51275
52248
|
css /* scss */ `
|
|
51276
52249
|
.o-menu-item-button {
|
|
@@ -51288,6 +52261,13 @@ css /* scss */ `
|
|
|
51288
52261
|
`;
|
|
51289
52262
|
class ActionButton extends Component {
|
|
51290
52263
|
static template = "o-spreadsheet-ActionButton";
|
|
52264
|
+
static props = {
|
|
52265
|
+
action: Object,
|
|
52266
|
+
hasTriangleDownIcon: { type: Boolean, optional: true },
|
|
52267
|
+
selectedColor: { type: String, optional: true },
|
|
52268
|
+
class: { type: String, optional: true },
|
|
52269
|
+
onClick: { type: Function, optional: true },
|
|
52270
|
+
};
|
|
51291
52271
|
actionButton = createAction(this.props.action);
|
|
51292
52272
|
setup() {
|
|
51293
52273
|
onWillUpdateProps((nextProps) => {
|
|
@@ -51330,13 +52310,6 @@ class ActionButton extends Component {
|
|
|
51330
52310
|
return "";
|
|
51331
52311
|
}
|
|
51332
52312
|
}
|
|
51333
|
-
ActionButton.props = {
|
|
51334
|
-
action: Object,
|
|
51335
|
-
hasTriangleDownIcon: { type: Boolean, optional: true },
|
|
51336
|
-
selectedColor: { type: String, optional: true },
|
|
51337
|
-
class: { type: String, optional: true },
|
|
51338
|
-
onClick: { type: Function, optional: true },
|
|
51339
|
-
};
|
|
51340
52313
|
|
|
51341
52314
|
/**
|
|
51342
52315
|
* List the available borders positions and the corresponding icons.
|
|
@@ -51433,6 +52406,17 @@ css /* scss */ `
|
|
|
51433
52406
|
`;
|
|
51434
52407
|
class BorderEditor extends Component {
|
|
51435
52408
|
static template = "o-spreadsheet-BorderEditor";
|
|
52409
|
+
static props = {
|
|
52410
|
+
class: { type: String, optional: true },
|
|
52411
|
+
currentBorderColor: { type: String, optional: false },
|
|
52412
|
+
currentBorderStyle: { type: String, optional: false },
|
|
52413
|
+
currentBorderPosition: { type: String, optional: true },
|
|
52414
|
+
onBorderColorPicked: Function,
|
|
52415
|
+
onBorderStylePicked: Function,
|
|
52416
|
+
onBorderPositionPicked: Function,
|
|
52417
|
+
maxHeight: { type: Number, optional: true },
|
|
52418
|
+
anchorRect: Object,
|
|
52419
|
+
};
|
|
51436
52420
|
static components = { ColorPickerWidget, Popover };
|
|
51437
52421
|
BORDER_POSITIONS = BORDER_POSITIONS;
|
|
51438
52422
|
lineStyleButtonRef = useRef("lineStyleButton");
|
|
@@ -51488,20 +52472,16 @@ class BorderEditor extends Component {
|
|
|
51488
52472
|
};
|
|
51489
52473
|
}
|
|
51490
52474
|
}
|
|
51491
|
-
BorderEditor.props = {
|
|
51492
|
-
class: { type: String, optional: true },
|
|
51493
|
-
currentBorderColor: { type: String, optional: false },
|
|
51494
|
-
currentBorderStyle: { type: String, optional: false },
|
|
51495
|
-
currentBorderPosition: { type: String, optional: true },
|
|
51496
|
-
onBorderColorPicked: Function,
|
|
51497
|
-
onBorderStylePicked: Function,
|
|
51498
|
-
onBorderPositionPicked: Function,
|
|
51499
|
-
maxHeight: { type: Number, optional: true },
|
|
51500
|
-
anchorRect: Object,
|
|
51501
|
-
};
|
|
51502
52475
|
|
|
51503
52476
|
class BorderEditorWidget extends Component {
|
|
51504
52477
|
static template = "o-spreadsheet-BorderEditorWidget";
|
|
52478
|
+
static props = {
|
|
52479
|
+
toggleBorderEditor: Function,
|
|
52480
|
+
showBorderEditor: Boolean,
|
|
52481
|
+
disabled: { type: Boolean, optional: true },
|
|
52482
|
+
dropdownMaxHeight: { type: Number, optional: true },
|
|
52483
|
+
class: { type: String, optional: true },
|
|
52484
|
+
};
|
|
51505
52485
|
static components = { BorderEditor };
|
|
51506
52486
|
borderEditorButtonRef = useRef("borderEditorButton");
|
|
51507
52487
|
state = useState({
|
|
@@ -51546,13 +52526,6 @@ class BorderEditorWidget extends Component {
|
|
|
51546
52526
|
});
|
|
51547
52527
|
}
|
|
51548
52528
|
}
|
|
51549
|
-
BorderEditorWidget.props = {
|
|
51550
|
-
toggleBorderEditor: Function,
|
|
51551
|
-
showBorderEditor: Boolean,
|
|
51552
|
-
disabled: { type: Boolean, optional: true },
|
|
51553
|
-
dropdownMaxHeight: { type: Number, optional: true },
|
|
51554
|
-
class: { type: String, optional: true },
|
|
51555
|
-
};
|
|
51556
52529
|
|
|
51557
52530
|
const COMPOSER_MAX_HEIGHT = 100;
|
|
51558
52531
|
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
@@ -51581,6 +52554,12 @@ css /* scss */ `
|
|
|
51581
52554
|
`;
|
|
51582
52555
|
class TopBarComposer extends Component {
|
|
51583
52556
|
static template = "o-spreadsheet-TopBarComposer";
|
|
52557
|
+
static props = {
|
|
52558
|
+
focus: {
|
|
52559
|
+
validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
|
|
52560
|
+
},
|
|
52561
|
+
onComposerContentFocused: Function,
|
|
52562
|
+
};
|
|
51584
52563
|
static components = { Composer };
|
|
51585
52564
|
get composerStyle() {
|
|
51586
52565
|
const style = {
|
|
@@ -51603,10 +52582,6 @@ class TopBarComposer extends Component {
|
|
|
51603
52582
|
});
|
|
51604
52583
|
}
|
|
51605
52584
|
}
|
|
51606
|
-
TopBarComposer.props = {
|
|
51607
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
51608
|
-
onComposerContentFocused: Function,
|
|
51609
|
-
};
|
|
51610
52585
|
|
|
51611
52586
|
css /* scss */ `
|
|
51612
52587
|
.o-font-size-editor {
|
|
@@ -51635,6 +52610,11 @@ css /* scss */ `
|
|
|
51635
52610
|
`;
|
|
51636
52611
|
class FontSizeEditor extends Component {
|
|
51637
52612
|
static template = "o-spreadsheet-FontSizeEditor";
|
|
52613
|
+
static props = {
|
|
52614
|
+
onToggle: Function,
|
|
52615
|
+
dropdownStyle: String,
|
|
52616
|
+
class: String,
|
|
52617
|
+
};
|
|
51638
52618
|
static components = {};
|
|
51639
52619
|
fontSizes = FONT_SIZES;
|
|
51640
52620
|
dropdown = useState({ isOpen: false });
|
|
@@ -51691,14 +52671,12 @@ class FontSizeEditor extends Component {
|
|
|
51691
52671
|
}
|
|
51692
52672
|
}
|
|
51693
52673
|
}
|
|
51694
|
-
FontSizeEditor.props = {
|
|
51695
|
-
onToggle: Function,
|
|
51696
|
-
dropdownStyle: String,
|
|
51697
|
-
class: String,
|
|
51698
|
-
};
|
|
51699
52674
|
|
|
51700
52675
|
class PaintFormatButton extends Component {
|
|
51701
52676
|
static template = "o-spreadsheet-PaintFormatButton";
|
|
52677
|
+
static props = {
|
|
52678
|
+
class: { type: String, optional: true },
|
|
52679
|
+
};
|
|
51702
52680
|
get isActive() {
|
|
51703
52681
|
return this.env.model.getters.isPaintingFormat();
|
|
51704
52682
|
}
|
|
@@ -51714,9 +52692,6 @@ class PaintFormatButton extends Component {
|
|
|
51714
52692
|
}
|
|
51715
52693
|
}
|
|
51716
52694
|
}
|
|
51717
|
-
PaintFormatButton.props = {
|
|
51718
|
-
class: { type: String, optional: true },
|
|
51719
|
-
};
|
|
51720
52695
|
|
|
51721
52696
|
// -----------------------------------------------------------------------------
|
|
51722
52697
|
// TopBar
|
|
@@ -51809,6 +52784,12 @@ css /* scss */ `
|
|
|
51809
52784
|
`;
|
|
51810
52785
|
class TopBar extends Component {
|
|
51811
52786
|
static template = "o-spreadsheet-TopBar";
|
|
52787
|
+
static props = {
|
|
52788
|
+
onClick: Function,
|
|
52789
|
+
focusComposer: String,
|
|
52790
|
+
onComposerContentFocused: Function,
|
|
52791
|
+
dropdownMaxHeight: Number,
|
|
52792
|
+
};
|
|
51812
52793
|
get dropdownStyle() {
|
|
51813
52794
|
return `max-height:${this.props.dropdownMaxHeight}px`;
|
|
51814
52795
|
}
|
|
@@ -51925,12 +52906,6 @@ class TopBar extends Component {
|
|
|
51925
52906
|
this.onClick();
|
|
51926
52907
|
}
|
|
51927
52908
|
}
|
|
51928
|
-
TopBar.props = {
|
|
51929
|
-
onClick: Function,
|
|
51930
|
-
focusComposer: String,
|
|
51931
|
-
onComposerContentFocused: Function,
|
|
51932
|
-
dropdownMaxHeight: Number,
|
|
51933
|
-
};
|
|
51934
52909
|
|
|
51935
52910
|
function instantiateClipboard() {
|
|
51936
52911
|
return new WebClipboardWrapper(navigator.clipboard);
|
|
@@ -52163,6 +53138,9 @@ css /* scss */ `
|
|
|
52163
53138
|
`;
|
|
52164
53139
|
class Spreadsheet extends Component {
|
|
52165
53140
|
static template = "o-spreadsheet-Spreadsheet";
|
|
53141
|
+
static props = {
|
|
53142
|
+
model: Object,
|
|
53143
|
+
};
|
|
52166
53144
|
static components = {
|
|
52167
53145
|
TopBar,
|
|
52168
53146
|
Grid,
|
|
@@ -52307,7 +53285,7 @@ class Spreadsheet extends Component {
|
|
|
52307
53285
|
}
|
|
52308
53286
|
onKeydown(ev) {
|
|
52309
53287
|
let keyDownString = "";
|
|
52310
|
-
if (ev
|
|
53288
|
+
if (isCtrlKey(ev)) {
|
|
52311
53289
|
keyDownString += "CTRL+";
|
|
52312
53290
|
}
|
|
52313
53291
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -52375,9 +53353,6 @@ class Spreadsheet extends Component {
|
|
|
52375
53353
|
return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
|
|
52376
53354
|
}
|
|
52377
53355
|
}
|
|
52378
|
-
Spreadsheet.props = {
|
|
52379
|
-
model: Object,
|
|
52380
|
-
};
|
|
52381
53356
|
|
|
52382
53357
|
class LocalTransportService {
|
|
52383
53358
|
listeners = [];
|
|
@@ -55044,7 +56019,8 @@ function addRows(construct, data, sheet) {
|
|
|
55044
56019
|
}
|
|
55045
56020
|
else if (cell.content && cell.content !== "") {
|
|
55046
56021
|
const isTableHeader = isCellTableHeader(c, r, sheet);
|
|
55047
|
-
|
|
56022
|
+
const isPlainText = !!(cell.format && data.formats[cell.format] === PLAIN_TEXT_FORMAT);
|
|
56023
|
+
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isPlainText));
|
|
55048
56024
|
}
|
|
55049
56025
|
attributes.push(...additionalAttrs);
|
|
55050
56026
|
cellNodes.push(escapeXml /*xml*/ `
|
|
@@ -55973,6 +56949,7 @@ const helpers = {
|
|
|
55973
56949
|
colorToRGBA,
|
|
55974
56950
|
positionToZone,
|
|
55975
56951
|
isDefined: isDefined$1,
|
|
56952
|
+
isMatrix,
|
|
55976
56953
|
lazy,
|
|
55977
56954
|
genericRepeat,
|
|
55978
56955
|
createAction,
|
|
@@ -56022,6 +56999,6 @@ const constants = {
|
|
|
56022
56999
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
56023
57000
|
|
|
56024
57001
|
|
|
56025
|
-
__info__.version = "17.1.0-alpha.
|
|
56026
|
-
__info__.date = "
|
|
56027
|
-
__info__.hash = "
|
|
57002
|
+
__info__.version = "17.1.0-alpha.7";
|
|
57003
|
+
__info__.date = "2024-01-12T13:45:00.505Z";
|
|
57004
|
+
__info__.hash = "cbce1ed";
|