@odoo/o-spreadsheet 17.0.53 → 17.0.55
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 +109 -73
- package/dist/o-spreadsheet.d.ts +1 -0
- package/dist/o-spreadsheet.esm.js +109 -73
- package/dist/o-spreadsheet.iife.js +109 -73
- package/dist/o-spreadsheet.iife.min.js +300 -298
- package/dist/o_spreadsheet.xml +7 -4
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 17.0.
|
|
6
|
-
* @date 2025-03-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.55
|
|
6
|
+
* @date 2025-03-26T12:44:29.690Z
|
|
7
|
+
* @hash c3a4769
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -949,7 +949,10 @@ function rgbaStringToHex(color) {
|
|
|
949
949
|
}
|
|
950
950
|
else if (stringVals.length === 4) {
|
|
951
951
|
const alpha = parseFloat(stringVals.pop() || "1");
|
|
952
|
-
|
|
952
|
+
if (isNaN(alpha)) {
|
|
953
|
+
throw new Error("invalid alpha value");
|
|
954
|
+
}
|
|
955
|
+
alphaHex = Math.round(alpha * 255);
|
|
953
956
|
}
|
|
954
957
|
const vals = stringVals.map((val) => parseInt(val, 10));
|
|
955
958
|
if (alphaHex !== 255) {
|
|
@@ -4494,11 +4497,13 @@ function getDefaultCellHeight(ctx, cell, colSize) {
|
|
|
4494
4497
|
if (!cell || (!cell.isFormula && !cell.content)) {
|
|
4495
4498
|
return DEFAULT_CELL_HEIGHT;
|
|
4496
4499
|
}
|
|
4497
|
-
const
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
const
|
|
4500
|
+
const content = cell.isFormula ? "" : cell.content;
|
|
4501
|
+
return getCellContentHeight(ctx, content, cell.style, colSize);
|
|
4502
|
+
}
|
|
4503
|
+
function getCellContentHeight(ctx, content, style, colSize) {
|
|
4504
|
+
const maxWidth = style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
|
|
4505
|
+
const numberOfLines = splitTextToWidth(ctx, content, style, maxWidth).length;
|
|
4506
|
+
const fontSize = computeTextFontSizeInPixels(style);
|
|
4502
4507
|
return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
|
|
4503
4508
|
}
|
|
4504
4509
|
const textWidthCache = {};
|
|
@@ -7769,7 +7774,7 @@ function isValidLocale(locale) {
|
|
|
7769
7774
|
*/
|
|
7770
7775
|
function canonicalizeNumberContent(content, locale) {
|
|
7771
7776
|
return content.startsWith("=")
|
|
7772
|
-
? canonicalizeFormula
|
|
7777
|
+
? canonicalizeFormula(content, locale)
|
|
7773
7778
|
: canonicalizeNumberLiteral(content, locale);
|
|
7774
7779
|
}
|
|
7775
7780
|
/**
|
|
@@ -7784,7 +7789,7 @@ function canonicalizeNumberContent(content, locale) {
|
|
|
7784
7789
|
*/
|
|
7785
7790
|
function canonicalizeContent(content, locale) {
|
|
7786
7791
|
return content.startsWith("=")
|
|
7787
|
-
? canonicalizeFormula
|
|
7792
|
+
? canonicalizeFormula(content, locale)
|
|
7788
7793
|
: canonicalizeLiteral(content, locale);
|
|
7789
7794
|
}
|
|
7790
7795
|
/**
|
|
@@ -7800,15 +7805,21 @@ function localizeContent(content, locale) {
|
|
|
7800
7805
|
? localizeFormula(content, locale)
|
|
7801
7806
|
: localizeLiteral(content, locale);
|
|
7802
7807
|
}
|
|
7808
|
+
/** Change a number string to its canonical form (en_US locale) */
|
|
7809
|
+
function canonicalizeNumberValue(content, locale) {
|
|
7810
|
+
return content.startsWith("=")
|
|
7811
|
+
? canonicalizeFormula(content, locale)
|
|
7812
|
+
: canonicalizeNumberLiteral(content, locale);
|
|
7813
|
+
}
|
|
7803
7814
|
/** Change a formula to its canonical form (en_US locale) */
|
|
7804
|
-
function canonicalizeFormula
|
|
7805
|
-
return _localizeFormula
|
|
7815
|
+
function canonicalizeFormula(formula, locale) {
|
|
7816
|
+
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
7806
7817
|
}
|
|
7807
7818
|
/** Change a formula from the canonical form to the given locale */
|
|
7808
7819
|
function localizeFormula(formula, locale) {
|
|
7809
|
-
return _localizeFormula
|
|
7820
|
+
return _localizeFormula(formula, DEFAULT_LOCALE, locale);
|
|
7810
7821
|
}
|
|
7811
|
-
function _localizeFormula
|
|
7822
|
+
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
7812
7823
|
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
7813
7824
|
fromLocale.decimalSeparator === toLocale.decimalSeparator) {
|
|
7814
7825
|
return formula;
|
|
@@ -8562,7 +8573,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
|
|
|
8562
8573
|
}
|
|
8563
8574
|
}
|
|
8564
8575
|
else if (dataSets.length === 1) {
|
|
8565
|
-
|
|
8576
|
+
const dataLength = getData(getters, dataSets[0]).length;
|
|
8577
|
+
for (let i = 0; i < dataLength; i++) {
|
|
8566
8578
|
labels.formattedValues.push("");
|
|
8567
8579
|
labels.values.push("");
|
|
8568
8580
|
}
|
|
@@ -24292,6 +24304,7 @@ class RemoveDuplicatesPanel extends owl.Component {
|
|
|
24292
24304
|
columns: {},
|
|
24293
24305
|
});
|
|
24294
24306
|
setup() {
|
|
24307
|
+
this.updateColumns();
|
|
24295
24308
|
owl.onWillUpdateProps(() => this.updateColumns());
|
|
24296
24309
|
}
|
|
24297
24310
|
toggleHasHeader() {
|
|
@@ -30362,9 +30375,9 @@ const XLSX_CHART_TYPES = [
|
|
|
30362
30375
|
/** In XLSX color format (no #) */
|
|
30363
30376
|
const AUTO_COLOR = "000000";
|
|
30364
30377
|
const XLSX_ICONSET_MAP = {
|
|
30365
|
-
|
|
30378
|
+
arrows: "3Arrows",
|
|
30366
30379
|
smiley: "3Symbols",
|
|
30367
|
-
|
|
30380
|
+
dots: "3TrafficLights1",
|
|
30368
30381
|
};
|
|
30369
30382
|
const NAMESPACE = {
|
|
30370
30383
|
styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
|
@@ -30780,6 +30793,7 @@ const ICON_SET_CONVERSION_MAP = {
|
|
|
30780
30793
|
};
|
|
30781
30794
|
/** Map between legend position in XLSX file and human readable position */
|
|
30782
30795
|
const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
|
|
30796
|
+
none: "none",
|
|
30783
30797
|
b: "bottom",
|
|
30784
30798
|
t: "top",
|
|
30785
30799
|
l: "left",
|
|
@@ -33012,7 +33026,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
|
|
|
33012
33026
|
? "right"
|
|
33013
33027
|
: "left",
|
|
33014
33028
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
|
|
33015
|
-
default: "
|
|
33029
|
+
default: "none",
|
|
33016
33030
|
}).asString()],
|
|
33017
33031
|
stacked: barChartGrouping === "stacked",
|
|
33018
33032
|
fontColor: "000000",
|
|
@@ -45470,12 +45484,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
45470
45484
|
continue;
|
|
45471
45485
|
}
|
|
45472
45486
|
const position = { col: col + c, row: row + r, sheetId: sheetId };
|
|
45473
|
-
|
|
45474
|
-
// MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
|
|
45475
|
-
// is not appropriate
|
|
45476
|
-
if (this.operation !== "CUT") {
|
|
45477
|
-
this.pasteMergeIfExist(origin.position, position);
|
|
45478
|
-
}
|
|
45487
|
+
this.pasteMergeIfExist(origin.position, position, this.operation);
|
|
45479
45488
|
this.pasteCell(origin, position, this.operation, clipboardOptions);
|
|
45480
45489
|
if (shouldPasteCF) {
|
|
45481
45490
|
this.pasteCf(origin.position, position);
|
|
@@ -45532,7 +45541,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
45532
45541
|
* If the origin position given is the top left of a merge, merge the target
|
|
45533
45542
|
* position.
|
|
45534
45543
|
*/
|
|
45535
|
-
pasteMergeIfExist(origin, target) {
|
|
45544
|
+
pasteMergeIfExist(origin, target, operation) {
|
|
45536
45545
|
let { sheetId, col, row } = origin;
|
|
45537
45546
|
const { col: mainCellColOrigin, row: mainCellRowOrigin } = this.getters.getMainCellPosition(origin);
|
|
45538
45547
|
if (mainCellColOrigin === col && mainCellRowOrigin === row) {
|
|
@@ -45540,6 +45549,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
45540
45549
|
if (!merge) {
|
|
45541
45550
|
return;
|
|
45542
45551
|
}
|
|
45552
|
+
if (operation === "CUT") {
|
|
45553
|
+
this.dispatch("REMOVE_MERGE", { sheetId, target: [merge] });
|
|
45554
|
+
}
|
|
45543
45555
|
({ sheetId, col, row } = target);
|
|
45544
45556
|
this.dispatch("ADD_MERGE", {
|
|
45545
45557
|
sheetId,
|
|
@@ -47831,12 +47843,7 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
47831
47843
|
}
|
|
47832
47844
|
break;
|
|
47833
47845
|
case "AUTORESIZE_ROWS":
|
|
47834
|
-
this.
|
|
47835
|
-
elements: cmd.rows,
|
|
47836
|
-
dimension: "ROW",
|
|
47837
|
-
size: null,
|
|
47838
|
-
sheetId: cmd.sheetId,
|
|
47839
|
-
});
|
|
47846
|
+
this.autoResizeRows(cmd.sheetId, cmd.rows);
|
|
47840
47847
|
break;
|
|
47841
47848
|
}
|
|
47842
47849
|
}
|
|
@@ -47934,6 +47941,48 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
47934
47941
|
}
|
|
47935
47942
|
return "Success" /* CommandResult.Success */;
|
|
47936
47943
|
}
|
|
47944
|
+
autoResizeRows(sheetId, rows) {
|
|
47945
|
+
const rowSizes = [];
|
|
47946
|
+
for (const row of rows) {
|
|
47947
|
+
let evaluatedRowSize = 0;
|
|
47948
|
+
for (const cellId of this.getters.getRowCells(sheetId, row)) {
|
|
47949
|
+
const cell = this.getters.getCellById(cellId);
|
|
47950
|
+
if (!cell) {
|
|
47951
|
+
continue;
|
|
47952
|
+
}
|
|
47953
|
+
const position = this.getters.getCellPosition(cell.id);
|
|
47954
|
+
const colSize = this.getters.getColSize(sheetId, position.col);
|
|
47955
|
+
if (cell.isFormula) {
|
|
47956
|
+
const content = this.getters.getEvaluatedCell(position).formattedValue;
|
|
47957
|
+
const evaluatedSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
|
|
47958
|
+
if (evaluatedSize > evaluatedRowSize && evaluatedSize > DEFAULT_CELL_HEIGHT) {
|
|
47959
|
+
evaluatedRowSize = evaluatedSize;
|
|
47960
|
+
}
|
|
47961
|
+
}
|
|
47962
|
+
else {
|
|
47963
|
+
const content = cell.content;
|
|
47964
|
+
const dynamicRowSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
|
|
47965
|
+
// Only keep the size of evaluated cells if it's bigger than the dynamic row size
|
|
47966
|
+
if (dynamicRowSize >= evaluatedRowSize && dynamicRowSize > DEFAULT_CELL_HEIGHT) {
|
|
47967
|
+
evaluatedRowSize = 0;
|
|
47968
|
+
}
|
|
47969
|
+
}
|
|
47970
|
+
}
|
|
47971
|
+
rowSizes.push(evaluatedRowSize || null);
|
|
47972
|
+
}
|
|
47973
|
+
const groupedSizes = new Map(rowSizes.map((size) => [size, []]));
|
|
47974
|
+
for (let i = 0; i < rowSizes.length; i++) {
|
|
47975
|
+
groupedSizes.get(rowSizes[i])?.push(rows[i]);
|
|
47976
|
+
}
|
|
47977
|
+
for (const [size, rows] of groupedSizes) {
|
|
47978
|
+
this.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
47979
|
+
elements: rows,
|
|
47980
|
+
dimension: "ROW",
|
|
47981
|
+
size,
|
|
47982
|
+
sheetId,
|
|
47983
|
+
});
|
|
47984
|
+
}
|
|
47985
|
+
}
|
|
47937
47986
|
}
|
|
47938
47987
|
|
|
47939
47988
|
const genericRepeatsTransforms = [
|
|
@@ -48583,37 +48632,6 @@ class ClipboardFigureImage {
|
|
|
48583
48632
|
}
|
|
48584
48633
|
}
|
|
48585
48634
|
|
|
48586
|
-
/** Change a number string to its canonical form (en_US locale) */
|
|
48587
|
-
function canonicalizeNumberValue(content, locale) {
|
|
48588
|
-
return content.startsWith("=")
|
|
48589
|
-
? canonicalizeFormula(content, locale)
|
|
48590
|
-
: canonicalizeNumberLiteral(content, locale);
|
|
48591
|
-
}
|
|
48592
|
-
/** Change a formula to its canonical form (en_US locale) */
|
|
48593
|
-
function canonicalizeFormula(formula, locale) {
|
|
48594
|
-
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
48595
|
-
}
|
|
48596
|
-
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
48597
|
-
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
48598
|
-
fromLocale.decimalSeparator === toLocale.decimalSeparator) {
|
|
48599
|
-
return formula;
|
|
48600
|
-
}
|
|
48601
|
-
const tokens = tokenize(formula, fromLocale);
|
|
48602
|
-
let localizedFormula = "";
|
|
48603
|
-
for (const token of tokens) {
|
|
48604
|
-
if (token.type === "NUMBER") {
|
|
48605
|
-
localizedFormula += token.value.replace(fromLocale.decimalSeparator, toLocale.decimalSeparator);
|
|
48606
|
-
}
|
|
48607
|
-
else if (token.type === "ARG_SEPARATOR") {
|
|
48608
|
-
localizedFormula += toLocale.formulaArgSeparator;
|
|
48609
|
-
}
|
|
48610
|
-
else {
|
|
48611
|
-
localizedFormula += token.value;
|
|
48612
|
-
}
|
|
48613
|
-
}
|
|
48614
|
-
return localizedFormula;
|
|
48615
|
-
}
|
|
48616
|
-
|
|
48617
48635
|
/** State of the clipboard when copying/cutting from the OS clipboard*/
|
|
48618
48636
|
class ClipboardOsState extends ClipboardCellsAbstractState {
|
|
48619
48637
|
values;
|
|
@@ -49190,8 +49208,8 @@ class EditionPlugin extends UIPlugin {
|
|
|
49190
49208
|
this.colorIndexByRange = {};
|
|
49191
49209
|
break;
|
|
49192
49210
|
case "CANCEL_EDITION":
|
|
49193
|
-
this.cancelEditionAndActivateSheet();
|
|
49194
49211
|
this.resetContent();
|
|
49212
|
+
this.cancelEditionAndActivateSheet();
|
|
49195
49213
|
this.colorIndexByRange = {};
|
|
49196
49214
|
break;
|
|
49197
49215
|
case "SET_CURRENT_CONTENT":
|
|
@@ -49202,8 +49220,8 @@ class EditionPlugin extends UIPlugin {
|
|
|
49202
49220
|
this.replaceSelection(cmd.text);
|
|
49203
49221
|
break;
|
|
49204
49222
|
case "SELECT_FIGURE":
|
|
49205
|
-
this.cancelEditionAndActivateSheet();
|
|
49206
49223
|
this.resetContent();
|
|
49224
|
+
this.cancelEditionAndActivateSheet();
|
|
49207
49225
|
break;
|
|
49208
49226
|
case "ADD_COLUMNS_ROWS":
|
|
49209
49227
|
this.onAddElements(cmd);
|
|
@@ -49246,8 +49264,8 @@ class EditionPlugin extends UIPlugin {
|
|
|
49246
49264
|
const sheetIdExists = !!this.getters.tryGetSheet(this.sheetId);
|
|
49247
49265
|
if (!sheetIdExists && this.mode !== "inactive") {
|
|
49248
49266
|
this.sheetId = this.getters.getActiveSheetId();
|
|
49249
|
-
this.cancelEditionAndActivateSheet();
|
|
49250
49267
|
this.resetContent();
|
|
49268
|
+
this.cancelEditionAndActivateSheet();
|
|
49251
49269
|
this.ui.raiseBlockingErrorUI(CELL_DELETED_MESSAGE);
|
|
49252
49270
|
}
|
|
49253
49271
|
break;
|
|
@@ -53469,7 +53487,9 @@ css /* scss */ `
|
|
|
53469
53487
|
margin-top: -1px;
|
|
53470
53488
|
border: 1px solid;
|
|
53471
53489
|
|
|
53472
|
-
|
|
53490
|
+
/* In readonly we always show the fx icon if the composer is empty, not matter the focus */
|
|
53491
|
+
.o-composer:empty:not(:focus):not(.active)::before,
|
|
53492
|
+
&.o-topbar-composer-readonly .o-composer:empty::before {
|
|
53473
53493
|
content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
|
|
53474
53494
|
position: relative;
|
|
53475
53495
|
top: 20%;
|
|
@@ -56470,10 +56490,14 @@ function addIconSetRule(cf, rule) {
|
|
|
56470
56490
|
continue;
|
|
56471
56491
|
}
|
|
56472
56492
|
const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
|
|
56493
|
+
const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
|
|
56494
|
+
if (isIconSetReversed(rule.icons)) {
|
|
56495
|
+
iconSetAttrs.push(["reverse", "1"]);
|
|
56496
|
+
}
|
|
56473
56497
|
conditionalFormats.push(escapeXml /*xml*/ `
|
|
56474
56498
|
<conditionalFormatting sqref="${range}">
|
|
56475
56499
|
<cfRule ${formatAttributes(ruleAttributes)}>
|
|
56476
|
-
<iconSet
|
|
56500
|
+
<iconSet ${formatAttributes(iconSetAttrs)}>
|
|
56477
56501
|
${joinXmlNodes(cfValueObjectNodes)}
|
|
56478
56502
|
</iconSet>
|
|
56479
56503
|
</cfRule>
|
|
@@ -56491,9 +56515,21 @@ function commonCfAttributes(cf) {
|
|
|
56491
56515
|
["stopIfTrue", cf.stopIfTrue ? 1 : 0],
|
|
56492
56516
|
];
|
|
56493
56517
|
}
|
|
56518
|
+
function isIconSetReversed(iconSet) {
|
|
56519
|
+
const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
|
|
56520
|
+
return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
|
|
56521
|
+
}
|
|
56494
56522
|
function getIconSet(iconSet) {
|
|
56495
|
-
return XLSX_ICONSET_MAP[
|
|
56496
|
-
|
|
56523
|
+
return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
|
|
56524
|
+
}
|
|
56525
|
+
/**
|
|
56526
|
+
* Partial detection based on "upper" point only.
|
|
56527
|
+
* We support any arbitrary icon in the set, while excel doesn't allow
|
|
56528
|
+
* mixing icons from different types.
|
|
56529
|
+
*/
|
|
56530
|
+
function detectIconsType(iconSet) {
|
|
56531
|
+
const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
|
|
56532
|
+
return type;
|
|
56497
56533
|
}
|
|
56498
56534
|
function thresholdAttributes(threshold, position) {
|
|
56499
56535
|
const type = getExcelThresholdType(threshold.type, position);
|
|
@@ -58069,6 +58105,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
58069
58105
|
exports.tokenize = tokenize;
|
|
58070
58106
|
|
|
58071
58107
|
|
|
58072
|
-
__info__.version = "17.0.
|
|
58073
|
-
__info__.date = "2025-03-
|
|
58074
|
-
__info__.hash = "
|
|
58108
|
+
__info__.version = "17.0.55";
|
|
58109
|
+
__info__.date = "2025-03-26T12:44:29.690Z";
|
|
58110
|
+
__info__.hash = "c3a4769";
|