@odoo/o-spreadsheet 16.4.0-alpha.7 → 16.5.0-alpha.0
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 +684 -475
- package/dist/o-spreadsheet.d.ts +140 -110
- package/dist/o-spreadsheet.esm.js +684 -475
- package/dist/o-spreadsheet.iife.js +684 -475
- package/dist/o-spreadsheet.iife.min.js +271 -267
- package/package.json +11 -11
|
@@ -236,6 +236,7 @@
|
|
|
236
236
|
const HEADER_FONT_SIZE = 11;
|
|
237
237
|
const DEFAULT_FONT = "'Roboto', arial";
|
|
238
238
|
const DEFAULT_VERTICAL_ALIGN = "bottom";
|
|
239
|
+
const DEFAULT_WRAPPING_MODE = "overflow";
|
|
239
240
|
// Borders
|
|
240
241
|
const DEFAULT_BORDER_DESC = { style: "thin", color: "#000000" };
|
|
241
242
|
const DEFAULT_FILTER_BORDER_DESC = { style: "thin", color: FILTERS_COLOR };
|
|
@@ -393,82 +394,6 @@
|
|
|
393
394
|
function clip(val, min, max) {
|
|
394
395
|
return val < min ? min : val > max ? max : val;
|
|
395
396
|
}
|
|
396
|
-
function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
397
|
-
return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* Get the default height of the cell given its style.
|
|
401
|
-
*/
|
|
402
|
-
function getDefaultCellHeight(cell) {
|
|
403
|
-
if (!cell || !cell.content) {
|
|
404
|
-
return DEFAULT_CELL_HEIGHT;
|
|
405
|
-
}
|
|
406
|
-
const fontSize = computeTextFontSizeInPixels(cell.style);
|
|
407
|
-
// the number of lines should be computed from the formula result, but it's not evaluated at this point
|
|
408
|
-
const numberOfLines = cell.isFormula ? 1 : cell.content.split(NEWLINE).length;
|
|
409
|
-
return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
|
|
410
|
-
}
|
|
411
|
-
function computeTextWidth(context, text, style) {
|
|
412
|
-
const font = computeTextFont(style);
|
|
413
|
-
if (!textWidthCache[font]) {
|
|
414
|
-
textWidthCache[font] = {};
|
|
415
|
-
}
|
|
416
|
-
if (textWidthCache[font][text] === undefined) {
|
|
417
|
-
context.save();
|
|
418
|
-
context.font = font;
|
|
419
|
-
const textWidth = context.measureText(text).width;
|
|
420
|
-
context.restore();
|
|
421
|
-
textWidthCache[font][text] = textWidth;
|
|
422
|
-
}
|
|
423
|
-
return textWidthCache[font][text];
|
|
424
|
-
}
|
|
425
|
-
const textWidthCache = {};
|
|
426
|
-
function fontSizeInPixels(fontSize) {
|
|
427
|
-
return Math.round((fontSize * 96) / 72);
|
|
428
|
-
}
|
|
429
|
-
function computeTextFont(style) {
|
|
430
|
-
const italic = style.italic ? "italic " : "";
|
|
431
|
-
const weight = style.bold ? "bold" : DEFAULT_FONT_WEIGHT;
|
|
432
|
-
const size = computeTextFontSizeInPixels(style);
|
|
433
|
-
return `${italic}${weight} ${size}px ${DEFAULT_FONT}`;
|
|
434
|
-
}
|
|
435
|
-
function computeTextFontSizeInPixels(style) {
|
|
436
|
-
const sizeInPt = style?.fontSize || DEFAULT_FONT_SIZE;
|
|
437
|
-
return fontSizeInPixels(sizeInPt);
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Return the font size that makes the width of a text match the given line width.
|
|
441
|
-
* Minimum font size is 1.
|
|
442
|
-
*
|
|
443
|
-
* @param getTextWidth function that takes a fontSize as argument, and return the width of the text with this font size.
|
|
444
|
-
*/
|
|
445
|
-
function getFontSizeMatchingWidth(lineWidth, maxFontSize, getTextWidth, precision = 0.25) {
|
|
446
|
-
let minFontSize = 1;
|
|
447
|
-
if (getTextWidth(minFontSize) > lineWidth)
|
|
448
|
-
return minFontSize;
|
|
449
|
-
if (getTextWidth(maxFontSize) < lineWidth)
|
|
450
|
-
return maxFontSize;
|
|
451
|
-
// Dichotomic search
|
|
452
|
-
let fontSize = (minFontSize + maxFontSize) / 2;
|
|
453
|
-
let currentTextWidth = getTextWidth(fontSize);
|
|
454
|
-
// Use a maximum number of iterations to be safe, because measuring text isn't 100% precise
|
|
455
|
-
let iterations = 0;
|
|
456
|
-
while (Math.abs(currentTextWidth - lineWidth) > precision && iterations < 20) {
|
|
457
|
-
if (currentTextWidth >= lineWidth) {
|
|
458
|
-
maxFontSize = (minFontSize + maxFontSize) / 2;
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
minFontSize = (minFontSize + maxFontSize) / 2;
|
|
462
|
-
}
|
|
463
|
-
fontSize = (minFontSize + maxFontSize) / 2;
|
|
464
|
-
currentTextWidth = getTextWidth(fontSize);
|
|
465
|
-
iterations++;
|
|
466
|
-
}
|
|
467
|
-
return fontSize;
|
|
468
|
-
}
|
|
469
|
-
function computeIconWidth(style) {
|
|
470
|
-
return computeTextFontSizeInPixels(style) + 2 * MIN_CF_ICON_MARGIN;
|
|
471
|
-
}
|
|
472
397
|
/**
|
|
473
398
|
* Create a range from start (included) to end (excluded).
|
|
474
399
|
* range(10, 13) => [10, 11, 12]
|
|
@@ -723,10 +648,6 @@
|
|
|
723
648
|
Object.keys(cleanObject).forEach((key) => !cleanObject[key] && delete cleanObject[key]);
|
|
724
649
|
return cleanObject;
|
|
725
650
|
}
|
|
726
|
-
/** Transform a string to lower case. If the string is undefined, return an empty string */
|
|
727
|
-
function toLowerCase(str) {
|
|
728
|
-
return str ? str.toLowerCase() : "";
|
|
729
|
-
}
|
|
730
651
|
function transpose2dArray(matrix, callback = (val) => val) {
|
|
731
652
|
if (!matrix.length)
|
|
732
653
|
return [];
|
|
@@ -815,6 +736,14 @@
|
|
|
815
736
|
return cache.get(args[0]);
|
|
816
737
|
},
|
|
817
738
|
}[funcName];
|
|
739
|
+
}
|
|
740
|
+
function removeIndexesFromArray(array, indexes) {
|
|
741
|
+
return array.filter((_, index) => !indexes.includes(index));
|
|
742
|
+
}
|
|
743
|
+
function insertItemsAtIndex(array, items, index) {
|
|
744
|
+
const newArray = [...array];
|
|
745
|
+
newArray.splice(index, 0, ...items);
|
|
746
|
+
return newArray;
|
|
818
747
|
}
|
|
819
748
|
|
|
820
749
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
@@ -958,13 +887,13 @@
|
|
|
958
887
|
let g = rgba.g.toString(16);
|
|
959
888
|
let b = rgba.b.toString(16);
|
|
960
889
|
let a = Math.round(rgba.a * 255).toString(16);
|
|
961
|
-
if (r.length
|
|
890
|
+
if (r.length === 1)
|
|
962
891
|
r = "0" + r;
|
|
963
|
-
if (g.length
|
|
892
|
+
if (g.length === 1)
|
|
964
893
|
g = "0" + g;
|
|
965
|
-
if (b.length
|
|
894
|
+
if (b.length === 1)
|
|
966
895
|
b = "0" + b;
|
|
967
|
-
if (a.length
|
|
896
|
+
if (a.length === 1)
|
|
968
897
|
a = "0" + a;
|
|
969
898
|
if (a === "ff")
|
|
970
899
|
a = "";
|
|
@@ -1067,13 +996,13 @@
|
|
|
1067
996
|
let l = 0;
|
|
1068
997
|
// Calculate hue
|
|
1069
998
|
// No difference
|
|
1070
|
-
if (delta
|
|
999
|
+
if (delta === 0)
|
|
1071
1000
|
h = 0;
|
|
1072
1001
|
// Red is max
|
|
1073
|
-
else if (cMax
|
|
1002
|
+
else if (cMax === r)
|
|
1074
1003
|
h = ((g - b) / delta) % 6;
|
|
1075
1004
|
// Green is max
|
|
1076
|
-
else if (cMax
|
|
1005
|
+
else if (cMax === g)
|
|
1077
1006
|
h = (b - r) / delta + 2;
|
|
1078
1007
|
// Blue is max
|
|
1079
1008
|
else
|
|
@@ -1084,7 +1013,7 @@
|
|
|
1084
1013
|
h += 360;
|
|
1085
1014
|
l = (cMax + cMin) / 2;
|
|
1086
1015
|
// Calculate saturation
|
|
1087
|
-
s = delta
|
|
1016
|
+
s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
|
1088
1017
|
// Multiply l and s by 100
|
|
1089
1018
|
s = +(s * 100).toFixed(1);
|
|
1090
1019
|
l = +(l * 100).toFixed(1);
|
|
@@ -1521,7 +1450,7 @@
|
|
|
1521
1450
|
}
|
|
1522
1451
|
function isLeapYear(year) {
|
|
1523
1452
|
const _year = Math.trunc(year);
|
|
1524
|
-
return (_year % 4 === 0 && _year % 100 != 0) || _year % 400
|
|
1453
|
+
return (_year % 4 === 0 && _year % 100 != 0) || _year % 400 === 0;
|
|
1525
1454
|
}
|
|
1526
1455
|
function getYearFrac(startDate, endDate, _dayCountConvention) {
|
|
1527
1456
|
if (startDate === endDate) {
|
|
@@ -2182,6 +2111,39 @@
|
|
|
2182
2111
|
}
|
|
2183
2112
|
return undefined;
|
|
2184
2113
|
}
|
|
2114
|
+
function createCurrencyFormat(currency) {
|
|
2115
|
+
const decimalPlaces = currency.decimalPlaces ?? 2;
|
|
2116
|
+
const position = currency.position ?? "before";
|
|
2117
|
+
const code = currency.code ?? "";
|
|
2118
|
+
const symbol = currency.symbol ?? "";
|
|
2119
|
+
const decimalRepresentation = decimalPlaces ? "." + "0".repeat(decimalPlaces) : "";
|
|
2120
|
+
const numberFormat = "#,##0" + decimalRepresentation;
|
|
2121
|
+
let textExpression = `${code} ${symbol}`.trim();
|
|
2122
|
+
if (position === "after" && code) {
|
|
2123
|
+
textExpression = " " + textExpression;
|
|
2124
|
+
}
|
|
2125
|
+
return insertTextInFormat(textExpression, position, numberFormat);
|
|
2126
|
+
}
|
|
2127
|
+
function insertTextInFormat(text, position, format) {
|
|
2128
|
+
const textExpression = `[$${text}]`;
|
|
2129
|
+
return position === "before" ? textExpression + format : format + textExpression;
|
|
2130
|
+
}
|
|
2131
|
+
function roundFormat(format) {
|
|
2132
|
+
const internalFormat = parseFormat(format);
|
|
2133
|
+
const roundedFormat = internalFormat.map((formatPart) => {
|
|
2134
|
+
if (formatPart.type === "NUMBER") {
|
|
2135
|
+
return {
|
|
2136
|
+
type: formatPart.type,
|
|
2137
|
+
format: {
|
|
2138
|
+
...formatPart.format,
|
|
2139
|
+
decimalPart: undefined,
|
|
2140
|
+
},
|
|
2141
|
+
};
|
|
2142
|
+
}
|
|
2143
|
+
return formatPart;
|
|
2144
|
+
});
|
|
2145
|
+
return convertInternalFormatToFormat(roundedFormat);
|
|
2146
|
+
}
|
|
2185
2147
|
function createLargeNumberFormat(format, magnitude, postFix, locale) {
|
|
2186
2148
|
const internalFormat = parseFormat(format || "#,##0");
|
|
2187
2149
|
const largeNumberFormat = internalFormat
|
|
@@ -3275,6 +3237,169 @@
|
|
|
3275
3237
|
return rows;
|
|
3276
3238
|
}
|
|
3277
3239
|
|
|
3240
|
+
function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
3241
|
+
return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
|
|
3242
|
+
}
|
|
3243
|
+
/**
|
|
3244
|
+
* Get the default height of the cell given its style.
|
|
3245
|
+
*/
|
|
3246
|
+
function getDefaultCellHeight(ctx, cell, colSize) {
|
|
3247
|
+
if (!cell || !cell.content)
|
|
3248
|
+
return DEFAULT_CELL_HEIGHT;
|
|
3249
|
+
const maxWidth = cell.style?.wrapping ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
|
|
3250
|
+
const numberOfLines = cell.isFormula
|
|
3251
|
+
? 1
|
|
3252
|
+
: splitTextToWidth(ctx, cell.content, cell.style, maxWidth).length;
|
|
3253
|
+
const fontSize = computeTextFontSizeInPixels(cell.style);
|
|
3254
|
+
return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
|
|
3255
|
+
}
|
|
3256
|
+
const textWidthCache = {};
|
|
3257
|
+
function computeTextWidth(context, text, style) {
|
|
3258
|
+
const font = computeTextFont(style);
|
|
3259
|
+
if (!textWidthCache[font]) {
|
|
3260
|
+
textWidthCache[font] = {};
|
|
3261
|
+
}
|
|
3262
|
+
if (textWidthCache[font][text] === undefined) {
|
|
3263
|
+
context.save();
|
|
3264
|
+
context.font = font;
|
|
3265
|
+
const textWidth = context.measureText(text).width;
|
|
3266
|
+
context.restore();
|
|
3267
|
+
textWidthCache[font][text] = textWidth;
|
|
3268
|
+
}
|
|
3269
|
+
return textWidthCache[font][text];
|
|
3270
|
+
}
|
|
3271
|
+
function fontSizeInPixels(fontSize) {
|
|
3272
|
+
return Math.round((fontSize * 96) / 72);
|
|
3273
|
+
}
|
|
3274
|
+
function computeTextFont(style) {
|
|
3275
|
+
const italic = style.italic ? "italic " : "";
|
|
3276
|
+
const weight = style.bold ? "bold" : DEFAULT_FONT_WEIGHT;
|
|
3277
|
+
const size = computeTextFontSizeInPixels(style);
|
|
3278
|
+
return `${italic}${weight} ${size}px ${DEFAULT_FONT}`;
|
|
3279
|
+
}
|
|
3280
|
+
function computeTextFontSizeInPixels(style) {
|
|
3281
|
+
const sizeInPt = style?.fontSize || DEFAULT_FONT_SIZE;
|
|
3282
|
+
return fontSizeInPixels(sizeInPt);
|
|
3283
|
+
}
|
|
3284
|
+
function splitWordToSpecificWidth(ctx, word, width, style) {
|
|
3285
|
+
const wordWidth = computeTextWidth(ctx, word, style);
|
|
3286
|
+
if (wordWidth <= width) {
|
|
3287
|
+
return [word];
|
|
3288
|
+
}
|
|
3289
|
+
const splitWord = [];
|
|
3290
|
+
let wordPart = "";
|
|
3291
|
+
for (let l of word) {
|
|
3292
|
+
const wordPartWidth = computeTextWidth(ctx, wordPart + l, style);
|
|
3293
|
+
if (wordPartWidth > width) {
|
|
3294
|
+
splitWord.push(wordPart);
|
|
3295
|
+
wordPart = l;
|
|
3296
|
+
}
|
|
3297
|
+
else {
|
|
3298
|
+
wordPart += l;
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
splitWord.push(wordPart);
|
|
3302
|
+
return splitWord;
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* Return the given text, split in multiple lines if needed. The text will be split in multiple
|
|
3306
|
+
* line if it contains NEWLINE characters, or if it's longer than the given width.
|
|
3307
|
+
*/
|
|
3308
|
+
function splitTextToWidth(ctx, text, style, width) {
|
|
3309
|
+
if (!style)
|
|
3310
|
+
style = {};
|
|
3311
|
+
const brokenText = [];
|
|
3312
|
+
// Checking if text contains NEWLINE before split makes it very slightly slower if text contains it,
|
|
3313
|
+
// but 5-10x faster if it doesn't
|
|
3314
|
+
const lines = text.includes(NEWLINE) ? text.split(NEWLINE) : [text];
|
|
3315
|
+
for (const line of lines) {
|
|
3316
|
+
const words = line.includes(" ") ? line.split(" ") : [line];
|
|
3317
|
+
if (!width) {
|
|
3318
|
+
brokenText.push(line);
|
|
3319
|
+
continue;
|
|
3320
|
+
}
|
|
3321
|
+
let textLine = "";
|
|
3322
|
+
let availableWidth = width;
|
|
3323
|
+
for (let word of words) {
|
|
3324
|
+
const splitWord = splitWordToSpecificWidth(ctx, word, width, style);
|
|
3325
|
+
const lastPart = splitWord.pop();
|
|
3326
|
+
const lastPartWidth = computeTextWidth(ctx, lastPart, style);
|
|
3327
|
+
// At this step: "splitWord" is an array composed of parts of word whose
|
|
3328
|
+
// length is at most equal to "width".
|
|
3329
|
+
// Last part contains the end of the word.
|
|
3330
|
+
// Note that: When word length is less than width, then lastPart is equal
|
|
3331
|
+
// to word and splitWord is empty
|
|
3332
|
+
if (splitWord.length) {
|
|
3333
|
+
if (textLine !== "") {
|
|
3334
|
+
brokenText.push(textLine);
|
|
3335
|
+
textLine = "";
|
|
3336
|
+
availableWidth = width;
|
|
3337
|
+
}
|
|
3338
|
+
splitWord.forEach((wordPart) => {
|
|
3339
|
+
brokenText.push(wordPart);
|
|
3340
|
+
});
|
|
3341
|
+
textLine = lastPart;
|
|
3342
|
+
availableWidth = width - lastPartWidth;
|
|
3343
|
+
}
|
|
3344
|
+
else {
|
|
3345
|
+
// here "lastPart" is equal to "word" and the "word" size is smaller than "width"
|
|
3346
|
+
const _word = textLine === "" ? lastPart : " " + lastPart;
|
|
3347
|
+
const wordWidth = computeTextWidth(ctx, _word, style);
|
|
3348
|
+
if (wordWidth <= availableWidth) {
|
|
3349
|
+
textLine += _word;
|
|
3350
|
+
availableWidth -= wordWidth;
|
|
3351
|
+
}
|
|
3352
|
+
else {
|
|
3353
|
+
brokenText.push(textLine);
|
|
3354
|
+
textLine = lastPart;
|
|
3355
|
+
availableWidth = width - lastPartWidth;
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
if (textLine !== "") {
|
|
3360
|
+
brokenText.push(textLine);
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
return brokenText;
|
|
3364
|
+
}
|
|
3365
|
+
/**
|
|
3366
|
+
* Return the font size that makes the width of a text match the given line width.
|
|
3367
|
+
* Minimum font size is 1.
|
|
3368
|
+
*
|
|
3369
|
+
* @param getTextWidth function that takes a fontSize as argument, and return the width of the text with this font size.
|
|
3370
|
+
*/
|
|
3371
|
+
function getFontSizeMatchingWidth(lineWidth, maxFontSize, getTextWidth, precision = 0.25) {
|
|
3372
|
+
let minFontSize = 1;
|
|
3373
|
+
if (getTextWidth(minFontSize) > lineWidth)
|
|
3374
|
+
return minFontSize;
|
|
3375
|
+
if (getTextWidth(maxFontSize) < lineWidth)
|
|
3376
|
+
return maxFontSize;
|
|
3377
|
+
// Dichotomic search
|
|
3378
|
+
let fontSize = (minFontSize + maxFontSize) / 2;
|
|
3379
|
+
let currentTextWidth = getTextWidth(fontSize);
|
|
3380
|
+
// Use a maximum number of iterations to be safe, because measuring text isn't 100% precise
|
|
3381
|
+
let iterations = 0;
|
|
3382
|
+
while (Math.abs(currentTextWidth - lineWidth) > precision && iterations < 20) {
|
|
3383
|
+
if (currentTextWidth >= lineWidth) {
|
|
3384
|
+
maxFontSize = (minFontSize + maxFontSize) / 2;
|
|
3385
|
+
}
|
|
3386
|
+
else {
|
|
3387
|
+
minFontSize = (minFontSize + maxFontSize) / 2;
|
|
3388
|
+
}
|
|
3389
|
+
fontSize = (minFontSize + maxFontSize) / 2;
|
|
3390
|
+
currentTextWidth = getTextWidth(fontSize);
|
|
3391
|
+
iterations++;
|
|
3392
|
+
}
|
|
3393
|
+
return fontSize;
|
|
3394
|
+
}
|
|
3395
|
+
function computeIconWidth(style) {
|
|
3396
|
+
return computeTextFontSizeInPixels(style) + 2 * MIN_CF_ICON_MARGIN;
|
|
3397
|
+
}
|
|
3398
|
+
/** Transform a string to lower case. If the string is undefined, return an empty string */
|
|
3399
|
+
function toLowerCase(str) {
|
|
3400
|
+
return str ? str.toLowerCase() : "";
|
|
3401
|
+
}
|
|
3402
|
+
|
|
3278
3403
|
/*
|
|
3279
3404
|
* https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
3280
3405
|
* */
|
|
@@ -3297,7 +3422,7 @@
|
|
|
3297
3422
|
else {
|
|
3298
3423
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
3299
3424
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
3300
|
-
var r = (Math.random() * 16) | 0, v = c
|
|
3425
|
+
var r = (Math.random() * 16) | 0, v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
3301
3426
|
return v.toString(16);
|
|
3302
3427
|
});
|
|
3303
3428
|
}
|
|
@@ -4125,6 +4250,7 @@
|
|
|
4125
4250
|
CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 92] = "NoSplitSeparatorInSelection";
|
|
4126
4251
|
CommandResult[CommandResult["NoActiveSheet"] = 93] = "NoActiveSheet";
|
|
4127
4252
|
CommandResult[CommandResult["InvalidLocale"] = 94] = "InvalidLocale";
|
|
4253
|
+
CommandResult[CommandResult["AlreadyInPaintingFormatMode"] = 95] = "AlreadyInPaintingFormatMode";
|
|
4128
4254
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
4129
4255
|
|
|
4130
4256
|
const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
@@ -5940,8 +6066,8 @@
|
|
|
5940
6066
|
return this.props.menuItems.some((menuItem) => !!menuItem.icon || !!menuItem.isActive);
|
|
5941
6067
|
}
|
|
5942
6068
|
getIconName(menu) {
|
|
5943
|
-
if (menu.icon) {
|
|
5944
|
-
return menu.icon;
|
|
6069
|
+
if (menu.icon(this.env)) {
|
|
6070
|
+
return menu.icon(this.env);
|
|
5945
6071
|
}
|
|
5946
6072
|
if (menu.isActive?.(this.env)) {
|
|
5947
6073
|
return "o-spreadsheet-Icon.CHECK";
|
|
@@ -6375,7 +6501,7 @@
|
|
|
6375
6501
|
for (let pivot = 0; pivot < dim; pivot++) {
|
|
6376
6502
|
let diagonalElement = C[pivot][pivot];
|
|
6377
6503
|
// if we have a 0 on the diagonal we'll need to swap with a lower row
|
|
6378
|
-
if (diagonalElement
|
|
6504
|
+
if (diagonalElement === 0) {
|
|
6379
6505
|
//look through every row below the i'th row
|
|
6380
6506
|
for (let row = pivot + 1; row < dim; row++) {
|
|
6381
6507
|
//if the ii'th row has a non-0 in the i'th col, swap it with that row
|
|
@@ -6402,7 +6528,7 @@
|
|
|
6402
6528
|
// the other rows so that there will be 0's in this column in the
|
|
6403
6529
|
// rows above and below this one
|
|
6404
6530
|
for (let row = 0; row < dim; row++) {
|
|
6405
|
-
if (row
|
|
6531
|
+
if (row === pivot) {
|
|
6406
6532
|
continue;
|
|
6407
6533
|
}
|
|
6408
6534
|
// We want to change this element to 0
|
|
@@ -12467,7 +12593,7 @@
|
|
|
12467
12593
|
return false;
|
|
12468
12594
|
}
|
|
12469
12595
|
catch (e) {
|
|
12470
|
-
return e?.errorType
|
|
12596
|
+
return e?.errorType === CellErrorType.NotAvailable;
|
|
12471
12597
|
}
|
|
12472
12598
|
},
|
|
12473
12599
|
isExported: true,
|
|
@@ -15183,6 +15309,8 @@
|
|
|
15183
15309
|
function createAction(item) {
|
|
15184
15310
|
const name = item.name;
|
|
15185
15311
|
const children = item.children;
|
|
15312
|
+
const description = item.description;
|
|
15313
|
+
const icon = item.icon;
|
|
15186
15314
|
return {
|
|
15187
15315
|
id: item.id || uuidGenerator$2.uuidv4(),
|
|
15188
15316
|
name: typeof name === "function" ? name : () => name,
|
|
@@ -15200,8 +15328,8 @@
|
|
|
15200
15328
|
: () => [],
|
|
15201
15329
|
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
15202
15330
|
separator: item.separator || false,
|
|
15203
|
-
icon:
|
|
15204
|
-
description:
|
|
15331
|
+
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
15332
|
+
description: typeof description === "function" ? description : () => description || "",
|
|
15205
15333
|
textColor: item.textColor,
|
|
15206
15334
|
sequence: item.sequence || 0,
|
|
15207
15335
|
};
|
|
@@ -16667,7 +16795,7 @@
|
|
|
16667
16795
|
function convertDateFormatForMoment(format) {
|
|
16668
16796
|
format = format.replace(/y/g, "Y");
|
|
16669
16797
|
format = format.replace(/d/g, "D");
|
|
16670
|
-
// "m" before "h"
|
|
16798
|
+
// "m" before "h" === month, "m" after "h" === minute
|
|
16671
16799
|
const indexH = format.indexOf("h");
|
|
16672
16800
|
if (indexH >= 0) {
|
|
16673
16801
|
format = format.slice(0, indexH).replace(/m/g, "M") + format.slice(indexH);
|
|
@@ -17521,6 +17649,7 @@
|
|
|
17521
17649
|
env.model.dispatch("SELECT_FIGURE", { id: figureId });
|
|
17522
17650
|
env.openSidePanel("ChartPanel");
|
|
17523
17651
|
},
|
|
17652
|
+
icon: "o-spreadsheet-Icon.EDIT",
|
|
17524
17653
|
},
|
|
17525
17654
|
getCopyMenuItem(figureId, env),
|
|
17526
17655
|
getCutMenuItem(figureId, env),
|
|
@@ -17552,6 +17681,7 @@
|
|
|
17552
17681
|
width,
|
|
17553
17682
|
});
|
|
17554
17683
|
},
|
|
17684
|
+
icon: "o-spreadsheet-Icon.REFRESH",
|
|
17555
17685
|
},
|
|
17556
17686
|
getDeleteMenuItem(figureId, onFigureDeleted, env),
|
|
17557
17687
|
];
|
|
@@ -17568,6 +17698,7 @@
|
|
|
17568
17698
|
env.model.dispatch("COPY");
|
|
17569
17699
|
await env.clipboard.write(env.model.getters.getClipboardContent());
|
|
17570
17700
|
},
|
|
17701
|
+
icon: "o-spreadsheet-Icon.COPY",
|
|
17571
17702
|
};
|
|
17572
17703
|
}
|
|
17573
17704
|
function getCutMenuItem(figureId, env) {
|
|
@@ -17581,6 +17712,7 @@
|
|
|
17581
17712
|
env.model.dispatch("CUT");
|
|
17582
17713
|
await env.clipboard.write(env.model.getters.getClipboardContent());
|
|
17583
17714
|
},
|
|
17715
|
+
icon: "o-spreadsheet-Icon.CUT",
|
|
17584
17716
|
};
|
|
17585
17717
|
}
|
|
17586
17718
|
function getDeleteMenuItem(figureId, onFigureDeleted, env) {
|
|
@@ -17595,6 +17727,7 @@
|
|
|
17595
17727
|
});
|
|
17596
17728
|
onFigureDeleted();
|
|
17597
17729
|
},
|
|
17730
|
+
icon: "o-spreadsheet-Icon.DELETE",
|
|
17598
17731
|
};
|
|
17599
17732
|
}
|
|
17600
17733
|
|
|
@@ -18662,7 +18795,7 @@
|
|
|
18662
18795
|
};
|
|
18663
18796
|
const categorieFunctionAll = {
|
|
18664
18797
|
name: _lt("All"),
|
|
18665
|
-
children: allFunctionListMenuBuilder
|
|
18798
|
+
children: [allFunctionListMenuBuilder],
|
|
18666
18799
|
};
|
|
18667
18800
|
function allFunctionListMenuBuilder() {
|
|
18668
18801
|
const fnNames = functionRegistry.getKeys();
|
|
@@ -18994,7 +19127,10 @@
|
|
|
18994
19127
|
};
|
|
18995
19128
|
const formatNumberNumber = {
|
|
18996
19129
|
name: _lt("Number"),
|
|
18997
|
-
description:
|
|
19130
|
+
description: (env) => formatValue(1000.12, {
|
|
19131
|
+
format: "#,##0.00",
|
|
19132
|
+
locale: env.model.getters.getLocale(),
|
|
19133
|
+
}),
|
|
18998
19134
|
execute: (env) => setFormatter(env, "#,##0.00"),
|
|
18999
19135
|
isActive: (env) => isFormatSelected(env, "#,##0.00"),
|
|
19000
19136
|
};
|
|
@@ -19005,21 +19141,34 @@
|
|
|
19005
19141
|
};
|
|
19006
19142
|
const formatNumberPercent = {
|
|
19007
19143
|
name: _lt("Percent"),
|
|
19008
|
-
description:
|
|
19144
|
+
description: (env) => formatValue(0.1012, {
|
|
19145
|
+
format: "0.00%",
|
|
19146
|
+
locale: env.model.getters.getLocale(),
|
|
19147
|
+
}),
|
|
19009
19148
|
execute: FORMAT_PERCENT_ACTION,
|
|
19010
19149
|
isActive: (env) => isFormatSelected(env, "0.00%"),
|
|
19011
19150
|
};
|
|
19012
19151
|
const formatNumberCurrency = {
|
|
19013
19152
|
name: _lt("Currency"),
|
|
19014
|
-
description:
|
|
19015
|
-
|
|
19016
|
-
|
|
19153
|
+
description: (env) => formatValue(1000.12, {
|
|
19154
|
+
format: env.model.config.defaultCurrencyFormat,
|
|
19155
|
+
locale: env.model.getters.getLocale(),
|
|
19156
|
+
}),
|
|
19157
|
+
execute: (env) => setFormatter(env, env.model.config.defaultCurrencyFormat),
|
|
19158
|
+
isActive: (env) => isFormatSelected(env, env.model.config.defaultCurrencyFormat),
|
|
19017
19159
|
};
|
|
19018
19160
|
const formatNumberCurrencyRounded = {
|
|
19019
19161
|
name: _lt("Currency rounded"),
|
|
19020
|
-
description:
|
|
19021
|
-
|
|
19022
|
-
|
|
19162
|
+
description: (env) => formatValue(1000, {
|
|
19163
|
+
format: roundFormat(env.model.config.defaultCurrencyFormat),
|
|
19164
|
+
locale: env.model.getters.getLocale(),
|
|
19165
|
+
}),
|
|
19166
|
+
execute: (env) => setFormatter(env, roundFormat(env.model.config.defaultCurrencyFormat)),
|
|
19167
|
+
isActive: (env) => isFormatSelected(env, roundFormat(env.model.config.defaultCurrencyFormat)),
|
|
19168
|
+
isVisible: (env) => {
|
|
19169
|
+
const currencyFormat = env.model.config.defaultCurrencyFormat;
|
|
19170
|
+
return currencyFormat !== roundFormat(currencyFormat);
|
|
19171
|
+
},
|
|
19023
19172
|
};
|
|
19024
19173
|
const formatCustomCurrency = {
|
|
19025
19174
|
name: _lt("Custom currency"),
|
|
@@ -19028,19 +19177,37 @@
|
|
|
19028
19177
|
};
|
|
19029
19178
|
const formatNumberDate = {
|
|
19030
19179
|
name: _lt("Date"),
|
|
19031
|
-
description:
|
|
19180
|
+
description: (env) => {
|
|
19181
|
+
const locale = env.model.getters.getLocale();
|
|
19182
|
+
return formatValue(parseLiteral("9/26/2023", DEFAULT_LOCALE), {
|
|
19183
|
+
format: locale.dateFormat,
|
|
19184
|
+
locale,
|
|
19185
|
+
});
|
|
19186
|
+
},
|
|
19032
19187
|
execute: (env) => setFormatter(env, env.model.getters.getLocale().dateFormat),
|
|
19033
19188
|
isActive: (env) => isFormatSelected(env, env.model.getters.getLocale().dateFormat),
|
|
19034
19189
|
};
|
|
19035
19190
|
const formatNumberTime = {
|
|
19036
19191
|
name: _lt("Time"),
|
|
19037
|
-
description:
|
|
19192
|
+
description: (env) => {
|
|
19193
|
+
const locale = env.model.getters.getLocale();
|
|
19194
|
+
return formatValue(parseLiteral("9/26/2023 10:43:00 PM", DEFAULT_LOCALE), {
|
|
19195
|
+
format: locale.timeFormat,
|
|
19196
|
+
locale,
|
|
19197
|
+
});
|
|
19198
|
+
},
|
|
19038
19199
|
execute: (env) => setFormatter(env, env.model.getters.getLocale().timeFormat),
|
|
19039
19200
|
isActive: (env) => isFormatSelected(env, env.model.getters.getLocale().timeFormat),
|
|
19040
19201
|
};
|
|
19041
19202
|
const formatNumberDateTime = {
|
|
19042
19203
|
name: _lt("Date time"),
|
|
19043
|
-
description:
|
|
19204
|
+
description: (env) => {
|
|
19205
|
+
const locale = env.model.getters.getLocale();
|
|
19206
|
+
return formatValue(parseLiteral("9/26/2023 22:43:00", DEFAULT_LOCALE), {
|
|
19207
|
+
format: locale.dateFormat + " " + locale.timeFormat,
|
|
19208
|
+
locale,
|
|
19209
|
+
});
|
|
19210
|
+
},
|
|
19044
19211
|
execute: (env) => {
|
|
19045
19212
|
const locale = env.model.getters.getLocale();
|
|
19046
19213
|
setFormatter(env, locale.dateFormat + " " + locale.timeFormat);
|
|
@@ -19112,7 +19279,7 @@
|
|
|
19112
19279
|
};
|
|
19113
19280
|
const formatAlignmentHorizontal = {
|
|
19114
19281
|
name: _lt("Horizontal align"),
|
|
19115
|
-
icon:
|
|
19282
|
+
icon: (env) => getHorizontalAlignmentIcon(env),
|
|
19116
19283
|
};
|
|
19117
19284
|
const formatAlignmentLeft = {
|
|
19118
19285
|
name: _lt("Left"),
|
|
@@ -19137,46 +19304,50 @@
|
|
|
19137
19304
|
};
|
|
19138
19305
|
const formatAlignmentVertical = {
|
|
19139
19306
|
name: _lt("Vertical align"),
|
|
19140
|
-
icon:
|
|
19307
|
+
icon: (env) => getVerticalAlignmentIcon(env),
|
|
19141
19308
|
};
|
|
19142
19309
|
const formatAlignmentTop = {
|
|
19143
19310
|
name: _lt("Top"),
|
|
19144
19311
|
execute: (env) => setStyle(env, { verticalAlign: "top" }),
|
|
19145
|
-
isActive: (env) => (env
|
|
19312
|
+
isActive: (env) => getVerticalAlign(env) === "top",
|
|
19146
19313
|
icon: "o-spreadsheet-Icon.ALIGN_TOP",
|
|
19147
19314
|
};
|
|
19148
19315
|
const formatAlignmentMiddle = {
|
|
19149
19316
|
name: _lt("Middle"),
|
|
19150
19317
|
execute: (env) => setStyle(env, { verticalAlign: "middle" }),
|
|
19151
|
-
isActive: (env) => (env
|
|
19318
|
+
isActive: (env) => getVerticalAlign(env) === "middle",
|
|
19152
19319
|
icon: "o-spreadsheet-Icon.ALIGN_MIDDLE",
|
|
19153
19320
|
};
|
|
19154
19321
|
const formatAlignmentBottom = {
|
|
19155
19322
|
name: _lt("Bottom"),
|
|
19156
19323
|
execute: (env) => setStyle(env, { verticalAlign: "bottom" }),
|
|
19157
|
-
isActive: (env) => (env
|
|
19324
|
+
isActive: (env) => getVerticalAlign(env) === "bottom",
|
|
19158
19325
|
icon: "o-spreadsheet-Icon.ALIGN_BOTTOM",
|
|
19159
19326
|
};
|
|
19160
|
-
const
|
|
19327
|
+
const formatWrappingIcon = {
|
|
19161
19328
|
name: _lt("Wrapping"),
|
|
19162
19329
|
icon: "o-spreadsheet-Icon.WRAPPING_OVERFLOW",
|
|
19163
19330
|
};
|
|
19331
|
+
const formatWrapping = {
|
|
19332
|
+
name: _lt("Wrapping"),
|
|
19333
|
+
icon: (env) => getWrapModeIcon(env),
|
|
19334
|
+
};
|
|
19164
19335
|
const formatWrappingOverflow = {
|
|
19165
19336
|
name: _lt("Overflow"),
|
|
19166
19337
|
execute: (env) => setStyle(env, { wrapping: "overflow" }),
|
|
19167
|
-
isActive: (env) => (env
|
|
19338
|
+
isActive: (env) => getWrappingMode(env) === "overflow",
|
|
19168
19339
|
icon: "o-spreadsheet-Icon.WRAPPING_OVERFLOW",
|
|
19169
19340
|
};
|
|
19170
19341
|
const formatWrappingWrap = {
|
|
19171
19342
|
name: _lt("Wrap"),
|
|
19172
19343
|
execute: (env) => setStyle(env, { wrapping: "wrap" }),
|
|
19173
|
-
isActive: (env) => env
|
|
19344
|
+
isActive: (env) => getWrappingMode(env) === "wrap",
|
|
19174
19345
|
icon: "o-spreadsheet-Icon.WRAPPING_WRAP",
|
|
19175
19346
|
};
|
|
19176
19347
|
const formatWrappingClip = {
|
|
19177
19348
|
name: _lt("Clip"),
|
|
19178
19349
|
execute: (env) => setStyle(env, { wrapping: "clip" }),
|
|
19179
|
-
isActive: (env) => env
|
|
19350
|
+
isActive: (env) => getWrappingMode(env) === "clip",
|
|
19180
19351
|
icon: "o-spreadsheet-Icon.WRAPPING_CLIP",
|
|
19181
19352
|
};
|
|
19182
19353
|
const textColor = {
|
|
@@ -19192,14 +19363,6 @@
|
|
|
19192
19363
|
execute: OPEN_CF_SIDEPANEL_ACTION,
|
|
19193
19364
|
icon: "o-spreadsheet-Icon.CONDITIONAL_FORMAT",
|
|
19194
19365
|
};
|
|
19195
|
-
const paintFormat = {
|
|
19196
|
-
name: _lt("Paint Format"),
|
|
19197
|
-
execute: (env) => env.model.dispatch("ACTIVATE_PAINT_FORMAT", {
|
|
19198
|
-
target: env.model.getters.getSelectedZones(),
|
|
19199
|
-
}),
|
|
19200
|
-
icon: "o-spreadsheet-Icon.PAINT_FORMAT",
|
|
19201
|
-
isActive: (env) => env.model.getters.isPaintingFormat(),
|
|
19202
|
-
};
|
|
19203
19366
|
const clearFormat = {
|
|
19204
19367
|
name: _lt("Clear formatting"),
|
|
19205
19368
|
description: "Ctrl+<",
|
|
@@ -19239,6 +19402,53 @@
|
|
|
19239
19402
|
}
|
|
19240
19403
|
const cell = env.model.getters.getActiveCell();
|
|
19241
19404
|
return cell.defaultAlign;
|
|
19405
|
+
}
|
|
19406
|
+
function getVerticalAlign(env) {
|
|
19407
|
+
const style = env.model.getters.getCurrentStyle();
|
|
19408
|
+
if (style.verticalAlign) {
|
|
19409
|
+
return style.verticalAlign;
|
|
19410
|
+
}
|
|
19411
|
+
return DEFAULT_VERTICAL_ALIGN;
|
|
19412
|
+
}
|
|
19413
|
+
function getWrappingMode(env) {
|
|
19414
|
+
const style = env.model.getters.getCurrentStyle();
|
|
19415
|
+
if (style.wrapping) {
|
|
19416
|
+
return style.wrapping;
|
|
19417
|
+
}
|
|
19418
|
+
return DEFAULT_WRAPPING_MODE;
|
|
19419
|
+
}
|
|
19420
|
+
function getHorizontalAlignmentIcon(env) {
|
|
19421
|
+
const horizontalAlign = getHorizontalAlign(env);
|
|
19422
|
+
switch (horizontalAlign) {
|
|
19423
|
+
case "right":
|
|
19424
|
+
return "o-spreadsheet-Icon.ALIGN_RIGHT";
|
|
19425
|
+
case "center":
|
|
19426
|
+
return "o-spreadsheet-Icon.ALIGN_CENTER";
|
|
19427
|
+
default:
|
|
19428
|
+
return "o-spreadsheet-Icon.ALIGN_LEFT";
|
|
19429
|
+
}
|
|
19430
|
+
}
|
|
19431
|
+
function getVerticalAlignmentIcon(env) {
|
|
19432
|
+
const verticalAlign = getVerticalAlign(env);
|
|
19433
|
+
switch (verticalAlign) {
|
|
19434
|
+
case "top":
|
|
19435
|
+
return "o-spreadsheet-Icon.ALIGN_TOP";
|
|
19436
|
+
case "middle":
|
|
19437
|
+
return "o-spreadsheet-Icon.ALIGN_MIDDLE";
|
|
19438
|
+
default:
|
|
19439
|
+
return "o-spreadsheet-Icon.ALIGN_BOTTOM";
|
|
19440
|
+
}
|
|
19441
|
+
}
|
|
19442
|
+
function getWrapModeIcon(env) {
|
|
19443
|
+
const wrapMode = getWrappingMode(env);
|
|
19444
|
+
switch (wrapMode) {
|
|
19445
|
+
case "wrap":
|
|
19446
|
+
return "o-spreadsheet-Icon.WRAPPING_WRAP";
|
|
19447
|
+
case "clip":
|
|
19448
|
+
return "o-spreadsheet-Icon.WRAPPING_CLIP";
|
|
19449
|
+
default:
|
|
19450
|
+
return "o-spreadsheet-Icon.WRAPPING_OVERFLOW";
|
|
19451
|
+
}
|
|
19242
19452
|
}
|
|
19243
19453
|
|
|
19244
19454
|
var ACTION_FORMAT = /*#__PURE__*/Object.freeze({
|
|
@@ -19270,6 +19480,7 @@
|
|
|
19270
19480
|
formatAlignmentTop: formatAlignmentTop,
|
|
19271
19481
|
formatAlignmentMiddle: formatAlignmentMiddle,
|
|
19272
19482
|
formatAlignmentBottom: formatAlignmentBottom,
|
|
19483
|
+
formatWrappingIcon: formatWrappingIcon,
|
|
19273
19484
|
formatWrapping: formatWrapping,
|
|
19274
19485
|
formatWrappingOverflow: formatWrappingOverflow,
|
|
19275
19486
|
formatWrappingWrap: formatWrappingWrap,
|
|
@@ -19277,7 +19488,6 @@
|
|
|
19277
19488
|
textColor: textColor,
|
|
19278
19489
|
fillColor: fillColor,
|
|
19279
19490
|
formatCF: formatCF,
|
|
19280
|
-
paintFormat: paintFormat,
|
|
19281
19491
|
clearFormat: clearFormat
|
|
19282
19492
|
});
|
|
19283
19493
|
|
|
@@ -20040,7 +20250,7 @@
|
|
|
20040
20250
|
separator: true,
|
|
20041
20251
|
})
|
|
20042
20252
|
.addChild("format_wrapping", ["format"], {
|
|
20043
|
-
...
|
|
20253
|
+
...formatWrappingIcon,
|
|
20044
20254
|
sequence: 80,
|
|
20045
20255
|
separator: true,
|
|
20046
20256
|
})
|
|
@@ -22330,17 +22540,45 @@
|
|
|
22330
22540
|
}
|
|
22331
22541
|
get formatProposals() {
|
|
22332
22542
|
const currency = this.availableCurrencies[this.state.selectedCurrencyIndex];
|
|
22333
|
-
const
|
|
22334
|
-
const
|
|
22335
|
-
const secondPosition = currency.position === "before" ? "after" : "before";
|
|
22543
|
+
const position = currency.position;
|
|
22544
|
+
const opposite = currency.position === "before" ? "after" : "before";
|
|
22336
22545
|
const symbol = this.state.currencySymbol.trim() ? this.state.currencySymbol : "";
|
|
22337
22546
|
const code = this.state.currencyCode.trim() ? this.state.currencyCode : "";
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
|
|
22343
|
-
|
|
22547
|
+
const decimalPlaces = currency.decimalPlaces;
|
|
22548
|
+
if (!symbol && !code) {
|
|
22549
|
+
return [];
|
|
22550
|
+
}
|
|
22551
|
+
const simple = symbol ? createCurrencyFormat({ symbol, position, decimalPlaces }) : "";
|
|
22552
|
+
const rounded = simple ? roundFormat(simple) : "";
|
|
22553
|
+
const simpleWithCode = createCurrencyFormat({ symbol, position, decimalPlaces, code });
|
|
22554
|
+
const roundedWithCode = roundFormat(simpleWithCode);
|
|
22555
|
+
const simpleOpposite = symbol
|
|
22556
|
+
? createCurrencyFormat({ symbol, position: opposite, decimalPlaces })
|
|
22557
|
+
: "";
|
|
22558
|
+
const roundedOpposite = simpleOpposite ? roundFormat(simpleOpposite) : "";
|
|
22559
|
+
const simpleOppositeWithCode = createCurrencyFormat({
|
|
22560
|
+
symbol,
|
|
22561
|
+
position: opposite,
|
|
22562
|
+
decimalPlaces,
|
|
22563
|
+
code,
|
|
22564
|
+
});
|
|
22565
|
+
const roundedOppositeWithCode = roundFormat(simpleOppositeWithCode);
|
|
22566
|
+
const formats = new Set([
|
|
22567
|
+
rounded,
|
|
22568
|
+
simple,
|
|
22569
|
+
roundedWithCode,
|
|
22570
|
+
simpleWithCode,
|
|
22571
|
+
roundedOpposite,
|
|
22572
|
+
simpleOpposite,
|
|
22573
|
+
roundedOppositeWithCode,
|
|
22574
|
+
simpleOppositeWithCode,
|
|
22575
|
+
]);
|
|
22576
|
+
return [...formats]
|
|
22577
|
+
.filter((format) => format !== "")
|
|
22578
|
+
.map((format) => ({
|
|
22579
|
+
format,
|
|
22580
|
+
example: formatValue(1000.0, { format, locale: this.env.model.getters.getLocale() }),
|
|
22581
|
+
}));
|
|
22344
22582
|
}
|
|
22345
22583
|
get isSameFormat() {
|
|
22346
22584
|
const selectedFormat = this.formatProposals[this.state.selectedFormatIndex];
|
|
@@ -22397,41 +22635,6 @@
|
|
|
22397
22635
|
initAvailableCurrencies() {
|
|
22398
22636
|
this.state.selectedCurrencyIndex = 0;
|
|
22399
22637
|
}
|
|
22400
|
-
initProposalBases(decimalPlaces) {
|
|
22401
|
-
const result = [{ format: "#,##0", example: "1,000" }];
|
|
22402
|
-
const decimalRepresentation = decimalPlaces ? "." + "0".repeat(decimalPlaces) : "";
|
|
22403
|
-
if (decimalRepresentation) {
|
|
22404
|
-
result.push({
|
|
22405
|
-
format: "#,##0" + decimalRepresentation,
|
|
22406
|
-
example: "1,000" + decimalRepresentation,
|
|
22407
|
-
});
|
|
22408
|
-
}
|
|
22409
|
-
return result;
|
|
22410
|
-
}
|
|
22411
|
-
createFormatProposals(proposalBases, symbol, code, position) {
|
|
22412
|
-
let formatProposals = [];
|
|
22413
|
-
// 1 - add proposal with symbol and without code
|
|
22414
|
-
if (symbol) {
|
|
22415
|
-
for (let base of proposalBases) {
|
|
22416
|
-
formatProposals.push(this.createFormatProposal(position, base.example, base.format, symbol));
|
|
22417
|
-
}
|
|
22418
|
-
}
|
|
22419
|
-
// 2 - if code exist --> add more proposal with symbol and with code
|
|
22420
|
-
if (code) {
|
|
22421
|
-
for (let base of proposalBases) {
|
|
22422
|
-
const expression = (position === "after" ? " " : "") + code + " " + symbol;
|
|
22423
|
-
formatProposals.push(this.createFormatProposal(position, base.example, base.format, expression));
|
|
22424
|
-
}
|
|
22425
|
-
}
|
|
22426
|
-
return formatProposals;
|
|
22427
|
-
}
|
|
22428
|
-
createFormatProposal(position, baseExample, formatBase, expression) {
|
|
22429
|
-
const formatExpression = "[$" + expression + "]";
|
|
22430
|
-
return {
|
|
22431
|
-
example: position === "before" ? expression + baseExample : baseExample + expression,
|
|
22432
|
-
format: position === "before" ? formatExpression + formatBase : formatBase + formatExpression,
|
|
22433
|
-
};
|
|
22434
|
-
}
|
|
22435
22638
|
getCommonFormat() {
|
|
22436
22639
|
const selectedZones = this.env.model.getters.getSelectedZones();
|
|
22437
22640
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -23234,7 +23437,7 @@
|
|
|
23234
23437
|
selection.removeAllRanges();
|
|
23235
23438
|
selection.addRange(range);
|
|
23236
23439
|
}
|
|
23237
|
-
if (start
|
|
23440
|
+
if (start === end && start === 0) {
|
|
23238
23441
|
range.setStart(this.el, 0);
|
|
23239
23442
|
range.setEnd(this.el, 0);
|
|
23240
23443
|
}
|
|
@@ -23487,7 +23690,7 @@
|
|
|
23487
23690
|
}, 0);
|
|
23488
23691
|
}
|
|
23489
23692
|
}
|
|
23490
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent
|
|
23693
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
23491
23694
|
usedCharacters++;
|
|
23492
23695
|
}
|
|
23493
23696
|
return usedCharacters;
|
|
@@ -25034,6 +25237,14 @@
|
|
|
25034
25237
|
};
|
|
25035
25238
|
}
|
|
25036
25239
|
|
|
25240
|
+
const CURSOR_SVG = /*xml*/ `
|
|
25241
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="16"><path d="M6.5.4c1.3-.8 2.9-.1 3.8 1.4l2.9 5.1c.2.4.9 1.6-.4 2.3l-1.6.9 1.8 3.1c.2.4.1 1-.2 1.2l-1.6 1c-.3.1-.9 0-1.1-.4l-1.8-3.1-1.6 1c-.6.4-1.7 0-2.2-.8L0 4.3"/><path fill="#fff" d="M9.1 2a1.4 1.1 60 0 0-1.7-.6L5.5 2.5l.9 1.6-1 .6-.9-1.6-.6.4 1.8 3.1-1.3.7-1.8-3.1-1 .6 3.8 6.6 6.8-3.98M3.9 8.8 10.82 5l.795 1.4-6.81 3.96"/></svg>
|
|
25242
|
+
`;
|
|
25243
|
+
css /* scss */ `
|
|
25244
|
+
.o-paint-format-cursor {
|
|
25245
|
+
cursor: url("data:image/svg+xml,${encodeURIComponent(CURSOR_SVG)}"), auto;
|
|
25246
|
+
}
|
|
25247
|
+
`;
|
|
25037
25248
|
function useCellHovered(env, gridRef, callback) {
|
|
25038
25249
|
let hoveredPosition = {
|
|
25039
25250
|
col: undefined,
|
|
@@ -25157,6 +25368,12 @@
|
|
|
25157
25368
|
}
|
|
25158
25369
|
return this.gridOverlay.el;
|
|
25159
25370
|
}
|
|
25371
|
+
get style() {
|
|
25372
|
+
return this.props.gridOverlayDimensions;
|
|
25373
|
+
}
|
|
25374
|
+
get isPaintingFormat() {
|
|
25375
|
+
return this.env.model.getters.isPaintingFormat();
|
|
25376
|
+
}
|
|
25160
25377
|
onMouseDown(ev) {
|
|
25161
25378
|
if (ev.button > 0) {
|
|
25162
25379
|
// not main button, probably a context menu
|
|
@@ -26334,6 +26551,9 @@
|
|
|
26334
26551
|
else if (this.menuState.isOpen) {
|
|
26335
26552
|
this.closeMenu();
|
|
26336
26553
|
}
|
|
26554
|
+
else if (this.env.model.getters.isPaintingFormat()) {
|
|
26555
|
+
this.env.model.dispatch("CANCEL_PAINT_FORMAT");
|
|
26556
|
+
}
|
|
26337
26557
|
else {
|
|
26338
26558
|
this.env.model.dispatch("CLEAN_CLIPBOARD_HIGHLIGHT");
|
|
26339
26559
|
}
|
|
@@ -27536,8 +27756,8 @@
|
|
|
27536
27756
|
throw new Error("Multiple escaped blocks in format");
|
|
27537
27757
|
}
|
|
27538
27758
|
convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
|
|
27539
|
-
convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _
|
|
27540
|
-
convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // *
|
|
27759
|
+
convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ === ignore width of next char for align purposes. Not supported ATM
|
|
27760
|
+
convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * === repeat next character enough to fill the line. Not supported ATM
|
|
27541
27761
|
convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
|
|
27542
27762
|
convertedFormat = convertedFormat.replace(/\\./g, (match) => match[1]); // unescape other characters
|
|
27543
27763
|
if (isXlsxDateFormat(convertedFormat)) {
|
|
@@ -28829,29 +29049,26 @@
|
|
|
28829
29049
|
return new XMLString(concat(str));
|
|
28830
29050
|
}
|
|
28831
29051
|
/**
|
|
28832
|
-
* Removes the namespace of all the xml tags in the string.
|
|
29052
|
+
* Removes the escaped namespace of all the xml tags in the string.
|
|
28833
29053
|
*
|
|
28834
|
-
* Eg. : "
|
|
29054
|
+
* Eg. : "NAMESPACEnsNAMESPACEtest a" => "test a"
|
|
28835
29055
|
*/
|
|
28836
|
-
function
|
|
28837
|
-
return
|
|
29056
|
+
function removeTagEscapedNamespaces(tag) {
|
|
29057
|
+
return tag.replace(/NAMESPACE.*NAMESPACE(.*)/, "$1");
|
|
28838
29058
|
}
|
|
28839
29059
|
/**
|
|
28840
|
-
*
|
|
29060
|
+
* Encase the namespaces in the element's tags with NAMESPACE string
|
|
28841
29061
|
*
|
|
28842
|
-
*
|
|
28843
|
-
*/
|
|
28844
|
-
function escapeNamespaces(query) {
|
|
28845
|
-
return query.replace(/([a-z0-9]+):(?=[a-z0-9]+)/gi, "$1\\:");
|
|
28846
|
-
}
|
|
28847
|
-
/**
|
|
28848
|
-
* Return true if the querySelector ignores the namespaces when searching for a tag in the DOM.
|
|
29062
|
+
* e.g. <x:foo> becomes <NAMESPACExNAMESPACEFoo>
|
|
28849
29063
|
*
|
|
28850
|
-
*
|
|
29064
|
+
* That's useful because namespaces aren't supported by the HTML specification, so it's arbitrary whether a HTML parser/querySelector
|
|
29065
|
+
* implementation will support namespaces in the tags or not.
|
|
28851
29066
|
*/
|
|
28852
|
-
function
|
|
28853
|
-
|
|
28854
|
-
|
|
29067
|
+
function escapeTagNamespaces(str) {
|
|
29068
|
+
return str.replaceAll(/(<\/?)([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "$1" + "NAMESPACE" + "$2" + "NAMESPACE" + "$3");
|
|
29069
|
+
}
|
|
29070
|
+
function escapeQueryNameSpaces(query) {
|
|
29071
|
+
return query.replaceAll(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "NAMESPACE" + "$1" + "NAMESPACE" + "$2");
|
|
28855
29072
|
}
|
|
28856
29073
|
|
|
28857
29074
|
class AttributeValue {
|
|
@@ -28881,14 +29098,20 @@
|
|
|
28881
29098
|
// The xml file we are currently parsing. We should have one Extractor class by XLSXImportFile, but
|
|
28882
29099
|
// the XLSXImportFile contains both the main .xml file, and the .rels file
|
|
28883
29100
|
currentFile = undefined;
|
|
28884
|
-
|
|
28885
|
-
|
|
29101
|
+
/**
|
|
29102
|
+
* /!\ Important : There should be no namespaces in the tags of the XML files.
|
|
29103
|
+
*
|
|
29104
|
+
* This class use native querySelector and querySelectorAll, that's used for HTML (not XML). These aren't supposed to
|
|
29105
|
+
* handled namespaces, as they are not supported by the HTML specification. Some implementations (most browsers) do
|
|
29106
|
+
* actually support namespaces, but some don't (e.g. jsdom).
|
|
29107
|
+
*
|
|
29108
|
+
* The namespace should be escaped as with NAMESPACE string (eg. <t:foo> => <NAMESPACEtNAMESPACEfoo>).
|
|
29109
|
+
*/
|
|
28886
29110
|
constructor(rootFile, xlsxStructure, warningManager) {
|
|
28887
29111
|
this.rootFile = rootFile;
|
|
28888
29112
|
this.currentFile = rootFile.file.fileName;
|
|
28889
29113
|
this.xlsxFileStructure = xlsxStructure;
|
|
28890
29114
|
this.warningManager = warningManager;
|
|
28891
|
-
this.areNamespaceIgnored = areNamespaceIgnoredByQuerySelector();
|
|
28892
29115
|
this.relationships = {};
|
|
28893
29116
|
if (rootFile.rels) {
|
|
28894
29117
|
this.extractRelationships(rootFile.rels).map((rel) => {
|
|
@@ -29114,29 +29337,13 @@
|
|
|
29114
29337
|
throw new Error("Cannot find target file");
|
|
29115
29338
|
return f;
|
|
29116
29339
|
}
|
|
29117
|
-
/**
|
|
29118
|
-
* Wrapper of querySelector, but we'll remove the namespaces from the query if areNamespacesIgnored is true.
|
|
29119
|
-
*
|
|
29120
|
-
* Why we need to do this :
|
|
29121
|
-
* - For an XML "<t:test />"
|
|
29122
|
-
* - on Jest(jsdom) : xml.querySelector("test") == null, xml.querySelector("t\\:test") == <t:test />
|
|
29123
|
-
* - on Browser : xml.querySelector("test") == <t:test />, xml.querySelector("t\\:test") == null
|
|
29124
|
-
*/
|
|
29125
29340
|
querySelector(element, query) {
|
|
29126
|
-
|
|
29127
|
-
return element.querySelector(
|
|
29341
|
+
const escapedQuery = escapeQueryNameSpaces(query);
|
|
29342
|
+
return element.querySelector(escapedQuery);
|
|
29128
29343
|
}
|
|
29129
|
-
/**
|
|
29130
|
-
* Wrapper of querySelectorAll, but we'll remove the namespaces from the query if areNamespacesIgnored is true.
|
|
29131
|
-
*
|
|
29132
|
-
* Why we need to do this :
|
|
29133
|
-
* - For an XML "<t:test />"
|
|
29134
|
-
* - on Jest(jsdom) : xml.querySelectorAll("test") == [], xml.querySelectorAll("t\\:test") == [<t:test />]
|
|
29135
|
-
* - on Browser : xml.querySelectorAll("test") == [<t:test />], xml.querySelectorAll("t\\:test") == []
|
|
29136
|
-
*/
|
|
29137
29344
|
querySelectorAll(element, query) {
|
|
29138
|
-
|
|
29139
|
-
return element.querySelectorAll(
|
|
29345
|
+
const escapedQuery = escapeQueryNameSpaces(query);
|
|
29346
|
+
return element.querySelectorAll(escapedQuery);
|
|
29140
29347
|
}
|
|
29141
29348
|
/**
|
|
29142
29349
|
* Get a color from its id in the Theme's colorScheme.
|
|
@@ -29376,7 +29583,7 @@
|
|
|
29376
29583
|
throw new Error("Missing plot area in the chart definition.");
|
|
29377
29584
|
}
|
|
29378
29585
|
for (let child of plotAreaElement.children) {
|
|
29379
|
-
const tag =
|
|
29586
|
+
const tag = removeTagEscapedNamespaces(child.tagName);
|
|
29380
29587
|
if (XLSX_CHART_TYPES.some((chartType) => chartType === tag)) {
|
|
29381
29588
|
return tag;
|
|
29382
29589
|
}
|
|
@@ -29388,7 +29595,7 @@
|
|
|
29388
29595
|
class XlsxFigureExtractor extends XlsxBaseExtractor {
|
|
29389
29596
|
extractFigures() {
|
|
29390
29597
|
return this.mapOnElements({ parent: this.rootFile.file.xml, query: "xdr:wsDr", children: true }, (figureElement) => {
|
|
29391
|
-
const anchorType =
|
|
29598
|
+
const anchorType = removeTagEscapedNamespaces(figureElement.tagName);
|
|
29392
29599
|
if (anchorType !== "twoCellAnchor") {
|
|
29393
29600
|
throw new Error("Only twoCellAnchor are supported for xlsx drawings.");
|
|
29394
29601
|
}
|
|
@@ -30022,7 +30229,8 @@
|
|
|
30022
30229
|
for (let key of Object.keys(files)) {
|
|
30023
30230
|
// Random files can be in xlsx (like a bin file for printer settings)
|
|
30024
30231
|
if (key.endsWith(".xml") || key.endsWith(".rels")) {
|
|
30025
|
-
|
|
30232
|
+
const contentString = escapeTagNamespaces(files[key]);
|
|
30233
|
+
this.xmls[key] = parseXML(new XMLString(contentString));
|
|
30026
30234
|
}
|
|
30027
30235
|
else if (key.includes("media/image")) {
|
|
30028
30236
|
this.images.push({
|
|
@@ -31089,7 +31297,7 @@
|
|
|
31089
31297
|
}
|
|
31090
31298
|
/**
|
|
31091
31299
|
* Set the borders of a cell.
|
|
31092
|
-
* It overrides the current border if override
|
|
31300
|
+
* It overrides the current border if override === true.
|
|
31093
31301
|
*/
|
|
31094
31302
|
setBorder(sheetId, col, row, border, override = true) {
|
|
31095
31303
|
if (override || !this.borders?.[sheetId]?.[col]?.[row]?.vertical) {
|
|
@@ -32359,7 +32567,9 @@
|
|
|
32359
32567
|
const numHeader = this.getters.getNumberRows(sheetId);
|
|
32360
32568
|
let gridHeight = 0;
|
|
32361
32569
|
for (let i = 0; i < numHeader; i++) {
|
|
32362
|
-
|
|
32570
|
+
// TODO : since the row size is an UI value now, this doesn't work anymore. Using the default cell height is
|
|
32571
|
+
// a temporary solution at best, but is broken.
|
|
32572
|
+
gridHeight += this.getters.getUserRowSize(sheetId, i) || DEFAULT_CELL_HEIGHT;
|
|
32363
32573
|
}
|
|
32364
32574
|
const figures = this.getters.getFigures(sheetId);
|
|
32365
32575
|
for (const figure of figures) {
|
|
@@ -32785,33 +32995,15 @@
|
|
|
32785
32995
|
}
|
|
32786
32996
|
|
|
32787
32997
|
class HeaderSizePlugin extends CorePlugin {
|
|
32788
|
-
static getters = ["
|
|
32998
|
+
static getters = ["getUserRowSize", "getColSize"];
|
|
32789
32999
|
sizes = {};
|
|
32790
33000
|
handle(cmd) {
|
|
32791
33001
|
switch (cmd.type) {
|
|
32792
33002
|
case "CREATE_SHEET": {
|
|
32793
|
-
|
|
32794
|
-
const sizes = {
|
|
32795
|
-
COL: computedSizes.COL.map((size) => ({
|
|
32796
|
-
manualSize: undefined,
|
|
32797
|
-
computedSize: lazy(size),
|
|
32798
|
-
})),
|
|
32799
|
-
ROW: computedSizes.ROW.map((size) => ({
|
|
32800
|
-
manualSize: undefined,
|
|
32801
|
-
computedSize: lazy(size),
|
|
32802
|
-
})),
|
|
32803
|
-
};
|
|
32804
|
-
this.history.update("sizes", cmd.sheetId, sizes);
|
|
33003
|
+
this.history.update("sizes", cmd.sheetId, { COL: [], ROW: [] });
|
|
32805
33004
|
break;
|
|
32806
33005
|
}
|
|
32807
33006
|
case "DUPLICATE_SHEET":
|
|
32808
|
-
// make sure the values are computed in case the original sheet is deleted
|
|
32809
|
-
for (const row of this.sizes[cmd.sheetId].ROW) {
|
|
32810
|
-
row.computedSize();
|
|
32811
|
-
}
|
|
32812
|
-
for (const col of this.sizes[cmd.sheetId].COL) {
|
|
32813
|
-
col.computedSize();
|
|
32814
|
-
}
|
|
32815
33007
|
this.history.update("sizes", cmd.sheetIdTo, deepCopy(this.sizes[cmd.sheetId]));
|
|
32816
33008
|
break;
|
|
32817
33009
|
case "DELETE_SHEET":
|
|
@@ -32820,21 +33012,8 @@
|
|
|
32820
33012
|
this.history.update("sizes", sizes);
|
|
32821
33013
|
break;
|
|
32822
33014
|
case "REMOVE_COLUMNS_ROWS": {
|
|
32823
|
-
|
|
32824
|
-
|
|
32825
|
-
sizes.splice(headerIndex, 1);
|
|
32826
|
-
}
|
|
32827
|
-
const min = Math.min(...cmd.elements);
|
|
32828
|
-
sizes = sizes.map((size, row) => {
|
|
32829
|
-
if (cmd.dimension === "ROW" && row >= min) {
|
|
32830
|
-
// invalidate sizes
|
|
32831
|
-
return {
|
|
32832
|
-
manualSize: size.manualSize,
|
|
32833
|
-
computedSize: lazy(() => this.getRowTallestCellSize(cmd.sheetId, row)),
|
|
32834
|
-
};
|
|
32835
|
-
}
|
|
32836
|
-
return size;
|
|
32837
|
-
});
|
|
33015
|
+
const arr = this.sizes[cmd.sheetId][cmd.dimension];
|
|
33016
|
+
const sizes = removeIndexesFromArray(arr, cmd.elements);
|
|
32838
33017
|
this.history.update("sizes", cmd.sheetId, cmd.dimension, sizes);
|
|
32839
33018
|
break;
|
|
32840
33019
|
}
|
|
@@ -32843,51 +33022,18 @@
|
|
|
32843
33022
|
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
32844
33023
|
const baseSize = sizes[cmd.base];
|
|
32845
33024
|
sizes.splice(addIndex, 0, ...Array(cmd.quantity).fill(baseSize));
|
|
32846
|
-
sizes = sizes.map((size, row) => {
|
|
32847
|
-
if (cmd.dimension === "ROW" && row > cmd.base + cmd.quantity) {
|
|
32848
|
-
// invalidate sizes
|
|
32849
|
-
return {
|
|
32850
|
-
manualSize: size.manualSize,
|
|
32851
|
-
computedSize: lazy(() => this.getRowTallestCellSize(cmd.sheetId, row)),
|
|
32852
|
-
};
|
|
32853
|
-
}
|
|
32854
|
-
return size;
|
|
32855
|
-
});
|
|
32856
33025
|
this.history.update("sizes", cmd.sheetId, cmd.dimension, sizes);
|
|
32857
33026
|
break;
|
|
32858
33027
|
}
|
|
32859
33028
|
case "RESIZE_COLUMNS_ROWS":
|
|
32860
|
-
|
|
32861
|
-
|
|
32862
|
-
|
|
32863
|
-
const size = height;
|
|
32864
|
-
this.history.update("sizes", cmd.sheetId, cmd.dimension, el, {
|
|
32865
|
-
manualSize: cmd.size || undefined,
|
|
32866
|
-
computedSize: lazy(size),
|
|
32867
|
-
});
|
|
32868
|
-
}
|
|
32869
|
-
else {
|
|
32870
|
-
this.history.update("sizes", cmd.sheetId, cmd.dimension, el, {
|
|
32871
|
-
manualSize: cmd.size || undefined,
|
|
32872
|
-
computedSize: lazy(cmd.size || DEFAULT_CELL_WIDTH),
|
|
32873
|
-
});
|
|
33029
|
+
if (cmd.dimension === "ROW") {
|
|
33030
|
+
for (const el of cmd.elements) {
|
|
33031
|
+
this.history.update("sizes", cmd.sheetId, cmd.dimension, el, cmd.size || undefined);
|
|
32874
33032
|
}
|
|
32875
33033
|
}
|
|
32876
|
-
|
|
32877
|
-
|
|
32878
|
-
|
|
32879
|
-
const { sheetId, row } = cmd;
|
|
32880
|
-
this.history.update("sizes", sheetId, "ROW", row, "computedSize", lazy(() => this.getRowTallestCellSize(sheetId, row)));
|
|
32881
|
-
}
|
|
32882
|
-
break;
|
|
32883
|
-
case "ADD_MERGE":
|
|
32884
|
-
case "REMOVE_MERGE":
|
|
32885
|
-
for (let target of cmd.target) {
|
|
32886
|
-
for (let row of range(target.top, target.bottom + 1)) {
|
|
32887
|
-
const rowHeight = this.getRowTallestCellSize(cmd.sheetId, row);
|
|
32888
|
-
if (rowHeight !== this.getRowSize(cmd.sheetId, row)) {
|
|
32889
|
-
this.history.update("sizes", cmd.sheetId, "ROW", row, "computedSize", lazy(rowHeight));
|
|
32890
|
-
}
|
|
33034
|
+
else {
|
|
33035
|
+
for (const el of cmd.elements) {
|
|
33036
|
+
this.history.update("sizes", cmd.sheetId, cmd.dimension, el, cmd.size || undefined);
|
|
32891
33037
|
}
|
|
32892
33038
|
}
|
|
32893
33039
|
break;
|
|
@@ -32895,94 +33041,29 @@
|
|
|
32895
33041
|
return;
|
|
32896
33042
|
}
|
|
32897
33043
|
getColSize(sheetId, index) {
|
|
32898
|
-
return this.
|
|
32899
|
-
}
|
|
32900
|
-
getRowSize(sheetId, index) {
|
|
32901
|
-
return this.getHeaderSize(sheetId, "ROW", index);
|
|
33044
|
+
return Math.round(this.sizes[sheetId]?.["COL"][index] || DEFAULT_CELL_WIDTH);
|
|
32902
33045
|
}
|
|
32903
|
-
|
|
32904
|
-
|
|
32905
|
-
|
|
32906
|
-
this.getDefaultHeaderSize(dimension));
|
|
32907
|
-
}
|
|
32908
|
-
computeSheetSizes(sheetId) {
|
|
32909
|
-
const sizes = { COL: [], ROW: [] };
|
|
32910
|
-
for (let col of range(0, this.getters.getNumberCols(sheetId))) {
|
|
32911
|
-
sizes.COL.push(this.getHeaderSize(sheetId, "COL", col));
|
|
32912
|
-
}
|
|
32913
|
-
for (let row of range(0, this.getters.getNumberRows(sheetId))) {
|
|
32914
|
-
let rowSize = this.sizes[sheetId]?.["ROW"]?.[row].manualSize;
|
|
32915
|
-
if (!rowSize) {
|
|
32916
|
-
const height = this.getRowTallestCellSize(sheetId, row);
|
|
32917
|
-
rowSize = height;
|
|
32918
|
-
}
|
|
32919
|
-
sizes.ROW.push(rowSize);
|
|
32920
|
-
}
|
|
32921
|
-
return sizes;
|
|
32922
|
-
}
|
|
32923
|
-
getDefaultHeaderSize(dimension) {
|
|
32924
|
-
return dimension === "COL" ? DEFAULT_CELL_WIDTH : DEFAULT_CELL_HEIGHT;
|
|
32925
|
-
}
|
|
32926
|
-
/**
|
|
32927
|
-
* Return the height the cell should have in the sheet, which is either DEFAULT_CELL_HEIGHT if the cell is in a multi-row
|
|
32928
|
-
* merge, or the height of the cell computed based on its font size.
|
|
32929
|
-
*/
|
|
32930
|
-
getCellHeight(position) {
|
|
32931
|
-
const merge = this.getters.getMerge(position);
|
|
32932
|
-
if (merge && merge.bottom !== merge.top) {
|
|
32933
|
-
return DEFAULT_CELL_HEIGHT;
|
|
32934
|
-
}
|
|
32935
|
-
const cell = this.getters.getCell(position);
|
|
32936
|
-
return getDefaultCellHeight(cell);
|
|
32937
|
-
}
|
|
32938
|
-
/**
|
|
32939
|
-
* Get the tallest cell of a row and its size.
|
|
32940
|
-
*
|
|
32941
|
-
* The tallest cell of the row correspond to the cell with the biggest font size,
|
|
32942
|
-
* and that is not part of a multi-line merge.
|
|
32943
|
-
*/
|
|
32944
|
-
getRowTallestCellSize(sheetId, row) {
|
|
32945
|
-
const cellIds = this.getters.getRowCells(sheetId, row);
|
|
32946
|
-
let maxHeight = 0;
|
|
32947
|
-
for (let i = 0; i < cellIds.length; i++) {
|
|
32948
|
-
const cell = this.getters.getCellById(cellIds[i]);
|
|
32949
|
-
if (!cell)
|
|
32950
|
-
continue;
|
|
32951
|
-
const position = this.getters.getCellPosition(cell.id);
|
|
32952
|
-
const cellHeight = this.getCellHeight(position);
|
|
32953
|
-
if (cellHeight > maxHeight && cellHeight > DEFAULT_CELL_HEIGHT) {
|
|
32954
|
-
maxHeight = cellHeight;
|
|
32955
|
-
}
|
|
32956
|
-
}
|
|
32957
|
-
if (maxHeight <= DEFAULT_CELL_HEIGHT) {
|
|
32958
|
-
return DEFAULT_CELL_HEIGHT;
|
|
32959
|
-
}
|
|
32960
|
-
return maxHeight;
|
|
33046
|
+
getUserRowSize(sheetId, index) {
|
|
33047
|
+
const rowSize = this.sizes[sheetId]?.["ROW"][index];
|
|
33048
|
+
return rowSize ? Math.round(rowSize) : undefined;
|
|
32961
33049
|
}
|
|
32962
33050
|
import(data) {
|
|
32963
33051
|
for (let sheet of data.sheets) {
|
|
32964
|
-
const
|
|
33052
|
+
const sizes = {
|
|
33053
|
+
COL: Array(sheet.colNumber).fill(undefined),
|
|
33054
|
+
ROW: Array(sheet.rowNumber).fill(undefined),
|
|
33055
|
+
};
|
|
32965
33056
|
for (let [rowIndex, row] of Object.entries(sheet.rows)) {
|
|
32966
33057
|
if (row.size) {
|
|
32967
|
-
|
|
33058
|
+
sizes["ROW"][rowIndex] = row.size;
|
|
32968
33059
|
}
|
|
32969
33060
|
}
|
|
32970
33061
|
for (let [colIndex, col] of Object.entries(sheet.cols)) {
|
|
32971
33062
|
if (col.size) {
|
|
32972
|
-
|
|
32973
|
-
}
|
|
32974
|
-
}
|
|
32975
|
-
|
|
32976
|
-
this.sizes[sheet.id] = {
|
|
32977
|
-
COL: computedSizes.COL.map((size, i) => ({
|
|
32978
|
-
manualSize: manualSizes.COL[i],
|
|
32979
|
-
computedSize: lazy(size),
|
|
32980
|
-
})),
|
|
32981
|
-
ROW: computedSizes.ROW.map((size, i) => ({
|
|
32982
|
-
manualSize: manualSizes.ROW[i],
|
|
32983
|
-
computedSize: lazy(size),
|
|
32984
|
-
})),
|
|
32985
|
-
};
|
|
33063
|
+
sizes["COL"][colIndex] = col.size;
|
|
33064
|
+
}
|
|
33065
|
+
}
|
|
33066
|
+
this.sizes[sheet.id] = sizes;
|
|
32986
33067
|
}
|
|
32987
33068
|
return;
|
|
32988
33069
|
}
|
|
@@ -33003,9 +33084,12 @@
|
|
|
33003
33084
|
if (sheet.rows === undefined) {
|
|
33004
33085
|
sheet.rows = {};
|
|
33005
33086
|
}
|
|
33006
|
-
for (
|
|
33007
|
-
if (exportDefaults || this.sizes[sheet.id]["ROW"][row]
|
|
33008
|
-
sheet.rows[row] = {
|
|
33087
|
+
for (const row of range(0, this.getters.getNumberRows(sheet.id))) {
|
|
33088
|
+
if (exportDefaults || this.sizes[sheet.id]["ROW"][row]) {
|
|
33089
|
+
sheet.rows[row] = {
|
|
33090
|
+
...sheet.rows[row],
|
|
33091
|
+
size: this.getUserRowSize(sheet.id, row) ?? DEFAULT_CELL_HEIGHT,
|
|
33092
|
+
};
|
|
33009
33093
|
}
|
|
33010
33094
|
}
|
|
33011
33095
|
// Export col sizes
|
|
@@ -33013,7 +33097,7 @@
|
|
|
33013
33097
|
sheet.cols = {};
|
|
33014
33098
|
}
|
|
33015
33099
|
for (let col of range(0, this.getters.getNumberCols(sheet.id))) {
|
|
33016
|
-
if (exportDefaults || this.sizes[sheet.id]["COL"][col]
|
|
33100
|
+
if (exportDefaults || this.sizes[sheet.id]["COL"][col]) {
|
|
33017
33101
|
sheet.cols[col] = { ...sheet.cols[col], size: this.getColSize(sheet.id, col) };
|
|
33018
33102
|
}
|
|
33019
33103
|
}
|
|
@@ -36569,7 +36653,7 @@
|
|
|
36569
36653
|
case "ContainsText":
|
|
36570
36654
|
return cell.value.toString().indexOf(values[0].toString()) > -1;
|
|
36571
36655
|
case "NotContains":
|
|
36572
|
-
return !cell.value || cell.value.toString().indexOf(values[0].toString())
|
|
36656
|
+
return !cell.value || cell.value.toString().indexOf(values[0].toString()) === -1;
|
|
36573
36657
|
case "GreaterThan":
|
|
36574
36658
|
return cell.value > values[0];
|
|
36575
36659
|
case "GreaterThanOrEqual":
|
|
@@ -36596,6 +36680,156 @@
|
|
|
36596
36680
|
};
|
|
36597
36681
|
}
|
|
36598
36682
|
|
|
36683
|
+
class UIRowSizePlugin extends UIPlugin {
|
|
36684
|
+
static getters = ["getRowSize"];
|
|
36685
|
+
tallestCellInRow = {};
|
|
36686
|
+
ctx = document.createElement("canvas").getContext("2d");
|
|
36687
|
+
handle(cmd) {
|
|
36688
|
+
switch (cmd.type) {
|
|
36689
|
+
case "START":
|
|
36690
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
36691
|
+
this.initializeSheet(sheetId);
|
|
36692
|
+
}
|
|
36693
|
+
break;
|
|
36694
|
+
case "CREATE_SHEET": {
|
|
36695
|
+
this.initializeSheet(cmd.sheetId);
|
|
36696
|
+
break;
|
|
36697
|
+
}
|
|
36698
|
+
case "DUPLICATE_SHEET": {
|
|
36699
|
+
const tallestCells = deepCopy(this.tallestCellInRow[cmd.sheetId]);
|
|
36700
|
+
this.history.update("tallestCellInRow", cmd.sheetIdTo, tallestCells);
|
|
36701
|
+
break;
|
|
36702
|
+
}
|
|
36703
|
+
case "DELETE_SHEET":
|
|
36704
|
+
const tallestCells = { ...this.tallestCellInRow };
|
|
36705
|
+
delete tallestCells[cmd.sheetId];
|
|
36706
|
+
this.history.update("tallestCellInRow", tallestCells);
|
|
36707
|
+
break;
|
|
36708
|
+
case "REMOVE_COLUMNS_ROWS": {
|
|
36709
|
+
if (cmd.dimension === "COL") {
|
|
36710
|
+
return;
|
|
36711
|
+
}
|
|
36712
|
+
const tallestCells = removeIndexesFromArray(this.tallestCellInRow[cmd.sheetId], cmd.elements);
|
|
36713
|
+
this.history.update("tallestCellInRow", cmd.sheetId, tallestCells);
|
|
36714
|
+
break;
|
|
36715
|
+
}
|
|
36716
|
+
case "ADD_COLUMNS_ROWS": {
|
|
36717
|
+
if (cmd.dimension === "COL") {
|
|
36718
|
+
return;
|
|
36719
|
+
}
|
|
36720
|
+
const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
|
|
36721
|
+
const newCells = Array(cmd.quantity).fill(undefined);
|
|
36722
|
+
const newTallestCells = insertItemsAtIndex(this.tallestCellInRow[cmd.sheetId], newCells, addIndex);
|
|
36723
|
+
this.history.update("tallestCellInRow", cmd.sheetId, newTallestCells);
|
|
36724
|
+
break;
|
|
36725
|
+
}
|
|
36726
|
+
case "RESIZE_COLUMNS_ROWS":
|
|
36727
|
+
{
|
|
36728
|
+
const sheetId = cmd.sheetId;
|
|
36729
|
+
if (cmd.dimension === "ROW") {
|
|
36730
|
+
for (const row of cmd.elements) {
|
|
36731
|
+
const tallestCell = this.getRowTallestCell(sheetId, row);
|
|
36732
|
+
this.history.update("tallestCellInRow", sheetId, row, tallestCell);
|
|
36733
|
+
}
|
|
36734
|
+
}
|
|
36735
|
+
else {
|
|
36736
|
+
// Recompute row heights on col size change, they might have changed because of wrapped text
|
|
36737
|
+
for (const row of range(0, this.getters.getNumberRows(sheetId))) {
|
|
36738
|
+
for (const col of cmd.elements) {
|
|
36739
|
+
this.updateRowSizeForCellChange(sheetId, row, col);
|
|
36740
|
+
}
|
|
36741
|
+
}
|
|
36742
|
+
}
|
|
36743
|
+
}
|
|
36744
|
+
break;
|
|
36745
|
+
case "UPDATE_CELL":
|
|
36746
|
+
this.updateRowSizeForCellChange(cmd.sheetId, cmd.row, cmd.col);
|
|
36747
|
+
break;
|
|
36748
|
+
case "ADD_MERGE":
|
|
36749
|
+
case "REMOVE_MERGE":
|
|
36750
|
+
for (const target of cmd.target) {
|
|
36751
|
+
for (const position of positions(target)) {
|
|
36752
|
+
this.updateRowSizeForCellChange(cmd.sheetId, position.row, position.col);
|
|
36753
|
+
}
|
|
36754
|
+
}
|
|
36755
|
+
}
|
|
36756
|
+
return;
|
|
36757
|
+
}
|
|
36758
|
+
getRowSize(sheetId, row) {
|
|
36759
|
+
return Math.round(this.getters.getUserRowSize(sheetId, row) ??
|
|
36760
|
+
this.tallestCellInRow[sheetId][row]?.size ??
|
|
36761
|
+
DEFAULT_CELL_HEIGHT);
|
|
36762
|
+
}
|
|
36763
|
+
updateRowSizeForCellChange(sheetId, row, col) {
|
|
36764
|
+
const tallestCellInRow = this.tallestCellInRow[sheetId]?.[row];
|
|
36765
|
+
if (tallestCellInRow?.cell.col === col) {
|
|
36766
|
+
const newTallestCell = this.getRowTallestCell(sheetId, row);
|
|
36767
|
+
this.history.update("tallestCellInRow", sheetId, row, newTallestCell);
|
|
36768
|
+
}
|
|
36769
|
+
const updatedCellHeight = this.getCellHeight({ sheetId, col, row });
|
|
36770
|
+
if (updatedCellHeight <= DEFAULT_CELL_HEIGHT) {
|
|
36771
|
+
return;
|
|
36772
|
+
}
|
|
36773
|
+
if ((!tallestCellInRow && updatedCellHeight > DEFAULT_CELL_HEIGHT) ||
|
|
36774
|
+
(tallestCellInRow && updatedCellHeight > tallestCellInRow.size)) {
|
|
36775
|
+
const newTallestCell = { cell: { sheetId, col, row }, size: updatedCellHeight };
|
|
36776
|
+
this.history.update("tallestCellInRow", sheetId, row, newTallestCell);
|
|
36777
|
+
}
|
|
36778
|
+
}
|
|
36779
|
+
initializeSheet(sheetId) {
|
|
36780
|
+
const tallestCells = [];
|
|
36781
|
+
for (let row = 0; row < this.getters.getNumberRows(sheetId); row++) {
|
|
36782
|
+
const tallestCell = this.getRowTallestCell(sheetId, row);
|
|
36783
|
+
tallestCells.push(tallestCell);
|
|
36784
|
+
}
|
|
36785
|
+
this.history.update("tallestCellInRow", sheetId, tallestCells);
|
|
36786
|
+
}
|
|
36787
|
+
/**
|
|
36788
|
+
* Return the height the cell should have in the sheet, which is either DEFAULT_CELL_HEIGHT if the cell is in a multi-row
|
|
36789
|
+
* merge, or the height of the cell computed based on its style/content.
|
|
36790
|
+
*/
|
|
36791
|
+
getCellHeight(position) {
|
|
36792
|
+
if (this.isInMultiRowMerge(position)) {
|
|
36793
|
+
return DEFAULT_CELL_HEIGHT;
|
|
36794
|
+
}
|
|
36795
|
+
const cell = this.getters.getCell(position);
|
|
36796
|
+
const colSize = this.getters.getColSize(position.sheetId, position.col);
|
|
36797
|
+
return getDefaultCellHeight(this.ctx, cell, colSize);
|
|
36798
|
+
}
|
|
36799
|
+
isInMultiRowMerge(position) {
|
|
36800
|
+
const merge = this.getters.getMerge(position);
|
|
36801
|
+
return !!merge && merge.bottom !== merge.top;
|
|
36802
|
+
}
|
|
36803
|
+
/**
|
|
36804
|
+
* Get the tallest cell of a row and its size.
|
|
36805
|
+
*/
|
|
36806
|
+
getRowTallestCell(sheetId, row) {
|
|
36807
|
+
const userRowSize = this.getters.getUserRowSize(sheetId, row);
|
|
36808
|
+
if (userRowSize !== undefined) {
|
|
36809
|
+
return undefined;
|
|
36810
|
+
}
|
|
36811
|
+
const cellIds = this.getters.getRowCells(sheetId, row);
|
|
36812
|
+
let maxHeight = 0;
|
|
36813
|
+
let tallestCell = undefined;
|
|
36814
|
+
for (let i = 0; i < cellIds.length; i++) {
|
|
36815
|
+
const cell = this.getters.getCellById(cellIds[i]);
|
|
36816
|
+
if (!cell) {
|
|
36817
|
+
continue;
|
|
36818
|
+
}
|
|
36819
|
+
const position = this.getters.getCellPosition(cell.id);
|
|
36820
|
+
const cellHeight = this.getCellHeight(position);
|
|
36821
|
+
if (cellHeight > maxHeight && cellHeight > DEFAULT_CELL_HEIGHT) {
|
|
36822
|
+
maxHeight = cellHeight;
|
|
36823
|
+
tallestCell = { cell: position, size: cellHeight };
|
|
36824
|
+
}
|
|
36825
|
+
}
|
|
36826
|
+
if (tallestCell && tallestCell.size > DEFAULT_CELL_HEIGHT) {
|
|
36827
|
+
return tallestCell;
|
|
36828
|
+
}
|
|
36829
|
+
return undefined;
|
|
36830
|
+
}
|
|
36831
|
+
}
|
|
36832
|
+
|
|
36599
36833
|
/**
|
|
36600
36834
|
* This plugin manage the autofill.
|
|
36601
36835
|
*
|
|
@@ -40029,10 +40263,8 @@
|
|
|
40029
40263
|
}
|
|
40030
40264
|
updateCellCommands.push(newCellValues);
|
|
40031
40265
|
}
|
|
40032
|
-
for (const cmd of updateCellCommands) {
|
|
40033
|
-
this.dispatch("UPDATE_CELL", cmd);
|
|
40034
|
-
}
|
|
40035
40266
|
}
|
|
40267
|
+
updateCellCommands.forEach((cmdPayload) => this.dispatch("UPDATE_CELL", cmdPayload));
|
|
40036
40268
|
}
|
|
40037
40269
|
/**
|
|
40038
40270
|
* Return the distances between main merge cells in the zone.
|
|
@@ -40133,24 +40365,28 @@
|
|
|
40133
40365
|
// Getters
|
|
40134
40366
|
// ---------------------------------------------------------------------------
|
|
40135
40367
|
getCellWidth(position) {
|
|
40136
|
-
const text = this.getCellText(position);
|
|
40137
40368
|
const style = this.getters.getCellComputedStyle(position);
|
|
40138
|
-
|
|
40139
|
-
|
|
40369
|
+
let contentWidth = 0;
|
|
40370
|
+
const content = this.getters.getEvaluatedCell(position).formattedValue;
|
|
40371
|
+
if (content) {
|
|
40372
|
+
const multiLineText = splitTextToWidth(this.ctx, content, style, undefined);
|
|
40373
|
+
contentWidth += Math.max(...multiLineText.map((line) => computeTextWidth(this.ctx, line, style)));
|
|
40374
|
+
}
|
|
40140
40375
|
const icon = this.getters.getConditionalIcon(position);
|
|
40141
40376
|
if (icon) {
|
|
40142
|
-
contentWidth += computeIconWidth(
|
|
40377
|
+
contentWidth += computeIconWidth(style);
|
|
40143
40378
|
}
|
|
40144
40379
|
const isFilterHeader = this.getters.isFilterHeader(position);
|
|
40145
40380
|
if (isFilterHeader) {
|
|
40146
40381
|
contentWidth += ICON_EDGE_LENGTH + FILTER_ICON_MARGIN;
|
|
40147
40382
|
}
|
|
40148
|
-
if (contentWidth
|
|
40149
|
-
|
|
40150
|
-
|
|
40151
|
-
|
|
40152
|
-
|
|
40153
|
-
|
|
40383
|
+
if (contentWidth === 0) {
|
|
40384
|
+
return 0;
|
|
40385
|
+
}
|
|
40386
|
+
contentWidth += 2 * PADDING_AUTORESIZE_HORIZONTAL;
|
|
40387
|
+
if (style.wrapping === "wrap") {
|
|
40388
|
+
const colWidth = this.getters.getColSize(this.getters.getActiveSheetId(), position.col);
|
|
40389
|
+
return Math.min(colWidth, contentWidth);
|
|
40154
40390
|
}
|
|
40155
40391
|
return contentWidth;
|
|
40156
40392
|
}
|
|
@@ -40173,56 +40409,7 @@
|
|
|
40173
40409
|
getCellMultiLineText(position, width) {
|
|
40174
40410
|
const style = this.getters.getCellStyle(position);
|
|
40175
40411
|
const text = this.getters.getCellText(position, this.getters.shouldShowFormulas());
|
|
40176
|
-
|
|
40177
|
-
for (const line of text.split("\n")) {
|
|
40178
|
-
const words = line.split(" ");
|
|
40179
|
-
if (!width) {
|
|
40180
|
-
brokenText.push(line);
|
|
40181
|
-
continue;
|
|
40182
|
-
}
|
|
40183
|
-
let textLine = "";
|
|
40184
|
-
let availableWidth = width;
|
|
40185
|
-
for (let word of words) {
|
|
40186
|
-
const splitWord = this.splitWordToSpecificWidth(this.ctx, word, width, style);
|
|
40187
|
-
const lastPart = splitWord.pop();
|
|
40188
|
-
const lastPartWidth = computeTextWidth(this.ctx, lastPart, style);
|
|
40189
|
-
// At this step: "splitWord" is an array composed of parts of word whose
|
|
40190
|
-
// length is at most equal to "width".
|
|
40191
|
-
// Last part contains the end of the word.
|
|
40192
|
-
// Note that: When word length is less than width, then lastPart is equal
|
|
40193
|
-
// to word and splitWord is empty
|
|
40194
|
-
if (splitWord.length) {
|
|
40195
|
-
if (textLine !== "") {
|
|
40196
|
-
brokenText.push(textLine);
|
|
40197
|
-
textLine = "";
|
|
40198
|
-
availableWidth = width;
|
|
40199
|
-
}
|
|
40200
|
-
splitWord.forEach((wordPart) => {
|
|
40201
|
-
brokenText.push(wordPart);
|
|
40202
|
-
});
|
|
40203
|
-
textLine = lastPart;
|
|
40204
|
-
availableWidth = width - lastPartWidth;
|
|
40205
|
-
}
|
|
40206
|
-
else {
|
|
40207
|
-
// here "lastPart" is equal to "word" and the "word" size is smaller than "width"
|
|
40208
|
-
const _word = textLine === "" ? lastPart : " " + lastPart;
|
|
40209
|
-
const wordWidth = computeTextWidth(this.ctx, _word, style);
|
|
40210
|
-
if (wordWidth <= availableWidth) {
|
|
40211
|
-
textLine += _word;
|
|
40212
|
-
availableWidth -= wordWidth;
|
|
40213
|
-
}
|
|
40214
|
-
else {
|
|
40215
|
-
brokenText.push(textLine);
|
|
40216
|
-
textLine = lastPart;
|
|
40217
|
-
availableWidth = width - lastPartWidth;
|
|
40218
|
-
}
|
|
40219
|
-
}
|
|
40220
|
-
}
|
|
40221
|
-
if (textLine !== "") {
|
|
40222
|
-
brokenText.push(textLine);
|
|
40223
|
-
}
|
|
40224
|
-
}
|
|
40225
|
-
return brokenText;
|
|
40412
|
+
return splitTextToWidth(this.ctx, text, style, width);
|
|
40226
40413
|
}
|
|
40227
40414
|
/**
|
|
40228
40415
|
* Returns the size, start and end coordinates of a column on an unfolded sheet
|
|
@@ -40281,26 +40468,6 @@
|
|
|
40281
40468
|
const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
|
|
40282
40469
|
return Math.max(0, ...sizes);
|
|
40283
40470
|
}
|
|
40284
|
-
splitWordToSpecificWidth(ctx, word, width, style) {
|
|
40285
|
-
const wordWidth = computeTextWidth(ctx, word, style);
|
|
40286
|
-
if (wordWidth <= width) {
|
|
40287
|
-
return [word];
|
|
40288
|
-
}
|
|
40289
|
-
const splitWord = [];
|
|
40290
|
-
let wordPart = "";
|
|
40291
|
-
for (let l of word) {
|
|
40292
|
-
const wordPartWidth = computeTextWidth(ctx, wordPart + l, style);
|
|
40293
|
-
if (wordPartWidth > width) {
|
|
40294
|
-
splitWord.push(wordPart);
|
|
40295
|
-
wordPart = l;
|
|
40296
|
-
}
|
|
40297
|
-
else {
|
|
40298
|
-
wordPart += l;
|
|
40299
|
-
}
|
|
40300
|
-
}
|
|
40301
|
-
splitWord.push(wordPart);
|
|
40302
|
-
return splitWord;
|
|
40303
|
-
}
|
|
40304
40471
|
/**
|
|
40305
40472
|
* Check that any "sheetId" in the command matches an existing
|
|
40306
40473
|
* sheet.
|
|
@@ -41292,7 +41459,7 @@
|
|
|
41292
41459
|
.join("\n") || "\t");
|
|
41293
41460
|
}
|
|
41294
41461
|
getHTMLContent() {
|
|
41295
|
-
if (this.cells.length
|
|
41462
|
+
if (this.cells.length === 1 && this.cells[0].length === 1) {
|
|
41296
41463
|
return this.getters.getCellText(this.cells[0][0].position);
|
|
41297
41464
|
}
|
|
41298
41465
|
let htmlTable = '<table border="1" style="border-collapse:collapse">';
|
|
@@ -41617,7 +41784,7 @@
|
|
|
41617
41784
|
status = "invisible";
|
|
41618
41785
|
state;
|
|
41619
41786
|
lastPasteState;
|
|
41620
|
-
|
|
41787
|
+
paintFormatStatus = "inactive";
|
|
41621
41788
|
originSheetId;
|
|
41622
41789
|
// ---------------------------------------------------------------------------
|
|
41623
41790
|
// Command Handling
|
|
@@ -41632,7 +41799,7 @@
|
|
|
41632
41799
|
if (!this.state) {
|
|
41633
41800
|
return 24 /* CommandResult.EmptyClipboard */;
|
|
41634
41801
|
}
|
|
41635
|
-
const pasteOption = cmd.pasteOption || (this.
|
|
41802
|
+
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
41636
41803
|
return this.state.isPasteAllowed(cmd.target, { pasteOption });
|
|
41637
41804
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
41638
41805
|
const state = new ClipboardOsState(cmd.text, this.getters, this.dispatch, this.selection);
|
|
@@ -41648,6 +41815,11 @@
|
|
|
41648
41815
|
const state = this.getClipboardStateForCopyCells(cut, "CUT");
|
|
41649
41816
|
return state.isPasteAllowed(paste);
|
|
41650
41817
|
}
|
|
41818
|
+
case "ACTIVATE_PAINT_FORMAT": {
|
|
41819
|
+
if (this.paintFormatStatus !== "inactive") {
|
|
41820
|
+
return 95 /* CommandResult.AlreadyInPaintingFormatMode */;
|
|
41821
|
+
}
|
|
41822
|
+
}
|
|
41651
41823
|
}
|
|
41652
41824
|
return 0 /* CommandResult.Success */;
|
|
41653
41825
|
}
|
|
@@ -41664,11 +41836,13 @@
|
|
|
41664
41836
|
if (!this.state) {
|
|
41665
41837
|
break;
|
|
41666
41838
|
}
|
|
41667
|
-
const pasteOption = cmd.pasteOption || (this.
|
|
41668
|
-
this._isPaintingFormat = false;
|
|
41839
|
+
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
41669
41840
|
this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
|
|
41670
41841
|
this.lastPasteState = this.state;
|
|
41671
|
-
this.
|
|
41842
|
+
if (this.paintFormatStatus === "oneOff") {
|
|
41843
|
+
this.paintFormatStatus = "inactive";
|
|
41844
|
+
this.status = "invisible";
|
|
41845
|
+
}
|
|
41672
41846
|
break;
|
|
41673
41847
|
case "CLEAN_CLIPBOARD_HIGHLIGHT":
|
|
41674
41848
|
this.status = "invisible";
|
|
@@ -41736,8 +41910,13 @@
|
|
|
41736
41910
|
case "ACTIVATE_PAINT_FORMAT": {
|
|
41737
41911
|
const zones = this.getters.getSelectedZones();
|
|
41738
41912
|
this.state = this.getClipboardStateForCopyCells(zones, "COPY");
|
|
41739
|
-
this._isPaintingFormat = true;
|
|
41740
41913
|
this.status = "visible";
|
|
41914
|
+
if (cmd.persistent) {
|
|
41915
|
+
this.paintFormatStatus = "persistent";
|
|
41916
|
+
}
|
|
41917
|
+
else {
|
|
41918
|
+
this.paintFormatStatus = "oneOff";
|
|
41919
|
+
}
|
|
41741
41920
|
break;
|
|
41742
41921
|
}
|
|
41743
41922
|
case "DELETE_SHEET":
|
|
@@ -41749,6 +41928,11 @@
|
|
|
41749
41928
|
this.status = "invisible";
|
|
41750
41929
|
}
|
|
41751
41930
|
break;
|
|
41931
|
+
case "CANCEL_PAINT_FORMAT": {
|
|
41932
|
+
this.paintFormatStatus = "inactive";
|
|
41933
|
+
this.status = "invisible";
|
|
41934
|
+
break;
|
|
41935
|
+
}
|
|
41752
41936
|
default:
|
|
41753
41937
|
if (isCoreCommand(cmd)) {
|
|
41754
41938
|
this.status = "invisible";
|
|
@@ -41779,7 +41963,7 @@
|
|
|
41779
41963
|
return this.state ? this.state.operation === "CUT" : false;
|
|
41780
41964
|
}
|
|
41781
41965
|
isPaintingFormat() {
|
|
41782
|
-
return this.
|
|
41966
|
+
return this.paintFormatStatus !== "inactive";
|
|
41783
41967
|
}
|
|
41784
41968
|
// ---------------------------------------------------------------------------
|
|
41785
41969
|
// Private methods
|
|
@@ -44414,6 +44598,7 @@
|
|
|
44414
44598
|
.add("evaluation", EvaluationPlugin)
|
|
44415
44599
|
.add("evaluation_chart", EvaluationChartPlugin)
|
|
44416
44600
|
.add("evaluation_cf", EvaluationConditionalFormatPlugin)
|
|
44601
|
+
.add("row_size", UIRowSizePlugin)
|
|
44417
44602
|
.add("custom_colors", CustomColorsPlugin);
|
|
44418
44603
|
|
|
44419
44604
|
const clickableCellRegistry = new Registry();
|
|
@@ -45669,11 +45854,11 @@
|
|
|
45669
45854
|
}
|
|
45670
45855
|
get title() {
|
|
45671
45856
|
const name = this.actionButton.name(this.env);
|
|
45672
|
-
const description = this.actionButton.description;
|
|
45857
|
+
const description = this.actionButton.description(this.env);
|
|
45673
45858
|
return name + (description ? ` (${description})` : "");
|
|
45674
45859
|
}
|
|
45675
45860
|
get iconTitle() {
|
|
45676
|
-
return this.actionButton.icon;
|
|
45861
|
+
return this.actionButton.icon(this.env);
|
|
45677
45862
|
}
|
|
45678
45863
|
onClick(ev) {
|
|
45679
45864
|
if (this.isEnabled) {
|
|
@@ -46058,6 +46243,27 @@
|
|
|
46058
46243
|
class: String,
|
|
46059
46244
|
};
|
|
46060
46245
|
|
|
46246
|
+
class PaintFormatButton extends owl.Component {
|
|
46247
|
+
static template = "o-spreadsheet-PaintFormatButton";
|
|
46248
|
+
get isActive() {
|
|
46249
|
+
return this.env.model.getters.isPaintingFormat();
|
|
46250
|
+
}
|
|
46251
|
+
onDblClick() {
|
|
46252
|
+
this.env.model.dispatch("ACTIVATE_PAINT_FORMAT", { persistent: true });
|
|
46253
|
+
}
|
|
46254
|
+
togglePaintFormat() {
|
|
46255
|
+
if (this.isActive) {
|
|
46256
|
+
this.env.model.dispatch("CANCEL_PAINT_FORMAT");
|
|
46257
|
+
}
|
|
46258
|
+
else {
|
|
46259
|
+
this.env.model.dispatch("ACTIVATE_PAINT_FORMAT", { persistent: false });
|
|
46260
|
+
}
|
|
46261
|
+
}
|
|
46262
|
+
}
|
|
46263
|
+
PaintFormatButton.props = {
|
|
46264
|
+
class: { type: String, optional: true },
|
|
46265
|
+
};
|
|
46266
|
+
|
|
46061
46267
|
// -----------------------------------------------------------------------------
|
|
46062
46268
|
// TopBar
|
|
46063
46269
|
// -----------------------------------------------------------------------------
|
|
@@ -46158,6 +46364,7 @@
|
|
|
46158
46364
|
TopBarComposer,
|
|
46159
46365
|
FontSizeEditor,
|
|
46160
46366
|
ActionButton,
|
|
46367
|
+
PaintFormatButton,
|
|
46161
46368
|
BorderEditorWidget,
|
|
46162
46369
|
};
|
|
46163
46370
|
state = owl.useState({
|
|
@@ -48010,7 +48217,7 @@
|
|
|
48010
48217
|
: "nextCluster";
|
|
48011
48218
|
while (true) {
|
|
48012
48219
|
const nextCellPosition = this.getNextCellPosition(currentPosition, dim, dir);
|
|
48013
|
-
// Break if nextPosition
|
|
48220
|
+
// Break if nextPosition === currentPosition, which happens if there's no next valid position
|
|
48014
48221
|
if (currentPosition.col === nextCellPosition.col &&
|
|
48015
48222
|
currentPosition.row === nextCellPosition.row) {
|
|
48016
48223
|
break;
|
|
@@ -49924,6 +50131,7 @@
|
|
|
49924
50131
|
...config,
|
|
49925
50132
|
mode: config.mode || "normal",
|
|
49926
50133
|
custom: config.custom || {},
|
|
50134
|
+
defaultCurrencyFormat: config.defaultCurrencyFormat || "[$$]#,##0.00",
|
|
49927
50135
|
external: this.setupExternalConfig(config.external || {}),
|
|
49928
50136
|
transportService,
|
|
49929
50137
|
client,
|
|
@@ -50221,6 +50429,7 @@
|
|
|
50221
50429
|
numberToLetters,
|
|
50222
50430
|
UuidGenerator,
|
|
50223
50431
|
formatValue,
|
|
50432
|
+
createCurrencyFormat,
|
|
50224
50433
|
computeTextWidth,
|
|
50225
50434
|
createEmptyWorkbookData,
|
|
50226
50435
|
createEmptySheet,
|
|
@@ -50306,9 +50515,9 @@
|
|
|
50306
50515
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
50307
50516
|
|
|
50308
50517
|
|
|
50309
|
-
__info__.version = '16.
|
|
50310
|
-
__info__.date = '2023-07-
|
|
50311
|
-
__info__.hash = '
|
|
50518
|
+
__info__.version = '16.5.0-alpha.0';
|
|
50519
|
+
__info__.date = '2023-07-24T06:48:58.196Z';
|
|
50520
|
+
__info__.hash = '3ba2c3c';
|
|
50312
50521
|
|
|
50313
50522
|
|
|
50314
50523
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|