@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
|
'use strict';
|
|
@@ -330,13 +330,6 @@ const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
|
|
|
330
330
|
//------------------------------------------------------------------------------
|
|
331
331
|
// Miscellaneous
|
|
332
332
|
//------------------------------------------------------------------------------
|
|
333
|
-
/**
|
|
334
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
335
|
-
* is ordered.
|
|
336
|
-
*/
|
|
337
|
-
function stringify(obj) {
|
|
338
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
339
|
-
}
|
|
340
333
|
/**
|
|
341
334
|
* Remove quotes from a quoted string
|
|
342
335
|
* ```js
|
|
@@ -559,7 +552,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
559
552
|
*/
|
|
560
553
|
function getItemId(item, itemsDic) {
|
|
561
554
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
562
|
-
if (
|
|
555
|
+
if (deepEquals(value, item)) {
|
|
563
556
|
return parseInt(key, 10);
|
|
564
557
|
}
|
|
565
558
|
}
|
|
@@ -1209,16 +1202,84 @@ function toXC(col, row, rangePart = { colFixed: false, rowFixed: false }) {
|
|
|
1209
1202
|
// -----------------------------------------------------------------------------
|
|
1210
1203
|
// Date Type
|
|
1211
1204
|
// -----------------------------------------------------------------------------
|
|
1205
|
+
/**
|
|
1206
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
1207
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
1208
|
+
* and it is timezone-agnostic.
|
|
1209
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
1210
|
+
*/
|
|
1211
|
+
class DateTime {
|
|
1212
|
+
jsDate;
|
|
1213
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
1214
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
1215
|
+
}
|
|
1216
|
+
static fromTimestamp(timestamp) {
|
|
1217
|
+
const date = new Date(timestamp);
|
|
1218
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
1219
|
+
}
|
|
1220
|
+
static now() {
|
|
1221
|
+
const now = new Date();
|
|
1222
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
1223
|
+
}
|
|
1224
|
+
toString() {
|
|
1225
|
+
return this.jsDate.toString();
|
|
1226
|
+
}
|
|
1227
|
+
toLocaleDateString() {
|
|
1228
|
+
return this.jsDate.toLocaleDateString();
|
|
1229
|
+
}
|
|
1230
|
+
getTime() {
|
|
1231
|
+
return this.jsDate.getTime();
|
|
1232
|
+
}
|
|
1233
|
+
getFullYear() {
|
|
1234
|
+
return this.jsDate.getUTCFullYear();
|
|
1235
|
+
}
|
|
1236
|
+
getMonth() {
|
|
1237
|
+
return this.jsDate.getUTCMonth();
|
|
1238
|
+
}
|
|
1239
|
+
getDate() {
|
|
1240
|
+
return this.jsDate.getUTCDate();
|
|
1241
|
+
}
|
|
1242
|
+
getDay() {
|
|
1243
|
+
return this.jsDate.getUTCDay();
|
|
1244
|
+
}
|
|
1245
|
+
getHours() {
|
|
1246
|
+
return this.jsDate.getUTCHours();
|
|
1247
|
+
}
|
|
1248
|
+
getMinutes() {
|
|
1249
|
+
return this.jsDate.getUTCMinutes();
|
|
1250
|
+
}
|
|
1251
|
+
getSeconds() {
|
|
1252
|
+
return this.jsDate.getUTCSeconds();
|
|
1253
|
+
}
|
|
1254
|
+
setFullYear(year) {
|
|
1255
|
+
return this.jsDate.setUTCFullYear(year);
|
|
1256
|
+
}
|
|
1257
|
+
setMonth(month) {
|
|
1258
|
+
return this.jsDate.setUTCMonth(month);
|
|
1259
|
+
}
|
|
1260
|
+
setDate(date) {
|
|
1261
|
+
return this.jsDate.setUTCDate(date);
|
|
1262
|
+
}
|
|
1263
|
+
setHours(hours) {
|
|
1264
|
+
return this.jsDate.setUTCHours(hours);
|
|
1265
|
+
}
|
|
1266
|
+
setMinutes(minutes) {
|
|
1267
|
+
return this.jsDate.setUTCMinutes(minutes);
|
|
1268
|
+
}
|
|
1269
|
+
setSeconds(seconds) {
|
|
1270
|
+
return this.jsDate.setUTCSeconds(seconds);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1212
1273
|
// -----------------------------------------------------------------------------
|
|
1213
1274
|
// Parsing
|
|
1214
1275
|
// -----------------------------------------------------------------------------
|
|
1215
|
-
const INITIAL_1900_DAY = new
|
|
1276
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
1216
1277
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
1217
1278
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
1218
|
-
const CURRENT_YEAR =
|
|
1219
|
-
const CURRENT_MONTH =
|
|
1220
|
-
const INITIAL_JS_DAY =
|
|
1221
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
1279
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
1280
|
+
const CURRENT_MONTH = DateTime.now().getMonth();
|
|
1281
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
1282
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
1222
1283
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
1223
1284
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
1224
1285
|
const dateSeparatorsRegex = /\/|-|\s/;
|
|
@@ -1279,7 +1340,7 @@ function _parseDateTime(str, locale) {
|
|
|
1279
1340
|
return {
|
|
1280
1341
|
value: date.value + time.value,
|
|
1281
1342
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
1282
|
-
jsDate: new
|
|
1343
|
+
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()),
|
|
1283
1344
|
};
|
|
1284
1345
|
}
|
|
1285
1346
|
return date || time;
|
|
@@ -1355,12 +1416,12 @@ function parseDate(parts, separator) {
|
|
|
1355
1416
|
// month + 1: months are 0-indexed in JS
|
|
1356
1417
|
const leadingZero = (monthStr?.length === 2 && month + 1 < 10) || (dayStr?.length === 2 && day < 10);
|
|
1357
1418
|
const fullYear = yearStr?.length !== 2;
|
|
1358
|
-
const jsDate = new
|
|
1419
|
+
const jsDate = new DateTime(year, month, day);
|
|
1359
1420
|
if (jsDate.getMonth() !== month || jsDate.getDate() !== day) {
|
|
1360
1421
|
// invalid date
|
|
1361
1422
|
return null;
|
|
1362
1423
|
}
|
|
1363
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
1424
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
1364
1425
|
const format = getFormatFromDateParts(parts, separator, leadingZero, fullYear);
|
|
1365
1426
|
return {
|
|
1366
1427
|
value: Math.round(delta / MS_PER_DAY),
|
|
@@ -1451,7 +1512,7 @@ function parseTime(str) {
|
|
|
1451
1512
|
if (hours >= 24) {
|
|
1452
1513
|
format = "hhhh:mm:ss";
|
|
1453
1514
|
}
|
|
1454
|
-
const jsDate = new
|
|
1515
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
1455
1516
|
return {
|
|
1456
1517
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
1457
1518
|
format: format,
|
|
@@ -1465,7 +1526,7 @@ function parseTime(str) {
|
|
|
1465
1526
|
// -----------------------------------------------------------------------------
|
|
1466
1527
|
function numberToJsDate(value) {
|
|
1467
1528
|
const truncValue = Math.trunc(value);
|
|
1468
|
-
let date =
|
|
1529
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
1469
1530
|
let time = value - truncValue;
|
|
1470
1531
|
time = time < 0 ? 1 + time : time;
|
|
1471
1532
|
const hours = Math.round(time * 24);
|
|
@@ -1485,7 +1546,7 @@ function jsDateToNumber(date) {
|
|
|
1485
1546
|
}
|
|
1486
1547
|
/** Return the number of days in the current month of the given date */
|
|
1487
1548
|
function getDaysInMonth(date) {
|
|
1488
|
-
return new
|
|
1549
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
1489
1550
|
}
|
|
1490
1551
|
function isLastDayOfMonth(date) {
|
|
1491
1552
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -1503,7 +1564,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
1503
1564
|
const yStart = date.getFullYear();
|
|
1504
1565
|
const mStart = date.getMonth();
|
|
1505
1566
|
const dStart = date.getDate();
|
|
1506
|
-
const jsDate = new
|
|
1567
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
1507
1568
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
1508
1569
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
1509
1570
|
}
|
|
@@ -2062,6 +2123,8 @@ exports.CommandResult = void 0;
|
|
|
2062
2123
|
CommandResult["NoChanges"] = "NoChanges";
|
|
2063
2124
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
2064
2125
|
|
|
2126
|
+
const PLAIN_TEXT_FORMAT = "@"; // see OpenXML spec §18.8.31
|
|
2127
|
+
|
|
2065
2128
|
const DEFAULT_LOCALES = [
|
|
2066
2129
|
{
|
|
2067
2130
|
name: "English (US)",
|
|
@@ -2726,20 +2789,20 @@ function flattenRowFirst(items, callback) {
|
|
|
2726
2789
|
}
|
|
2727
2790
|
|
|
2728
2791
|
function toCriterionDateNumber(dateValue) {
|
|
2729
|
-
const today =
|
|
2792
|
+
const today = DateTime.now();
|
|
2730
2793
|
switch (dateValue) {
|
|
2731
2794
|
case "today":
|
|
2732
2795
|
return jsDateToNumber(today);
|
|
2733
2796
|
case "yesterday":
|
|
2734
|
-
return jsDateToNumber(
|
|
2797
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
|
|
2735
2798
|
case "tomorrow":
|
|
2736
|
-
return jsDateToNumber(
|
|
2799
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
|
|
2737
2800
|
case "lastWeek":
|
|
2738
|
-
return jsDateToNumber(
|
|
2801
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
|
|
2739
2802
|
case "lastMonth":
|
|
2740
|
-
return jsDateToNumber(
|
|
2803
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
|
|
2741
2804
|
case "lastYear":
|
|
2742
|
-
return jsDateToNumber(
|
|
2805
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
|
|
2743
2806
|
}
|
|
2744
2807
|
}
|
|
2745
2808
|
/** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
|
|
@@ -2825,6 +2888,9 @@ function parseFormat(formatString) {
|
|
|
2825
2888
|
* Formats a cell value with its format.
|
|
2826
2889
|
*/
|
|
2827
2890
|
function formatValue(value, { format, locale }) {
|
|
2891
|
+
if (format === PLAIN_TEXT_FORMAT) {
|
|
2892
|
+
return toString(value) || "";
|
|
2893
|
+
}
|
|
2828
2894
|
switch (typeof value) {
|
|
2829
2895
|
case "string":
|
|
2830
2896
|
return value;
|
|
@@ -3097,7 +3163,7 @@ function formatJSTime(jsDate, format) {
|
|
|
3097
3163
|
.map((p) => {
|
|
3098
3164
|
switch (p) {
|
|
3099
3165
|
case "hhhh":
|
|
3100
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
3166
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
3101
3167
|
return helapsedHours.toString();
|
|
3102
3168
|
case "hh":
|
|
3103
3169
|
return hours.toString().padStart(2, "0");
|
|
@@ -4665,6 +4731,9 @@ function transformRangeData(range, executed) {
|
|
|
4665
4731
|
|
|
4666
4732
|
class ChartJsComponent extends owl.Component {
|
|
4667
4733
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
4734
|
+
static props = {
|
|
4735
|
+
figure: Object,
|
|
4736
|
+
};
|
|
4668
4737
|
canvas = owl.useRef("graphContainer");
|
|
4669
4738
|
chart;
|
|
4670
4739
|
get background() {
|
|
@@ -4717,9 +4786,6 @@ class ChartJsComponent extends owl.Component {
|
|
|
4717
4786
|
this.chart.update("active");
|
|
4718
4787
|
}
|
|
4719
4788
|
}
|
|
4720
|
-
ChartJsComponent.props = {
|
|
4721
|
-
figure: Object,
|
|
4722
|
-
};
|
|
4723
4789
|
|
|
4724
4790
|
/**
|
|
4725
4791
|
* AbstractChart is the class from which every Chart should inherit.
|
|
@@ -5296,7 +5362,7 @@ function createScorecardChartRuntime(chart, getters) {
|
|
|
5296
5362
|
};
|
|
5297
5363
|
baselineCell = getters.getEvaluatedCell(baselinePosition);
|
|
5298
5364
|
}
|
|
5299
|
-
const background = getters.
|
|
5365
|
+
const { background, fontColor } = getters.getStyleOfSingleCellChart(chart.background, chart.keyValue);
|
|
5300
5366
|
const locale = getters.getLocale();
|
|
5301
5367
|
return {
|
|
5302
5368
|
title: _t(chart.title),
|
|
@@ -5305,7 +5371,7 @@ function createScorecardChartRuntime(chart, getters) {
|
|
|
5305
5371
|
baselineArrow: getBaselineArrowDirection(baselineCell, keyValueCell, chart.baselineMode),
|
|
5306
5372
|
baselineColor: getBaselineColor(baselineCell, chart.baselineMode, keyValueCell, chart.baselineColorUp, chart.baselineColorDown),
|
|
5307
5373
|
baselineDescr: chart.baselineDescr ? _t(chart.baselineDescr) : "",
|
|
5308
|
-
fontColor
|
|
5374
|
+
fontColor,
|
|
5309
5375
|
background,
|
|
5310
5376
|
baselineStyle: chart.baselineMode !== "percentage" && baseline
|
|
5311
5377
|
? getters.getCellStyle({
|
|
@@ -5570,6 +5636,9 @@ class KeyValueElement extends ScorecardScalableElement {
|
|
|
5570
5636
|
|
|
5571
5637
|
class ScorecardChart extends owl.Component {
|
|
5572
5638
|
static template = "o-spreadsheet-ScorecardChart";
|
|
5639
|
+
static props = {
|
|
5640
|
+
figure: Object,
|
|
5641
|
+
};
|
|
5573
5642
|
canvas = owl.useRef("chartContainer");
|
|
5574
5643
|
get runtime() {
|
|
5575
5644
|
return this.env.model.getters.getChartRuntime(this.props.figure.id);
|
|
@@ -5587,9 +5656,6 @@ class ScorecardChart extends owl.Component {
|
|
|
5587
5656
|
drawScoreChart(config, canvas);
|
|
5588
5657
|
}
|
|
5589
5658
|
}
|
|
5590
|
-
ScorecardChart.props = {
|
|
5591
|
-
figure: Object,
|
|
5592
|
-
};
|
|
5593
5659
|
|
|
5594
5660
|
/**
|
|
5595
5661
|
* Registry
|
|
@@ -5731,6 +5797,9 @@ function detectLink(value) {
|
|
|
5731
5797
|
}
|
|
5732
5798
|
|
|
5733
5799
|
function evaluateLiteral(content, localeFormat) {
|
|
5800
|
+
if (localeFormat.format === PLAIN_TEXT_FORMAT) {
|
|
5801
|
+
return textCell(content || "", localeFormat);
|
|
5802
|
+
}
|
|
5734
5803
|
return createEvaluatedCell(parseLiteral(content || "", localeFormat.locale), localeFormat);
|
|
5735
5804
|
}
|
|
5736
5805
|
function parseLiteral(content, locale) {
|
|
@@ -5765,6 +5834,9 @@ function createEvaluatedCell(value, localeFormat) {
|
|
|
5765
5834
|
}
|
|
5766
5835
|
function _createEvaluatedCell(value, localeFormat) {
|
|
5767
5836
|
try {
|
|
5837
|
+
if (localeFormat.format === PLAIN_TEXT_FORMAT) {
|
|
5838
|
+
return textCell(toString(value), localeFormat);
|
|
5839
|
+
}
|
|
5768
5840
|
for (const builder of builders) {
|
|
5769
5841
|
const evaluateCell = builder(value, localeFormat);
|
|
5770
5842
|
if (evaluateCell) {
|
|
@@ -6262,11 +6334,11 @@ css /* scss */ `
|
|
|
6262
6334
|
class ErrorToolTip extends owl.Component {
|
|
6263
6335
|
static maxSize = { maxHeight: ERROR_TOOLTIP_MAX_HEIGHT };
|
|
6264
6336
|
static template = "o-spreadsheet-ErrorToolTip";
|
|
6337
|
+
static props = {
|
|
6338
|
+
errors: Array,
|
|
6339
|
+
onClosed: { type: Function, optional: true },
|
|
6340
|
+
};
|
|
6265
6341
|
}
|
|
6266
|
-
ErrorToolTip.props = {
|
|
6267
|
-
errors: Array,
|
|
6268
|
-
onClosed: { type: Function, optional: true },
|
|
6269
|
-
};
|
|
6270
6342
|
const ErrorToolTipPopoverBuilder = {
|
|
6271
6343
|
onHover: (position, getters) => {
|
|
6272
6344
|
const cell = getters.getEvaluatedCell(position);
|
|
@@ -6308,6 +6380,14 @@ css /*SCSS*/ `
|
|
|
6308
6380
|
`;
|
|
6309
6381
|
class FilterMenuValueItem extends owl.Component {
|
|
6310
6382
|
static template = "o-spreadsheet-FilterMenuValueItem";
|
|
6383
|
+
static props = {
|
|
6384
|
+
value: String,
|
|
6385
|
+
isChecked: Boolean,
|
|
6386
|
+
isSelected: Boolean,
|
|
6387
|
+
onMouseMove: Function,
|
|
6388
|
+
onClick: Function,
|
|
6389
|
+
scrolledTo: { type: String, optional: true },
|
|
6390
|
+
};
|
|
6311
6391
|
itemRef = owl.useRef("menuValueItem");
|
|
6312
6392
|
setup() {
|
|
6313
6393
|
owl.onWillPatch(() => {
|
|
@@ -6325,17 +6405,9 @@ class FilterMenuValueItem extends owl.Component {
|
|
|
6325
6405
|
});
|
|
6326
6406
|
}
|
|
6327
6407
|
}
|
|
6328
|
-
FilterMenuValueItem.props = {
|
|
6329
|
-
value: String,
|
|
6330
|
-
isChecked: Boolean,
|
|
6331
|
-
isSelected: Boolean,
|
|
6332
|
-
onMouseMove: Function,
|
|
6333
|
-
onClick: Function,
|
|
6334
|
-
scrolledTo: { type: String, optional: true },
|
|
6335
|
-
};
|
|
6336
6408
|
|
|
6337
6409
|
const FILTER_MENU_HEIGHT = 295;
|
|
6338
|
-
const CSS
|
|
6410
|
+
const CSS = css /* scss */ `
|
|
6339
6411
|
.o-filter-menu {
|
|
6340
6412
|
box-sizing: border-box;
|
|
6341
6413
|
padding: 8px 16px;
|
|
@@ -6431,9 +6503,12 @@ const CSS$2 = css /* scss */ `
|
|
|
6431
6503
|
}
|
|
6432
6504
|
`;
|
|
6433
6505
|
class FilterMenu extends owl.Component {
|
|
6434
|
-
static size = { width: MENU_WIDTH, height: FILTER_MENU_HEIGHT };
|
|
6435
6506
|
static template = "o-spreadsheet-FilterMenu";
|
|
6436
|
-
static
|
|
6507
|
+
static props = {
|
|
6508
|
+
filterPosition: Object,
|
|
6509
|
+
onClosed: { type: Function, optional: true },
|
|
6510
|
+
};
|
|
6511
|
+
static style = CSS;
|
|
6437
6512
|
static components = { FilterMenuValueItem };
|
|
6438
6513
|
state = owl.useState({
|
|
6439
6514
|
values: [],
|
|
@@ -6585,10 +6660,6 @@ class FilterMenu extends owl.Component {
|
|
|
6585
6660
|
this.props.onClosed?.();
|
|
6586
6661
|
}
|
|
6587
6662
|
}
|
|
6588
|
-
FilterMenu.props = {
|
|
6589
|
-
filterPosition: Object,
|
|
6590
|
-
onClosed: { type: Function, optional: true },
|
|
6591
|
-
};
|
|
6592
6663
|
const FilterMenuPopoverBuilder = {
|
|
6593
6664
|
onOpen: (position, getters) => {
|
|
6594
6665
|
return {
|
|
@@ -6600,6 +6671,7 @@ const FilterMenuPopoverBuilder = {
|
|
|
6600
6671
|
},
|
|
6601
6672
|
};
|
|
6602
6673
|
|
|
6674
|
+
const macRegex = /Mac/i;
|
|
6603
6675
|
/**
|
|
6604
6676
|
* Return true if the event was triggered from
|
|
6605
6677
|
* a child element.
|
|
@@ -6651,7 +6723,7 @@ const letterRegex = /^[a-zA-Z]$/;
|
|
|
6651
6723
|
*/
|
|
6652
6724
|
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
6653
6725
|
let keyDownString = "";
|
|
6654
|
-
if (ev
|
|
6726
|
+
if (isCtrlKey(ev) && ev.key !== "Ctrl")
|
|
6655
6727
|
keyDownString += "Ctrl+";
|
|
6656
6728
|
if (ev.metaKey)
|
|
6657
6729
|
keyDownString += "Ctrl+";
|
|
@@ -6664,7 +6736,15 @@ function keyboardEventToShortcutString(ev, mode = "key") {
|
|
|
6664
6736
|
return keyDownString;
|
|
6665
6737
|
}
|
|
6666
6738
|
function isMacOS() {
|
|
6667
|
-
return navigator.userAgent
|
|
6739
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
6740
|
+
}
|
|
6741
|
+
/**
|
|
6742
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
6743
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
6744
|
+
* On Mac, this is the "meta" or "command" key.
|
|
6745
|
+
*/
|
|
6746
|
+
function isCtrlKey(ev) {
|
|
6747
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
6668
6748
|
}
|
|
6669
6749
|
|
|
6670
6750
|
/**
|
|
@@ -6781,6 +6861,19 @@ css /* scss */ `
|
|
|
6781
6861
|
`;
|
|
6782
6862
|
class Popover extends owl.Component {
|
|
6783
6863
|
static template = "o-spreadsheet-Popover";
|
|
6864
|
+
static props = {
|
|
6865
|
+
anchorRect: Object,
|
|
6866
|
+
containerRect: { type: Object, optional: true },
|
|
6867
|
+
positioning: { type: String, optional: true },
|
|
6868
|
+
maxWidth: { type: Number, optional: true },
|
|
6869
|
+
maxHeight: { type: Number, optional: true },
|
|
6870
|
+
verticalOffset: { type: Number, optional: true },
|
|
6871
|
+
onMouseWheel: { type: Function, optional: true },
|
|
6872
|
+
onPopoverHidden: { type: Function, optional: true },
|
|
6873
|
+
onPopoverMoved: { type: Function, optional: true },
|
|
6874
|
+
zIndex: { type: Number, optional: true },
|
|
6875
|
+
slots: Object,
|
|
6876
|
+
};
|
|
6784
6877
|
static defaultProps = {
|
|
6785
6878
|
positioning: "BottomLeft",
|
|
6786
6879
|
verticalOffset: 0,
|
|
@@ -6837,19 +6930,6 @@ class Popover extends owl.Component {
|
|
|
6837
6930
|
});
|
|
6838
6931
|
}
|
|
6839
6932
|
}
|
|
6840
|
-
Popover.props = {
|
|
6841
|
-
anchorRect: Object,
|
|
6842
|
-
containerRect: { type: Object, optional: true },
|
|
6843
|
-
positioning: { type: String, optional: true },
|
|
6844
|
-
maxWidth: { type: Number, optional: true },
|
|
6845
|
-
maxHeight: { type: Number, optional: true },
|
|
6846
|
-
verticalOffset: { type: Number, optional: true },
|
|
6847
|
-
onMouseWheel: { type: Function, optional: true },
|
|
6848
|
-
onPopoverHidden: { type: Function, optional: true },
|
|
6849
|
-
onPopoverMoved: { type: Function, optional: true },
|
|
6850
|
-
zIndex: { type: Number, optional: true },
|
|
6851
|
-
slots: Object,
|
|
6852
|
-
};
|
|
6853
6933
|
class PopoverPositionContext {
|
|
6854
6934
|
anchorRect;
|
|
6855
6935
|
containerRect;
|
|
@@ -7031,6 +7111,15 @@ css /* scss */ `
|
|
|
7031
7111
|
`;
|
|
7032
7112
|
class Menu extends owl.Component {
|
|
7033
7113
|
static template = "o-spreadsheet-Menu";
|
|
7114
|
+
static props = {
|
|
7115
|
+
position: Object,
|
|
7116
|
+
menuItems: Array,
|
|
7117
|
+
depth: { type: Number, optional: true },
|
|
7118
|
+
maxHeight: { type: Number, optional: true },
|
|
7119
|
+
onClose: Function,
|
|
7120
|
+
onMenuClicked: { type: Function, optional: true },
|
|
7121
|
+
menuId: { type: String, optional: true },
|
|
7122
|
+
};
|
|
7034
7123
|
static components = { Menu, Popover };
|
|
7035
7124
|
static defaultProps = {
|
|
7036
7125
|
depth: 1,
|
|
@@ -7187,15 +7276,6 @@ class Menu extends owl.Component {
|
|
|
7187
7276
|
}
|
|
7188
7277
|
}
|
|
7189
7278
|
}
|
|
7190
|
-
Menu.props = {
|
|
7191
|
-
position: Object,
|
|
7192
|
-
menuItems: Array,
|
|
7193
|
-
depth: { type: Number, optional: true },
|
|
7194
|
-
maxHeight: { type: Number, optional: true },
|
|
7195
|
-
onClose: Function,
|
|
7196
|
-
onMenuClicked: { type: Function, optional: true },
|
|
7197
|
-
menuId: { type: String, optional: true },
|
|
7198
|
-
};
|
|
7199
7279
|
|
|
7200
7280
|
const LINK_TOOLTIP_HEIGHT = 32;
|
|
7201
7281
|
const LINK_TOOLTIP_WIDTH = 220;
|
|
@@ -7248,8 +7328,12 @@ css /* scss */ `
|
|
|
7248
7328
|
}
|
|
7249
7329
|
`;
|
|
7250
7330
|
class LinkDisplay extends owl.Component {
|
|
7251
|
-
static components = { Menu };
|
|
7252
7331
|
static template = "o-spreadsheet-LinkDisplay";
|
|
7332
|
+
static props = {
|
|
7333
|
+
cellPosition: Object,
|
|
7334
|
+
onClosed: { type: Function, optional: true },
|
|
7335
|
+
};
|
|
7336
|
+
static components = { Menu };
|
|
7253
7337
|
get cell() {
|
|
7254
7338
|
const { col, row } = this.props.cellPosition;
|
|
7255
7339
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -7304,10 +7388,6 @@ const LinkCellPopoverBuilder = {
|
|
|
7304
7388
|
};
|
|
7305
7389
|
},
|
|
7306
7390
|
};
|
|
7307
|
-
LinkDisplay.props = {
|
|
7308
|
-
cellPosition: Object,
|
|
7309
|
-
onClosed: { type: Function, optional: true },
|
|
7310
|
-
};
|
|
7311
7391
|
|
|
7312
7392
|
/**
|
|
7313
7393
|
* Tokenizer
|
|
@@ -7941,6 +8021,10 @@ css /* scss */ `
|
|
|
7941
8021
|
`;
|
|
7942
8022
|
class LinkEditor extends owl.Component {
|
|
7943
8023
|
static template = "o-spreadsheet-LinkEditor";
|
|
8024
|
+
static props = {
|
|
8025
|
+
cellPosition: Object,
|
|
8026
|
+
onClosed: { type: Function, optional: true },
|
|
8027
|
+
};
|
|
7944
8028
|
static components = { Menu };
|
|
7945
8029
|
menuItems = linkMenuRegistry.getMenuItems();
|
|
7946
8030
|
link = owl.useState(this.defaultState);
|
|
@@ -8038,10 +8122,6 @@ const LinkEditorPopoverBuilder = {
|
|
|
8038
8122
|
};
|
|
8039
8123
|
},
|
|
8040
8124
|
};
|
|
8041
|
-
LinkEditor.props = {
|
|
8042
|
-
cellPosition: Object,
|
|
8043
|
-
onClosed: { type: Function, optional: true },
|
|
8044
|
-
};
|
|
8045
8125
|
|
|
8046
8126
|
const cellPopoverRegistry = new Registry();
|
|
8047
8127
|
cellPopoverRegistry
|
|
@@ -8324,6 +8404,7 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale })
|
|
|
8324
8404
|
labels: labels.map(truncateLabel),
|
|
8325
8405
|
datasets: [],
|
|
8326
8406
|
},
|
|
8407
|
+
platform: undefined,
|
|
8327
8408
|
plugins: [],
|
|
8328
8409
|
};
|
|
8329
8410
|
}
|
|
@@ -8903,7 +8984,7 @@ function createGaugeChartRuntime(chart, getters) {
|
|
|
8903
8984
|
});
|
|
8904
8985
|
return {
|
|
8905
8986
|
chartJsConfig: config,
|
|
8906
|
-
background: getters.
|
|
8987
|
+
background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
|
|
8907
8988
|
};
|
|
8908
8989
|
}
|
|
8909
8990
|
|
|
@@ -8984,7 +9065,7 @@ function getFormatMinDisplayUnit(format) {
|
|
|
8984
9065
|
else if (format.includes("h") || format.includes("H")) {
|
|
8985
9066
|
return "hour";
|
|
8986
9067
|
}
|
|
8987
|
-
else if (format.includes("
|
|
9068
|
+
else if (format.includes("d")) {
|
|
8988
9069
|
return "day";
|
|
8989
9070
|
}
|
|
8990
9071
|
else if (format.includes("M")) {
|
|
@@ -9496,6 +9577,27 @@ function calculatePercentage(dataset, dataIndex) {
|
|
|
9496
9577
|
const percentage = (dataset[dataIndex] / total) * 100;
|
|
9497
9578
|
return percentage.toFixed(2);
|
|
9498
9579
|
}
|
|
9580
|
+
function filterNegativeValues(labels, datasets) {
|
|
9581
|
+
const dataPointsIndexes = labels.reduce((indexes, label, i) => {
|
|
9582
|
+
const shouldKeep = datasets.some((dataset) => {
|
|
9583
|
+
const dataPoint = dataset.data[i];
|
|
9584
|
+
return typeof dataPoint !== "number" || dataPoint >= 0;
|
|
9585
|
+
});
|
|
9586
|
+
if (shouldKeep) {
|
|
9587
|
+
indexes.push(i);
|
|
9588
|
+
}
|
|
9589
|
+
return indexes;
|
|
9590
|
+
}, []);
|
|
9591
|
+
const filteredLabels = dataPointsIndexes.map((i) => labels[i] || "");
|
|
9592
|
+
const filteredDatasets = datasets.map((dataset) => ({
|
|
9593
|
+
...dataset,
|
|
9594
|
+
data: dataPointsIndexes.map((i) => {
|
|
9595
|
+
const dataPoint = dataset.data[i];
|
|
9596
|
+
return typeof dataPoint !== "number" || dataPoint >= 0 ? dataPoint : 0;
|
|
9597
|
+
}),
|
|
9598
|
+
}));
|
|
9599
|
+
return { labels: filteredLabels, dataSetsValues: filteredDatasets };
|
|
9600
|
+
}
|
|
9499
9601
|
function createPieChartRuntime(chart, getters) {
|
|
9500
9602
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
9501
9603
|
let labels = labelValues.formattedValues;
|
|
@@ -9509,6 +9611,7 @@ function createPieChartRuntime(chart, getters) {
|
|
|
9509
9611
|
if (chart.aggregated) {
|
|
9510
9612
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
9511
9613
|
}
|
|
9614
|
+
({ dataSetsValues, labels } = filterNegativeValues(labels, dataSetsValues));
|
|
9512
9615
|
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
9513
9616
|
const locale = getters.getLocale();
|
|
9514
9617
|
const config = getPieConfiguration(chart, labels, { format: dataSetFormat, locale });
|
|
@@ -9606,6 +9709,10 @@ css /* scss */ `
|
|
|
9606
9709
|
`;
|
|
9607
9710
|
class ChartFigure extends owl.Component {
|
|
9608
9711
|
static template = "o-spreadsheet-ChartFigure";
|
|
9712
|
+
static props = {
|
|
9713
|
+
figure: Object,
|
|
9714
|
+
onFigureDeleted: Function,
|
|
9715
|
+
};
|
|
9609
9716
|
static components = {};
|
|
9610
9717
|
onDoubleClick() {
|
|
9611
9718
|
this.env.model.dispatch("SELECT_FIGURE", { id: this.props.figure.id });
|
|
@@ -9623,13 +9730,13 @@ class ChartFigure extends owl.Component {
|
|
|
9623
9730
|
return component;
|
|
9624
9731
|
}
|
|
9625
9732
|
}
|
|
9626
|
-
ChartFigure.props = {
|
|
9627
|
-
figure: Object,
|
|
9628
|
-
onFigureDeleted: Function,
|
|
9629
|
-
};
|
|
9630
9733
|
|
|
9631
9734
|
class ImageFigure extends owl.Component {
|
|
9632
9735
|
static template = "o-spreadsheet-ImageFigure";
|
|
9736
|
+
static props = {
|
|
9737
|
+
figure: Object,
|
|
9738
|
+
onFigureDeleted: Function,
|
|
9739
|
+
};
|
|
9633
9740
|
static components = {};
|
|
9634
9741
|
// ---------------------------------------------------------------------------
|
|
9635
9742
|
// Getters
|
|
@@ -9641,10 +9748,6 @@ class ImageFigure extends owl.Component {
|
|
|
9641
9748
|
return this.env.model.getters.getImagePath(this.figureId);
|
|
9642
9749
|
}
|
|
9643
9750
|
}
|
|
9644
|
-
ImageFigure.props = {
|
|
9645
|
-
figure: Object,
|
|
9646
|
-
onFigureDeleted: Function,
|
|
9647
|
-
};
|
|
9648
9751
|
|
|
9649
9752
|
function centerFigurePosition(getters, size) {
|
|
9650
9753
|
const { x: offsetCorrectionX, y: offsetCorrectionY } = getters.getMainViewportCoordinates();
|
|
@@ -10346,7 +10449,7 @@ function setStyle(env, style) {
|
|
|
10346
10449
|
// Simple actions
|
|
10347
10450
|
//------------------------------------------------------------------------------
|
|
10348
10451
|
const PASTE_ACTION = async (env) => paste$1(env);
|
|
10349
|
-
const
|
|
10452
|
+
const PASTE_AS_VALUE_ACTION = async (env) => paste$1(env, "asValue");
|
|
10350
10453
|
async function paste$1(env, pasteOption) {
|
|
10351
10454
|
const spreadsheetClipboard = env.model.getters.getClipboardTextContent();
|
|
10352
10455
|
const osClipboard = await env.clipboard.readText();
|
|
@@ -10359,7 +10462,7 @@ async function paste$1(env, pasteOption) {
|
|
|
10359
10462
|
else {
|
|
10360
10463
|
interactivePaste(env, target, pasteOption);
|
|
10361
10464
|
}
|
|
10362
|
-
if (env.model.getters.isCutOperation() && pasteOption !== "
|
|
10465
|
+
if (env.model.getters.isCutOperation() && pasteOption !== "asValue") {
|
|
10363
10466
|
await env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
10364
10467
|
}
|
|
10365
10468
|
break;
|
|
@@ -10774,9 +10877,9 @@ const pasteSpecial = {
|
|
|
10774
10877
|
icon: "o-spreadsheet-Icon.PASTE",
|
|
10775
10878
|
};
|
|
10776
10879
|
const pasteSpecialValue = {
|
|
10777
|
-
name: _t("Paste value
|
|
10880
|
+
name: _t("Paste as value"),
|
|
10778
10881
|
description: "Ctrl+Shift+V",
|
|
10779
|
-
execute:
|
|
10882
|
+
execute: PASTE_AS_VALUE_ACTION,
|
|
10780
10883
|
};
|
|
10781
10884
|
const pasteSpecialFormat = {
|
|
10782
10885
|
name: _t("Paste format only"),
|
|
@@ -10932,6 +11035,9 @@ function arg(definition, description = "") {
|
|
|
10932
11035
|
function makeArg(str, description) {
|
|
10933
11036
|
let parts = str.match(ARG_REGEXP);
|
|
10934
11037
|
let name = parts[1].trim();
|
|
11038
|
+
if (!name) {
|
|
11039
|
+
throw new Error(`Function argument definition is missing a name: '${str}'.`);
|
|
11040
|
+
}
|
|
10935
11041
|
let types = [];
|
|
10936
11042
|
let isOptional = false;
|
|
10937
11043
|
let isRepeating = false;
|
|
@@ -14654,7 +14760,7 @@ const DATE = {
|
|
|
14654
14760
|
if (_year < 1900) {
|
|
14655
14761
|
_year += 1900;
|
|
14656
14762
|
}
|
|
14657
|
-
const jsDate = new
|
|
14763
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
14658
14764
|
const result = jsDateToRoundNumber(jsDate);
|
|
14659
14765
|
assert(() => result >= 0, _t("The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900."));
|
|
14660
14766
|
return result;
|
|
@@ -14697,7 +14803,7 @@ const DATEDIF = {
|
|
|
14697
14803
|
// See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
|
|
14698
14804
|
let days = jsEndDate.getDate() - jsStartDate.getDate();
|
|
14699
14805
|
if (days < 0) {
|
|
14700
|
-
const monthBeforeEndMonth = new
|
|
14806
|
+
const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
|
|
14701
14807
|
const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
|
|
14702
14808
|
days = daysInMonthBeforeEndMonth - Math.abs(days);
|
|
14703
14809
|
}
|
|
@@ -14706,7 +14812,7 @@ const DATEDIF = {
|
|
|
14706
14812
|
if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
|
|
14707
14813
|
return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
|
|
14708
14814
|
}
|
|
14709
|
-
const endDateWithinOneYear = new
|
|
14815
|
+
const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
|
|
14710
14816
|
let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
|
|
14711
14817
|
if (days < 0) {
|
|
14712
14818
|
endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
|
|
@@ -14823,7 +14929,7 @@ const EOMONTH = {
|
|
|
14823
14929
|
const _months = Math.trunc(toNumber(months, this.locale));
|
|
14824
14930
|
const yStart = _startDate.getFullYear();
|
|
14825
14931
|
const mStart = _startDate.getMonth();
|
|
14826
|
-
const jsDate = new
|
|
14932
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
14827
14933
|
return jsDateToRoundNumber(jsDate);
|
|
14828
14934
|
},
|
|
14829
14935
|
isExported: true,
|
|
@@ -14860,17 +14966,17 @@ const ISOWEEKNUM = {
|
|
|
14860
14966
|
// The first week of the year is the week that contains the first
|
|
14861
14967
|
// Thursday of the year.
|
|
14862
14968
|
let firstThursday = 1;
|
|
14863
|
-
while (new
|
|
14969
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
14864
14970
|
firstThursday += 1;
|
|
14865
14971
|
}
|
|
14866
|
-
const firstDayOfFirstWeek = new
|
|
14972
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
14867
14973
|
// The last week of the year is the week that contains the last Thursday of
|
|
14868
14974
|
// the year.
|
|
14869
14975
|
let lastThursday = 31;
|
|
14870
|
-
while (new
|
|
14976
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
14871
14977
|
lastThursday -= 1;
|
|
14872
14978
|
}
|
|
14873
|
-
const lastDayOfLastWeek = new
|
|
14979
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
14874
14980
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
14875
14981
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
14876
14982
|
let offsetYear;
|
|
@@ -14896,17 +15002,17 @@ const ISOWEEKNUM = {
|
|
|
14896
15002
|
case 1:
|
|
14897
15003
|
// firstDay is the 1st day of the 1st week of the year after
|
|
14898
15004
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
14899
|
-
firstDay = new
|
|
15005
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
14900
15006
|
break;
|
|
14901
15007
|
case -1:
|
|
14902
15008
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
14903
15009
|
// The first week of the previous year is the week that contains the
|
|
14904
15010
|
// first Thursday of the previous year.
|
|
14905
15011
|
let firstThursdayPreviousYear = 1;
|
|
14906
|
-
while (new
|
|
15012
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
14907
15013
|
firstThursdayPreviousYear += 1;
|
|
14908
15014
|
}
|
|
14909
|
-
firstDay = new
|
|
15015
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
14910
15016
|
break;
|
|
14911
15017
|
}
|
|
14912
15018
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -15041,8 +15147,8 @@ const NETWORKDAYS_INTL = {
|
|
|
15041
15147
|
});
|
|
15042
15148
|
}
|
|
15043
15149
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
15044
|
-
const stopDate =
|
|
15045
|
-
let stepDate =
|
|
15150
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
15151
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
15046
15152
|
const timeStopDate = stopDate.getTime();
|
|
15047
15153
|
let timeStepDate = stepDate.getTime();
|
|
15048
15154
|
let netWorkingDay = 0;
|
|
@@ -15068,8 +15174,7 @@ const NOW = {
|
|
|
15068
15174
|
return getDateTimeFormat(this.locale);
|
|
15069
15175
|
},
|
|
15070
15176
|
compute: function () {
|
|
15071
|
-
let today =
|
|
15072
|
-
today.setMilliseconds(0);
|
|
15177
|
+
let today = DateTime.now();
|
|
15073
15178
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
15074
15179
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
15075
15180
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -15143,8 +15248,8 @@ const TODAY = {
|
|
|
15143
15248
|
return this.locale.dateFormat;
|
|
15144
15249
|
},
|
|
15145
15250
|
compute: function () {
|
|
15146
|
-
const today =
|
|
15147
|
-
const jsDate = new
|
|
15251
|
+
const today = DateTime.now();
|
|
15252
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
15148
15253
|
return jsDateToRoundNumber(jsDate);
|
|
15149
15254
|
},
|
|
15150
15255
|
isExported: true,
|
|
@@ -15199,10 +15304,10 @@ const WEEKNUM = {
|
|
|
15199
15304
|
}
|
|
15200
15305
|
const y = _date.getFullYear();
|
|
15201
15306
|
let dayStart = 1;
|
|
15202
|
-
let startDayOfFirstWeek = new
|
|
15307
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
15203
15308
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
15204
15309
|
dayStart += 1;
|
|
15205
|
-
startDayOfFirstWeek = new
|
|
15310
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
15206
15311
|
}
|
|
15207
15312
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
15208
15313
|
if (dif < 0) {
|
|
@@ -15260,7 +15365,7 @@ const WORKDAY_INTL = {
|
|
|
15260
15365
|
timesHoliday.add(holiday.getTime());
|
|
15261
15366
|
});
|
|
15262
15367
|
}
|
|
15263
|
-
let stepDate =
|
|
15368
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
15264
15369
|
let timeStepDate = stepDate.getTime();
|
|
15265
15370
|
const unitDay = Math.sign(_numDays);
|
|
15266
15371
|
let stepDay = Math.abs(_numDays);
|
|
@@ -15324,7 +15429,7 @@ const MONTH_START = {
|
|
|
15324
15429
|
const _startDate = toJsDate(date, this.locale);
|
|
15325
15430
|
const yStart = _startDate.getFullYear();
|
|
15326
15431
|
const mStart = _startDate.getMonth();
|
|
15327
|
-
const jsDate = new
|
|
15432
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
15328
15433
|
return jsDateToRoundNumber(jsDate);
|
|
15329
15434
|
},
|
|
15330
15435
|
};
|
|
@@ -15366,7 +15471,7 @@ const QUARTER_START = {
|
|
|
15366
15471
|
compute: function (date) {
|
|
15367
15472
|
const quarter = QUARTER.compute.bind(this)(date);
|
|
15368
15473
|
const year = YEAR.compute.bind(this)(date);
|
|
15369
|
-
const jsDate = new
|
|
15474
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
15370
15475
|
return jsDateToRoundNumber(jsDate);
|
|
15371
15476
|
},
|
|
15372
15477
|
};
|
|
@@ -15383,7 +15488,7 @@ const QUARTER_END = {
|
|
|
15383
15488
|
compute: function (date) {
|
|
15384
15489
|
const quarter = QUARTER.compute.bind(this)(date);
|
|
15385
15490
|
const year = YEAR.compute.bind(this)(date);
|
|
15386
|
-
const jsDate = new
|
|
15491
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
15387
15492
|
return jsDateToRoundNumber(jsDate);
|
|
15388
15493
|
},
|
|
15389
15494
|
};
|
|
@@ -15399,7 +15504,7 @@ const YEAR_START = {
|
|
|
15399
15504
|
},
|
|
15400
15505
|
compute: function (date) {
|
|
15401
15506
|
const year = YEAR.compute.bind(this)(date);
|
|
15402
|
-
const jsDate = new
|
|
15507
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
15403
15508
|
return jsDateToRoundNumber(jsDate);
|
|
15404
15509
|
},
|
|
15405
15510
|
};
|
|
@@ -15415,7 +15520,7 @@ const YEAR_END = {
|
|
|
15415
15520
|
},
|
|
15416
15521
|
compute: function (date) {
|
|
15417
15522
|
const year = YEAR.compute.bind(this)(date);
|
|
15418
|
-
const jsDate = new
|
|
15523
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
15419
15524
|
return jsDateToRoundNumber(jsDate);
|
|
15420
15525
|
},
|
|
15421
15526
|
};
|
|
@@ -15463,8 +15568,8 @@ const DEFAULT_DELTA_ARG = 0;
|
|
|
15463
15568
|
const DELTA = {
|
|
15464
15569
|
description: _t("Compare two numeric values, returning 1 if they're equal."),
|
|
15465
15570
|
args: [
|
|
15466
|
-
arg(" (number)", _t("The first number to compare.")),
|
|
15467
|
-
arg(` (number, default=${DEFAULT_DELTA_ARG})`, _t("The second number to compare.")),
|
|
15571
|
+
arg("number1 (number)", _t("The first number to compare.")),
|
|
15572
|
+
arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _t("The second number to compare.")),
|
|
15468
15573
|
],
|
|
15469
15574
|
returns: ["NUMBER"],
|
|
15470
15575
|
compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
|
|
@@ -15891,7 +15996,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
15891
15996
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity, locale) {
|
|
15892
15997
|
const startDate = toJsDate(settlement, locale);
|
|
15893
15998
|
const endDate = toJsDate(maturity, locale);
|
|
15894
|
-
const startDatePlusOneYear =
|
|
15999
|
+
const startDatePlusOneYear = toJsDate(settlement, locale);
|
|
15895
16000
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
15896
16001
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _t("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
15897
16002
|
}
|
|
@@ -16026,7 +16131,7 @@ const AMORLINC = {
|
|
|
16026
16131
|
arg("salvage (number)", _t("The value of the asset at the end of depreciation.")),
|
|
16027
16132
|
arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
|
|
16028
16133
|
arg("rate (number)", _t("The deprecation rate.")),
|
|
16029
|
-
arg(" (number, optional)", _t("An indicator of what day count method to use.")),
|
|
16134
|
+
arg("day_count_convention (number, optional)", _t("An indicator of what day count method to use.")),
|
|
16030
16135
|
],
|
|
16031
16136
|
returns: ["NUMBER"],
|
|
16032
16137
|
compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
|
|
@@ -19198,8 +19303,8 @@ const MID = {
|
|
|
19198
19303
|
description: _t("A segment of a string."),
|
|
19199
19304
|
args: [
|
|
19200
19305
|
arg("text (string)", _t("The string to extract a segment from.")),
|
|
19201
|
-
arg(" (number)", _t("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
19202
|
-
arg(" (number)", _t("The length of the segment to extract.")),
|
|
19306
|
+
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.")),
|
|
19307
|
+
arg("extract_length (number)", _t("The length of the segment to extract.")),
|
|
19203
19308
|
],
|
|
19204
19309
|
returns: ["STRING"],
|
|
19205
19310
|
compute: function (text, starting_at, extract_length) {
|
|
@@ -20015,6 +20120,11 @@ const formatNumberAutomatic = {
|
|
|
20015
20120
|
execute: (env) => setFormatter(env, ""),
|
|
20016
20121
|
isActive: (env) => isAutomaticFormatSelected(env),
|
|
20017
20122
|
};
|
|
20123
|
+
const formatNumberPlainText = {
|
|
20124
|
+
name: _t("Plain text"),
|
|
20125
|
+
execute: (env) => setFormatter(env, PLAIN_TEXT_FORMAT),
|
|
20126
|
+
isActive: (env) => isFormatSelected(env, PLAIN_TEXT_FORMAT),
|
|
20127
|
+
};
|
|
20018
20128
|
const formatNumberNumber = createFormatActionSpec({
|
|
20019
20129
|
name: _t("Number"),
|
|
20020
20130
|
descriptionValue: 1000.12,
|
|
@@ -20374,6 +20484,7 @@ var ACTION_FORMAT = /*#__PURE__*/Object.freeze({
|
|
|
20374
20484
|
formatNumberFullWeekDayAndMonth: formatNumberFullWeekDayAndMonth,
|
|
20375
20485
|
formatNumberNumber: formatNumberNumber,
|
|
20376
20486
|
formatNumberPercent: formatNumberPercent,
|
|
20487
|
+
formatNumberPlainText: formatNumberPlainText,
|
|
20377
20488
|
formatNumberShortMonth: formatNumberShortMonth,
|
|
20378
20489
|
formatNumberShortWeekDay: formatNumberShortWeekDay,
|
|
20379
20490
|
formatNumberTime: formatNumberTime,
|
|
@@ -20804,6 +20915,10 @@ numberFormatMenuRegistry
|
|
|
20804
20915
|
.add("format_number_automatic", {
|
|
20805
20916
|
...formatNumberAutomatic,
|
|
20806
20917
|
sequence: 10,
|
|
20918
|
+
})
|
|
20919
|
+
.add("format_number_plain_text", {
|
|
20920
|
+
...formatNumberPlainText,
|
|
20921
|
+
sequence: 15,
|
|
20807
20922
|
separator: true,
|
|
20808
20923
|
})
|
|
20809
20924
|
.add("format_number_number", {
|
|
@@ -21402,10 +21517,10 @@ const arrowMap = {
|
|
|
21402
21517
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
21403
21518
|
const direction = arrowMap[ev.key];
|
|
21404
21519
|
if (ev.shiftKey) {
|
|
21405
|
-
selection.resizeAnchorZone(direction, ev
|
|
21520
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
21406
21521
|
}
|
|
21407
21522
|
else {
|
|
21408
|
-
selection.moveAnchorCell(direction, ev
|
|
21523
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
21409
21524
|
}
|
|
21410
21525
|
}
|
|
21411
21526
|
|
|
@@ -21472,6 +21587,15 @@ css /* scss */ `
|
|
|
21472
21587
|
*/
|
|
21473
21588
|
class SelectionInput extends owl.Component {
|
|
21474
21589
|
static template = "o-spreadsheet-SelectionInput";
|
|
21590
|
+
static props = {
|
|
21591
|
+
ranges: Function,
|
|
21592
|
+
hasSingleRange: { type: Boolean, optional: true },
|
|
21593
|
+
required: { type: Boolean, optional: true },
|
|
21594
|
+
isInvalid: { type: Boolean, optional: true },
|
|
21595
|
+
class: { type: String, optional: true },
|
|
21596
|
+
onSelectionChanged: { type: Function, optional: true },
|
|
21597
|
+
onSelectionConfirmed: { type: Function, optional: true },
|
|
21598
|
+
};
|
|
21475
21599
|
id = uuidGenerator$1.uuidv4();
|
|
21476
21600
|
previousRanges = this.props.ranges() || [];
|
|
21477
21601
|
originSheet = this.env.model.getters.getActiveSheetId();
|
|
@@ -21634,15 +21758,6 @@ class SelectionInput extends owl.Component {
|
|
|
21634
21758
|
this.env.model.dispatch("UNFOCUS_SELECTION_INPUT");
|
|
21635
21759
|
}
|
|
21636
21760
|
}
|
|
21637
|
-
SelectionInput.props = {
|
|
21638
|
-
ranges: Function,
|
|
21639
|
-
hasSingleRange: { type: Boolean, optional: true },
|
|
21640
|
-
required: { type: Boolean, optional: true },
|
|
21641
|
-
isInvalid: { type: Boolean, optional: true },
|
|
21642
|
-
class: { type: String, optional: true },
|
|
21643
|
-
onSelectionChanged: { type: Function, optional: true },
|
|
21644
|
-
onSelectionConfirmed: { type: Function, optional: true },
|
|
21645
|
-
};
|
|
21646
21761
|
|
|
21647
21762
|
css /* scss */ `
|
|
21648
21763
|
.o-validation-error,
|
|
@@ -21658,6 +21773,10 @@ css /* scss */ `
|
|
|
21658
21773
|
`;
|
|
21659
21774
|
class ValidationMessages extends owl.Component {
|
|
21660
21775
|
static template = "o-spreadsheet-ValidationMessages";
|
|
21776
|
+
static props = {
|
|
21777
|
+
messages: Array,
|
|
21778
|
+
msgType: String,
|
|
21779
|
+
};
|
|
21661
21780
|
get divClasses() {
|
|
21662
21781
|
if (this.props.msgType === "warning") {
|
|
21663
21782
|
return "o-validation-warning text-warning";
|
|
@@ -21665,14 +21784,96 @@ class ValidationMessages extends owl.Component {
|
|
|
21665
21784
|
return "o-validation-error text-danger";
|
|
21666
21785
|
}
|
|
21667
21786
|
}
|
|
21668
|
-
|
|
21669
|
-
|
|
21670
|
-
|
|
21671
|
-
|
|
21787
|
+
|
|
21788
|
+
css /* scss */ `
|
|
21789
|
+
.o-checkbox {
|
|
21790
|
+
display: flex;
|
|
21791
|
+
justify-items: center;
|
|
21792
|
+
input {
|
|
21793
|
+
margin-right: 5px;
|
|
21794
|
+
}
|
|
21795
|
+
}
|
|
21796
|
+
`;
|
|
21797
|
+
class Checkbox extends owl.Component {
|
|
21798
|
+
static template = "o-spreadsheet.Checkbox";
|
|
21799
|
+
static props = {
|
|
21800
|
+
label: { type: String, optional: true },
|
|
21801
|
+
value: { type: Boolean, optional: true },
|
|
21802
|
+
className: { type: String, optional: true },
|
|
21803
|
+
name: { type: String, optional: true },
|
|
21804
|
+
onChange: Function,
|
|
21805
|
+
};
|
|
21806
|
+
static defaultProps = { value: false };
|
|
21807
|
+
onChange(ev) {
|
|
21808
|
+
const value = ev.target.checked;
|
|
21809
|
+
this.props.onChange(value);
|
|
21810
|
+
}
|
|
21811
|
+
}
|
|
21812
|
+
|
|
21813
|
+
class Section extends owl.Component {
|
|
21814
|
+
static template = "o_spreadsheet.Section";
|
|
21815
|
+
static props = {
|
|
21816
|
+
class: { type: String, optional: true },
|
|
21817
|
+
slots: Object,
|
|
21818
|
+
};
|
|
21819
|
+
}
|
|
21820
|
+
|
|
21821
|
+
class ChartDataSeries extends owl.Component {
|
|
21822
|
+
static template = "o-spreadsheet.ChartDataSeries";
|
|
21823
|
+
static components = { SelectionInput, Section };
|
|
21824
|
+
static props = {
|
|
21825
|
+
ranges: Function,
|
|
21826
|
+
hasSingleRange: { type: Boolean, optional: true },
|
|
21827
|
+
onSelectionChanged: Function,
|
|
21828
|
+
onSelectionConfirmed: Function,
|
|
21829
|
+
};
|
|
21830
|
+
get title() {
|
|
21831
|
+
return this.props.hasSingleRange ? _t("Data range") : _t("Data series");
|
|
21832
|
+
}
|
|
21833
|
+
}
|
|
21834
|
+
|
|
21835
|
+
class ChartErrorSection extends owl.Component {
|
|
21836
|
+
static template = "o-spreadsheet.ChartErrorSection";
|
|
21837
|
+
static components = { Section, ValidationMessages };
|
|
21838
|
+
static props = { messages: { type: Array, element: String } };
|
|
21839
|
+
}
|
|
21840
|
+
|
|
21841
|
+
class ChartLabelRange extends owl.Component {
|
|
21842
|
+
static template = "o-spreadsheet.ChartLabelRange";
|
|
21843
|
+
static components = { SelectionInput, Checkbox, Section };
|
|
21844
|
+
static props = {
|
|
21845
|
+
title: { type: String, optional: true },
|
|
21846
|
+
range: Function,
|
|
21847
|
+
isInvalid: Boolean,
|
|
21848
|
+
required: { type: Boolean, optional: true },
|
|
21849
|
+
onSelectionChanged: Function,
|
|
21850
|
+
onSelectionConfirmed: Function,
|
|
21851
|
+
options: { type: Array, optional: true },
|
|
21852
|
+
};
|
|
21853
|
+
static defaultProps = {
|
|
21854
|
+
title: _t("Categories / Labels"),
|
|
21855
|
+
options: [],
|
|
21856
|
+
required: false,
|
|
21857
|
+
};
|
|
21858
|
+
}
|
|
21672
21859
|
|
|
21673
21860
|
class LineBarPieConfigPanel extends owl.Component {
|
|
21674
21861
|
static template = "o-spreadsheet-LineBarPieConfigPanel";
|
|
21675
|
-
static components = {
|
|
21862
|
+
static components = {
|
|
21863
|
+
SelectionInput,
|
|
21864
|
+
ValidationMessages,
|
|
21865
|
+
ChartDataSeries,
|
|
21866
|
+
ChartLabelRange,
|
|
21867
|
+
Section,
|
|
21868
|
+
Checkbox,
|
|
21869
|
+
ChartErrorSection,
|
|
21870
|
+
};
|
|
21871
|
+
static props = {
|
|
21872
|
+
figureId: String,
|
|
21873
|
+
definition: Object,
|
|
21874
|
+
updateChart: Function,
|
|
21875
|
+
canUpdateChart: Function,
|
|
21876
|
+
};
|
|
21676
21877
|
state = owl.useState({
|
|
21677
21878
|
datasetDispatchResult: undefined,
|
|
21678
21879
|
labelsDispatchResult: undefined,
|
|
@@ -21696,9 +21897,22 @@ class LineBarPieConfigPanel extends owl.Component {
|
|
|
21696
21897
|
get isLabelInvalid() {
|
|
21697
21898
|
return !!this.state.labelsDispatchResult?.isCancelledBecause("InvalidLabelRange" /* CommandResult.InvalidLabelRange */);
|
|
21698
21899
|
}
|
|
21699
|
-
|
|
21900
|
+
get dataSetsHaveTitleLabel() {
|
|
21901
|
+
return _t("Use row %s as headers", this.calculateHeaderPosition() || "");
|
|
21902
|
+
}
|
|
21903
|
+
getLabelRangeOptions() {
|
|
21904
|
+
return [
|
|
21905
|
+
{
|
|
21906
|
+
name: "aggregated",
|
|
21907
|
+
label: _t("Aggregate"),
|
|
21908
|
+
value: this.props.definition.aggregated,
|
|
21909
|
+
onChange: this.onUpdateAggregated.bind(this),
|
|
21910
|
+
},
|
|
21911
|
+
];
|
|
21912
|
+
}
|
|
21913
|
+
onUpdateDataSetsHaveTitle(dataSetsHaveTitle) {
|
|
21700
21914
|
this.props.updateChart(this.props.figureId, {
|
|
21701
|
-
dataSetsHaveTitle
|
|
21915
|
+
dataSetsHaveTitle,
|
|
21702
21916
|
});
|
|
21703
21917
|
}
|
|
21704
21918
|
/**
|
|
@@ -21738,9 +21952,9 @@ class LineBarPieConfigPanel extends owl.Component {
|
|
|
21738
21952
|
getLabelRange() {
|
|
21739
21953
|
return this.labelRange || "";
|
|
21740
21954
|
}
|
|
21741
|
-
onUpdateAggregated(
|
|
21955
|
+
onUpdateAggregated(aggregated) {
|
|
21742
21956
|
this.props.updateChart(this.props.figureId, {
|
|
21743
|
-
aggregated
|
|
21957
|
+
aggregated,
|
|
21744
21958
|
});
|
|
21745
21959
|
}
|
|
21746
21960
|
calculateHeaderPosition() {
|
|
@@ -21760,23 +21974,20 @@ class LineBarPieConfigPanel extends owl.Component {
|
|
|
21760
21974
|
return undefined;
|
|
21761
21975
|
}
|
|
21762
21976
|
}
|
|
21763
|
-
LineBarPieConfigPanel.props = {
|
|
21764
|
-
figureId: String,
|
|
21765
|
-
definition: Object,
|
|
21766
|
-
updateChart: Function,
|
|
21767
|
-
canUpdateChart: Function,
|
|
21768
|
-
};
|
|
21769
21977
|
|
|
21770
21978
|
class BarConfigPanel extends LineBarPieConfigPanel {
|
|
21771
21979
|
static template = "o-spreadsheet-BarConfigPanel";
|
|
21772
|
-
|
|
21980
|
+
get stackedLabel() {
|
|
21981
|
+
return _t("Stacked barchart");
|
|
21982
|
+
}
|
|
21983
|
+
onUpdateStacked(stacked) {
|
|
21773
21984
|
this.props.updateChart(this.props.figureId, {
|
|
21774
|
-
stacked
|
|
21985
|
+
stacked,
|
|
21775
21986
|
});
|
|
21776
21987
|
}
|
|
21777
|
-
onUpdateAggregated(
|
|
21988
|
+
onUpdateAggregated(aggregated) {
|
|
21778
21989
|
this.props.updateChart(this.props.figureId, {
|
|
21779
|
-
aggregated
|
|
21990
|
+
aggregated,
|
|
21780
21991
|
});
|
|
21781
21992
|
}
|
|
21782
21993
|
}
|
|
@@ -22104,6 +22315,12 @@ css /* scss */ `
|
|
|
22104
22315
|
`;
|
|
22105
22316
|
class ColorPicker extends owl.Component {
|
|
22106
22317
|
static template = "o-spreadsheet-ColorPicker";
|
|
22318
|
+
static props = {
|
|
22319
|
+
onColorPicked: Function,
|
|
22320
|
+
currentColor: { type: String, optional: true },
|
|
22321
|
+
maxHeight: { type: Number, optional: true },
|
|
22322
|
+
anchorRect: Object,
|
|
22323
|
+
};
|
|
22107
22324
|
static defaultProps = { currentColor: "" };
|
|
22108
22325
|
static components = { Popover };
|
|
22109
22326
|
COLORS = COLOR_PICKER_DEFAULTS;
|
|
@@ -22239,12 +22456,6 @@ class ColorPicker extends owl.Component {
|
|
|
22239
22456
|
return isSameColor(color1, color2);
|
|
22240
22457
|
}
|
|
22241
22458
|
}
|
|
22242
|
-
ColorPicker.props = {
|
|
22243
|
-
onColorPicked: Function,
|
|
22244
|
-
currentColor: { type: String, optional: true },
|
|
22245
|
-
maxHeight: { type: Number, optional: true },
|
|
22246
|
-
anchorRect: Object,
|
|
22247
|
-
};
|
|
22248
22459
|
|
|
22249
22460
|
css /* scss */ `
|
|
22250
22461
|
.o-color-picker-widget {
|
|
@@ -22282,6 +22493,17 @@ css /* scss */ `
|
|
|
22282
22493
|
`;
|
|
22283
22494
|
class ColorPickerWidget extends owl.Component {
|
|
22284
22495
|
static template = "o-spreadsheet-ColorPickerWidget";
|
|
22496
|
+
static props = {
|
|
22497
|
+
currentColor: { type: String, optional: true },
|
|
22498
|
+
toggleColorPicker: Function,
|
|
22499
|
+
showColorPicker: Boolean,
|
|
22500
|
+
onColorPicked: Function,
|
|
22501
|
+
icon: String,
|
|
22502
|
+
title: { type: String, optional: true },
|
|
22503
|
+
disabled: { type: Boolean, optional: true },
|
|
22504
|
+
dropdownMaxHeight: { type: Number, optional: true },
|
|
22505
|
+
class: { type: String, optional: true },
|
|
22506
|
+
};
|
|
22285
22507
|
static components = { ColorPicker };
|
|
22286
22508
|
colorPickerButtonRef = owl.useRef("colorPickerButton");
|
|
22287
22509
|
get iconStyle() {
|
|
@@ -22300,44 +22522,55 @@ class ColorPickerWidget extends owl.Component {
|
|
|
22300
22522
|
};
|
|
22301
22523
|
}
|
|
22302
22524
|
}
|
|
22303
|
-
ColorPickerWidget.props = {
|
|
22304
|
-
currentColor: { type: String, optional: true },
|
|
22305
|
-
toggleColorPicker: Function,
|
|
22306
|
-
showColorPicker: Boolean,
|
|
22307
|
-
onColorPicked: Function,
|
|
22308
|
-
icon: String,
|
|
22309
|
-
title: { type: String, optional: true },
|
|
22310
|
-
disabled: { type: Boolean, optional: true },
|
|
22311
|
-
dropdownMaxHeight: { type: Number, optional: true },
|
|
22312
|
-
class: { type: String, optional: true },
|
|
22313
|
-
};
|
|
22314
22525
|
|
|
22315
|
-
class
|
|
22316
|
-
static template = "o-spreadsheet
|
|
22317
|
-
static components = { ColorPickerWidget };
|
|
22318
|
-
|
|
22319
|
-
|
|
22320
|
-
|
|
22321
|
-
}
|
|
22322
|
-
|
|
22323
|
-
this.state.fillColorTool = false;
|
|
22324
|
-
}
|
|
22526
|
+
class ChartColor extends owl.Component {
|
|
22527
|
+
static template = "o-spreadsheet.ChartColor";
|
|
22528
|
+
static components = { ColorPickerWidget, Section };
|
|
22529
|
+
static props = {
|
|
22530
|
+
currentColor: { type: String, optional: true },
|
|
22531
|
+
onColorPicked: Function,
|
|
22532
|
+
};
|
|
22533
|
+
state;
|
|
22325
22534
|
setup() {
|
|
22326
|
-
this.state
|
|
22327
|
-
owl.useExternalListener(window, "click", this.
|
|
22535
|
+
this.state = owl.useState({ pickerOpened: false });
|
|
22536
|
+
owl.useExternalListener(window, "click", this.closePicker);
|
|
22328
22537
|
}
|
|
22329
|
-
|
|
22330
|
-
this.state.
|
|
22538
|
+
closePicker() {
|
|
22539
|
+
this.state.pickerOpened = false;
|
|
22540
|
+
}
|
|
22541
|
+
togglePicker() {
|
|
22542
|
+
this.state.pickerOpened = !this.state.pickerOpened;
|
|
22543
|
+
}
|
|
22544
|
+
}
|
|
22545
|
+
|
|
22546
|
+
class ChartTitle extends owl.Component {
|
|
22547
|
+
static template = "o-spreadsheet.ChartTitle";
|
|
22548
|
+
static components = { ColorPickerWidget, Section };
|
|
22549
|
+
static props = { title: String, update: Function };
|
|
22550
|
+
updateTitle(ev) {
|
|
22551
|
+
this.props.update(ev.target.value);
|
|
22552
|
+
}
|
|
22553
|
+
}
|
|
22554
|
+
|
|
22555
|
+
class LineBarPieDesignPanel extends owl.Component {
|
|
22556
|
+
static template = "o-spreadsheet-LineBarPieDesignPanel";
|
|
22557
|
+
static components = { ChartColor, ColorPickerWidget, ChartTitle, Section };
|
|
22558
|
+
static props = {
|
|
22559
|
+
figureId: String,
|
|
22560
|
+
definition: Object,
|
|
22561
|
+
updateChart: Function,
|
|
22562
|
+
canUpdateChart: Function,
|
|
22563
|
+
};
|
|
22564
|
+
get title() {
|
|
22565
|
+
return _t(this.props.definition.title);
|
|
22331
22566
|
}
|
|
22332
22567
|
updateBackgroundColor(color) {
|
|
22333
22568
|
this.props.updateChart(this.props.figureId, {
|
|
22334
22569
|
background: color,
|
|
22335
22570
|
});
|
|
22336
22571
|
}
|
|
22337
|
-
updateTitle() {
|
|
22338
|
-
this.props.updateChart(this.props.figureId, {
|
|
22339
|
-
title: this.state.title,
|
|
22340
|
-
});
|
|
22572
|
+
updateTitle(title) {
|
|
22573
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
22341
22574
|
}
|
|
22342
22575
|
updateSelect(attr, ev) {
|
|
22343
22576
|
this.props.updateChart(this.props.figureId, {
|
|
@@ -22345,12 +22578,6 @@ class LineBarPieDesignPanel extends owl.Component {
|
|
|
22345
22578
|
});
|
|
22346
22579
|
}
|
|
22347
22580
|
}
|
|
22348
|
-
LineBarPieDesignPanel.props = {
|
|
22349
|
-
figureId: String,
|
|
22350
|
-
definition: Object,
|
|
22351
|
-
updateChart: Function,
|
|
22352
|
-
canUpdateChart: Function,
|
|
22353
|
-
};
|
|
22354
22581
|
|
|
22355
22582
|
class BarChartDesignPanel extends LineBarPieDesignPanel {
|
|
22356
22583
|
static template = "o-spreadsheet-BarChartDesignPanel";
|
|
@@ -22358,7 +22585,13 @@ class BarChartDesignPanel extends LineBarPieDesignPanel {
|
|
|
22358
22585
|
|
|
22359
22586
|
class GaugeChartConfigPanel extends owl.Component {
|
|
22360
22587
|
static template = "o-spreadsheet-GaugeChartConfigPanel";
|
|
22361
|
-
static components = { SelectionInput,
|
|
22588
|
+
static components = { SelectionInput, ChartErrorSection, ChartDataSeries };
|
|
22589
|
+
static props = {
|
|
22590
|
+
figureId: String,
|
|
22591
|
+
definition: Object,
|
|
22592
|
+
updateChart: Function,
|
|
22593
|
+
canUpdateChart: Function,
|
|
22594
|
+
};
|
|
22362
22595
|
state = owl.useState({
|
|
22363
22596
|
dataRangeDispatchResult: undefined,
|
|
22364
22597
|
});
|
|
@@ -22385,12 +22618,6 @@ class GaugeChartConfigPanel extends owl.Component {
|
|
|
22385
22618
|
return this.dataRange || "";
|
|
22386
22619
|
}
|
|
22387
22620
|
}
|
|
22388
|
-
GaugeChartConfigPanel.props = {
|
|
22389
|
-
figureId: String,
|
|
22390
|
-
definition: Object,
|
|
22391
|
-
updateChart: Function,
|
|
22392
|
-
canUpdateChart: Function,
|
|
22393
|
-
};
|
|
22394
22621
|
|
|
22395
22622
|
css /* scss */ `
|
|
22396
22623
|
.o-gauge-color-set {
|
|
@@ -22425,31 +22652,35 @@ css /* scss */ `
|
|
|
22425
22652
|
`;
|
|
22426
22653
|
class GaugeChartDesignPanel extends owl.Component {
|
|
22427
22654
|
static template = "o-spreadsheet-GaugeChartDesignPanel";
|
|
22428
|
-
static components = { ColorPickerWidget,
|
|
22655
|
+
static components = { ColorPickerWidget, ChartErrorSection, ChartColor, ChartTitle, Section };
|
|
22656
|
+
static props = {
|
|
22657
|
+
figureId: String,
|
|
22658
|
+
definition: Object,
|
|
22659
|
+
updateChart: Function,
|
|
22660
|
+
canUpdateChart: Function,
|
|
22661
|
+
};
|
|
22429
22662
|
state = owl.useState({
|
|
22430
|
-
title: "",
|
|
22431
22663
|
openedMenu: undefined,
|
|
22432
22664
|
sectionRuleDispatchResult: undefined,
|
|
22433
22665
|
sectionRule: deepCopy(this.props.definition.sectionRule),
|
|
22434
22666
|
});
|
|
22435
22667
|
setup() {
|
|
22436
|
-
this.state.title = _t(this.props.definition.title);
|
|
22437
22668
|
owl.useExternalListener(window, "click", this.closeMenus);
|
|
22438
22669
|
}
|
|
22670
|
+
get title() {
|
|
22671
|
+
return _t(this.props.definition.title);
|
|
22672
|
+
}
|
|
22439
22673
|
get designErrorMessages() {
|
|
22440
22674
|
const cancelledReasons = [...(this.state.sectionRuleDispatchResult?.reasons || [])];
|
|
22441
22675
|
return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
|
|
22442
22676
|
}
|
|
22443
22677
|
updateBackgroundColor(color) {
|
|
22444
|
-
this.state.openedMenu = undefined;
|
|
22445
22678
|
this.props.updateChart(this.props.figureId, {
|
|
22446
22679
|
background: color,
|
|
22447
22680
|
});
|
|
22448
22681
|
}
|
|
22449
|
-
updateTitle() {
|
|
22450
|
-
this.props.updateChart(this.props.figureId, {
|
|
22451
|
-
title: this.state.title,
|
|
22452
|
-
});
|
|
22682
|
+
updateTitle(title) {
|
|
22683
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
22453
22684
|
}
|
|
22454
22685
|
isRangeMinInvalid() {
|
|
22455
22686
|
return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause("EmptyGaugeRangeMin" /* CommandResult.EmptyGaugeRangeMin */) ||
|
|
@@ -22499,12 +22730,6 @@ class GaugeChartDesignPanel extends owl.Component {
|
|
|
22499
22730
|
this.state.openedMenu = undefined;
|
|
22500
22731
|
}
|
|
22501
22732
|
}
|
|
22502
|
-
GaugeChartDesignPanel.props = {
|
|
22503
|
-
figureId: String,
|
|
22504
|
-
definition: Object,
|
|
22505
|
-
updateChart: Function,
|
|
22506
|
-
canUpdateChart: Function,
|
|
22507
|
-
};
|
|
22508
22733
|
|
|
22509
22734
|
class LineConfigPanel extends LineBarPieConfigPanel {
|
|
22510
22735
|
static template = "o-spreadsheet-LineConfigPanel";
|
|
@@ -22515,24 +22740,42 @@ class LineConfigPanel extends LineBarPieConfigPanel {
|
|
|
22515
22740
|
}
|
|
22516
22741
|
return false;
|
|
22517
22742
|
}
|
|
22518
|
-
|
|
22743
|
+
get stackedLabel() {
|
|
22744
|
+
return _t("Stacked linechart");
|
|
22745
|
+
}
|
|
22746
|
+
get cumulativeLabel() {
|
|
22747
|
+
return _t("Cumulative data");
|
|
22748
|
+
}
|
|
22749
|
+
getLabelRangeOptions() {
|
|
22750
|
+
const options = super.getLabelRangeOptions();
|
|
22751
|
+
if (this.canTreatLabelsAsText) {
|
|
22752
|
+
options.push({
|
|
22753
|
+
name: "labelsAsText",
|
|
22754
|
+
value: this.props.definition.labelsAsText,
|
|
22755
|
+
label: _t("Treat labels as text"),
|
|
22756
|
+
onChange: this.onUpdateLabelsAsText.bind(this),
|
|
22757
|
+
});
|
|
22758
|
+
}
|
|
22759
|
+
return options;
|
|
22760
|
+
}
|
|
22761
|
+
onUpdateLabelsAsText(labelsAsText) {
|
|
22519
22762
|
this.props.updateChart(this.props.figureId, {
|
|
22520
|
-
labelsAsText
|
|
22763
|
+
labelsAsText,
|
|
22521
22764
|
});
|
|
22522
22765
|
}
|
|
22523
|
-
onUpdateStacked(
|
|
22766
|
+
onUpdateStacked(stacked) {
|
|
22524
22767
|
this.props.updateChart(this.props.figureId, {
|
|
22525
|
-
stacked
|
|
22768
|
+
stacked,
|
|
22526
22769
|
});
|
|
22527
22770
|
}
|
|
22528
|
-
onUpdateAggregated(
|
|
22771
|
+
onUpdateAggregated(aggregated) {
|
|
22529
22772
|
this.props.updateChart(this.props.figureId, {
|
|
22530
|
-
aggregated
|
|
22773
|
+
aggregated,
|
|
22531
22774
|
});
|
|
22532
22775
|
}
|
|
22533
|
-
onUpdateCumulative(
|
|
22776
|
+
onUpdateCumulative(cumulative) {
|
|
22534
22777
|
this.props.updateChart(this.props.figureId, {
|
|
22535
|
-
cumulative
|
|
22778
|
+
cumulative,
|
|
22536
22779
|
});
|
|
22537
22780
|
}
|
|
22538
22781
|
}
|
|
@@ -22543,7 +22786,13 @@ class LineChartDesignPanel extends LineBarPieDesignPanel {
|
|
|
22543
22786
|
|
|
22544
22787
|
class ScorecardChartConfigPanel extends owl.Component {
|
|
22545
22788
|
static template = "o-spreadsheet-ScorecardChartConfigPanel";
|
|
22546
|
-
static components = { SelectionInput, ValidationMessages };
|
|
22789
|
+
static components = { SelectionInput, ValidationMessages, ChartErrorSection, Section };
|
|
22790
|
+
static props = {
|
|
22791
|
+
figureId: String,
|
|
22792
|
+
definition: Object,
|
|
22793
|
+
updateChart: Function,
|
|
22794
|
+
canUpdateChart: Function,
|
|
22795
|
+
};
|
|
22547
22796
|
state = owl.useState({
|
|
22548
22797
|
keyValueDispatchResult: undefined,
|
|
22549
22798
|
baselineDispatchResult: undefined,
|
|
@@ -22595,28 +22844,27 @@ class ScorecardChartConfigPanel extends owl.Component {
|
|
|
22595
22844
|
this.props.updateChart(this.props.figureId, { baselineMode: ev.target.value });
|
|
22596
22845
|
}
|
|
22597
22846
|
}
|
|
22598
|
-
ScorecardChartConfigPanel.props = {
|
|
22599
|
-
figureId: String,
|
|
22600
|
-
definition: Object,
|
|
22601
|
-
updateChart: Function,
|
|
22602
|
-
canUpdateChart: Function,
|
|
22603
|
-
};
|
|
22604
22847
|
|
|
22605
22848
|
class ScorecardChartDesignPanel extends owl.Component {
|
|
22606
22849
|
static template = "o-spreadsheet-ScorecardChartDesignPanel";
|
|
22607
|
-
static components = { ColorPickerWidget };
|
|
22850
|
+
static components = { ColorPickerWidget, ChartColor, ChartTitle, Section };
|
|
22851
|
+
static props = {
|
|
22852
|
+
figureId: String,
|
|
22853
|
+
definition: Object,
|
|
22854
|
+
updateChart: Function,
|
|
22855
|
+
canUpdateChart: Function,
|
|
22856
|
+
};
|
|
22608
22857
|
state = owl.useState({
|
|
22609
|
-
title: "",
|
|
22610
22858
|
openedColorPicker: undefined,
|
|
22611
22859
|
});
|
|
22612
22860
|
setup() {
|
|
22613
|
-
this.state.title = _t(this.props.definition.title);
|
|
22614
22861
|
owl.useExternalListener(window, "click", this.closeMenus);
|
|
22615
22862
|
}
|
|
22616
|
-
|
|
22617
|
-
this.props.
|
|
22618
|
-
|
|
22619
|
-
|
|
22863
|
+
get title() {
|
|
22864
|
+
return _t(this.props.definition.title);
|
|
22865
|
+
}
|
|
22866
|
+
updateTitle(title) {
|
|
22867
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
22620
22868
|
}
|
|
22621
22869
|
translate(term) {
|
|
22622
22870
|
return _t(term);
|
|
@@ -22650,12 +22898,6 @@ class ScorecardChartDesignPanel extends owl.Component {
|
|
|
22650
22898
|
this.state.openedColorPicker = undefined;
|
|
22651
22899
|
}
|
|
22652
22900
|
}
|
|
22653
|
-
ScorecardChartDesignPanel.props = {
|
|
22654
|
-
figureId: String,
|
|
22655
|
-
definition: Object,
|
|
22656
|
-
updateChart: Function,
|
|
22657
|
-
canUpdateChart: Function,
|
|
22658
|
-
};
|
|
22659
22901
|
|
|
22660
22902
|
const chartSidePanelComponentRegistry = new Registry();
|
|
22661
22903
|
chartSidePanelComponentRegistry
|
|
@@ -22706,6 +22948,8 @@ css /* scss */ `
|
|
|
22706
22948
|
`;
|
|
22707
22949
|
class ChartPanel extends owl.Component {
|
|
22708
22950
|
static template = "o-spreadsheet-ChartPanel";
|
|
22951
|
+
static components = { Section };
|
|
22952
|
+
static props = { onCloseSidePanel: Function };
|
|
22709
22953
|
state;
|
|
22710
22954
|
get figureId() {
|
|
22711
22955
|
return this.state.figureId;
|
|
@@ -22792,9 +23036,6 @@ class ChartPanel extends owl.Component {
|
|
|
22792
23036
|
this.state.panel = panel;
|
|
22793
23037
|
}
|
|
22794
23038
|
}
|
|
22795
|
-
ChartPanel.props = {
|
|
22796
|
-
onCloseSidePanel: Function,
|
|
22797
|
-
};
|
|
22798
23039
|
|
|
22799
23040
|
css /* scss */ `
|
|
22800
23041
|
.o-spreadsheet {
|
|
@@ -22905,6 +23146,9 @@ css /* scss */ `
|
|
|
22905
23146
|
`;
|
|
22906
23147
|
class IconPicker extends owl.Component {
|
|
22907
23148
|
static template = "o-spreadsheet-IconPicker";
|
|
23149
|
+
static props = {
|
|
23150
|
+
onIconPicked: Function,
|
|
23151
|
+
};
|
|
22908
23152
|
icons = ICONS;
|
|
22909
23153
|
iconSets = ICON_SETS;
|
|
22910
23154
|
onIconClick(icon) {
|
|
@@ -22913,9 +23157,6 @@ class IconPicker extends owl.Component {
|
|
|
22913
23157
|
}
|
|
22914
23158
|
}
|
|
22915
23159
|
}
|
|
22916
|
-
IconPicker.props = {
|
|
22917
|
-
onIconPicked: Function,
|
|
22918
|
-
};
|
|
22919
23160
|
|
|
22920
23161
|
function useDragAndDropListItems() {
|
|
22921
23162
|
let dndHelper;
|
|
@@ -23270,6 +23511,11 @@ css /* scss */ `
|
|
|
23270
23511
|
`;
|
|
23271
23512
|
class ConditionalFormatPreviewList extends owl.Component {
|
|
23272
23513
|
static template = "o-spreadsheet-ConditionalFormatPreviewList";
|
|
23514
|
+
static props = {
|
|
23515
|
+
conditionalFormats: Array,
|
|
23516
|
+
onPreviewClick: Function,
|
|
23517
|
+
onAddConditionalFormat: Function,
|
|
23518
|
+
};
|
|
23273
23519
|
icons = ICONS;
|
|
23274
23520
|
dragAndDrop = useDragAndDropListItems();
|
|
23275
23521
|
cfListRef = owl.useRef("cfList");
|
|
@@ -23350,11 +23596,6 @@ class ConditionalFormatPreviewList extends owl.Component {
|
|
|
23350
23596
|
}
|
|
23351
23597
|
}
|
|
23352
23598
|
}
|
|
23353
|
-
ConditionalFormatPreviewList.props = {
|
|
23354
|
-
conditionalFormats: Array,
|
|
23355
|
-
onPreviewClick: Function,
|
|
23356
|
-
onAddConditionalFormat: Function,
|
|
23357
|
-
};
|
|
23358
23599
|
|
|
23359
23600
|
css /* scss */ `
|
|
23360
23601
|
label {
|
|
@@ -23527,11 +23768,16 @@ css /* scss */ `
|
|
|
23527
23768
|
`;
|
|
23528
23769
|
class ConditionalFormattingEditor extends owl.Component {
|
|
23529
23770
|
static template = "o-spreadsheet-ConditionalFormattingEditor";
|
|
23771
|
+
static props = {
|
|
23772
|
+
editedCf: { type: Object, optional: true },
|
|
23773
|
+
onExitEdition: Function,
|
|
23774
|
+
};
|
|
23530
23775
|
static components = {
|
|
23531
23776
|
SelectionInput,
|
|
23532
23777
|
IconPicker,
|
|
23533
23778
|
ColorPickerWidget,
|
|
23534
23779
|
ConditionalFormatPreviewList,
|
|
23780
|
+
Section,
|
|
23535
23781
|
};
|
|
23536
23782
|
icons = ICONS;
|
|
23537
23783
|
cellIsOperators = CellIsOperators;
|
|
@@ -23791,13 +24037,13 @@ class ConditionalFormattingEditor extends owl.Component {
|
|
|
23791
24037
|
this.state.rules.iconSet.icons[target] = icon;
|
|
23792
24038
|
}
|
|
23793
24039
|
}
|
|
23794
|
-
ConditionalFormattingEditor.props = {
|
|
23795
|
-
editedCf: { type: Object, optional: true },
|
|
23796
|
-
onExitEdition: Function,
|
|
23797
|
-
};
|
|
23798
24040
|
|
|
23799
24041
|
class ConditionalFormattingPanel extends owl.Component {
|
|
23800
24042
|
static template = "o-spreadsheet-ConditionalFormattingPanel";
|
|
24043
|
+
static props = {
|
|
24044
|
+
selection: { type: Object, optional: true },
|
|
24045
|
+
onCloseSidePanel: Function,
|
|
24046
|
+
};
|
|
23801
24047
|
static components = {
|
|
23802
24048
|
ConditionalFormatPreviewList,
|
|
23803
24049
|
ConditionalFormattingEditor,
|
|
@@ -23856,10 +24102,6 @@ class ConditionalFormattingPanel extends owl.Component {
|
|
|
23856
24102
|
this.state.editedCf = cf;
|
|
23857
24103
|
}
|
|
23858
24104
|
}
|
|
23859
|
-
ConditionalFormattingPanel.props = {
|
|
23860
|
-
selection: { type: Object, optional: true },
|
|
23861
|
-
onCloseSidePanel: Function,
|
|
23862
|
-
};
|
|
23863
24105
|
|
|
23864
24106
|
css /* scss */ `
|
|
23865
24107
|
.o-custom-currency {
|
|
@@ -23870,6 +24112,8 @@ css /* scss */ `
|
|
|
23870
24112
|
`;
|
|
23871
24113
|
class CustomCurrencyPanel extends owl.Component {
|
|
23872
24114
|
static template = "o-spreadsheet-CustomCurrencyPanel";
|
|
24115
|
+
static components = { Section };
|
|
24116
|
+
static props = { onCloseSidePanel: Function };
|
|
23873
24117
|
availableCurrencies;
|
|
23874
24118
|
state;
|
|
23875
24119
|
setup() {
|
|
@@ -23992,9 +24236,6 @@ class CustomCurrencyPanel extends owl.Component {
|
|
|
23992
24236
|
return currency.name + (currency.code ? ` (${currency.code})` : "");
|
|
23993
24237
|
}
|
|
23994
24238
|
}
|
|
23995
|
-
CustomCurrencyPanel.props = {
|
|
23996
|
-
onCloseSidePanel: Function,
|
|
23997
|
-
};
|
|
23998
24239
|
|
|
23999
24240
|
css /* scss */ `
|
|
24000
24241
|
.o-find-and-replace {
|
|
@@ -24014,11 +24255,20 @@ css /* scss */ `
|
|
|
24014
24255
|
padding: 4px 0 4px 4px;
|
|
24015
24256
|
}
|
|
24016
24257
|
}
|
|
24258
|
+
|
|
24259
|
+
.o-matches-count div {
|
|
24260
|
+
text-overflow: ellipsis;
|
|
24261
|
+
overflow: hidden;
|
|
24262
|
+
white-space: nowrap;
|
|
24263
|
+
}
|
|
24017
24264
|
}
|
|
24018
24265
|
`;
|
|
24019
24266
|
class FindAndReplacePanel extends owl.Component {
|
|
24020
24267
|
static template = "o-spreadsheet-FindAndReplacePanel";
|
|
24021
|
-
static components = { SelectionInput };
|
|
24268
|
+
static components = { SelectionInput, Section, Checkbox };
|
|
24269
|
+
static props = {
|
|
24270
|
+
onCloseSidePanel: Function,
|
|
24271
|
+
};
|
|
24022
24272
|
debounceTimeoutId;
|
|
24023
24273
|
initialShowFormulaState = false;
|
|
24024
24274
|
dataRange = "";
|
|
@@ -24093,19 +24343,16 @@ class FindAndReplacePanel extends owl.Component {
|
|
|
24093
24343
|
this.replace();
|
|
24094
24344
|
}
|
|
24095
24345
|
}
|
|
24096
|
-
searchFormulas(
|
|
24097
|
-
const showFormula = ev.target.checked;
|
|
24346
|
+
searchFormulas(showFormula) {
|
|
24098
24347
|
this.env.model.dispatch("SET_FORMULA_VISIBILITY", {
|
|
24099
24348
|
show: showFormula,
|
|
24100
24349
|
});
|
|
24101
24350
|
this.updateSearch({ searchFormulas: showFormula });
|
|
24102
24351
|
}
|
|
24103
|
-
searchExactMatch(
|
|
24104
|
-
const exactMatch = ev.target.checked;
|
|
24352
|
+
searchExactMatch(exactMatch) {
|
|
24105
24353
|
this.updateSearch({ exactMatch });
|
|
24106
24354
|
}
|
|
24107
|
-
searchMatchCase(
|
|
24108
|
-
const matchCase = ev.target.checked;
|
|
24355
|
+
searchMatchCase(matchCase) {
|
|
24109
24356
|
this.updateSearch({ matchCase });
|
|
24110
24357
|
}
|
|
24111
24358
|
changeSearchScope(ev) {
|
|
@@ -24158,9 +24405,6 @@ class FindAndReplacePanel extends owl.Component {
|
|
|
24158
24405
|
});
|
|
24159
24406
|
}
|
|
24160
24407
|
}
|
|
24161
|
-
FindAndReplacePanel.props = {
|
|
24162
|
-
onCloseSidePanel: Function,
|
|
24163
|
-
};
|
|
24164
24408
|
|
|
24165
24409
|
css /* scss */ `
|
|
24166
24410
|
.o-more-formats-panel {
|
|
@@ -24192,13 +24436,13 @@ const DATE_FORMAT_ACTIONS = createActions([
|
|
|
24192
24436
|
]);
|
|
24193
24437
|
class MoreFormatsPanel extends owl.Component {
|
|
24194
24438
|
static template = "o-spreadsheet-MoreFormatsPanel";
|
|
24439
|
+
static props = {
|
|
24440
|
+
onCloseSidePanel: Function,
|
|
24441
|
+
};
|
|
24195
24442
|
get dateFormatsActions() {
|
|
24196
24443
|
return DATE_FORMAT_ACTIONS;
|
|
24197
24444
|
}
|
|
24198
24445
|
}
|
|
24199
|
-
MoreFormatsPanel.props = {
|
|
24200
|
-
onCloseSidePanel: Function,
|
|
24201
|
-
};
|
|
24202
24446
|
|
|
24203
24447
|
css /* scss */ `
|
|
24204
24448
|
.o-checkbox-selection {
|
|
@@ -24207,7 +24451,7 @@ css /* scss */ `
|
|
|
24207
24451
|
`;
|
|
24208
24452
|
class RemoveDuplicatesPanel extends owl.Component {
|
|
24209
24453
|
static template = "o-spreadsheet-RemoveDuplicatesPanel";
|
|
24210
|
-
static components = { ValidationMessages };
|
|
24454
|
+
static components = { ValidationMessages, Section, Checkbox };
|
|
24211
24455
|
state = owl.useState({
|
|
24212
24456
|
hasHeader: false,
|
|
24213
24457
|
columns: {},
|
|
@@ -24296,6 +24540,8 @@ css /* scss */ `
|
|
|
24296
24540
|
`;
|
|
24297
24541
|
class SettingsPanel extends owl.Component {
|
|
24298
24542
|
static template = "o-spreadsheet-SettingsPanel";
|
|
24543
|
+
static components = { Section };
|
|
24544
|
+
static props = { onCloseSidePanel: Function };
|
|
24299
24545
|
loadedLocales = [];
|
|
24300
24546
|
setup() {
|
|
24301
24547
|
owl.onWillStart(() => this.loadLocales());
|
|
@@ -24344,9 +24590,6 @@ class SettingsPanel extends owl.Component {
|
|
|
24344
24590
|
return this.loadedLocales;
|
|
24345
24591
|
}
|
|
24346
24592
|
}
|
|
24347
|
-
SettingsPanel.props = {
|
|
24348
|
-
onCloseSidePanel: Function,
|
|
24349
|
-
};
|
|
24350
24593
|
|
|
24351
24594
|
const SplitToColumnsInteractiveContent = {
|
|
24352
24595
|
SplitIsDestructive: _t("This will overwrite data in the subsequent columns. Split anyway?"),
|
|
@@ -24442,7 +24685,7 @@ dataValidationEvaluatorRegistry.add("dateIs", {
|
|
|
24442
24685
|
return false;
|
|
24443
24686
|
}
|
|
24444
24687
|
if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
|
|
24445
|
-
const today = jsDateToRoundNumber(
|
|
24688
|
+
const today = jsDateToRoundNumber(DateTime.now());
|
|
24446
24689
|
return isDateBetween(dateValue, today, criterionValue);
|
|
24447
24690
|
}
|
|
24448
24691
|
return areDatesSameDay(dateValue, criterionValue);
|
|
@@ -24934,7 +25177,8 @@ const SEPARATORS = [
|
|
|
24934
25177
|
];
|
|
24935
25178
|
class SplitIntoColumnsPanel extends owl.Component {
|
|
24936
25179
|
static template = "o-spreadsheet-SplitIntoColumnsPanel";
|
|
24937
|
-
static components = { ValidationMessages };
|
|
25180
|
+
static components = { ValidationMessages, Section, Checkbox };
|
|
25181
|
+
static props = { onCloseSidePanel: Function };
|
|
24938
25182
|
state = owl.useState({ separatorValue: "auto", addNewColumns: false, customSeparator: "" });
|
|
24939
25183
|
setup() {
|
|
24940
25184
|
owl.onWillUpdateProps(() => {
|
|
@@ -24956,10 +25200,8 @@ class SplitIntoColumnsPanel extends owl.Component {
|
|
|
24956
25200
|
return;
|
|
24957
25201
|
this.state.customSeparator = ev.target.value;
|
|
24958
25202
|
}
|
|
24959
|
-
updateAddNewColumnsCheckbox(
|
|
24960
|
-
|
|
24961
|
-
return;
|
|
24962
|
-
this.state.addNewColumns = ev.target.checked;
|
|
25203
|
+
updateAddNewColumnsCheckbox(addNewColumns) {
|
|
25204
|
+
this.state.addNewColumns = addNewColumns;
|
|
24963
25205
|
}
|
|
24964
25206
|
confirm() {
|
|
24965
25207
|
const result = interactiveSplitToColumns(this.env, this.separatorValue, this.state.addNewColumns);
|
|
@@ -25013,13 +25255,15 @@ class SplitIntoColumnsPanel extends owl.Component {
|
|
|
25013
25255
|
return !this.separatorValue || this.errorMessages.length > 0;
|
|
25014
25256
|
}
|
|
25015
25257
|
}
|
|
25016
|
-
SplitIntoColumnsPanel.props = {
|
|
25017
|
-
onCloseSidePanel: Function,
|
|
25018
|
-
};
|
|
25019
25258
|
|
|
25020
25259
|
/** This component looks like a select input, but on click it opens a Menu with the items given as props instead of a dropdown */
|
|
25021
25260
|
class SelectMenu extends owl.Component {
|
|
25022
25261
|
static template = "o-spreadsheet-SelectMenu";
|
|
25262
|
+
static props = {
|
|
25263
|
+
menuItems: Array,
|
|
25264
|
+
selectedValue: String,
|
|
25265
|
+
class: { type: String, optional: true },
|
|
25266
|
+
};
|
|
25023
25267
|
static components = { Menu };
|
|
25024
25268
|
selectRef = owl.useRef("select");
|
|
25025
25269
|
selectRect = useAbsoluteBoundingRect(this.selectRef);
|
|
@@ -25039,13 +25283,12 @@ class SelectMenu extends owl.Component {
|
|
|
25039
25283
|
};
|
|
25040
25284
|
}
|
|
25041
25285
|
}
|
|
25042
|
-
SelectMenu.props = {
|
|
25043
|
-
menuItems: Array,
|
|
25044
|
-
selectedValue: String,
|
|
25045
|
-
class: { type: String, optional: true },
|
|
25046
|
-
};
|
|
25047
25286
|
|
|
25048
25287
|
class DataValidationCriterionForm extends owl.Component {
|
|
25288
|
+
static props = {
|
|
25289
|
+
criterion: Object,
|
|
25290
|
+
onCriterionChanged: Function,
|
|
25291
|
+
};
|
|
25049
25292
|
setup() {
|
|
25050
25293
|
owl.onMounted(() => {
|
|
25051
25294
|
interactiveStopEdition(this.env);
|
|
@@ -25059,10 +25302,6 @@ class DataValidationCriterionForm extends owl.Component {
|
|
|
25059
25302
|
this.props.onCriterionChanged(filteredCriterion);
|
|
25060
25303
|
}
|
|
25061
25304
|
}
|
|
25062
|
-
DataValidationCriterionForm.props = {
|
|
25063
|
-
criterion: Object,
|
|
25064
|
-
onCriterionChanged: Function,
|
|
25065
|
-
};
|
|
25066
25305
|
|
|
25067
25306
|
css /* scss */ `
|
|
25068
25307
|
.o-dv-input {
|
|
@@ -25077,6 +25316,15 @@ css /* scss */ `
|
|
|
25077
25316
|
`;
|
|
25078
25317
|
class DataValidationInput extends owl.Component {
|
|
25079
25318
|
static template = "o-spreadsheet-DataValidationInput";
|
|
25319
|
+
static props = {
|
|
25320
|
+
value: { type: String, optional: true },
|
|
25321
|
+
criterionType: String,
|
|
25322
|
+
onValueChanged: Function,
|
|
25323
|
+
onKeyDown: { type: Function, optional: true },
|
|
25324
|
+
focused: { type: Boolean, optional: true },
|
|
25325
|
+
onBlur: { type: Function, optional: true },
|
|
25326
|
+
onFocus: { type: Function, optional: true },
|
|
25327
|
+
};
|
|
25080
25328
|
static defaultProps = {
|
|
25081
25329
|
value: "",
|
|
25082
25330
|
onKeyDown: () => { },
|
|
@@ -25115,15 +25363,6 @@ class DataValidationInput extends owl.Component {
|
|
|
25115
25363
|
return this.env.model.getters.getDataValidationInvalidCriterionValueMessage(this.props.criterionType, canonicalizeContent(this.props.value, this.env.model.getters.getLocale()));
|
|
25116
25364
|
}
|
|
25117
25365
|
}
|
|
25118
|
-
DataValidationInput.props = {
|
|
25119
|
-
value: { type: String, optional: true },
|
|
25120
|
-
criterionType: String,
|
|
25121
|
-
onValueChanged: Function,
|
|
25122
|
-
onKeyDown: { type: Function, optional: true },
|
|
25123
|
-
focused: { type: Boolean, optional: true },
|
|
25124
|
-
onBlur: { type: Function, optional: true },
|
|
25125
|
-
onFocus: { type: Function, optional: true },
|
|
25126
|
-
};
|
|
25127
25366
|
|
|
25128
25367
|
const DATES_VALUES = {
|
|
25129
25368
|
today: _t("today"),
|
|
@@ -25459,7 +25698,11 @@ css /* scss */ `
|
|
|
25459
25698
|
`;
|
|
25460
25699
|
class DataValidationEditor extends owl.Component {
|
|
25461
25700
|
static template = "o-spreadsheet-DataValidationEditor";
|
|
25462
|
-
static components = { SelectionInput, SelectMenu };
|
|
25701
|
+
static components = { SelectionInput, SelectMenu, Section };
|
|
25702
|
+
static props = {
|
|
25703
|
+
rule: { type: Object, optional: true },
|
|
25704
|
+
onExit: Function,
|
|
25705
|
+
};
|
|
25463
25706
|
state = owl.useState({ rule: this.defaultDataValidationRule });
|
|
25464
25707
|
setup() {
|
|
25465
25708
|
if (this.props.rule) {
|
|
@@ -25535,10 +25778,6 @@ class DataValidationEditor extends owl.Component {
|
|
|
25535
25778
|
return dataValidationPanelCriteriaRegistry.get(this.state.rule.criterion.type).component;
|
|
25536
25779
|
}
|
|
25537
25780
|
}
|
|
25538
|
-
DataValidationEditor.props = {
|
|
25539
|
-
rule: { type: Object, optional: true },
|
|
25540
|
-
onExit: Function,
|
|
25541
|
-
};
|
|
25542
25781
|
|
|
25543
25782
|
css /* scss */ `
|
|
25544
25783
|
.o-sidePanel {
|
|
@@ -25568,6 +25807,10 @@ css /* scss */ `
|
|
|
25568
25807
|
`;
|
|
25569
25808
|
class DataValidationPreview extends owl.Component {
|
|
25570
25809
|
static template = "o-spreadsheet-DataValidationPreview";
|
|
25810
|
+
static props = {
|
|
25811
|
+
onClick: Function,
|
|
25812
|
+
rule: Object,
|
|
25813
|
+
};
|
|
25571
25814
|
deleteDataValidation() {
|
|
25572
25815
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
25573
25816
|
this.env.model.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: this.props.rule.id });
|
|
@@ -25584,13 +25827,12 @@ class DataValidationPreview extends owl.Component {
|
|
|
25584
25827
|
.getPreview(this.props.rule.criterion, this.env.model.getters);
|
|
25585
25828
|
}
|
|
25586
25829
|
}
|
|
25587
|
-
DataValidationPreview.props = {
|
|
25588
|
-
onClick: Function,
|
|
25589
|
-
rule: Object,
|
|
25590
|
-
};
|
|
25591
25830
|
|
|
25592
25831
|
class DataValidationPanel extends owl.Component {
|
|
25593
25832
|
static template = "o-spreadsheet-DataValidationPanel";
|
|
25833
|
+
static props = {
|
|
25834
|
+
onCloseSidePanel: Function,
|
|
25835
|
+
};
|
|
25594
25836
|
static components = { DataValidationPreview, DataValidationEditor };
|
|
25595
25837
|
state = owl.useState({ mode: "list", activeRule: undefined });
|
|
25596
25838
|
onPreviewClick(id) {
|
|
@@ -25620,9 +25862,6 @@ class DataValidationPanel extends owl.Component {
|
|
|
25620
25862
|
return this.env.model.getters.getDataValidationRules(sheetId);
|
|
25621
25863
|
}
|
|
25622
25864
|
}
|
|
25623
|
-
DataValidationPanel.props = {
|
|
25624
|
-
onCloseSidePanel: Function,
|
|
25625
|
-
};
|
|
25626
25865
|
|
|
25627
25866
|
const sidePanelRegistry = new Registry();
|
|
25628
25867
|
sidePanelRegistry.add("ConditionalFormatting", {
|
|
@@ -25754,6 +25993,13 @@ css /*SCSS*/ `
|
|
|
25754
25993
|
`;
|
|
25755
25994
|
class FigureComponent extends owl.Component {
|
|
25756
25995
|
static template = "o-spreadsheet-FigureComponent";
|
|
25996
|
+
static props = {
|
|
25997
|
+
figure: Object,
|
|
25998
|
+
style: { type: String, optional: true },
|
|
25999
|
+
onFigureDeleted: { type: Function, optional: true },
|
|
26000
|
+
onMouseDown: { type: Function, optional: true },
|
|
26001
|
+
onClickAnchor: { type: Function, optional: true },
|
|
26002
|
+
};
|
|
25757
26003
|
static components = { Menu };
|
|
25758
26004
|
static defaultProps = {
|
|
25759
26005
|
onFigureDeleted: () => { },
|
|
@@ -25896,13 +26142,6 @@ class FigureComponent extends owl.Component {
|
|
|
25896
26142
|
.menuBuilder(this.props.figure.id, this.props.onFigureDeleted, this.env);
|
|
25897
26143
|
}
|
|
25898
26144
|
}
|
|
25899
|
-
FigureComponent.props = {
|
|
25900
|
-
figure: Object,
|
|
25901
|
-
style: { type: String, optional: true },
|
|
25902
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
25903
|
-
onMouseDown: { type: Function, optional: true },
|
|
25904
|
-
onClickAnchor: { type: Function, optional: true },
|
|
25905
|
-
};
|
|
25906
26145
|
|
|
25907
26146
|
const ToggleGroupInteractiveContent = {
|
|
25908
26147
|
CannotHideAllRows: _t("Cannot hide all the rows of a sheet."),
|
|
@@ -26040,6 +26279,10 @@ css /* scss */ `
|
|
|
26040
26279
|
`;
|
|
26041
26280
|
class Autofill extends owl.Component {
|
|
26042
26281
|
static template = "o-spreadsheet-Autofill";
|
|
26282
|
+
static props = {
|
|
26283
|
+
position: Object,
|
|
26284
|
+
isVisible: Boolean,
|
|
26285
|
+
};
|
|
26043
26286
|
state = owl.useState({
|
|
26044
26287
|
position: { left: 0, top: 0 },
|
|
26045
26288
|
handler: false,
|
|
@@ -26108,18 +26351,14 @@ class Autofill extends owl.Component {
|
|
|
26108
26351
|
this.env.model.dispatch("AUTOFILL_AUTO");
|
|
26109
26352
|
}
|
|
26110
26353
|
}
|
|
26111
|
-
Autofill.props = {
|
|
26112
|
-
position: Object,
|
|
26113
|
-
isVisible: Boolean,
|
|
26114
|
-
};
|
|
26115
26354
|
class TooltipComponent extends owl.Component {
|
|
26355
|
+
static props = {
|
|
26356
|
+
content: String,
|
|
26357
|
+
};
|
|
26116
26358
|
static template = owl.xml /* xml */ `
|
|
26117
26359
|
<div t-esc="props.content"/>
|
|
26118
26360
|
`;
|
|
26119
26361
|
}
|
|
26120
|
-
TooltipComponent.props = {
|
|
26121
|
-
content: String,
|
|
26122
|
-
};
|
|
26123
26362
|
|
|
26124
26363
|
css /* scss */ `
|
|
26125
26364
|
.o-client-tag {
|
|
@@ -26133,6 +26372,13 @@ css /* scss */ `
|
|
|
26133
26372
|
`;
|
|
26134
26373
|
class ClientTag extends owl.Component {
|
|
26135
26374
|
static template = "o-spreadsheet-ClientTag";
|
|
26375
|
+
static props = {
|
|
26376
|
+
active: Boolean,
|
|
26377
|
+
name: String,
|
|
26378
|
+
color: String,
|
|
26379
|
+
col: Number,
|
|
26380
|
+
row: Number,
|
|
26381
|
+
};
|
|
26136
26382
|
get tagStyle() {
|
|
26137
26383
|
const { col, row, color } = this.props;
|
|
26138
26384
|
const { height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
@@ -26150,13 +26396,6 @@ class ClientTag extends owl.Component {
|
|
|
26150
26396
|
});
|
|
26151
26397
|
}
|
|
26152
26398
|
}
|
|
26153
|
-
ClientTag.props = {
|
|
26154
|
-
active: Boolean,
|
|
26155
|
-
name: String,
|
|
26156
|
-
color: String,
|
|
26157
|
-
col: Number,
|
|
26158
|
-
row: Number,
|
|
26159
|
-
};
|
|
26160
26399
|
|
|
26161
26400
|
function getHtmlContentFromPattern(pattern, value, highlightColor, className) {
|
|
26162
26401
|
const pendingHtmlContent = [];
|
|
@@ -26196,14 +26435,14 @@ css /* scss */ `
|
|
|
26196
26435
|
`;
|
|
26197
26436
|
class TextValueProvider extends owl.Component {
|
|
26198
26437
|
static template = "o-spreadsheet-TextValueProvider";
|
|
26438
|
+
static props = {
|
|
26439
|
+
values: Array,
|
|
26440
|
+
selectedIndex: { type: Number, optional: true },
|
|
26441
|
+
getHtmlContent: Function,
|
|
26442
|
+
onValueSelected: Function,
|
|
26443
|
+
onValueHovered: Function,
|
|
26444
|
+
};
|
|
26199
26445
|
}
|
|
26200
|
-
TextValueProvider.props = {
|
|
26201
|
-
values: Array,
|
|
26202
|
-
selectedIndex: { type: Number, optional: true },
|
|
26203
|
-
getHtmlContent: Function,
|
|
26204
|
-
onValueSelected: Function,
|
|
26205
|
-
onValueHovered: Function,
|
|
26206
|
-
};
|
|
26207
26446
|
|
|
26208
26447
|
class ContentEditableHelper {
|
|
26209
26448
|
// todo make el private and expose dedicated methods
|
|
@@ -26565,6 +26804,11 @@ css /* scss */ `
|
|
|
26565
26804
|
`;
|
|
26566
26805
|
class FunctionDescriptionProvider extends owl.Component {
|
|
26567
26806
|
static template = "o-spreadsheet-FunctionDescriptionProvider";
|
|
26807
|
+
static props = {
|
|
26808
|
+
functionName: String,
|
|
26809
|
+
functionDescription: Object,
|
|
26810
|
+
argToFocus: Number,
|
|
26811
|
+
};
|
|
26568
26812
|
assistantState = owl.useState({
|
|
26569
26813
|
allowCellSelectionBehind: false,
|
|
26570
26814
|
});
|
|
@@ -26589,11 +26833,6 @@ class FunctionDescriptionProvider extends owl.Component {
|
|
|
26589
26833
|
}, 2000);
|
|
26590
26834
|
}
|
|
26591
26835
|
}
|
|
26592
|
-
FunctionDescriptionProvider.props = {
|
|
26593
|
-
functionName: String,
|
|
26594
|
-
functionDescription: Object,
|
|
26595
|
-
argToFocus: Number,
|
|
26596
|
-
};
|
|
26597
26836
|
|
|
26598
26837
|
const functions$2 = functionRegistry.content;
|
|
26599
26838
|
const ASSISTANT_WIDTH = 300;
|
|
@@ -26659,6 +26898,16 @@ css /* scss */ `
|
|
|
26659
26898
|
`;
|
|
26660
26899
|
class Composer extends owl.Component {
|
|
26661
26900
|
static template = "o-spreadsheet-Composer";
|
|
26901
|
+
static props = {
|
|
26902
|
+
focus: {
|
|
26903
|
+
validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
|
|
26904
|
+
},
|
|
26905
|
+
onComposerContentFocused: Function,
|
|
26906
|
+
inputStyle: { type: String, optional: true },
|
|
26907
|
+
rect: { type: Object, optional: true },
|
|
26908
|
+
delimitation: { type: Object, optional: true },
|
|
26909
|
+
onComposerUnmounted: { type: Function, optional: true },
|
|
26910
|
+
};
|
|
26662
26911
|
static components = { TextValueProvider, FunctionDescriptionProvider };
|
|
26663
26912
|
static defaultProps = {
|
|
26664
26913
|
inputStyle: "",
|
|
@@ -27215,14 +27464,6 @@ class Composer extends owl.Component {
|
|
|
27215
27464
|
this.autoCompleteState.getHtmlContent = (value) => [{ value }];
|
|
27216
27465
|
}
|
|
27217
27466
|
}
|
|
27218
|
-
Composer.props = {
|
|
27219
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27220
|
-
onComposerContentFocused: Function,
|
|
27221
|
-
inputStyle: { type: String, optional: true },
|
|
27222
|
-
rect: { type: Object, optional: true },
|
|
27223
|
-
delimitation: { type: Object, optional: true },
|
|
27224
|
-
onComposerUnmounted: { type: Function, optional: true },
|
|
27225
|
-
};
|
|
27226
27467
|
|
|
27227
27468
|
const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
|
|
27228
27469
|
const GRID_CELL_REFERENCE_TOP_OFFSET = 28;
|
|
@@ -27254,6 +27495,14 @@ css /* scss */ `
|
|
|
27254
27495
|
*/
|
|
27255
27496
|
class GridComposer extends owl.Component {
|
|
27256
27497
|
static template = "o-spreadsheet-GridComposer";
|
|
27498
|
+
static props = {
|
|
27499
|
+
focus: {
|
|
27500
|
+
validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
|
|
27501
|
+
},
|
|
27502
|
+
onComposerUnmounted: Function,
|
|
27503
|
+
onComposerContentFocused: Function,
|
|
27504
|
+
gridDims: Object,
|
|
27505
|
+
};
|
|
27257
27506
|
static components = { Composer };
|
|
27258
27507
|
gridComposerRef;
|
|
27259
27508
|
zone;
|
|
@@ -27360,22 +27609,22 @@ class GridComposer extends owl.Component {
|
|
|
27360
27609
|
});
|
|
27361
27610
|
}
|
|
27362
27611
|
}
|
|
27363
|
-
GridComposer.props = {
|
|
27364
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27365
|
-
onComposerUnmounted: Function,
|
|
27366
|
-
onComposerContentFocused: Function,
|
|
27367
|
-
gridDims: Object,
|
|
27368
|
-
};
|
|
27369
27612
|
|
|
27370
|
-
|
|
27613
|
+
css /* scss */ `
|
|
27371
27614
|
.o-grid-cell-icon {
|
|
27372
27615
|
width: ${GRID_ICON_EDGE_LENGTH}px;
|
|
27373
27616
|
height: ${GRID_ICON_EDGE_LENGTH}px;
|
|
27374
27617
|
}
|
|
27375
27618
|
`;
|
|
27376
27619
|
class GridCellIcon extends owl.Component {
|
|
27377
|
-
static style = CSS$1;
|
|
27378
27620
|
static template = "o-spreadsheet-GridCellIcon";
|
|
27621
|
+
static props = {
|
|
27622
|
+
cellPosition: Object,
|
|
27623
|
+
horizontalAlign: { type: String, optional: true },
|
|
27624
|
+
verticalAlign: { type: String, optional: true },
|
|
27625
|
+
offset: { type: Object, optional: true },
|
|
27626
|
+
slots: Object,
|
|
27627
|
+
};
|
|
27379
27628
|
get iconStyle() {
|
|
27380
27629
|
const x = this.getIconHorizontalPosition();
|
|
27381
27630
|
const y = this.getIconVerticalPosition();
|
|
@@ -27424,15 +27673,8 @@ class GridCellIcon extends owl.Component {
|
|
|
27424
27673
|
return !(rect.width === 0 || rect.height === 0);
|
|
27425
27674
|
}
|
|
27426
27675
|
}
|
|
27427
|
-
GridCellIcon.props = {
|
|
27428
|
-
cellPosition: Object,
|
|
27429
|
-
horizontalAlign: { type: String, optional: true },
|
|
27430
|
-
verticalAlign: { type: String, optional: true },
|
|
27431
|
-
offset: { type: Object, optional: true },
|
|
27432
|
-
slots: Object,
|
|
27433
|
-
};
|
|
27434
27676
|
|
|
27435
|
-
|
|
27677
|
+
css /* scss */ `
|
|
27436
27678
|
.o-filter-icon {
|
|
27437
27679
|
color: ${FILTERS_COLOR};
|
|
27438
27680
|
display: flex;
|
|
@@ -27447,8 +27689,10 @@ const CSS = css /* scss */ `
|
|
|
27447
27689
|
}
|
|
27448
27690
|
`;
|
|
27449
27691
|
class FilterIcon extends owl.Component {
|
|
27450
|
-
static style = CSS;
|
|
27451
27692
|
static template = "o-spreadsheet-FilterIcon";
|
|
27693
|
+
static props = {
|
|
27694
|
+
cellPosition: Object,
|
|
27695
|
+
};
|
|
27452
27696
|
onClick() {
|
|
27453
27697
|
const position = this.props.cellPosition;
|
|
27454
27698
|
const activePopoverType = this.env.model.getters.getPersistentPopoverTypeAtPosition(position);
|
|
@@ -27467,12 +27711,12 @@ class FilterIcon extends owl.Component {
|
|
|
27467
27711
|
return this.env.model.getters.isFilterActive(this.props.cellPosition);
|
|
27468
27712
|
}
|
|
27469
27713
|
}
|
|
27470
|
-
FilterIcon.props = {
|
|
27471
|
-
cellPosition: Object,
|
|
27472
|
-
};
|
|
27473
27714
|
|
|
27474
27715
|
class FilterIconsOverlay extends owl.Component {
|
|
27475
27716
|
static template = "o-spreadsheet-FilterIconsOverlay";
|
|
27717
|
+
static props = {
|
|
27718
|
+
gridPosition: { type: Object, optional: true },
|
|
27719
|
+
};
|
|
27476
27720
|
static components = {
|
|
27477
27721
|
GridCellIcon,
|
|
27478
27722
|
FilterIcon,
|
|
@@ -27486,9 +27730,6 @@ class FilterIconsOverlay extends owl.Component {
|
|
|
27486
27730
|
return headerPositions.map((position) => ({ sheetId, ...position }));
|
|
27487
27731
|
}
|
|
27488
27732
|
}
|
|
27489
|
-
FilterIconsOverlay.props = {
|
|
27490
|
-
gridPosition: { type: Object, optional: true },
|
|
27491
|
-
};
|
|
27492
27733
|
|
|
27493
27734
|
const CHECKBOX_WIDTH = 15;
|
|
27494
27735
|
const MARGIN = (GRID_ICON_EDGE_LENGTH - CHECKBOX_WIDTH) / 2;
|
|
@@ -27502,6 +27743,9 @@ css /* scss */ `
|
|
|
27502
27743
|
`;
|
|
27503
27744
|
class DataValidationCheckbox extends owl.Component {
|
|
27504
27745
|
static template = "o-spreadsheet-DataValidationCheckbox";
|
|
27746
|
+
static props = {
|
|
27747
|
+
cellPosition: Object,
|
|
27748
|
+
};
|
|
27505
27749
|
onCheckboxChange(ev) {
|
|
27506
27750
|
const newValue = ev.target.checked;
|
|
27507
27751
|
const { sheetId, col, row } = this.props.cellPosition;
|
|
@@ -27516,9 +27760,6 @@ class DataValidationCheckbox extends owl.Component {
|
|
|
27516
27760
|
return !!cell?.isFormula;
|
|
27517
27761
|
}
|
|
27518
27762
|
}
|
|
27519
|
-
DataValidationCheckbox.props = {
|
|
27520
|
-
cellPosition: Object,
|
|
27521
|
-
};
|
|
27522
27763
|
|
|
27523
27764
|
const ICON_WIDTH = 13;
|
|
27524
27765
|
css /* scss */ `
|
|
@@ -27541,18 +27782,19 @@ css /* scss */ `
|
|
|
27541
27782
|
`;
|
|
27542
27783
|
class DataValidationListIcon extends owl.Component {
|
|
27543
27784
|
static template = "o-spreadsheet-DataValidationListIcon";
|
|
27785
|
+
static props = {
|
|
27786
|
+
cellPosition: Object,
|
|
27787
|
+
};
|
|
27544
27788
|
onClick() {
|
|
27545
27789
|
const { col, row } = this.props.cellPosition;
|
|
27546
27790
|
this.env.model.selection.selectCell(col, row);
|
|
27547
27791
|
this.env.startCellEdition();
|
|
27548
27792
|
}
|
|
27549
27793
|
}
|
|
27550
|
-
DataValidationListIcon.props = {
|
|
27551
|
-
cellPosition: Object,
|
|
27552
|
-
};
|
|
27553
27794
|
|
|
27554
27795
|
class DataValidationOverlay extends owl.Component {
|
|
27555
27796
|
static template = "o-spreadsheet-DataValidationOverlay";
|
|
27797
|
+
static props = {};
|
|
27556
27798
|
static components = { GridCellIcon, DataValidationCheckbox, DataValidationListIcon };
|
|
27557
27799
|
get checkBoxCellPositions() {
|
|
27558
27800
|
return this.env.model.getters.getDataValidationCheckBoxCellPositions();
|
|
@@ -27563,7 +27805,6 @@ class DataValidationOverlay extends owl.Component {
|
|
|
27563
27805
|
: this.env.model.getters.getDataValidationListCellsPositions();
|
|
27564
27806
|
}
|
|
27565
27807
|
}
|
|
27566
|
-
DataValidationOverlay.props = {};
|
|
27567
27808
|
|
|
27568
27809
|
/**
|
|
27569
27810
|
* Transform a figure with coordinates from the model, to coordinates as they are shown on the screen,
|
|
@@ -27899,6 +28140,9 @@ css /*SCSS*/ `
|
|
|
27899
28140
|
*/
|
|
27900
28141
|
class FiguresContainer extends owl.Component {
|
|
27901
28142
|
static template = "o-spreadsheet-FiguresContainer";
|
|
28143
|
+
static props = {
|
|
28144
|
+
onFigureDeleted: Function,
|
|
28145
|
+
};
|
|
27902
28146
|
static components = { FigureComponent };
|
|
27903
28147
|
dnd = owl.useState({
|
|
27904
28148
|
draggedFigure: undefined,
|
|
@@ -28148,9 +28392,6 @@ class FiguresContainer extends owl.Component {
|
|
|
28148
28392
|
}
|
|
28149
28393
|
}
|
|
28150
28394
|
}
|
|
28151
|
-
FiguresContainer.props = {
|
|
28152
|
-
onFigureDeleted: Function,
|
|
28153
|
-
};
|
|
28154
28395
|
|
|
28155
28396
|
css /* scss */ `
|
|
28156
28397
|
.o-grid-add-rows {
|
|
@@ -28169,6 +28410,9 @@ css /* scss */ `
|
|
|
28169
28410
|
`;
|
|
28170
28411
|
class GridAddRowsFooter extends owl.Component {
|
|
28171
28412
|
static template = "o-spreadsheet-GridAddRowsFooter";
|
|
28413
|
+
static props = {
|
|
28414
|
+
focusGrid: Function,
|
|
28415
|
+
};
|
|
28172
28416
|
static components = { ValidationMessages };
|
|
28173
28417
|
inputRef = owl.useRef("inputRef");
|
|
28174
28418
|
state = owl.useState({
|
|
@@ -28235,9 +28479,6 @@ class GridAddRowsFooter extends owl.Component {
|
|
|
28235
28479
|
this.props.focusGrid();
|
|
28236
28480
|
}
|
|
28237
28481
|
}
|
|
28238
|
-
GridAddRowsFooter.props = {
|
|
28239
|
-
focusGrid: Function,
|
|
28240
|
-
};
|
|
28241
28482
|
|
|
28242
28483
|
/**
|
|
28243
28484
|
* Manages an event listener on a ref. Useful for hooks that want to manage
|
|
@@ -28393,6 +28634,16 @@ function useTouchMove(gridRef, handler, canMoveUp) {
|
|
|
28393
28634
|
}
|
|
28394
28635
|
class GridOverlay extends owl.Component {
|
|
28395
28636
|
static template = "o-spreadsheet-GridOverlay";
|
|
28637
|
+
static props = {
|
|
28638
|
+
onCellHovered: { type: Function, optional: true },
|
|
28639
|
+
onCellDoubleClicked: { type: Function, optional: true },
|
|
28640
|
+
onCellClicked: { type: Function, optional: true },
|
|
28641
|
+
onCellRightClicked: { type: Function, optional: true },
|
|
28642
|
+
onGridResized: { type: Function, optional: true },
|
|
28643
|
+
onFigureDeleted: { type: Function, optional: true },
|
|
28644
|
+
onGridMoved: Function,
|
|
28645
|
+
gridOverlayDimensions: String,
|
|
28646
|
+
};
|
|
28396
28647
|
static components = { FiguresContainer, DataValidationOverlay, GridAddRowsFooter };
|
|
28397
28648
|
static defaultProps = {
|
|
28398
28649
|
onCellHovered: () => { },
|
|
@@ -28444,7 +28695,10 @@ class GridOverlay extends owl.Component {
|
|
|
28444
28695
|
return;
|
|
28445
28696
|
}
|
|
28446
28697
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
28447
|
-
this.props.onCellClicked(col, row, {
|
|
28698
|
+
this.props.onCellClicked(col, row, {
|
|
28699
|
+
expandZone: ev.shiftKey,
|
|
28700
|
+
addZone: isCtrlKey(ev),
|
|
28701
|
+
});
|
|
28448
28702
|
}
|
|
28449
28703
|
onDoubleClick(ev) {
|
|
28450
28704
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -28463,19 +28717,15 @@ class GridOverlay extends owl.Component {
|
|
|
28463
28717
|
return [colIndex, rowIndex];
|
|
28464
28718
|
}
|
|
28465
28719
|
}
|
|
28466
|
-
GridOverlay.props = {
|
|
28467
|
-
onCellHovered: { type: Function, optional: true },
|
|
28468
|
-
onCellDoubleClicked: { type: Function, optional: true },
|
|
28469
|
-
onCellClicked: { type: Function, optional: true },
|
|
28470
|
-
onCellRightClicked: { type: Function, optional: true },
|
|
28471
|
-
onGridResized: { type: Function, optional: true },
|
|
28472
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
28473
|
-
onGridMoved: Function,
|
|
28474
|
-
gridOverlayDimensions: String,
|
|
28475
|
-
};
|
|
28476
28720
|
|
|
28477
28721
|
class GridPopover extends owl.Component {
|
|
28478
28722
|
static template = "o-spreadsheet-GridPopover";
|
|
28723
|
+
static props = {
|
|
28724
|
+
hoveredCell: Object,
|
|
28725
|
+
onClosePopover: Function,
|
|
28726
|
+
onMouseWheel: Function,
|
|
28727
|
+
gridRect: Object,
|
|
28728
|
+
};
|
|
28479
28729
|
static components = { Popover };
|
|
28480
28730
|
zIndex = ComponentsImportance.GridPopover;
|
|
28481
28731
|
get cellPopover() {
|
|
@@ -28495,14 +28745,11 @@ class GridPopover extends owl.Component {
|
|
|
28495
28745
|
};
|
|
28496
28746
|
}
|
|
28497
28747
|
}
|
|
28498
|
-
GridPopover.props = {
|
|
28499
|
-
hoveredCell: Object,
|
|
28500
|
-
onClosePopover: Function,
|
|
28501
|
-
onMouseWheel: Function,
|
|
28502
|
-
gridRect: Object,
|
|
28503
|
-
};
|
|
28504
28748
|
|
|
28505
28749
|
class AbstractResizer extends owl.Component {
|
|
28750
|
+
static props = {
|
|
28751
|
+
onOpenContextMenu: Function,
|
|
28752
|
+
};
|
|
28506
28753
|
PADDING = 0;
|
|
28507
28754
|
MAX_SIZE_MARGIN = 0;
|
|
28508
28755
|
MIN_ELEMENT_SIZE = 0;
|
|
@@ -28674,7 +28921,7 @@ class AbstractResizer extends owl.Component {
|
|
|
28674
28921
|
this._increaseSelection(index);
|
|
28675
28922
|
}
|
|
28676
28923
|
else {
|
|
28677
|
-
this._selectElement(index, ev
|
|
28924
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
28678
28925
|
}
|
|
28679
28926
|
this.lastSelectedElementIndex = index;
|
|
28680
28927
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -28759,10 +29006,10 @@ css /* scss */ `
|
|
|
28759
29006
|
}
|
|
28760
29007
|
}
|
|
28761
29008
|
`;
|
|
28762
|
-
AbstractResizer.props = {
|
|
28763
|
-
onOpenContextMenu: Function,
|
|
28764
|
-
};
|
|
28765
29009
|
class ColResizer extends AbstractResizer {
|
|
29010
|
+
static props = {
|
|
29011
|
+
onOpenContextMenu: Function,
|
|
29012
|
+
};
|
|
28766
29013
|
static template = "o-spreadsheet-ColResizer";
|
|
28767
29014
|
colResizerRef;
|
|
28768
29015
|
setup() {
|
|
@@ -28831,8 +29078,8 @@ class ColResizer extends AbstractResizer {
|
|
|
28831
29078
|
this.env.raiseError(MergeErrorMessage);
|
|
28832
29079
|
}
|
|
28833
29080
|
}
|
|
28834
|
-
_selectElement(index,
|
|
28835
|
-
this.env.model.selection.selectColumn(index,
|
|
29081
|
+
_selectElement(index, addDistinctHeader) {
|
|
29082
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
28836
29083
|
}
|
|
28837
29084
|
_increaseSelection(index) {
|
|
28838
29085
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -28924,10 +29171,10 @@ css /* scss */ `
|
|
|
28924
29171
|
}
|
|
28925
29172
|
}
|
|
28926
29173
|
`;
|
|
28927
|
-
ColResizer.props = {
|
|
28928
|
-
onOpenContextMenu: Function,
|
|
28929
|
-
};
|
|
28930
29174
|
class RowResizer extends AbstractResizer {
|
|
29175
|
+
static props = {
|
|
29176
|
+
onOpenContextMenu: Function,
|
|
29177
|
+
};
|
|
28931
29178
|
static template = "o-spreadsheet-RowResizer";
|
|
28932
29179
|
setup() {
|
|
28933
29180
|
super.setup();
|
|
@@ -28996,8 +29243,8 @@ class RowResizer extends AbstractResizer {
|
|
|
28996
29243
|
this.env.raiseError(MergeErrorMessage);
|
|
28997
29244
|
}
|
|
28998
29245
|
}
|
|
28999
|
-
_selectElement(index,
|
|
29000
|
-
this.env.model.selection.selectRow(index,
|
|
29246
|
+
_selectElement(index, addDistinctHeader) {
|
|
29247
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
29001
29248
|
}
|
|
29002
29249
|
_increaseSelection(index) {
|
|
29003
29250
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -29048,19 +29295,16 @@ css /* scss */ `
|
|
|
29048
29295
|
}
|
|
29049
29296
|
}
|
|
29050
29297
|
`;
|
|
29051
|
-
RowResizer.props = {
|
|
29052
|
-
onOpenContextMenu: Function,
|
|
29053
|
-
};
|
|
29054
29298
|
class HeadersOverlay extends owl.Component {
|
|
29299
|
+
static props = {
|
|
29300
|
+
onOpenContextMenu: Function,
|
|
29301
|
+
};
|
|
29055
29302
|
static template = "o-spreadsheet-HeadersOverlay";
|
|
29056
29303
|
static components = { ColResizer, RowResizer };
|
|
29057
29304
|
selectAll() {
|
|
29058
29305
|
this.env.model.selection.selectAll();
|
|
29059
29306
|
}
|
|
29060
29307
|
}
|
|
29061
|
-
HeadersOverlay.props = {
|
|
29062
|
-
onOpenContextMenu: Function,
|
|
29063
|
-
};
|
|
29064
29308
|
|
|
29065
29309
|
function useGridDrawing(refName, model, canvasSize) {
|
|
29066
29310
|
const canvasRef = owl.useRef(refName);
|
|
@@ -29118,6 +29362,12 @@ css /* scss */ `
|
|
|
29118
29362
|
`;
|
|
29119
29363
|
class Border extends owl.Component {
|
|
29120
29364
|
static template = "o-spreadsheet-Border";
|
|
29365
|
+
static props = {
|
|
29366
|
+
zone: Object,
|
|
29367
|
+
orientation: String,
|
|
29368
|
+
isMoving: Boolean,
|
|
29369
|
+
onMoveHighlight: Function,
|
|
29370
|
+
};
|
|
29121
29371
|
get style() {
|
|
29122
29372
|
const isTop = ["n", "w", "e"].includes(this.props.orientation);
|
|
29123
29373
|
const isLeft = ["n", "w", "s"].includes(this.props.orientation);
|
|
@@ -29146,12 +29396,6 @@ class Border extends owl.Component {
|
|
|
29146
29396
|
this.props.onMoveHighlight(ev.clientX, ev.clientY);
|
|
29147
29397
|
}
|
|
29148
29398
|
}
|
|
29149
|
-
Border.props = {
|
|
29150
|
-
zone: Object,
|
|
29151
|
-
orientation: String,
|
|
29152
|
-
isMoving: Boolean,
|
|
29153
|
-
onMoveHighlight: Function,
|
|
29154
|
-
};
|
|
29155
29399
|
|
|
29156
29400
|
css /* scss */ `
|
|
29157
29401
|
.o-corner {
|
|
@@ -29178,6 +29422,13 @@ css /* scss */ `
|
|
|
29178
29422
|
`;
|
|
29179
29423
|
class Corner extends owl.Component {
|
|
29180
29424
|
static template = "o-spreadsheet-Corner";
|
|
29425
|
+
static props = {
|
|
29426
|
+
zone: Object,
|
|
29427
|
+
color: String,
|
|
29428
|
+
orientation: String,
|
|
29429
|
+
isResizing: Boolean,
|
|
29430
|
+
onResizeHighlight: Function,
|
|
29431
|
+
};
|
|
29181
29432
|
isTop = this.props.orientation[0] === "n";
|
|
29182
29433
|
isLeft = this.props.orientation[1] === "w";
|
|
29183
29434
|
get style() {
|
|
@@ -29206,13 +29457,6 @@ class Corner extends owl.Component {
|
|
|
29206
29457
|
this.props.onResizeHighlight(this.isLeft, this.isTop);
|
|
29207
29458
|
}
|
|
29208
29459
|
}
|
|
29209
|
-
Corner.props = {
|
|
29210
|
-
zone: Object,
|
|
29211
|
-
color: String,
|
|
29212
|
-
orientation: String,
|
|
29213
|
-
isResizing: Boolean,
|
|
29214
|
-
onResizeHighlight: Function,
|
|
29215
|
-
};
|
|
29216
29460
|
|
|
29217
29461
|
css /*SCSS*/ `
|
|
29218
29462
|
.o-highlight {
|
|
@@ -29221,6 +29465,10 @@ css /*SCSS*/ `
|
|
|
29221
29465
|
`;
|
|
29222
29466
|
class Highlight extends owl.Component {
|
|
29223
29467
|
static template = "o-spreadsheet-Highlight";
|
|
29468
|
+
static props = {
|
|
29469
|
+
zone: Object,
|
|
29470
|
+
color: String,
|
|
29471
|
+
};
|
|
29224
29472
|
static components = {
|
|
29225
29473
|
Corner,
|
|
29226
29474
|
Border,
|
|
@@ -29304,10 +29552,6 @@ class Highlight extends owl.Component {
|
|
|
29304
29552
|
dragAndDropBeyondTheViewport(this.env, mouseMove, mouseUp);
|
|
29305
29553
|
}
|
|
29306
29554
|
}
|
|
29307
|
-
Highlight.props = {
|
|
29308
|
-
zone: Object,
|
|
29309
|
-
color: String,
|
|
29310
|
-
};
|
|
29311
29555
|
|
|
29312
29556
|
let ScrollBar$1 = class ScrollBar {
|
|
29313
29557
|
direction;
|
|
@@ -29347,6 +29591,14 @@ css /* scss */ `
|
|
|
29347
29591
|
}
|
|
29348
29592
|
`;
|
|
29349
29593
|
class ScrollBar extends owl.Component {
|
|
29594
|
+
static props = {
|
|
29595
|
+
width: { type: Number, optional: true },
|
|
29596
|
+
height: { type: Number, optional: true },
|
|
29597
|
+
direction: String,
|
|
29598
|
+
position: Object,
|
|
29599
|
+
offset: Number,
|
|
29600
|
+
onScroll: Function,
|
|
29601
|
+
};
|
|
29350
29602
|
static template = owl.xml /*xml*/ `
|
|
29351
29603
|
<div
|
|
29352
29604
|
t-attf-class="o-scrollbar {{props.direction}}"
|
|
@@ -29390,16 +29642,11 @@ class ScrollBar extends owl.Component {
|
|
|
29390
29642
|
}
|
|
29391
29643
|
}
|
|
29392
29644
|
}
|
|
29393
|
-
ScrollBar.props = {
|
|
29394
|
-
width: { type: Number, optional: true },
|
|
29395
|
-
height: { type: Number, optional: true },
|
|
29396
|
-
direction: String,
|
|
29397
|
-
position: Object,
|
|
29398
|
-
offset: Number,
|
|
29399
|
-
onScroll: Function,
|
|
29400
|
-
};
|
|
29401
29645
|
|
|
29402
29646
|
class HorizontalScrollBar extends owl.Component {
|
|
29647
|
+
static props = {
|
|
29648
|
+
leftOffset: { type: Number, optional: true },
|
|
29649
|
+
};
|
|
29403
29650
|
static components = { ScrollBar };
|
|
29404
29651
|
static template = owl.xml /*xml*/ `
|
|
29405
29652
|
<ScrollBar
|
|
@@ -29440,11 +29687,11 @@ class HorizontalScrollBar extends owl.Component {
|
|
|
29440
29687
|
});
|
|
29441
29688
|
}
|
|
29442
29689
|
}
|
|
29443
|
-
HorizontalScrollBar.props = {
|
|
29444
|
-
leftOffset: { type: Number, optional: true },
|
|
29445
|
-
};
|
|
29446
29690
|
|
|
29447
29691
|
class VerticalScrollBar extends owl.Component {
|
|
29692
|
+
static props = {
|
|
29693
|
+
topOffset: { type: Number, optional: true },
|
|
29694
|
+
};
|
|
29448
29695
|
static components = { ScrollBar };
|
|
29449
29696
|
static template = owl.xml /*xml*/ `
|
|
29450
29697
|
<ScrollBar
|
|
@@ -29485,9 +29732,6 @@ class VerticalScrollBar extends owl.Component {
|
|
|
29485
29732
|
});
|
|
29486
29733
|
}
|
|
29487
29734
|
}
|
|
29488
|
-
VerticalScrollBar.props = {
|
|
29489
|
-
topOffset: { type: Number, optional: true },
|
|
29490
|
-
};
|
|
29491
29735
|
|
|
29492
29736
|
const registries$1 = {
|
|
29493
29737
|
ROW: rowMenuRegistry,
|
|
@@ -29501,6 +29745,13 @@ const registries$1 = {
|
|
|
29501
29745
|
// -----------------------------------------------------------------------------
|
|
29502
29746
|
class Grid extends owl.Component {
|
|
29503
29747
|
static template = "o-spreadsheet-Grid";
|
|
29748
|
+
static props = {
|
|
29749
|
+
sidePanelIsOpen: Boolean,
|
|
29750
|
+
exposeFocus: Function,
|
|
29751
|
+
focusComposer: String,
|
|
29752
|
+
onComposerContentFocused: Function,
|
|
29753
|
+
onGridComposerCellFocused: Function,
|
|
29754
|
+
};
|
|
29504
29755
|
static components = {
|
|
29505
29756
|
GridComposer,
|
|
29506
29757
|
GridOverlay,
|
|
@@ -29690,7 +29941,7 @@ class Grid extends owl.Component {
|
|
|
29690
29941
|
"Ctrl+Shift+E": () => this.setHorizontalAlign("center"),
|
|
29691
29942
|
"Ctrl+Shift+L": () => this.setHorizontalAlign("left"),
|
|
29692
29943
|
"Ctrl+Shift+R": () => this.setHorizontalAlign("right"),
|
|
29693
|
-
"Ctrl+Shift+V": () =>
|
|
29944
|
+
"Ctrl+Shift+V": () => PASTE_AS_VALUE_ACTION(this.env),
|
|
29694
29945
|
"Ctrl+Shift+<": () => this.clearFormatting(),
|
|
29695
29946
|
"Ctrl+<": () => this.clearFormatting(),
|
|
29696
29947
|
"Ctrl+Shift+ ": () => {
|
|
@@ -29798,17 +30049,17 @@ class Grid extends owl.Component {
|
|
|
29798
30049
|
// ---------------------------------------------------------------------------
|
|
29799
30050
|
// Zone selection with mouse
|
|
29800
30051
|
// ---------------------------------------------------------------------------
|
|
29801
|
-
onCellClicked(col, row, {
|
|
30052
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
29802
30053
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
29803
30054
|
this.closeOpenedPopover();
|
|
29804
30055
|
}
|
|
29805
30056
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
29806
30057
|
interactiveStopEdition(this.env);
|
|
29807
30058
|
}
|
|
29808
|
-
if (
|
|
30059
|
+
if (expandZone) {
|
|
29809
30060
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
29810
30061
|
}
|
|
29811
|
-
else if (
|
|
30062
|
+
else if (addZone) {
|
|
29812
30063
|
this.env.model.selection.addCellToSelection(col, row);
|
|
29813
30064
|
}
|
|
29814
30065
|
else {
|
|
@@ -30105,13 +30356,6 @@ class Grid extends owl.Component {
|
|
|
30105
30356
|
}
|
|
30106
30357
|
}
|
|
30107
30358
|
}
|
|
30108
|
-
Grid.props = {
|
|
30109
|
-
sidePanelIsOpen: Boolean,
|
|
30110
|
-
exposeFocus: Function,
|
|
30111
|
-
focusComposer: String,
|
|
30112
|
-
onComposerContentFocused: Function,
|
|
30113
|
-
onGridComposerCellFocused: Function,
|
|
30114
|
-
};
|
|
30115
30359
|
|
|
30116
30360
|
/**
|
|
30117
30361
|
* Represent a raw XML string
|
|
@@ -30611,7 +30855,7 @@ const XLSX_FORMATS_CONVERSION_MAP = {
|
|
|
30611
30855
|
46: "hhhh:mm:ss",
|
|
30612
30856
|
47: "hhhh:mm:ss",
|
|
30613
30857
|
48: undefined,
|
|
30614
|
-
49:
|
|
30858
|
+
49: PLAIN_TEXT_FORMAT,
|
|
30615
30859
|
};
|
|
30616
30860
|
/**
|
|
30617
30861
|
* Mapping format index to format defined by default
|
|
@@ -31532,20 +31776,26 @@ function convertFigures(sheetData) {
|
|
|
31532
31776
|
.filter(isDefined$1);
|
|
31533
31777
|
}
|
|
31534
31778
|
function convertFigure(figure, id, sheetData) {
|
|
31535
|
-
|
|
31536
|
-
|
|
31537
|
-
|
|
31538
|
-
|
|
31539
|
-
|
|
31540
|
-
convertEMUToDotValue(figure.
|
|
31541
|
-
|
|
31542
|
-
|
|
31779
|
+
let x1, y1;
|
|
31780
|
+
let height, width;
|
|
31781
|
+
if (figure.anchors.length === 1) {
|
|
31782
|
+
// one cell anchor
|
|
31783
|
+
({ x: x1, y: y1 } = getPositionFromAnchor(figure.anchors[0], sheetData));
|
|
31784
|
+
width = convertEMUToDotValue(figure.figureSize.cx);
|
|
31785
|
+
height = convertEMUToDotValue(figure.figureSize.cy);
|
|
31786
|
+
}
|
|
31787
|
+
else {
|
|
31788
|
+
({ x: x1, y: y1 } = getPositionFromAnchor(figure.anchors[0], sheetData));
|
|
31789
|
+
const { x: x2, y: y2 } = getPositionFromAnchor(figure.anchors[1], sheetData);
|
|
31790
|
+
width = x2 - x1;
|
|
31791
|
+
height = y2 - y1;
|
|
31792
|
+
}
|
|
31543
31793
|
const figureData = { id, x: x1, y: y1 };
|
|
31544
31794
|
if (isChartData(figure.data)) {
|
|
31545
31795
|
return {
|
|
31546
31796
|
...figureData,
|
|
31547
|
-
width
|
|
31548
|
-
height
|
|
31797
|
+
width,
|
|
31798
|
+
height,
|
|
31549
31799
|
tag: "chart",
|
|
31550
31800
|
data: convertChartData(figure.data),
|
|
31551
31801
|
};
|
|
@@ -31611,6 +31861,12 @@ function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
|
31611
31861
|
const dataXC = zoneToXc(zone);
|
|
31612
31862
|
return getFullReference(sheetName, dataXC);
|
|
31613
31863
|
}
|
|
31864
|
+
function getPositionFromAnchor(anchor, sheetData) {
|
|
31865
|
+
return {
|
|
31866
|
+
x: getColPosition(anchor.col, sheetData) + convertEMUToDotValue(anchor.colOffset),
|
|
31867
|
+
y: getRowPosition(anchor.row, sheetData) + convertEMUToDotValue(anchor.rowOffset),
|
|
31868
|
+
};
|
|
31869
|
+
}
|
|
31614
31870
|
|
|
31615
31871
|
/**
|
|
31616
31872
|
* Match external reference (ex. '[1]Sheet 3'!$B$4)
|
|
@@ -32734,27 +32990,50 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
|
|
|
32734
32990
|
}
|
|
32735
32991
|
}
|
|
32736
32992
|
|
|
32993
|
+
const ONE_CELL_ANCHOR = "oneCellAnchor";
|
|
32994
|
+
const TWO_CELL_ANCHOR = "twoCellAnchor";
|
|
32737
32995
|
class XlsxFigureExtractor extends XlsxBaseExtractor {
|
|
32738
32996
|
extractFigures() {
|
|
32739
32997
|
return this.mapOnElements({ parent: this.rootFile.file.xml, query: "xdr:wsDr", children: true }, (figureElement) => {
|
|
32740
32998
|
const anchorType = removeTagEscapedNamespaces(figureElement.tagName);
|
|
32741
|
-
|
|
32742
|
-
throw new Error("Only twoCellAnchor are supported for xlsx drawings.");
|
|
32743
|
-
}
|
|
32999
|
+
const anchors = this.extractFigureAnchorsByType(figureElement, anchorType);
|
|
32744
33000
|
const chartElement = this.querySelector(figureElement, "c:chart");
|
|
32745
33001
|
const imageElement = this.querySelector(figureElement, "a:blip");
|
|
32746
33002
|
if (!chartElement && !imageElement) {
|
|
32747
33003
|
throw new Error("Only chart and image figures are currently supported.");
|
|
32748
33004
|
}
|
|
32749
33005
|
return {
|
|
32750
|
-
anchors
|
|
32751
|
-
this.extractFigureAnchor("xdr:from", figureElement),
|
|
32752
|
-
this.extractFigureAnchor("xdr:to", figureElement),
|
|
32753
|
-
],
|
|
33006
|
+
anchors,
|
|
32754
33007
|
data: chartElement ? this.extractChart(chartElement) : this.extractImage(figureElement),
|
|
33008
|
+
figureSize: anchorType === ONE_CELL_ANCHOR
|
|
33009
|
+
? this.extractFigureSizeFromSizeTag(figureElement, "xdr:ext")
|
|
33010
|
+
: undefined,
|
|
32755
33011
|
};
|
|
32756
33012
|
});
|
|
32757
33013
|
}
|
|
33014
|
+
extractFigureAnchorsByType(figureElement, anchorType) {
|
|
33015
|
+
switch (anchorType) {
|
|
33016
|
+
case ONE_CELL_ANCHOR:
|
|
33017
|
+
return [this.extractFigureAnchor("xdr:from", figureElement)];
|
|
33018
|
+
case TWO_CELL_ANCHOR:
|
|
33019
|
+
return [
|
|
33020
|
+
this.extractFigureAnchor("xdr:from", figureElement),
|
|
33021
|
+
this.extractFigureAnchor("xdr:to", figureElement),
|
|
33022
|
+
];
|
|
33023
|
+
default:
|
|
33024
|
+
throw new Error(`${anchorType} is not supported for xlsx drawings. `);
|
|
33025
|
+
}
|
|
33026
|
+
}
|
|
33027
|
+
extractFigureSizeFromSizeTag(figureElement, sizeTag) {
|
|
33028
|
+
const sizeElement = this.querySelector(figureElement, sizeTag);
|
|
33029
|
+
if (!sizeElement) {
|
|
33030
|
+
throw new Error(`Missing size element '${sizeTag}'`);
|
|
33031
|
+
}
|
|
33032
|
+
return {
|
|
33033
|
+
cx: this.extractAttr(sizeElement, "cx", { required: true }).asNum(),
|
|
33034
|
+
cy: this.extractAttr(sizeElement, "cy", { required: true }).asNum(),
|
|
33035
|
+
};
|
|
33036
|
+
}
|
|
32758
33037
|
extractFigureAnchor(anchorTag, figureElement) {
|
|
32759
33038
|
const anchor = this.querySelector(figureElement, anchorTag);
|
|
32760
33039
|
if (!anchor) {
|
|
@@ -32783,15 +33062,15 @@ class XlsxFigureExtractor extends XlsxBaseExtractor {
|
|
|
32783
33062
|
if (!image) {
|
|
32784
33063
|
throw new Error("Unable to extract image");
|
|
32785
33064
|
}
|
|
32786
|
-
const shapePropertyElement = this.querySelector(figureElement, "a:xfrm");
|
|
32787
33065
|
const extension = image.fileName.split(".").at(-1);
|
|
33066
|
+
const anchorType = removeTagEscapedNamespaces(figureElement.tagName);
|
|
33067
|
+
const sizeElement = anchorType === TWO_CELL_ANCHOR ? this.querySelector(figureElement, "a:xfrm") : figureElement;
|
|
33068
|
+
const sizeTag = anchorType === TWO_CELL_ANCHOR ? "a:ext" : "xdr:ext";
|
|
33069
|
+
const size = this.extractFigureSizeFromSizeTag(sizeElement, sizeTag);
|
|
32788
33070
|
return {
|
|
32789
33071
|
imageSrc: image.imageSrc,
|
|
32790
33072
|
mimetype: extension ? IMAGE_EXTENSION_TO_MIMETYPE_MAPPING[extension] : undefined,
|
|
32791
|
-
size
|
|
32792
|
-
cx: this.extractChildAttr(shapePropertyElement, "a:ext", "cx", { required: true }).asNum(),
|
|
32793
|
-
cy: this.extractChildAttr(shapePropertyElement, "a:ext", "cy", { required: true }).asNum(),
|
|
32794
|
-
},
|
|
33073
|
+
size,
|
|
32795
33074
|
};
|
|
32796
33075
|
}
|
|
32797
33076
|
}
|
|
@@ -34744,7 +35023,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
34744
35023
|
*/
|
|
34745
35024
|
function getBorderId(border) {
|
|
34746
35025
|
for (let [key, value] of Object.entries(borders)) {
|
|
34747
|
-
if (
|
|
35026
|
+
if (deepEquals(value, border)) {
|
|
34748
35027
|
return parseInt(key, 10);
|
|
34749
35028
|
}
|
|
34750
35029
|
}
|
|
@@ -35915,7 +36194,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35915
36194
|
}
|
|
35916
36195
|
createLiteralCell(id, content, format, style) {
|
|
35917
36196
|
const locale = this.getters.getLocale();
|
|
35918
|
-
|
|
36197
|
+
if (format !== PLAIN_TEXT_FORMAT) {
|
|
36198
|
+
content = toString(parseLiteral(content, locale));
|
|
36199
|
+
}
|
|
35919
36200
|
return {
|
|
35920
36201
|
id,
|
|
35921
36202
|
content,
|
|
@@ -40062,56 +40343,758 @@ class CompilationParametersBuilder {
|
|
|
40062
40343
|
}
|
|
40063
40344
|
}
|
|
40064
40345
|
|
|
40346
|
+
function quickselect(arr, k, left, right, compare) {
|
|
40347
|
+
quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
|
|
40348
|
+
}
|
|
40349
|
+
|
|
40350
|
+
function quickselectStep(arr, k, left, right, compare) {
|
|
40351
|
+
|
|
40352
|
+
while (right > left) {
|
|
40353
|
+
if (right - left > 600) {
|
|
40354
|
+
var n = right - left + 1;
|
|
40355
|
+
var m = k - left + 1;
|
|
40356
|
+
var z = Math.log(n);
|
|
40357
|
+
var s = 0.5 * Math.exp(2 * z / 3);
|
|
40358
|
+
var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
|
|
40359
|
+
var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
|
|
40360
|
+
var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
|
|
40361
|
+
quickselectStep(arr, k, newLeft, newRight, compare);
|
|
40362
|
+
}
|
|
40363
|
+
|
|
40364
|
+
var t = arr[k];
|
|
40365
|
+
var i = left;
|
|
40366
|
+
var j = right;
|
|
40367
|
+
|
|
40368
|
+
swap(arr, left, k);
|
|
40369
|
+
if (compare(arr[right], t) > 0) swap(arr, left, right);
|
|
40370
|
+
|
|
40371
|
+
while (i < j) {
|
|
40372
|
+
swap(arr, i, j);
|
|
40373
|
+
i++;
|
|
40374
|
+
j--;
|
|
40375
|
+
while (compare(arr[i], t) < 0) i++;
|
|
40376
|
+
while (compare(arr[j], t) > 0) j--;
|
|
40377
|
+
}
|
|
40378
|
+
|
|
40379
|
+
if (compare(arr[left], t) === 0) swap(arr, left, j);
|
|
40380
|
+
else {
|
|
40381
|
+
j++;
|
|
40382
|
+
swap(arr, j, right);
|
|
40383
|
+
}
|
|
40384
|
+
|
|
40385
|
+
if (j <= k) left = j + 1;
|
|
40386
|
+
if (k <= j) right = j - 1;
|
|
40387
|
+
}
|
|
40388
|
+
}
|
|
40389
|
+
|
|
40390
|
+
function swap(arr, i, j) {
|
|
40391
|
+
var tmp = arr[i];
|
|
40392
|
+
arr[i] = arr[j];
|
|
40393
|
+
arr[j] = tmp;
|
|
40394
|
+
}
|
|
40395
|
+
|
|
40396
|
+
function defaultCompare(a, b) {
|
|
40397
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
40398
|
+
}
|
|
40399
|
+
|
|
40400
|
+
class RBush {
|
|
40401
|
+
constructor(maxEntries = 9) {
|
|
40402
|
+
// max entries in a node is 9 by default; min node fill is 40% for best performance
|
|
40403
|
+
this._maxEntries = Math.max(4, maxEntries);
|
|
40404
|
+
this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
|
|
40405
|
+
this.clear();
|
|
40406
|
+
}
|
|
40407
|
+
|
|
40408
|
+
all() {
|
|
40409
|
+
return this._all(this.data, []);
|
|
40410
|
+
}
|
|
40411
|
+
|
|
40412
|
+
search(bbox) {
|
|
40413
|
+
let node = this.data;
|
|
40414
|
+
const result = [];
|
|
40415
|
+
|
|
40416
|
+
if (!intersects(bbox, node)) return result;
|
|
40417
|
+
|
|
40418
|
+
const toBBox = this.toBBox;
|
|
40419
|
+
const nodesToSearch = [];
|
|
40420
|
+
|
|
40421
|
+
while (node) {
|
|
40422
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
40423
|
+
const child = node.children[i];
|
|
40424
|
+
const childBBox = node.leaf ? toBBox(child) : child;
|
|
40425
|
+
|
|
40426
|
+
if (intersects(bbox, childBBox)) {
|
|
40427
|
+
if (node.leaf) result.push(child);
|
|
40428
|
+
else if (contains(bbox, childBBox)) this._all(child, result);
|
|
40429
|
+
else nodesToSearch.push(child);
|
|
40430
|
+
}
|
|
40431
|
+
}
|
|
40432
|
+
node = nodesToSearch.pop();
|
|
40433
|
+
}
|
|
40434
|
+
|
|
40435
|
+
return result;
|
|
40436
|
+
}
|
|
40437
|
+
|
|
40438
|
+
collides(bbox) {
|
|
40439
|
+
let node = this.data;
|
|
40440
|
+
|
|
40441
|
+
if (!intersects(bbox, node)) return false;
|
|
40442
|
+
|
|
40443
|
+
const nodesToSearch = [];
|
|
40444
|
+
while (node) {
|
|
40445
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
40446
|
+
const child = node.children[i];
|
|
40447
|
+
const childBBox = node.leaf ? this.toBBox(child) : child;
|
|
40448
|
+
|
|
40449
|
+
if (intersects(bbox, childBBox)) {
|
|
40450
|
+
if (node.leaf || contains(bbox, childBBox)) return true;
|
|
40451
|
+
nodesToSearch.push(child);
|
|
40452
|
+
}
|
|
40453
|
+
}
|
|
40454
|
+
node = nodesToSearch.pop();
|
|
40455
|
+
}
|
|
40456
|
+
|
|
40457
|
+
return false;
|
|
40458
|
+
}
|
|
40459
|
+
|
|
40460
|
+
load(data) {
|
|
40461
|
+
if (!(data && data.length)) return this;
|
|
40462
|
+
|
|
40463
|
+
if (data.length < this._minEntries) {
|
|
40464
|
+
for (let i = 0; i < data.length; i++) {
|
|
40465
|
+
this.insert(data[i]);
|
|
40466
|
+
}
|
|
40467
|
+
return this;
|
|
40468
|
+
}
|
|
40469
|
+
|
|
40470
|
+
// recursively build the tree with the given data from scratch using OMT algorithm
|
|
40471
|
+
let node = this._build(data.slice(), 0, data.length - 1, 0);
|
|
40472
|
+
|
|
40473
|
+
if (!this.data.children.length) {
|
|
40474
|
+
// save as is if tree is empty
|
|
40475
|
+
this.data = node;
|
|
40476
|
+
|
|
40477
|
+
} else if (this.data.height === node.height) {
|
|
40478
|
+
// split root if trees have the same height
|
|
40479
|
+
this._splitRoot(this.data, node);
|
|
40480
|
+
|
|
40481
|
+
} else {
|
|
40482
|
+
if (this.data.height < node.height) {
|
|
40483
|
+
// swap trees if inserted one is bigger
|
|
40484
|
+
const tmpNode = this.data;
|
|
40485
|
+
this.data = node;
|
|
40486
|
+
node = tmpNode;
|
|
40487
|
+
}
|
|
40488
|
+
|
|
40489
|
+
// insert the small tree into the large tree at appropriate level
|
|
40490
|
+
this._insert(node, this.data.height - node.height - 1, true);
|
|
40491
|
+
}
|
|
40492
|
+
|
|
40493
|
+
return this;
|
|
40494
|
+
}
|
|
40495
|
+
|
|
40496
|
+
insert(item) {
|
|
40497
|
+
if (item) this._insert(item, this.data.height - 1);
|
|
40498
|
+
return this;
|
|
40499
|
+
}
|
|
40500
|
+
|
|
40501
|
+
clear() {
|
|
40502
|
+
this.data = createNode([]);
|
|
40503
|
+
return this;
|
|
40504
|
+
}
|
|
40505
|
+
|
|
40506
|
+
remove(item, equalsFn) {
|
|
40507
|
+
if (!item) return this;
|
|
40508
|
+
|
|
40509
|
+
let node = this.data;
|
|
40510
|
+
const bbox = this.toBBox(item);
|
|
40511
|
+
const path = [];
|
|
40512
|
+
const indexes = [];
|
|
40513
|
+
let i, parent, goingUp;
|
|
40514
|
+
|
|
40515
|
+
// depth-first iterative tree traversal
|
|
40516
|
+
while (node || path.length) {
|
|
40517
|
+
|
|
40518
|
+
if (!node) { // go up
|
|
40519
|
+
node = path.pop();
|
|
40520
|
+
parent = path[path.length - 1];
|
|
40521
|
+
i = indexes.pop();
|
|
40522
|
+
goingUp = true;
|
|
40523
|
+
}
|
|
40524
|
+
|
|
40525
|
+
if (node.leaf) { // check current node
|
|
40526
|
+
const index = findItem(item, node.children, equalsFn);
|
|
40527
|
+
|
|
40528
|
+
if (index !== -1) {
|
|
40529
|
+
// item found, remove the item and condense tree upwards
|
|
40530
|
+
node.children.splice(index, 1);
|
|
40531
|
+
path.push(node);
|
|
40532
|
+
this._condense(path);
|
|
40533
|
+
return this;
|
|
40534
|
+
}
|
|
40535
|
+
}
|
|
40536
|
+
|
|
40537
|
+
if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
|
|
40538
|
+
path.push(node);
|
|
40539
|
+
indexes.push(i);
|
|
40540
|
+
i = 0;
|
|
40541
|
+
parent = node;
|
|
40542
|
+
node = node.children[0];
|
|
40543
|
+
|
|
40544
|
+
} else if (parent) { // go right
|
|
40545
|
+
i++;
|
|
40546
|
+
node = parent.children[i];
|
|
40547
|
+
goingUp = false;
|
|
40548
|
+
|
|
40549
|
+
} else node = null; // nothing found
|
|
40550
|
+
}
|
|
40551
|
+
|
|
40552
|
+
return this;
|
|
40553
|
+
}
|
|
40554
|
+
|
|
40555
|
+
toBBox(item) { return item; }
|
|
40556
|
+
|
|
40557
|
+
compareMinX(a, b) { return a.minX - b.minX; }
|
|
40558
|
+
compareMinY(a, b) { return a.minY - b.minY; }
|
|
40559
|
+
|
|
40560
|
+
toJSON() { return this.data; }
|
|
40561
|
+
|
|
40562
|
+
fromJSON(data) {
|
|
40563
|
+
this.data = data;
|
|
40564
|
+
return this;
|
|
40565
|
+
}
|
|
40566
|
+
|
|
40567
|
+
_all(node, result) {
|
|
40568
|
+
const nodesToSearch = [];
|
|
40569
|
+
while (node) {
|
|
40570
|
+
if (node.leaf) result.push(...node.children);
|
|
40571
|
+
else nodesToSearch.push(...node.children);
|
|
40572
|
+
|
|
40573
|
+
node = nodesToSearch.pop();
|
|
40574
|
+
}
|
|
40575
|
+
return result;
|
|
40576
|
+
}
|
|
40577
|
+
|
|
40578
|
+
_build(items, left, right, height) {
|
|
40579
|
+
|
|
40580
|
+
const N = right - left + 1;
|
|
40581
|
+
let M = this._maxEntries;
|
|
40582
|
+
let node;
|
|
40583
|
+
|
|
40584
|
+
if (N <= M) {
|
|
40585
|
+
// reached leaf level; return leaf
|
|
40586
|
+
node = createNode(items.slice(left, right + 1));
|
|
40587
|
+
calcBBox(node, this.toBBox);
|
|
40588
|
+
return node;
|
|
40589
|
+
}
|
|
40590
|
+
|
|
40591
|
+
if (!height) {
|
|
40592
|
+
// target height of the bulk-loaded tree
|
|
40593
|
+
height = Math.ceil(Math.log(N) / Math.log(M));
|
|
40594
|
+
|
|
40595
|
+
// target number of root entries to maximize storage utilization
|
|
40596
|
+
M = Math.ceil(N / Math.pow(M, height - 1));
|
|
40597
|
+
}
|
|
40598
|
+
|
|
40599
|
+
node = createNode([]);
|
|
40600
|
+
node.leaf = false;
|
|
40601
|
+
node.height = height;
|
|
40602
|
+
|
|
40603
|
+
// split the items into M mostly square tiles
|
|
40604
|
+
|
|
40605
|
+
const N2 = Math.ceil(N / M);
|
|
40606
|
+
const N1 = N2 * Math.ceil(Math.sqrt(M));
|
|
40607
|
+
|
|
40608
|
+
multiSelect(items, left, right, N1, this.compareMinX);
|
|
40609
|
+
|
|
40610
|
+
for (let i = left; i <= right; i += N1) {
|
|
40611
|
+
|
|
40612
|
+
const right2 = Math.min(i + N1 - 1, right);
|
|
40613
|
+
|
|
40614
|
+
multiSelect(items, i, right2, N2, this.compareMinY);
|
|
40615
|
+
|
|
40616
|
+
for (let j = i; j <= right2; j += N2) {
|
|
40617
|
+
|
|
40618
|
+
const right3 = Math.min(j + N2 - 1, right2);
|
|
40619
|
+
|
|
40620
|
+
// pack each entry recursively
|
|
40621
|
+
node.children.push(this._build(items, j, right3, height - 1));
|
|
40622
|
+
}
|
|
40623
|
+
}
|
|
40624
|
+
|
|
40625
|
+
calcBBox(node, this.toBBox);
|
|
40626
|
+
|
|
40627
|
+
return node;
|
|
40628
|
+
}
|
|
40629
|
+
|
|
40630
|
+
_chooseSubtree(bbox, node, level, path) {
|
|
40631
|
+
while (true) {
|
|
40632
|
+
path.push(node);
|
|
40633
|
+
|
|
40634
|
+
if (node.leaf || path.length - 1 === level) break;
|
|
40635
|
+
|
|
40636
|
+
let minArea = Infinity;
|
|
40637
|
+
let minEnlargement = Infinity;
|
|
40638
|
+
let targetNode;
|
|
40639
|
+
|
|
40640
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
40641
|
+
const child = node.children[i];
|
|
40642
|
+
const area = bboxArea(child);
|
|
40643
|
+
const enlargement = enlargedArea(bbox, child) - area;
|
|
40644
|
+
|
|
40645
|
+
// choose entry with the least area enlargement
|
|
40646
|
+
if (enlargement < minEnlargement) {
|
|
40647
|
+
minEnlargement = enlargement;
|
|
40648
|
+
minArea = area < minArea ? area : minArea;
|
|
40649
|
+
targetNode = child;
|
|
40650
|
+
|
|
40651
|
+
} else if (enlargement === minEnlargement) {
|
|
40652
|
+
// otherwise choose one with the smallest area
|
|
40653
|
+
if (area < minArea) {
|
|
40654
|
+
minArea = area;
|
|
40655
|
+
targetNode = child;
|
|
40656
|
+
}
|
|
40657
|
+
}
|
|
40658
|
+
}
|
|
40659
|
+
|
|
40660
|
+
node = targetNode || node.children[0];
|
|
40661
|
+
}
|
|
40662
|
+
|
|
40663
|
+
return node;
|
|
40664
|
+
}
|
|
40665
|
+
|
|
40666
|
+
_insert(item, level, isNode) {
|
|
40667
|
+
const bbox = isNode ? item : this.toBBox(item);
|
|
40668
|
+
const insertPath = [];
|
|
40669
|
+
|
|
40670
|
+
// find the best node for accommodating the item, saving all nodes along the path too
|
|
40671
|
+
const node = this._chooseSubtree(bbox, this.data, level, insertPath);
|
|
40672
|
+
|
|
40673
|
+
// put the item into the node
|
|
40674
|
+
node.children.push(item);
|
|
40675
|
+
extend(node, bbox);
|
|
40676
|
+
|
|
40677
|
+
// split on node overflow; propagate upwards if necessary
|
|
40678
|
+
while (level >= 0) {
|
|
40679
|
+
if (insertPath[level].children.length > this._maxEntries) {
|
|
40680
|
+
this._split(insertPath, level);
|
|
40681
|
+
level--;
|
|
40682
|
+
} else break;
|
|
40683
|
+
}
|
|
40684
|
+
|
|
40685
|
+
// adjust bboxes along the insertion path
|
|
40686
|
+
this._adjustParentBBoxes(bbox, insertPath, level);
|
|
40687
|
+
}
|
|
40688
|
+
|
|
40689
|
+
// split overflowed node into two
|
|
40690
|
+
_split(insertPath, level) {
|
|
40691
|
+
const node = insertPath[level];
|
|
40692
|
+
const M = node.children.length;
|
|
40693
|
+
const m = this._minEntries;
|
|
40694
|
+
|
|
40695
|
+
this._chooseSplitAxis(node, m, M);
|
|
40696
|
+
|
|
40697
|
+
const splitIndex = this._chooseSplitIndex(node, m, M);
|
|
40698
|
+
|
|
40699
|
+
const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
|
|
40700
|
+
newNode.height = node.height;
|
|
40701
|
+
newNode.leaf = node.leaf;
|
|
40702
|
+
|
|
40703
|
+
calcBBox(node, this.toBBox);
|
|
40704
|
+
calcBBox(newNode, this.toBBox);
|
|
40705
|
+
|
|
40706
|
+
if (level) insertPath[level - 1].children.push(newNode);
|
|
40707
|
+
else this._splitRoot(node, newNode);
|
|
40708
|
+
}
|
|
40709
|
+
|
|
40710
|
+
_splitRoot(node, newNode) {
|
|
40711
|
+
// split root node
|
|
40712
|
+
this.data = createNode([node, newNode]);
|
|
40713
|
+
this.data.height = node.height + 1;
|
|
40714
|
+
this.data.leaf = false;
|
|
40715
|
+
calcBBox(this.data, this.toBBox);
|
|
40716
|
+
}
|
|
40717
|
+
|
|
40718
|
+
_chooseSplitIndex(node, m, M) {
|
|
40719
|
+
let index;
|
|
40720
|
+
let minOverlap = Infinity;
|
|
40721
|
+
let minArea = Infinity;
|
|
40722
|
+
|
|
40723
|
+
for (let i = m; i <= M - m; i++) {
|
|
40724
|
+
const bbox1 = distBBox(node, 0, i, this.toBBox);
|
|
40725
|
+
const bbox2 = distBBox(node, i, M, this.toBBox);
|
|
40726
|
+
|
|
40727
|
+
const overlap = intersectionArea(bbox1, bbox2);
|
|
40728
|
+
const area = bboxArea(bbox1) + bboxArea(bbox2);
|
|
40729
|
+
|
|
40730
|
+
// choose distribution with minimum overlap
|
|
40731
|
+
if (overlap < minOverlap) {
|
|
40732
|
+
minOverlap = overlap;
|
|
40733
|
+
index = i;
|
|
40734
|
+
|
|
40735
|
+
minArea = area < minArea ? area : minArea;
|
|
40736
|
+
|
|
40737
|
+
} else if (overlap === minOverlap) {
|
|
40738
|
+
// otherwise choose distribution with minimum area
|
|
40739
|
+
if (area < minArea) {
|
|
40740
|
+
minArea = area;
|
|
40741
|
+
index = i;
|
|
40742
|
+
}
|
|
40743
|
+
}
|
|
40744
|
+
}
|
|
40745
|
+
|
|
40746
|
+
return index || M - m;
|
|
40747
|
+
}
|
|
40748
|
+
|
|
40749
|
+
// sorts node children by the best axis for split
|
|
40750
|
+
_chooseSplitAxis(node, m, M) {
|
|
40751
|
+
const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
|
|
40752
|
+
const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
|
|
40753
|
+
const xMargin = this._allDistMargin(node, m, M, compareMinX);
|
|
40754
|
+
const yMargin = this._allDistMargin(node, m, M, compareMinY);
|
|
40755
|
+
|
|
40756
|
+
// if total distributions margin value is minimal for x, sort by minX,
|
|
40757
|
+
// otherwise it's already sorted by minY
|
|
40758
|
+
if (xMargin < yMargin) node.children.sort(compareMinX);
|
|
40759
|
+
}
|
|
40760
|
+
|
|
40761
|
+
// total margin of all possible split distributions where each node is at least m full
|
|
40762
|
+
_allDistMargin(node, m, M, compare) {
|
|
40763
|
+
node.children.sort(compare);
|
|
40764
|
+
|
|
40765
|
+
const toBBox = this.toBBox;
|
|
40766
|
+
const leftBBox = distBBox(node, 0, m, toBBox);
|
|
40767
|
+
const rightBBox = distBBox(node, M - m, M, toBBox);
|
|
40768
|
+
let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
|
|
40769
|
+
|
|
40770
|
+
for (let i = m; i < M - m; i++) {
|
|
40771
|
+
const child = node.children[i];
|
|
40772
|
+
extend(leftBBox, node.leaf ? toBBox(child) : child);
|
|
40773
|
+
margin += bboxMargin(leftBBox);
|
|
40774
|
+
}
|
|
40775
|
+
|
|
40776
|
+
for (let i = M - m - 1; i >= m; i--) {
|
|
40777
|
+
const child = node.children[i];
|
|
40778
|
+
extend(rightBBox, node.leaf ? toBBox(child) : child);
|
|
40779
|
+
margin += bboxMargin(rightBBox);
|
|
40780
|
+
}
|
|
40781
|
+
|
|
40782
|
+
return margin;
|
|
40783
|
+
}
|
|
40784
|
+
|
|
40785
|
+
_adjustParentBBoxes(bbox, path, level) {
|
|
40786
|
+
// adjust bboxes along the given tree path
|
|
40787
|
+
for (let i = level; i >= 0; i--) {
|
|
40788
|
+
extend(path[i], bbox);
|
|
40789
|
+
}
|
|
40790
|
+
}
|
|
40791
|
+
|
|
40792
|
+
_condense(path) {
|
|
40793
|
+
// go through the path, removing empty nodes and updating bboxes
|
|
40794
|
+
for (let i = path.length - 1, siblings; i >= 0; i--) {
|
|
40795
|
+
if (path[i].children.length === 0) {
|
|
40796
|
+
if (i > 0) {
|
|
40797
|
+
siblings = path[i - 1].children;
|
|
40798
|
+
siblings.splice(siblings.indexOf(path[i]), 1);
|
|
40799
|
+
|
|
40800
|
+
} else this.clear();
|
|
40801
|
+
|
|
40802
|
+
} else calcBBox(path[i], this.toBBox);
|
|
40803
|
+
}
|
|
40804
|
+
}
|
|
40805
|
+
}
|
|
40806
|
+
|
|
40807
|
+
function findItem(item, items, equalsFn) {
|
|
40808
|
+
if (!equalsFn) return items.indexOf(item);
|
|
40809
|
+
|
|
40810
|
+
for (let i = 0; i < items.length; i++) {
|
|
40811
|
+
if (equalsFn(item, items[i])) return i;
|
|
40812
|
+
}
|
|
40813
|
+
return -1;
|
|
40814
|
+
}
|
|
40815
|
+
|
|
40816
|
+
// calculate node's bbox from bboxes of its children
|
|
40817
|
+
function calcBBox(node, toBBox) {
|
|
40818
|
+
distBBox(node, 0, node.children.length, toBBox, node);
|
|
40819
|
+
}
|
|
40820
|
+
|
|
40821
|
+
// min bounding rectangle of node children from k to p-1
|
|
40822
|
+
function distBBox(node, k, p, toBBox, destNode) {
|
|
40823
|
+
if (!destNode) destNode = createNode(null);
|
|
40824
|
+
destNode.minX = Infinity;
|
|
40825
|
+
destNode.minY = Infinity;
|
|
40826
|
+
destNode.maxX = -Infinity;
|
|
40827
|
+
destNode.maxY = -Infinity;
|
|
40828
|
+
|
|
40829
|
+
for (let i = k; i < p; i++) {
|
|
40830
|
+
const child = node.children[i];
|
|
40831
|
+
extend(destNode, node.leaf ? toBBox(child) : child);
|
|
40832
|
+
}
|
|
40833
|
+
|
|
40834
|
+
return destNode;
|
|
40835
|
+
}
|
|
40836
|
+
|
|
40837
|
+
function extend(a, b) {
|
|
40838
|
+
a.minX = Math.min(a.minX, b.minX);
|
|
40839
|
+
a.minY = Math.min(a.minY, b.minY);
|
|
40840
|
+
a.maxX = Math.max(a.maxX, b.maxX);
|
|
40841
|
+
a.maxY = Math.max(a.maxY, b.maxY);
|
|
40842
|
+
return a;
|
|
40843
|
+
}
|
|
40844
|
+
|
|
40845
|
+
function compareNodeMinX(a, b) { return a.minX - b.minX; }
|
|
40846
|
+
function compareNodeMinY(a, b) { return a.minY - b.minY; }
|
|
40847
|
+
|
|
40848
|
+
function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
|
|
40849
|
+
function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
|
|
40850
|
+
|
|
40851
|
+
function enlargedArea(a, b) {
|
|
40852
|
+
return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
|
|
40853
|
+
(Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
|
|
40854
|
+
}
|
|
40855
|
+
|
|
40856
|
+
function intersectionArea(a, b) {
|
|
40857
|
+
const minX = Math.max(a.minX, b.minX);
|
|
40858
|
+
const minY = Math.max(a.minY, b.minY);
|
|
40859
|
+
const maxX = Math.min(a.maxX, b.maxX);
|
|
40860
|
+
const maxY = Math.min(a.maxY, b.maxY);
|
|
40861
|
+
|
|
40862
|
+
return Math.max(0, maxX - minX) *
|
|
40863
|
+
Math.max(0, maxY - minY);
|
|
40864
|
+
}
|
|
40865
|
+
|
|
40866
|
+
function contains(a, b) {
|
|
40867
|
+
return a.minX <= b.minX &&
|
|
40868
|
+
a.minY <= b.minY &&
|
|
40869
|
+
b.maxX <= a.maxX &&
|
|
40870
|
+
b.maxY <= a.maxY;
|
|
40871
|
+
}
|
|
40872
|
+
|
|
40873
|
+
function intersects(a, b) {
|
|
40874
|
+
return b.minX <= a.maxX &&
|
|
40875
|
+
b.minY <= a.maxY &&
|
|
40876
|
+
b.maxX >= a.minX &&
|
|
40877
|
+
b.maxY >= a.minY;
|
|
40878
|
+
}
|
|
40879
|
+
|
|
40880
|
+
function createNode(children) {
|
|
40881
|
+
return {
|
|
40882
|
+
children,
|
|
40883
|
+
height: 1,
|
|
40884
|
+
leaf: true,
|
|
40885
|
+
minX: Infinity,
|
|
40886
|
+
minY: Infinity,
|
|
40887
|
+
maxX: -Infinity,
|
|
40888
|
+
maxY: -Infinity
|
|
40889
|
+
};
|
|
40890
|
+
}
|
|
40891
|
+
|
|
40892
|
+
// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
|
|
40893
|
+
// combines selection algorithm with binary divide & conquer approach
|
|
40894
|
+
|
|
40895
|
+
function multiSelect(arr, left, right, n, compare) {
|
|
40896
|
+
const stack = [left, right];
|
|
40897
|
+
|
|
40898
|
+
while (stack.length) {
|
|
40899
|
+
right = stack.pop();
|
|
40900
|
+
left = stack.pop();
|
|
40901
|
+
|
|
40902
|
+
if (right - left <= n) continue;
|
|
40903
|
+
|
|
40904
|
+
const mid = left + Math.ceil((right - left) / n / 2) * n;
|
|
40905
|
+
quickselect(arr, mid, left, right, compare);
|
|
40906
|
+
|
|
40907
|
+
stack.push(left, mid, mid, right);
|
|
40908
|
+
}
|
|
40909
|
+
}
|
|
40910
|
+
|
|
40065
40911
|
/**
|
|
40066
|
-
*
|
|
40912
|
+
* R-Tree Data Structure
|
|
40913
|
+
*
|
|
40914
|
+
* R-Tree is a spatial data structure used for efficient indexing and querying
|
|
40915
|
+
* of multi-dimensional objects, particularly in geometric and spatial applications.
|
|
40916
|
+
*
|
|
40917
|
+
* It organizes objects into a tree hierarchy, grouping nearby objects together
|
|
40918
|
+
* in bounding boxes. Each node in the tree represents a bounding box that
|
|
40919
|
+
* contains its child nodes or leaf objects. This hierarchical structure allows
|
|
40920
|
+
* for faster spatial queries.
|
|
40921
|
+
*
|
|
40922
|
+
* @see https://en.wikipedia.org/wiki/R-tree
|
|
40923
|
+
*
|
|
40924
|
+
* Consider a 2D Space with four zones: A, B, C, D
|
|
40925
|
+
* +--------------------------+
|
|
40926
|
+
* | |
|
|
40927
|
+
* | +---+ +-------+ |
|
|
40928
|
+
* | | A | | B | |
|
|
40929
|
+
* | +---+ +-------+ |
|
|
40930
|
+
* | |
|
|
40931
|
+
* | |
|
|
40932
|
+
* | +---+ |
|
|
40933
|
+
* | | C | |
|
|
40934
|
+
* | +---+ |
|
|
40935
|
+
* | +-----------+ |
|
|
40936
|
+
* | | D | |
|
|
40937
|
+
* | +-----------+ |
|
|
40938
|
+
* | |
|
|
40939
|
+
* +--------------------------+
|
|
40940
|
+
*
|
|
40941
|
+
* It groups together zones that are spatially close into a minimum bounding box.
|
|
40942
|
+
* For example, A and B are grouped together in rectangle R1, and C and D are grouped
|
|
40943
|
+
* in R2.
|
|
40944
|
+
*
|
|
40945
|
+
* R0
|
|
40946
|
+
* +--------------------------+
|
|
40947
|
+
* | R1 |
|
|
40948
|
+
* | +-----------------+ |
|
|
40949
|
+
* | | A | | B | |
|
|
40950
|
+
* | +-----------------+ |
|
|
40951
|
+
* | |
|
|
40952
|
+
* | R2 |
|
|
40953
|
+
* | +---+---+---+ |
|
|
40954
|
+
* | | | C | | |
|
|
40955
|
+
* | | +---+ | |
|
|
40956
|
+
* | +-----------+ |
|
|
40957
|
+
* | | D | |
|
|
40958
|
+
* | +-----------+ |
|
|
40959
|
+
* | |
|
|
40960
|
+
* +--------------------------+
|
|
40961
|
+
*
|
|
40962
|
+
* The tree would look like this:
|
|
40963
|
+
* R0
|
|
40964
|
+
* / \
|
|
40965
|
+
* / \
|
|
40966
|
+
* R1 R2
|
|
40967
|
+
* | |
|
|
40968
|
+
* A,B C,D
|
|
40969
|
+
|
|
40970
|
+
* Choosing how to group the zones is crucial for the performance of the tree.
|
|
40971
|
+
* Key considerations include avoiding excessive empty space coverage and minimizing overlap
|
|
40972
|
+
* to reduce the number of subtrees processed during searches.
|
|
40973
|
+
*
|
|
40974
|
+
* Various heuristics exist for determining the optimal grouping strategy, such as "least enlargement"
|
|
40975
|
+
* which prioritizes grouping nodes resulting in the smallest increase in bounding box size. In cases where
|
|
40976
|
+
* the choice cannot be made based on this criterion due to the same enlargement for different groupings,
|
|
40977
|
+
* we then evaluate "least area," aiming to minimize the overall area of bounding boxes.
|
|
40978
|
+
*
|
|
40979
|
+
* This implementation is tailored for spreadsheet use, indexing objects associated
|
|
40980
|
+
* with a zone and a sheet.
|
|
40981
|
+
*
|
|
40982
|
+
* It uses the RBush library under the hood. One 2D RBush R-tree per sheet.
|
|
40983
|
+
* @see https://github.com/mourner/rbush
|
|
40984
|
+
*/
|
|
40985
|
+
class SpreadsheetRTree {
|
|
40986
|
+
/**
|
|
40987
|
+
* One 2D R-tree per sheet
|
|
40988
|
+
*/
|
|
40989
|
+
rTrees = {};
|
|
40990
|
+
/**
|
|
40991
|
+
* Bulk-inserts the given items into the tree. Bulk insertion is usually ~2-3 times
|
|
40992
|
+
* faster than inserting items one by one. After bulk loading (bulk insertion into
|
|
40993
|
+
* an empty tree), subsequent query performance is also ~20-30% better.
|
|
40994
|
+
*/
|
|
40995
|
+
constructor(items = []) {
|
|
40996
|
+
const rangesPerSheet = {};
|
|
40997
|
+
for (const item of items) {
|
|
40998
|
+
const sheetId = item.boundingBox.sheetId;
|
|
40999
|
+
if (!rangesPerSheet[sheetId]) {
|
|
41000
|
+
rangesPerSheet[sheetId] = [];
|
|
41001
|
+
}
|
|
41002
|
+
rangesPerSheet[sheetId].push(item);
|
|
41003
|
+
}
|
|
41004
|
+
for (const sheetId in rangesPerSheet) {
|
|
41005
|
+
this.rTrees[sheetId] = new ZoneRBush();
|
|
41006
|
+
this.rTrees[sheetId].load(rangesPerSheet[sheetId]); // bulk-insert
|
|
41007
|
+
}
|
|
41008
|
+
}
|
|
41009
|
+
insert(item) {
|
|
41010
|
+
const sheetId = item.boundingBox.sheetId;
|
|
41011
|
+
if (!this.rTrees[sheetId]) {
|
|
41012
|
+
this.rTrees[sheetId] = new ZoneRBush();
|
|
41013
|
+
}
|
|
41014
|
+
this.rTrees[sheetId].insert(item);
|
|
41015
|
+
}
|
|
41016
|
+
search({ zone, sheetId }) {
|
|
41017
|
+
if (!this.rTrees[sheetId]) {
|
|
41018
|
+
return [];
|
|
41019
|
+
}
|
|
41020
|
+
return this.rTrees[sheetId].search({
|
|
41021
|
+
minX: zone.left,
|
|
41022
|
+
minY: zone.top,
|
|
41023
|
+
maxX: zone.right,
|
|
41024
|
+
maxY: zone.bottom,
|
|
41025
|
+
});
|
|
41026
|
+
}
|
|
41027
|
+
remove(item) {
|
|
41028
|
+
const sheetId = item.boundingBox.sheetId;
|
|
41029
|
+
if (!this.rTrees[sheetId]) {
|
|
41030
|
+
return;
|
|
41031
|
+
}
|
|
41032
|
+
this.rTrees[sheetId].remove(item, deepEquals);
|
|
41033
|
+
}
|
|
41034
|
+
}
|
|
41035
|
+
/**
|
|
41036
|
+
* RBush extension to use zones as bounding boxes
|
|
41037
|
+
*/
|
|
41038
|
+
class ZoneRBush extends RBush {
|
|
41039
|
+
toBBox({ boundingBox }) {
|
|
41040
|
+
const zone = boundingBox.zone;
|
|
41041
|
+
return {
|
|
41042
|
+
minX: zone.left,
|
|
41043
|
+
minY: zone.top,
|
|
41044
|
+
maxX: zone.right,
|
|
41045
|
+
maxY: zone.bottom,
|
|
41046
|
+
};
|
|
41047
|
+
}
|
|
41048
|
+
compareMinX(a, b) {
|
|
41049
|
+
return a.boundingBox.zone.left - b.boundingBox.zone.left;
|
|
41050
|
+
}
|
|
41051
|
+
compareMinY(a, b) {
|
|
41052
|
+
return a.boundingBox.zone.top - b.boundingBox.zone.top;
|
|
41053
|
+
}
|
|
41054
|
+
}
|
|
41055
|
+
|
|
41056
|
+
/**
|
|
41057
|
+
* Implementation of a dependency Graph.
|
|
40067
41058
|
* The graph is used to evaluate the cells in the correct
|
|
40068
41059
|
* order, and should be updated each time a cell's content is modified
|
|
40069
41060
|
*
|
|
41061
|
+
* It uses an R-Tree data structure to efficiently find dependent cells.
|
|
40070
41062
|
*/
|
|
40071
41063
|
class FormulaDependencyGraph {
|
|
40072
|
-
|
|
40073
|
-
* Internal structure:
|
|
40074
|
-
* - key: a cell position (encoded as an integer)
|
|
40075
|
-
* - value: a set of cell positions that depends on the key
|
|
40076
|
-
*
|
|
40077
|
-
* Given
|
|
40078
|
-
* - A1:"= B1 + SQRT(B2)"
|
|
40079
|
-
* - C1:"= B1";
|
|
40080
|
-
* - C2:"= C1"
|
|
40081
|
-
*
|
|
40082
|
-
* we will have something like:
|
|
40083
|
-
* - B1 ---> (A1, C1) meaning A1 and C1 depends on B1
|
|
40084
|
-
* - B2 ---> (A1) meaning A1 depends on B2
|
|
40085
|
-
* - C1 ---> (C2) meaning C2 depends on C1
|
|
40086
|
-
*/
|
|
40087
|
-
inverseDependencies = new Map();
|
|
41064
|
+
encoder;
|
|
40088
41065
|
dependencies = new Map();
|
|
41066
|
+
rTree;
|
|
41067
|
+
constructor(encoder, data = []) {
|
|
41068
|
+
this.encoder = encoder;
|
|
41069
|
+
this.rTree = new SpreadsheetRTree(data);
|
|
41070
|
+
}
|
|
40089
41071
|
removeAllDependencies(formulaPositionId) {
|
|
40090
|
-
const
|
|
40091
|
-
if (!
|
|
41072
|
+
const ranges = this.dependencies.get(formulaPositionId);
|
|
41073
|
+
if (!ranges) {
|
|
40092
41074
|
return;
|
|
40093
41075
|
}
|
|
40094
|
-
for (const
|
|
40095
|
-
this.
|
|
41076
|
+
for (const range of ranges) {
|
|
41077
|
+
this.rTree.remove(range);
|
|
40096
41078
|
}
|
|
40097
41079
|
this.dependencies.delete(formulaPositionId);
|
|
40098
41080
|
}
|
|
40099
41081
|
addDependencies(formulaPositionId, dependencies) {
|
|
40100
|
-
|
|
40101
|
-
|
|
40102
|
-
|
|
40103
|
-
|
|
40104
|
-
|
|
40105
|
-
|
|
40106
|
-
|
|
40107
|
-
|
|
41082
|
+
const rTreeItems = dependencies.map(({ sheetId, zone }) => ({
|
|
41083
|
+
data: formulaPositionId,
|
|
41084
|
+
boundingBox: {
|
|
41085
|
+
zone,
|
|
41086
|
+
sheetId,
|
|
41087
|
+
},
|
|
41088
|
+
}));
|
|
41089
|
+
for (const item of rTreeItems) {
|
|
41090
|
+
this.rTree.insert(item);
|
|
40108
41091
|
}
|
|
40109
41092
|
const existingDependencies = this.dependencies.get(formulaPositionId);
|
|
40110
41093
|
if (existingDependencies) {
|
|
40111
|
-
existingDependencies.push(...
|
|
41094
|
+
existingDependencies.push(...rTreeItems);
|
|
40112
41095
|
}
|
|
40113
41096
|
else {
|
|
40114
|
-
this.dependencies.set(formulaPositionId,
|
|
41097
|
+
this.dependencies.set(formulaPositionId, rTreeItems);
|
|
40115
41098
|
}
|
|
40116
41099
|
}
|
|
40117
41100
|
/**
|
|
@@ -40119,20 +41102,20 @@ class FormulaDependencyGraph {
|
|
|
40119
41102
|
* in the correct order they should be evaluated.
|
|
40120
41103
|
* This is called a topological ordering (excluding cycles)
|
|
40121
41104
|
*/
|
|
40122
|
-
getCellsDependingOn(
|
|
41105
|
+
getCellsDependingOn(ranges) {
|
|
40123
41106
|
const visited = new JetSet();
|
|
40124
|
-
const queue = Array.from(
|
|
41107
|
+
const queue = Array.from(ranges).reverse();
|
|
40125
41108
|
while (queue.length > 0) {
|
|
40126
|
-
const
|
|
40127
|
-
visited.add(
|
|
40128
|
-
const
|
|
40129
|
-
for (const
|
|
40130
|
-
if (!visited.has(
|
|
40131
|
-
queue.push(
|
|
41109
|
+
const range = queue.pop();
|
|
41110
|
+
visited.add(...this.encoder.encodeBoundingBox(range));
|
|
41111
|
+
const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
|
|
41112
|
+
for (const positionId of impactedPositionIds) {
|
|
41113
|
+
if (!visited.has(positionId)) {
|
|
41114
|
+
queue.push(this.encoder.decodeToBoundingBox(positionId));
|
|
40132
41115
|
}
|
|
40133
41116
|
}
|
|
40134
41117
|
}
|
|
40135
|
-
visited.delete(...
|
|
41118
|
+
visited.delete(...ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
|
|
40136
41119
|
return visited;
|
|
40137
41120
|
}
|
|
40138
41121
|
}
|
|
@@ -40220,9 +41203,9 @@ class Evaluator {
|
|
|
40220
41203
|
context;
|
|
40221
41204
|
getters;
|
|
40222
41205
|
compilationParams;
|
|
40223
|
-
|
|
41206
|
+
encoder = new PositionBitsEncoder();
|
|
40224
41207
|
evaluatedCells = new Map();
|
|
40225
|
-
formulaDependencies = lazy(new FormulaDependencyGraph());
|
|
41208
|
+
formulaDependencies = lazy(new FormulaDependencyGraph(this.encoder));
|
|
40226
41209
|
blockedArrayFormulas = new Set();
|
|
40227
41210
|
spreadingRelations = new SpreadingRelation();
|
|
40228
41211
|
constructor(context, getters) {
|
|
@@ -40231,23 +41214,23 @@ class Evaluator {
|
|
|
40231
41214
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40232
41215
|
}
|
|
40233
41216
|
getEvaluatedCell(position) {
|
|
40234
|
-
return (this.evaluatedCells.get(this.
|
|
41217
|
+
return (this.evaluatedCells.get(this.encoder.encode(position)) ||
|
|
40235
41218
|
createEvaluatedCell("", { locale: this.getters.getLocale() }));
|
|
40236
41219
|
}
|
|
40237
41220
|
getSpreadPositionsOf(position) {
|
|
40238
|
-
const positionId = this.
|
|
41221
|
+
const positionId = this.encoder.encode(position);
|
|
40239
41222
|
if (!this.spreadingRelations.isArrayFormula(positionId)) {
|
|
40240
41223
|
return [];
|
|
40241
41224
|
}
|
|
40242
|
-
return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map(this.
|
|
41225
|
+
return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map((positionId) => this.encoder.decode(positionId));
|
|
40243
41226
|
}
|
|
40244
41227
|
getArrayFormulaSpreadingOn(position) {
|
|
40245
|
-
const positionId = this.
|
|
41228
|
+
const positionId = this.encoder.encode(position);
|
|
40246
41229
|
const formulaPosition = this.getArrayFormulaSpreadingOnId(positionId);
|
|
40247
|
-
return formulaPosition !== undefined ? this.
|
|
41230
|
+
return formulaPosition !== undefined ? this.encoder.decode(formulaPosition) : undefined;
|
|
40248
41231
|
}
|
|
40249
41232
|
getEvaluatedPositions() {
|
|
40250
|
-
return [...this.evaluatedCells.keys()].map(this.
|
|
41233
|
+
return [...this.evaluatedCells.keys()].map((p) => this.encoder.decode(p));
|
|
40251
41234
|
}
|
|
40252
41235
|
getArrayFormulaSpreadingOnId(positionId) {
|
|
40253
41236
|
if (!this.spreadingRelations.hasArrayFormulaResult(positionId)) {
|
|
@@ -40257,7 +41240,7 @@ class Evaluator {
|
|
|
40257
41240
|
return Array.from(arrayFormulas).find((positionId) => !this.blockedArrayFormulas.has(positionId));
|
|
40258
41241
|
}
|
|
40259
41242
|
updateDependencies(position) {
|
|
40260
|
-
const positionId = this.
|
|
41243
|
+
const positionId = this.encoder.encode(position);
|
|
40261
41244
|
this.formulaDependencies().removeAllDependencies(positionId);
|
|
40262
41245
|
const dependencies = this.getDirectDependencies(positionId);
|
|
40263
41246
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
@@ -40267,12 +41250,12 @@ class Evaluator {
|
|
|
40267
41250
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40268
41251
|
}
|
|
40269
41252
|
evaluateCells(positions) {
|
|
40270
|
-
const cells = positions.map(this.
|
|
41253
|
+
const cells = positions.map((p) => this.encoder.encode(p));
|
|
40271
41254
|
const cellsToCompute = new JetSet(cells);
|
|
40272
|
-
const
|
|
41255
|
+
const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
|
|
40273
41256
|
cellsToCompute.add(...this.getCellsDependingOn(cells));
|
|
40274
|
-
cellsToCompute.add(...
|
|
40275
|
-
cellsToCompute.add(...this.getCellsDependingOn(
|
|
41257
|
+
cellsToCompute.add(...arrayFormulasPositionIds);
|
|
41258
|
+
cellsToCompute.add(...this.getCellsDependingOn(arrayFormulasPositionIds));
|
|
40276
41259
|
this.evaluate(cellsToCompute);
|
|
40277
41260
|
}
|
|
40278
41261
|
getArrayFormulasImpactedByChangesOf(positionIds) {
|
|
@@ -40295,12 +41278,14 @@ class Evaluator {
|
|
|
40295
41278
|
this.blockedArrayFormulas = new Set();
|
|
40296
41279
|
this.spreadingRelations = new SpreadingRelation();
|
|
40297
41280
|
this.formulaDependencies = lazy(() => {
|
|
40298
|
-
const
|
|
40299
|
-
|
|
40300
|
-
|
|
40301
|
-
|
|
40302
|
-
|
|
40303
|
-
|
|
41281
|
+
const dependencies = [...this.getAllCells()].flatMap((positionId) => this.getDirectDependencies(positionId).map((range) => ({
|
|
41282
|
+
data: positionId,
|
|
41283
|
+
boundingBox: {
|
|
41284
|
+
zone: range.zone,
|
|
41285
|
+
sheetId: range.sheetId,
|
|
41286
|
+
},
|
|
41287
|
+
})));
|
|
41288
|
+
return new FormulaDependencyGraph(this.encoder, dependencies);
|
|
40304
41289
|
});
|
|
40305
41290
|
}
|
|
40306
41291
|
evaluateAllCells() {
|
|
@@ -40322,7 +41307,7 @@ class Evaluator {
|
|
|
40322
41307
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
40323
41308
|
const cellIds = this.getters.getCells(sheetId);
|
|
40324
41309
|
for (const cellId in cellIds) {
|
|
40325
|
-
positionIds.add(this.
|
|
41310
|
+
positionIds.add(this.encoder.encode(this.getters.getCellPosition(cellId)));
|
|
40326
41311
|
}
|
|
40327
41312
|
}
|
|
40328
41313
|
return positionIds;
|
|
@@ -40367,7 +41352,7 @@ class Evaluator {
|
|
|
40367
41352
|
if (!this.blockedArrayFormulas.has(positionId)) {
|
|
40368
41353
|
this.invalidateSpreading(positionId);
|
|
40369
41354
|
}
|
|
40370
|
-
const cellPosition = this.
|
|
41355
|
+
const cellPosition = this.encoder.decode(positionId);
|
|
40371
41356
|
const cell = this.getters.getCell(cellPosition);
|
|
40372
41357
|
if (cell === undefined) {
|
|
40373
41358
|
return createEvaluatedCell("", { locale: this.getters.getLocale() });
|
|
@@ -40390,7 +41375,7 @@ class Evaluator {
|
|
|
40390
41375
|
}
|
|
40391
41376
|
}
|
|
40392
41377
|
computeAndSave(position) {
|
|
40393
|
-
const positionId = this.
|
|
41378
|
+
const positionId = this.encoder.encode(position);
|
|
40394
41379
|
const evaluatedCell = this.computeCell(positionId);
|
|
40395
41380
|
if (!this.evaluatedCells.has(positionId)) {
|
|
40396
41381
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
@@ -40445,15 +41430,15 @@ class Evaluator {
|
|
|
40445
41430
|
throw new Error(_t("Result couldn't be automatically expanded. Please insert more columns and rows."));
|
|
40446
41431
|
}
|
|
40447
41432
|
updateSpreadRelation({ sheetId, col, row, }) {
|
|
40448
|
-
const arrayFormulaPositionId = this.
|
|
41433
|
+
const arrayFormulaPositionId = this.encoder.encode({ sheetId, col, row });
|
|
40449
41434
|
return (i, j) => {
|
|
40450
41435
|
const position = { sheetId, col: i + col, row: j + row };
|
|
40451
|
-
const resultPositionId = this.
|
|
41436
|
+
const resultPositionId = this.encoder.encode(position);
|
|
40452
41437
|
this.spreadingRelations.addRelation({ resultPositionId, arrayFormulaPositionId });
|
|
40453
41438
|
};
|
|
40454
41439
|
}
|
|
40455
41440
|
checkCollision({ sheetId, col, row }) {
|
|
40456
|
-
const formulaPositionId = this.
|
|
41441
|
+
const formulaPositionId = this.encoder.encode({ sheetId, col, row });
|
|
40457
41442
|
return (i, j) => {
|
|
40458
41443
|
const position = { sheetId: sheetId, col: i + col, row: j + row };
|
|
40459
41444
|
const rawCell = this.getters.getCell(position);
|
|
@@ -40474,7 +41459,7 @@ class Evaluator {
|
|
|
40474
41459
|
format: format || matrixResult[i][j]?.format,
|
|
40475
41460
|
locale: this.getters.getLocale(),
|
|
40476
41461
|
});
|
|
40477
|
-
const positionId = this.
|
|
41462
|
+
const positionId = this.encoder.encode(position);
|
|
40478
41463
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
40479
41464
|
// check if formula dependencies present in the spread zone
|
|
40480
41465
|
// if so, they need to be recomputed
|
|
@@ -40506,29 +41491,17 @@ class Evaluator {
|
|
|
40506
41491
|
if (!cell?.isFormula) {
|
|
40507
41492
|
return [];
|
|
40508
41493
|
}
|
|
40509
|
-
|
|
40510
|
-
for (const range of cell.compiledFormula.dependencies) {
|
|
40511
|
-
if (range.invalidSheetName || range.invalidXc) {
|
|
40512
|
-
continue;
|
|
40513
|
-
}
|
|
40514
|
-
const sheetId = range.sheetId;
|
|
40515
|
-
forEachPositionsInZone(range.zone, (col, row) => {
|
|
40516
|
-
dependencies.push(this.encodePosition({ sheetId, col, row }));
|
|
40517
|
-
});
|
|
40518
|
-
}
|
|
40519
|
-
return dependencies;
|
|
41494
|
+
return cell.compiledFormula.dependencies;
|
|
40520
41495
|
}
|
|
40521
41496
|
getCellsDependingOn(positionIds) {
|
|
40522
|
-
|
|
41497
|
+
const ranges = [];
|
|
41498
|
+
for (const positionId of positionIds) {
|
|
41499
|
+
ranges.push(this.encoder.decodeToBoundingBox(positionId));
|
|
41500
|
+
}
|
|
41501
|
+
return this.formulaDependencies().getCellsDependingOn(ranges);
|
|
40523
41502
|
}
|
|
40524
41503
|
getCell(positionId) {
|
|
40525
|
-
return this.getters.getCell(this.
|
|
40526
|
-
}
|
|
40527
|
-
encodePosition(position) {
|
|
40528
|
-
return this.positionEncoder.encode(position);
|
|
40529
|
-
}
|
|
40530
|
-
decodePosition(positionId) {
|
|
40531
|
-
return this.positionEncoder.decode(positionId);
|
|
41504
|
+
return this.getters.getCell(this.encoder.decode(positionId));
|
|
40532
41505
|
}
|
|
40533
41506
|
}
|
|
40534
41507
|
function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
@@ -40584,6 +41557,13 @@ class PositionBitsEncoder {
|
|
|
40584
41557
|
encode({ sheetId, col, row }) {
|
|
40585
41558
|
return (this.encodeSheet(sheetId) << 42n) | (BigInt(col) << 21n) | BigInt(row);
|
|
40586
41559
|
}
|
|
41560
|
+
encodeBoundingBox({ sheetId, zone }) {
|
|
41561
|
+
const positions = [];
|
|
41562
|
+
forEachPositionsInZone(zone, (col, row) => {
|
|
41563
|
+
positions.push(this.encode({ sheetId, col, row }));
|
|
41564
|
+
});
|
|
41565
|
+
return positions;
|
|
41566
|
+
}
|
|
40587
41567
|
decode(id) {
|
|
40588
41568
|
// keep only the last 21 bits by AND-ing the bit sequence with 21 ones
|
|
40589
41569
|
const row = Number(id & 2097151n);
|
|
@@ -40591,6 +41571,10 @@ class PositionBitsEncoder {
|
|
|
40591
41571
|
const sheetId = this.decodeSheet(id >> 42n);
|
|
40592
41572
|
return { sheetId, col, row };
|
|
40593
41573
|
}
|
|
41574
|
+
decodeToBoundingBox(id) {
|
|
41575
|
+
const { sheetId, col, row } = this.decode(id);
|
|
41576
|
+
return { sheetId, zone: { left: col, top: row, right: col, bottom: row } };
|
|
41577
|
+
}
|
|
40594
41578
|
encodeSheet(sheetId) {
|
|
40595
41579
|
const sheetKey = this.sheetMapping[sheetId];
|
|
40596
41580
|
if (sheetKey === undefined) {
|
|
@@ -40773,7 +41757,12 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40773
41757
|
// Getters
|
|
40774
41758
|
// ---------------------------------------------------------------------------
|
|
40775
41759
|
evaluateFormula(sheetId, formulaString) {
|
|
40776
|
-
|
|
41760
|
+
try {
|
|
41761
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
41762
|
+
}
|
|
41763
|
+
catch (error) {
|
|
41764
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
41765
|
+
}
|
|
40777
41766
|
}
|
|
40778
41767
|
/**
|
|
40779
41768
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -41042,7 +42031,7 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
41042
42031
|
}
|
|
41043
42032
|
|
|
41044
42033
|
class EvaluationChartPlugin extends UIPlugin {
|
|
41045
|
-
static getters = ["getChartRuntime", "
|
|
42034
|
+
static getters = ["getChartRuntime", "getStyleOfSingleCellChart"];
|
|
41046
42035
|
charts = {};
|
|
41047
42036
|
createRuntimeChart = chartRuntimeFactory(this.getters);
|
|
41048
42037
|
handle(cmd) {
|
|
@@ -41080,25 +42069,26 @@ class EvaluationChartPlugin extends UIPlugin {
|
|
|
41080
42069
|
return this.charts[figureId];
|
|
41081
42070
|
}
|
|
41082
42071
|
/**
|
|
41083
|
-
* Get the background
|
|
41084
|
-
* of the chart. In order of priority, it will return :
|
|
41085
|
-
*
|
|
41086
|
-
* - the chart background color if one is defined
|
|
41087
|
-
* - the fill color of the cell if one is defined
|
|
41088
|
-
* - the fill color of the cell from conditional formats if one is defined
|
|
41089
|
-
* - the default chart color if no other color is defined
|
|
42072
|
+
* Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
|
|
41090
42073
|
*/
|
|
41091
|
-
|
|
42074
|
+
getStyleOfSingleCellChart(chartBackground, mainRange) {
|
|
41092
42075
|
if (chartBackground)
|
|
41093
|
-
return chartBackground;
|
|
42076
|
+
return { background: chartBackground, fontColor: chartFontColor(chartBackground) };
|
|
41094
42077
|
if (!mainRange) {
|
|
41095
|
-
return
|
|
42078
|
+
return {
|
|
42079
|
+
background: BACKGROUND_CHART_COLOR,
|
|
42080
|
+
fontColor: chartFontColor(BACKGROUND_CHART_COLOR),
|
|
42081
|
+
};
|
|
41096
42082
|
}
|
|
41097
42083
|
const col = mainRange.zone.left;
|
|
41098
42084
|
const row = mainRange.zone.top;
|
|
41099
42085
|
const sheetId = mainRange.sheetId;
|
|
41100
42086
|
const style = this.getters.getCellComputedStyle({ sheetId, col, row });
|
|
41101
|
-
|
|
42087
|
+
const background = style.fillColor || BACKGROUND_CHART_COLOR;
|
|
42088
|
+
return {
|
|
42089
|
+
background,
|
|
42090
|
+
fontColor: style.textColor || chartFontColor(background),
|
|
42091
|
+
};
|
|
41102
42092
|
}
|
|
41103
42093
|
exportForExcel(data) {
|
|
41104
42094
|
for (const sheet of data.sheets) {
|
|
@@ -41209,45 +42199,40 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
41209
42199
|
getComputedStyles(sheetId) {
|
|
41210
42200
|
const computedStyle = {};
|
|
41211
42201
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
41212
|
-
|
|
41213
|
-
|
|
41214
|
-
|
|
41215
|
-
|
|
41216
|
-
|
|
41217
|
-
|
|
41218
|
-
|
|
41219
|
-
|
|
41220
|
-
|
|
41221
|
-
|
|
41222
|
-
|
|
41223
|
-
for (let
|
|
41224
|
-
|
|
41225
|
-
|
|
41226
|
-
|
|
41227
|
-
const
|
|
41228
|
-
|
|
41229
|
-
|
|
41230
|
-
|
|
41231
|
-
|
|
41232
|
-
|
|
41233
|
-
});
|
|
41234
|
-
}
|
|
41235
|
-
return value;
|
|
41236
|
-
});
|
|
41237
|
-
if (predicate && predicate(target, { ...cf.rule, values })) {
|
|
41238
|
-
if (!computedStyle[col])
|
|
41239
|
-
computedStyle[col] = [];
|
|
41240
|
-
// we must combine all the properties of all the CF rules applied to the given cell
|
|
41241
|
-
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
42202
|
+
switch (cf.rule.type) {
|
|
42203
|
+
case "ColorScaleRule":
|
|
42204
|
+
for (let range of cf.ranges) {
|
|
42205
|
+
this.applyColorScale(sheetId, range, cf.rule, computedStyle);
|
|
42206
|
+
}
|
|
42207
|
+
break;
|
|
42208
|
+
case "CellIsRule":
|
|
42209
|
+
const formulas = cf.rule.values.map((value) => value.startsWith("=") ? compile(value) : undefined);
|
|
42210
|
+
for (let ref of cf.ranges) {
|
|
42211
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
42212
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
42213
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
42214
|
+
const predicate = this.rulePredicate[cf.rule.type];
|
|
42215
|
+
const target = { sheetId, col, row };
|
|
42216
|
+
const values = cf.rule.values.map((value, i) => {
|
|
42217
|
+
const compiledFormula = formulas[i];
|
|
42218
|
+
if (compiledFormula) {
|
|
42219
|
+
return this.getters.getTranslatedCellFormula(sheetId, col - zone.left, row - zone.top, {
|
|
42220
|
+
...compiledFormula,
|
|
42221
|
+
dependencies: compiledFormula.dependencies.map((d) => this.getters.getRangeFromSheetXC(sheetId, d)),
|
|
42222
|
+
});
|
|
41242
42223
|
}
|
|
42224
|
+
return value;
|
|
42225
|
+
});
|
|
42226
|
+
if (predicate && predicate(target, { ...cf.rule, values })) {
|
|
42227
|
+
if (!computedStyle[col])
|
|
42228
|
+
computedStyle[col] = [];
|
|
42229
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
42230
|
+
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
41243
42231
|
}
|
|
41244
42232
|
}
|
|
41245
42233
|
}
|
|
41246
|
-
|
|
41247
|
-
|
|
41248
|
-
}
|
|
41249
|
-
catch (_) {
|
|
41250
|
-
// we don't care about the errors within the evaluation of a rule
|
|
42234
|
+
}
|
|
42235
|
+
break;
|
|
41251
42236
|
}
|
|
41252
42237
|
}
|
|
41253
42238
|
return computedStyle;
|
|
@@ -41858,11 +42843,6 @@ class AutofillPlugin extends UIPlugin {
|
|
|
41858
42843
|
return "Success" /* CommandResult.Success */;
|
|
41859
42844
|
}
|
|
41860
42845
|
return "InvalidAutofillSelection" /* CommandResult.InvalidAutofillSelection */;
|
|
41861
|
-
case "AUTOFILL_AUTO":
|
|
41862
|
-
const zone = this.getters.getSelectedZone();
|
|
41863
|
-
return zone.top === zone.bottom
|
|
41864
|
-
? "Success" /* CommandResult.Success */
|
|
41865
|
-
: "CancelledForUnknownReason" /* CommandResult.CancelledForUnknownReason */;
|
|
41866
42846
|
}
|
|
41867
42847
|
return "Success" /* CommandResult.Success */;
|
|
41868
42848
|
}
|
|
@@ -42019,7 +42999,7 @@ class AutofillPlugin extends UIPlugin {
|
|
|
42019
42999
|
let row = zone.bottom;
|
|
42020
43000
|
if (col > 0) {
|
|
42021
43001
|
let leftPosition = { sheetId, col: col - 1, row };
|
|
42022
|
-
while (this.getters.
|
|
43002
|
+
while (this.getters.getCorrespondingFormulaCell(leftPosition) ||
|
|
42023
43003
|
this.getters.getCell(leftPosition)?.content) {
|
|
42024
43004
|
row += 1;
|
|
42025
43005
|
leftPosition = { sheetId, col: col - 1, row };
|
|
@@ -42029,7 +43009,7 @@ class AutofillPlugin extends UIPlugin {
|
|
|
42029
43009
|
col = zone.right;
|
|
42030
43010
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
42031
43011
|
let rightPosition = { sheetId, col: col + 1, row };
|
|
42032
|
-
while (this.getters.
|
|
43012
|
+
while (this.getters.getCorrespondingFormulaCell(rightPosition) ||
|
|
42033
43013
|
this.getters.getCell(rightPosition)?.content) {
|
|
42034
43014
|
row += 1;
|
|
42035
43015
|
rightPosition = { sheetId, col: col + 1, row };
|
|
@@ -43624,7 +44604,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43624
44604
|
isPasteAllowed(target, clipboardOption) {
|
|
43625
44605
|
const sheetId = this.getters.getActiveSheetId();
|
|
43626
44606
|
if (this.operation === "CUT" && clipboardOption?.pasteOption !== undefined) {
|
|
43627
|
-
// cannot paste only format or
|
|
44607
|
+
// cannot paste only format or as value if the previous operation is a CUT
|
|
43628
44608
|
return "WrongPasteOption" /* CommandResult.WrongPasteOption */;
|
|
43629
44609
|
}
|
|
43630
44610
|
if (target.length > 1) {
|
|
@@ -43806,7 +44786,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43806
44786
|
// This condition is used to determine if we have to paste the CF or not.
|
|
43807
44787
|
// We have to do it when the command handled is "PASTE", not "INSERT_CELL"
|
|
43808
44788
|
// or "DELETE_CELL". So, the state should be the local state
|
|
43809
|
-
const shouldPasteCF = clipboardOptions?.pasteOption !== "
|
|
44789
|
+
const shouldPasteCF = clipboardOptions?.pasteOption !== "asValue" && clipboardOptions?.shouldPasteCF;
|
|
43810
44790
|
const shouldPasteDV = !clipboardOptions?.pasteOption;
|
|
43811
44791
|
const sheetId = this.getters.getActiveSheetId();
|
|
43812
44792
|
// first, add missing cols/rows if needed
|
|
@@ -43842,10 +44822,11 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43842
44822
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43843
44823
|
const { sheetId, col, row } = target;
|
|
43844
44824
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43845
|
-
|
|
44825
|
+
const originFormat = origin.cell?.format ?? origin.evaluatedCell.format;
|
|
44826
|
+
if (clipboardOption?.pasteOption === "asValue") {
|
|
43846
44827
|
const locale = this.getters.getLocale();
|
|
43847
44828
|
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43848
|
-
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
44829
|
+
this.dispatch("UPDATE_CELL", { ...target, content, format: originFormat });
|
|
43849
44830
|
return;
|
|
43850
44831
|
}
|
|
43851
44832
|
const targetBorders = this.getters.getCellBorder(target);
|
|
@@ -43861,7 +44842,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43861
44842
|
this.dispatch("UPDATE_CELL", {
|
|
43862
44843
|
...target,
|
|
43863
44844
|
style: origin.cell?.style ?? null,
|
|
43864
|
-
format:
|
|
44845
|
+
format: originFormat ?? targetCell.format,
|
|
43865
44846
|
});
|
|
43866
44847
|
return;
|
|
43867
44848
|
}
|
|
@@ -50064,6 +51045,20 @@ css /* scss */ `
|
|
|
50064
51045
|
`;
|
|
50065
51046
|
class RippleEffect extends owl.Component {
|
|
50066
51047
|
static template = "o-spreadsheet-RippleEffect";
|
|
51048
|
+
static props = {
|
|
51049
|
+
x: String,
|
|
51050
|
+
y: String,
|
|
51051
|
+
color: String,
|
|
51052
|
+
opacity: Number,
|
|
51053
|
+
duration: Number,
|
|
51054
|
+
width: Number,
|
|
51055
|
+
height: Number,
|
|
51056
|
+
offsetY: Number,
|
|
51057
|
+
offsetX: Number,
|
|
51058
|
+
allowOverflow: Boolean,
|
|
51059
|
+
onAnimationEnd: Function,
|
|
51060
|
+
style: String,
|
|
51061
|
+
};
|
|
50067
51062
|
rippleRef = owl.useRef("ripple");
|
|
50068
51063
|
setup() {
|
|
50069
51064
|
let animation = undefined;
|
|
@@ -50099,22 +51094,23 @@ class RippleEffect extends owl.Component {
|
|
|
50099
51094
|
});
|
|
50100
51095
|
}
|
|
50101
51096
|
}
|
|
50102
|
-
RippleEffect.props = {
|
|
50103
|
-
x: String,
|
|
50104
|
-
y: String,
|
|
50105
|
-
color: String,
|
|
50106
|
-
opacity: Number,
|
|
50107
|
-
duration: Number,
|
|
50108
|
-
width: Number,
|
|
50109
|
-
height: Number,
|
|
50110
|
-
offsetY: Number,
|
|
50111
|
-
offsetX: Number,
|
|
50112
|
-
allowOverflow: Boolean,
|
|
50113
|
-
onAnimationEnd: Function,
|
|
50114
|
-
style: String,
|
|
50115
|
-
};
|
|
50116
51097
|
class Ripple extends owl.Component {
|
|
50117
51098
|
static template = "o-spreadsheet-Ripple";
|
|
51099
|
+
static props = {
|
|
51100
|
+
color: { type: String, optional: true },
|
|
51101
|
+
opacity: { type: Number, optional: true },
|
|
51102
|
+
duration: { type: Number, optional: true },
|
|
51103
|
+
ignoreClickPosition: { type: Boolean, optional: true },
|
|
51104
|
+
width: { type: Number, optional: true },
|
|
51105
|
+
height: { type: Number, optional: true },
|
|
51106
|
+
offsetY: { type: Number, optional: true },
|
|
51107
|
+
offsetX: { type: Number, optional: true },
|
|
51108
|
+
allowOverflow: { type: Boolean, optional: true },
|
|
51109
|
+
enabled: { type: Boolean, optional: true },
|
|
51110
|
+
onAnimationEnd: { type: Function, optional: true },
|
|
51111
|
+
slots: Object,
|
|
51112
|
+
class: { type: String, optional: true },
|
|
51113
|
+
};
|
|
50118
51114
|
static components = { RippleEffect };
|
|
50119
51115
|
static defaultProps = {
|
|
50120
51116
|
color: "#aaaaaa",
|
|
@@ -50200,21 +51196,6 @@ class Ripple extends owl.Component {
|
|
|
50200
51196
|
};
|
|
50201
51197
|
}
|
|
50202
51198
|
}
|
|
50203
|
-
Ripple.props = {
|
|
50204
|
-
color: { type: String, optional: true },
|
|
50205
|
-
opacity: { type: Number, optional: true },
|
|
50206
|
-
duration: { type: Number, optional: true },
|
|
50207
|
-
ignoreClickPosition: { type: Boolean, optional: true },
|
|
50208
|
-
width: { type: Number, optional: true },
|
|
50209
|
-
height: { type: Number, optional: true },
|
|
50210
|
-
offsetY: { type: Number, optional: true },
|
|
50211
|
-
offsetX: { type: Number, optional: true },
|
|
50212
|
-
allowOverflow: { type: Boolean, optional: true },
|
|
50213
|
-
enabled: { type: Boolean, optional: true },
|
|
50214
|
-
onAnimationEnd: { type: Function, optional: true },
|
|
50215
|
-
slots: Object,
|
|
50216
|
-
class: { type: String, optional: true },
|
|
50217
|
-
};
|
|
50218
51199
|
|
|
50219
51200
|
function interactiveRenameSheet(env, sheetId, name, errorCallback) {
|
|
50220
51201
|
const result = env.model.dispatch("RENAME_SHEET", { sheetId, name });
|
|
@@ -50272,6 +51253,12 @@ css /* scss */ `
|
|
|
50272
51253
|
`;
|
|
50273
51254
|
class BottomBarSheet extends owl.Component {
|
|
50274
51255
|
static template = "o-spreadsheet-BottomBarSheet";
|
|
51256
|
+
static props = {
|
|
51257
|
+
sheetId: String,
|
|
51258
|
+
openContextMenu: Function,
|
|
51259
|
+
style: { type: String, optional: true },
|
|
51260
|
+
onMouseDown: { type: Function, optional: true },
|
|
51261
|
+
};
|
|
50275
51262
|
static components = { Ripple };
|
|
50276
51263
|
static defaultProps = {
|
|
50277
51264
|
onMouseDown: () => { },
|
|
@@ -50393,12 +51380,6 @@ class BottomBarSheet extends owl.Component {
|
|
|
50393
51380
|
return this.env.model.getters.getSheetName(this.props.sheetId);
|
|
50394
51381
|
}
|
|
50395
51382
|
}
|
|
50396
|
-
BottomBarSheet.props = {
|
|
50397
|
-
sheetId: String,
|
|
50398
|
-
openContextMenu: Function,
|
|
50399
|
-
style: { type: String, optional: true },
|
|
50400
|
-
onMouseDown: { type: Function, optional: true },
|
|
50401
|
-
};
|
|
50402
51383
|
|
|
50403
51384
|
// -----------------------------------------------------------------------------
|
|
50404
51385
|
// SpreadSheet
|
|
@@ -50416,6 +51397,10 @@ css /* scss */ `
|
|
|
50416
51397
|
`;
|
|
50417
51398
|
class BottomBarStatistic extends owl.Component {
|
|
50418
51399
|
static template = "o-spreadsheet-BottomBarStatisic";
|
|
51400
|
+
static props = {
|
|
51401
|
+
openContextMenu: Function,
|
|
51402
|
+
closeContextMenu: Function,
|
|
51403
|
+
};
|
|
50419
51404
|
static components = { Ripple };
|
|
50420
51405
|
selectedStatisticFn = "";
|
|
50421
51406
|
statisticFnResults = {};
|
|
@@ -50462,10 +51447,6 @@ class BottomBarStatistic extends owl.Component {
|
|
|
50462
51447
|
return fnName + ": " + (fnValue !== undefined ? formatValue(fnValue, { locale }) : "__");
|
|
50463
51448
|
}
|
|
50464
51449
|
}
|
|
50465
|
-
BottomBarStatistic.props = {
|
|
50466
|
-
openContextMenu: Function,
|
|
50467
|
-
closeContextMenu: Function,
|
|
50468
|
-
};
|
|
50469
51450
|
|
|
50470
51451
|
// -----------------------------------------------------------------------------
|
|
50471
51452
|
// SpreadSheet
|
|
@@ -50516,6 +51497,9 @@ css /* scss */ `
|
|
|
50516
51497
|
`;
|
|
50517
51498
|
class BottomBar extends owl.Component {
|
|
50518
51499
|
static template = "o-spreadsheet-BottomBar";
|
|
51500
|
+
static props = {
|
|
51501
|
+
onClick: Function,
|
|
51502
|
+
};
|
|
50519
51503
|
static components = { Menu, Ripple, BottomBarSheet, BottomBarStatistic };
|
|
50520
51504
|
bottomBarRef = owl.useRef("bottomBar");
|
|
50521
51505
|
sheetListRef = owl.useRef("sheetList");
|
|
@@ -50701,9 +51685,6 @@ class BottomBar extends owl.Component {
|
|
|
50701
51685
|
return this.sheetListRef.el.scrollWidth - this.sheetListRef.el.clientWidth;
|
|
50702
51686
|
}
|
|
50703
51687
|
}
|
|
50704
|
-
BottomBar.props = {
|
|
50705
|
-
onClick: Function,
|
|
50706
|
-
};
|
|
50707
51688
|
|
|
50708
51689
|
css /* scss */ `
|
|
50709
51690
|
.o-dashboard-clickable-cell {
|
|
@@ -50714,6 +51695,7 @@ css /* scss */ `
|
|
|
50714
51695
|
let tKey = 1;
|
|
50715
51696
|
class SpreadsheetDashboard extends owl.Component {
|
|
50716
51697
|
static template = "o-spreadsheet-SpreadsheetDashboard";
|
|
51698
|
+
static props = {};
|
|
50717
51699
|
static components = {
|
|
50718
51700
|
GridOverlay,
|
|
50719
51701
|
GridPopover,
|
|
@@ -50832,7 +51814,6 @@ class SpreadsheetDashboard extends owl.Component {
|
|
|
50832
51814
|
return { ...this.canvasPosition, ...this.env.model.getters.getSheetViewDimensionWithHeaders() };
|
|
50833
51815
|
}
|
|
50834
51816
|
}
|
|
50835
|
-
SpreadsheetDashboard.props = {};
|
|
50836
51817
|
|
|
50837
51818
|
css /* scss */ `
|
|
50838
51819
|
.o-header-group {
|
|
@@ -50860,6 +51841,11 @@ css /* scss */ `
|
|
|
50860
51841
|
`;
|
|
50861
51842
|
class AbstractHeaderGroup extends owl.Component {
|
|
50862
51843
|
static template = "o-spreadsheet-HeaderGroup";
|
|
51844
|
+
static props = {
|
|
51845
|
+
group: Object,
|
|
51846
|
+
layerOffset: Number,
|
|
51847
|
+
openContextMenu: Function,
|
|
51848
|
+
};
|
|
50863
51849
|
toggleGroup() {
|
|
50864
51850
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
50865
51851
|
const { start, end } = this.props.group;
|
|
@@ -50896,11 +51882,6 @@ class AbstractHeaderGroup extends owl.Component {
|
|
|
50896
51882
|
this.props.openContextMenu(position, menuItems);
|
|
50897
51883
|
}
|
|
50898
51884
|
}
|
|
50899
|
-
AbstractHeaderGroup.props = {
|
|
50900
|
-
group: Object,
|
|
50901
|
-
layerOffset: Number,
|
|
50902
|
-
openContextMenu: Function,
|
|
50903
|
-
};
|
|
50904
51885
|
class RowGroup extends AbstractHeaderGroup {
|
|
50905
51886
|
dimension = "ROW";
|
|
50906
51887
|
get groupBorderStyle() {
|
|
@@ -51031,6 +52012,10 @@ css /* scss */ `
|
|
|
51031
52012
|
`;
|
|
51032
52013
|
class HeaderGroupContainer extends owl.Component {
|
|
51033
52014
|
static template = "o-spreadsheet-HeaderGroupContainer";
|
|
52015
|
+
static props = {
|
|
52016
|
+
dimension: String,
|
|
52017
|
+
layers: Array,
|
|
52018
|
+
};
|
|
51034
52019
|
static components = { RowGroup, ColGroup, Menu };
|
|
51035
52020
|
menu = owl.useState({ isOpen: false, position: null, menuItems: [] });
|
|
51036
52021
|
getLayerOffset(layerIndex) {
|
|
@@ -51093,10 +52078,6 @@ class HeaderGroupContainer extends owl.Component {
|
|
|
51093
52078
|
}
|
|
51094
52079
|
}
|
|
51095
52080
|
}
|
|
51096
|
-
HeaderGroupContainer.props = {
|
|
51097
|
-
dimension: String,
|
|
51098
|
-
layers: Array,
|
|
51099
|
-
};
|
|
51100
52081
|
|
|
51101
52082
|
css /* scss */ `
|
|
51102
52083
|
.o-sidePanel {
|
|
@@ -51207,14 +52188,6 @@ css /* scss */ `
|
|
|
51207
52188
|
text-align: left;
|
|
51208
52189
|
}
|
|
51209
52190
|
|
|
51210
|
-
.o-checkbox {
|
|
51211
|
-
display: flex;
|
|
51212
|
-
justify-items: center;
|
|
51213
|
-
input {
|
|
51214
|
-
margin-right: 5px;
|
|
51215
|
-
}
|
|
51216
|
-
}
|
|
51217
|
-
|
|
51218
52191
|
.o-inflection {
|
|
51219
52192
|
table {
|
|
51220
52193
|
table-layout: fixed;
|
|
@@ -51255,6 +52228,11 @@ css /* scss */ `
|
|
|
51255
52228
|
`;
|
|
51256
52229
|
class SidePanel extends owl.Component {
|
|
51257
52230
|
static template = "o-spreadsheet-SidePanel";
|
|
52231
|
+
static props = {
|
|
52232
|
+
component: String,
|
|
52233
|
+
panelProps: { type: Object, optional: true },
|
|
52234
|
+
onCloseSidePanel: Function,
|
|
52235
|
+
};
|
|
51258
52236
|
state;
|
|
51259
52237
|
setup() {
|
|
51260
52238
|
this.state = owl.useState({
|
|
@@ -51268,11 +52246,6 @@ class SidePanel extends owl.Component {
|
|
|
51268
52246
|
: this.state.panel.title;
|
|
51269
52247
|
}
|
|
51270
52248
|
}
|
|
51271
|
-
SidePanel.props = {
|
|
51272
|
-
component: String,
|
|
51273
|
-
panelProps: { type: Object, optional: true },
|
|
51274
|
-
onCloseSidePanel: Function,
|
|
51275
|
-
};
|
|
51276
52249
|
|
|
51277
52250
|
css /* scss */ `
|
|
51278
52251
|
.o-menu-item-button {
|
|
@@ -51290,6 +52263,13 @@ css /* scss */ `
|
|
|
51290
52263
|
`;
|
|
51291
52264
|
class ActionButton extends owl.Component {
|
|
51292
52265
|
static template = "o-spreadsheet-ActionButton";
|
|
52266
|
+
static props = {
|
|
52267
|
+
action: Object,
|
|
52268
|
+
hasTriangleDownIcon: { type: Boolean, optional: true },
|
|
52269
|
+
selectedColor: { type: String, optional: true },
|
|
52270
|
+
class: { type: String, optional: true },
|
|
52271
|
+
onClick: { type: Function, optional: true },
|
|
52272
|
+
};
|
|
51293
52273
|
actionButton = createAction(this.props.action);
|
|
51294
52274
|
setup() {
|
|
51295
52275
|
owl.onWillUpdateProps((nextProps) => {
|
|
@@ -51332,13 +52312,6 @@ class ActionButton extends owl.Component {
|
|
|
51332
52312
|
return "";
|
|
51333
52313
|
}
|
|
51334
52314
|
}
|
|
51335
|
-
ActionButton.props = {
|
|
51336
|
-
action: Object,
|
|
51337
|
-
hasTriangleDownIcon: { type: Boolean, optional: true },
|
|
51338
|
-
selectedColor: { type: String, optional: true },
|
|
51339
|
-
class: { type: String, optional: true },
|
|
51340
|
-
onClick: { type: Function, optional: true },
|
|
51341
|
-
};
|
|
51342
52315
|
|
|
51343
52316
|
/**
|
|
51344
52317
|
* List the available borders positions and the corresponding icons.
|
|
@@ -51435,6 +52408,17 @@ css /* scss */ `
|
|
|
51435
52408
|
`;
|
|
51436
52409
|
class BorderEditor extends owl.Component {
|
|
51437
52410
|
static template = "o-spreadsheet-BorderEditor";
|
|
52411
|
+
static props = {
|
|
52412
|
+
class: { type: String, optional: true },
|
|
52413
|
+
currentBorderColor: { type: String, optional: false },
|
|
52414
|
+
currentBorderStyle: { type: String, optional: false },
|
|
52415
|
+
currentBorderPosition: { type: String, optional: true },
|
|
52416
|
+
onBorderColorPicked: Function,
|
|
52417
|
+
onBorderStylePicked: Function,
|
|
52418
|
+
onBorderPositionPicked: Function,
|
|
52419
|
+
maxHeight: { type: Number, optional: true },
|
|
52420
|
+
anchorRect: Object,
|
|
52421
|
+
};
|
|
51438
52422
|
static components = { ColorPickerWidget, Popover };
|
|
51439
52423
|
BORDER_POSITIONS = BORDER_POSITIONS;
|
|
51440
52424
|
lineStyleButtonRef = owl.useRef("lineStyleButton");
|
|
@@ -51490,20 +52474,16 @@ class BorderEditor extends owl.Component {
|
|
|
51490
52474
|
};
|
|
51491
52475
|
}
|
|
51492
52476
|
}
|
|
51493
|
-
BorderEditor.props = {
|
|
51494
|
-
class: { type: String, optional: true },
|
|
51495
|
-
currentBorderColor: { type: String, optional: false },
|
|
51496
|
-
currentBorderStyle: { type: String, optional: false },
|
|
51497
|
-
currentBorderPosition: { type: String, optional: true },
|
|
51498
|
-
onBorderColorPicked: Function,
|
|
51499
|
-
onBorderStylePicked: Function,
|
|
51500
|
-
onBorderPositionPicked: Function,
|
|
51501
|
-
maxHeight: { type: Number, optional: true },
|
|
51502
|
-
anchorRect: Object,
|
|
51503
|
-
};
|
|
51504
52477
|
|
|
51505
52478
|
class BorderEditorWidget extends owl.Component {
|
|
51506
52479
|
static template = "o-spreadsheet-BorderEditorWidget";
|
|
52480
|
+
static props = {
|
|
52481
|
+
toggleBorderEditor: Function,
|
|
52482
|
+
showBorderEditor: Boolean,
|
|
52483
|
+
disabled: { type: Boolean, optional: true },
|
|
52484
|
+
dropdownMaxHeight: { type: Number, optional: true },
|
|
52485
|
+
class: { type: String, optional: true },
|
|
52486
|
+
};
|
|
51507
52487
|
static components = { BorderEditor };
|
|
51508
52488
|
borderEditorButtonRef = owl.useRef("borderEditorButton");
|
|
51509
52489
|
state = owl.useState({
|
|
@@ -51548,13 +52528,6 @@ class BorderEditorWidget extends owl.Component {
|
|
|
51548
52528
|
});
|
|
51549
52529
|
}
|
|
51550
52530
|
}
|
|
51551
|
-
BorderEditorWidget.props = {
|
|
51552
|
-
toggleBorderEditor: Function,
|
|
51553
|
-
showBorderEditor: Boolean,
|
|
51554
|
-
disabled: { type: Boolean, optional: true },
|
|
51555
|
-
dropdownMaxHeight: { type: Number, optional: true },
|
|
51556
|
-
class: { type: String, optional: true },
|
|
51557
|
-
};
|
|
51558
52531
|
|
|
51559
52532
|
const COMPOSER_MAX_HEIGHT = 100;
|
|
51560
52533
|
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
@@ -51583,6 +52556,12 @@ css /* scss */ `
|
|
|
51583
52556
|
`;
|
|
51584
52557
|
class TopBarComposer extends owl.Component {
|
|
51585
52558
|
static template = "o-spreadsheet-TopBarComposer";
|
|
52559
|
+
static props = {
|
|
52560
|
+
focus: {
|
|
52561
|
+
validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value),
|
|
52562
|
+
},
|
|
52563
|
+
onComposerContentFocused: Function,
|
|
52564
|
+
};
|
|
51586
52565
|
static components = { Composer };
|
|
51587
52566
|
get composerStyle() {
|
|
51588
52567
|
const style = {
|
|
@@ -51605,10 +52584,6 @@ class TopBarComposer extends owl.Component {
|
|
|
51605
52584
|
});
|
|
51606
52585
|
}
|
|
51607
52586
|
}
|
|
51608
|
-
TopBarComposer.props = {
|
|
51609
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
51610
|
-
onComposerContentFocused: Function,
|
|
51611
|
-
};
|
|
51612
52587
|
|
|
51613
52588
|
css /* scss */ `
|
|
51614
52589
|
.o-font-size-editor {
|
|
@@ -51637,6 +52612,11 @@ css /* scss */ `
|
|
|
51637
52612
|
`;
|
|
51638
52613
|
class FontSizeEditor extends owl.Component {
|
|
51639
52614
|
static template = "o-spreadsheet-FontSizeEditor";
|
|
52615
|
+
static props = {
|
|
52616
|
+
onToggle: Function,
|
|
52617
|
+
dropdownStyle: String,
|
|
52618
|
+
class: String,
|
|
52619
|
+
};
|
|
51640
52620
|
static components = {};
|
|
51641
52621
|
fontSizes = FONT_SIZES;
|
|
51642
52622
|
dropdown = owl.useState({ isOpen: false });
|
|
@@ -51693,14 +52673,12 @@ class FontSizeEditor extends owl.Component {
|
|
|
51693
52673
|
}
|
|
51694
52674
|
}
|
|
51695
52675
|
}
|
|
51696
|
-
FontSizeEditor.props = {
|
|
51697
|
-
onToggle: Function,
|
|
51698
|
-
dropdownStyle: String,
|
|
51699
|
-
class: String,
|
|
51700
|
-
};
|
|
51701
52676
|
|
|
51702
52677
|
class PaintFormatButton extends owl.Component {
|
|
51703
52678
|
static template = "o-spreadsheet-PaintFormatButton";
|
|
52679
|
+
static props = {
|
|
52680
|
+
class: { type: String, optional: true },
|
|
52681
|
+
};
|
|
51704
52682
|
get isActive() {
|
|
51705
52683
|
return this.env.model.getters.isPaintingFormat();
|
|
51706
52684
|
}
|
|
@@ -51716,9 +52694,6 @@ class PaintFormatButton extends owl.Component {
|
|
|
51716
52694
|
}
|
|
51717
52695
|
}
|
|
51718
52696
|
}
|
|
51719
|
-
PaintFormatButton.props = {
|
|
51720
|
-
class: { type: String, optional: true },
|
|
51721
|
-
};
|
|
51722
52697
|
|
|
51723
52698
|
// -----------------------------------------------------------------------------
|
|
51724
52699
|
// TopBar
|
|
@@ -51811,6 +52786,12 @@ css /* scss */ `
|
|
|
51811
52786
|
`;
|
|
51812
52787
|
class TopBar extends owl.Component {
|
|
51813
52788
|
static template = "o-spreadsheet-TopBar";
|
|
52789
|
+
static props = {
|
|
52790
|
+
onClick: Function,
|
|
52791
|
+
focusComposer: String,
|
|
52792
|
+
onComposerContentFocused: Function,
|
|
52793
|
+
dropdownMaxHeight: Number,
|
|
52794
|
+
};
|
|
51814
52795
|
get dropdownStyle() {
|
|
51815
52796
|
return `max-height:${this.props.dropdownMaxHeight}px`;
|
|
51816
52797
|
}
|
|
@@ -51927,12 +52908,6 @@ class TopBar extends owl.Component {
|
|
|
51927
52908
|
this.onClick();
|
|
51928
52909
|
}
|
|
51929
52910
|
}
|
|
51930
|
-
TopBar.props = {
|
|
51931
|
-
onClick: Function,
|
|
51932
|
-
focusComposer: String,
|
|
51933
|
-
onComposerContentFocused: Function,
|
|
51934
|
-
dropdownMaxHeight: Number,
|
|
51935
|
-
};
|
|
51936
52911
|
|
|
51937
52912
|
function instantiateClipboard() {
|
|
51938
52913
|
return new WebClipboardWrapper(navigator.clipboard);
|
|
@@ -52165,6 +53140,9 @@ css /* scss */ `
|
|
|
52165
53140
|
`;
|
|
52166
53141
|
class Spreadsheet extends owl.Component {
|
|
52167
53142
|
static template = "o-spreadsheet-Spreadsheet";
|
|
53143
|
+
static props = {
|
|
53144
|
+
model: Object,
|
|
53145
|
+
};
|
|
52168
53146
|
static components = {
|
|
52169
53147
|
TopBar,
|
|
52170
53148
|
Grid,
|
|
@@ -52309,7 +53287,7 @@ class Spreadsheet extends owl.Component {
|
|
|
52309
53287
|
}
|
|
52310
53288
|
onKeydown(ev) {
|
|
52311
53289
|
let keyDownString = "";
|
|
52312
|
-
if (ev
|
|
53290
|
+
if (isCtrlKey(ev)) {
|
|
52313
53291
|
keyDownString += "CTRL+";
|
|
52314
53292
|
}
|
|
52315
53293
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -52377,9 +53355,6 @@ class Spreadsheet extends owl.Component {
|
|
|
52377
53355
|
return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
|
|
52378
53356
|
}
|
|
52379
53357
|
}
|
|
52380
|
-
Spreadsheet.props = {
|
|
52381
|
-
model: Object,
|
|
52382
|
-
};
|
|
52383
53358
|
|
|
52384
53359
|
class LocalTransportService {
|
|
52385
53360
|
listeners = [];
|
|
@@ -55046,7 +56021,8 @@ function addRows(construct, data, sheet) {
|
|
|
55046
56021
|
}
|
|
55047
56022
|
else if (cell.content && cell.content !== "") {
|
|
55048
56023
|
const isTableHeader = isCellTableHeader(c, r, sheet);
|
|
55049
|
-
|
|
56024
|
+
const isPlainText = !!(cell.format && data.formats[cell.format] === PLAIN_TEXT_FORMAT);
|
|
56025
|
+
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isPlainText));
|
|
55050
56026
|
}
|
|
55051
56027
|
attributes.push(...additionalAttrs);
|
|
55052
56028
|
cellNodes.push(escapeXml /*xml*/ `
|
|
@@ -55975,6 +56951,7 @@ const helpers = {
|
|
|
55975
56951
|
colorToRGBA,
|
|
55976
56952
|
positionToZone,
|
|
55977
56953
|
isDefined: isDefined$1,
|
|
56954
|
+
isMatrix,
|
|
55978
56955
|
lazy,
|
|
55979
56956
|
genericRepeat,
|
|
55980
56957
|
createAction,
|
|
@@ -56059,6 +57036,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
56059
57036
|
exports.tokenize = tokenize;
|
|
56060
57037
|
|
|
56061
57038
|
|
|
56062
|
-
__info__.version = "17.1.0-alpha.
|
|
56063
|
-
__info__.date = "
|
|
56064
|
-
__info__.hash = "
|
|
57039
|
+
__info__.version = "17.1.0-alpha.7";
|
|
57040
|
+
__info__.date = "2024-01-12T13:45:00.505Z";
|
|
57041
|
+
__info__.hash = "cbce1ed";
|