@odoo/o-spreadsheet 18.3.7 → 18.3.9
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 +125 -56
- package/dist/o-spreadsheet.esm.js +125 -56
- package/dist/o-spreadsheet.iife.js +125 -56
- package/dist/o-spreadsheet.iife.min.js +165 -165
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.3.
|
|
6
|
-
* @date 2025-06-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.3.9
|
|
6
|
+
* @date 2025-06-19T18:24:02.754Z
|
|
7
|
+
* @hash a820230
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -5881,7 +5881,9 @@
|
|
|
5881
5881
|
}
|
|
5882
5882
|
|
|
5883
5883
|
function evaluateLiteral(literalCell, localeFormat) {
|
|
5884
|
-
const value = isTextFormat(localeFormat.format)
|
|
5884
|
+
const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
|
|
5885
|
+
? literalCell.content
|
|
5886
|
+
: literalCell.parsedValue;
|
|
5885
5887
|
const functionResult = { value, format: localeFormat.format };
|
|
5886
5888
|
return createEvaluatedCell(functionResult, localeFormat.locale);
|
|
5887
5889
|
}
|
|
@@ -5930,6 +5932,9 @@
|
|
|
5930
5932
|
if (isEvaluationError(value)) {
|
|
5931
5933
|
return errorCell(value, message);
|
|
5932
5934
|
}
|
|
5935
|
+
if (value === null) {
|
|
5936
|
+
return emptyCell(format);
|
|
5937
|
+
}
|
|
5933
5938
|
if (isTextFormat(format)) {
|
|
5934
5939
|
// TO DO:
|
|
5935
5940
|
// with the next line, the value of the cell is transformed depending on the format.
|
|
@@ -5937,9 +5942,6 @@
|
|
|
5937
5942
|
// to interpret the value as a number.
|
|
5938
5943
|
return textCell(toString(value), format, formattedValue);
|
|
5939
5944
|
}
|
|
5940
|
-
if (value === null) {
|
|
5941
|
-
return emptyCell(format);
|
|
5942
|
-
}
|
|
5943
5945
|
if (typeof value === "number") {
|
|
5944
5946
|
if (isDateTimeFormat(format || "")) {
|
|
5945
5947
|
return dateTimeCell(value, format, formattedValue);
|
|
@@ -20950,6 +20952,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20950
20952
|
if (isTrendLineAxis(dataset.xAxisID) || dataset.hidden) {
|
|
20951
20953
|
continue;
|
|
20952
20954
|
}
|
|
20955
|
+
const yAxisScale = chart.scales[dataset.yAxisID];
|
|
20953
20956
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
20954
20957
|
const parsedValue = dataset._parsed[i];
|
|
20955
20958
|
const value = Number(chart.config.type === "radar" ? parsedValue.r : parsedValue.y);
|
|
@@ -20960,10 +20963,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20960
20963
|
const xPosition = point.x;
|
|
20961
20964
|
let yPosition = 0;
|
|
20962
20965
|
if (chart.config.type === "line" || chart.config.type === "radar") {
|
|
20963
|
-
yPosition = point.y - 10;
|
|
20966
|
+
yPosition = value < 0 ? point.y + 10 : point.y - 10;
|
|
20964
20967
|
}
|
|
20965
20968
|
else {
|
|
20966
|
-
|
|
20969
|
+
const yZeroLine = yAxisScale.getPixelForValue(0);
|
|
20970
|
+
const distanceFromAxisOrigin = Math.abs(yZeroLine - point.y);
|
|
20971
|
+
const textHeight = 12; // ChartJS default text height
|
|
20972
|
+
if (distanceFromAxisOrigin < textHeight) {
|
|
20973
|
+
yPosition = value < 0 ? yZeroLine + textHeight / 2 : yZeroLine - textHeight / 2;
|
|
20974
|
+
}
|
|
20975
|
+
else {
|
|
20976
|
+
yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
|
|
20977
|
+
}
|
|
20967
20978
|
}
|
|
20968
20979
|
yPosition = Math.min(yPosition, yMax);
|
|
20969
20980
|
yPosition = Math.max(yPosition, yMin);
|
|
@@ -20973,7 +20984,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20973
20984
|
}
|
|
20974
20985
|
for (const otherPosition of textsPositions[xPosition] || []) {
|
|
20975
20986
|
if (Math.abs(otherPosition - yPosition) < 13) {
|
|
20976
|
-
yPosition = otherPosition - 13;
|
|
20987
|
+
yPosition = value < 0 ? otherPosition + 13 : otherPosition - 13;
|
|
20977
20988
|
}
|
|
20978
20989
|
}
|
|
20979
20990
|
textsPositions[xPosition].push(yPosition);
|
|
@@ -20992,6 +21003,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20992
21003
|
if (isTrendLineAxis(dataset.xAxisID)) {
|
|
20993
21004
|
return; // ignore trend lines
|
|
20994
21005
|
}
|
|
21006
|
+
const xAxisScale = chart.scales[dataset.xAxisID];
|
|
21007
|
+
const xZeroLine = xAxisScale.getPixelForValue(0);
|
|
20995
21008
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
20996
21009
|
const value = Number(dataset._parsed[i].x);
|
|
20997
21010
|
if (isNaN(value)) {
|
|
@@ -21000,17 +21013,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21000
21013
|
const displayValue = options.callback(value, dataset, i);
|
|
21001
21014
|
const point = dataset.data[i];
|
|
21002
21015
|
const yPosition = point.y;
|
|
21003
|
-
|
|
21004
|
-
|
|
21005
|
-
|
|
21016
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
|
|
21017
|
+
const distanceFromAxisOrigin = Math.abs(point.x - xZeroLine);
|
|
21018
|
+
const PADDING = 3;
|
|
21019
|
+
let xPosition;
|
|
21020
|
+
if (distanceFromAxisOrigin < textWidth) {
|
|
21021
|
+
xPosition =
|
|
21022
|
+
value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
|
|
21023
|
+
}
|
|
21024
|
+
else {
|
|
21025
|
+
xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
21026
|
+
xPosition = Math.min(xPosition, xMax);
|
|
21027
|
+
xPosition = Math.max(xPosition, xMin);
|
|
21028
|
+
}
|
|
21006
21029
|
// Avoid overlapping texts with same Y
|
|
21007
21030
|
if (!textsPositions[yPosition]) {
|
|
21008
21031
|
textsPositions[yPosition] = [];
|
|
21009
21032
|
}
|
|
21010
|
-
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
|
|
21011
21033
|
for (const otherPosition of textsPositions[yPosition]) {
|
|
21012
21034
|
if (Math.abs(otherPosition - xPosition) < textWidth) {
|
|
21013
|
-
xPosition =
|
|
21035
|
+
xPosition =
|
|
21036
|
+
value < 0 ? otherPosition - textWidth - PADDING : otherPosition + textWidth + PADDING;
|
|
21014
21037
|
}
|
|
21015
21038
|
}
|
|
21016
21039
|
textsPositions[yPosition].push(xPosition);
|
|
@@ -21032,10 +21055,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21032
21055
|
const midAngle = (startAngle + endAngle) / 2;
|
|
21033
21056
|
const midRadius = (innerRadius + outerRadius) / 2;
|
|
21034
21057
|
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
21035
|
-
const y = bar.y + midRadius * Math.sin(midAngle)
|
|
21058
|
+
const y = bar.y + midRadius * Math.sin(midAngle);
|
|
21059
|
+
const displayValue = options.callback(value, dataset, i);
|
|
21060
|
+
const textHeight = 12; // ChartJS default
|
|
21061
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: textHeight }, "px");
|
|
21062
|
+
const radius = outerRadius - innerRadius;
|
|
21063
|
+
// Check if the text fits in the slice. Not perfect, but good enough heuristic.
|
|
21064
|
+
if (textWidth >= radius || radius < textHeight) {
|
|
21065
|
+
continue;
|
|
21066
|
+
}
|
|
21067
|
+
const sliceAngle = endAngle - startAngle;
|
|
21068
|
+
const midWidth = 2 * midRadius * Math.tan(sliceAngle / 2);
|
|
21069
|
+
if (sliceAngle < Math.PI / 2 && (textWidth >= midWidth || midWidth < textHeight)) {
|
|
21070
|
+
continue;
|
|
21071
|
+
}
|
|
21036
21072
|
ctx.fillStyle = chartFontColor(options.background);
|
|
21037
21073
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
21038
|
-
const displayValue = options.callback(value, dataset, i);
|
|
21039
21074
|
drawTextWithBackground(displayValue, x, y, ctx);
|
|
21040
21075
|
}
|
|
21041
21076
|
}
|
|
@@ -26385,7 +26420,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26385
26420
|
background: definition.background,
|
|
26386
26421
|
callback: (value, dataset) => {
|
|
26387
26422
|
value = Math.abs(Number(value));
|
|
26388
|
-
return
|
|
26423
|
+
return value === 0
|
|
26424
|
+
? ""
|
|
26425
|
+
: formatChartDatasetValue(axisFormats, locale)(value, dataset.xAxisID || "x");
|
|
26389
26426
|
},
|
|
26390
26427
|
};
|
|
26391
26428
|
}
|
|
@@ -33171,7 +33208,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33171
33208
|
*/
|
|
33172
33209
|
handleMissingValue(parentElement, missingElementName, optionalArgs) {
|
|
33173
33210
|
if (optionalArgs?.required) {
|
|
33174
|
-
if (optionalArgs?.default) {
|
|
33211
|
+
if (optionalArgs?.default !== undefined) {
|
|
33175
33212
|
this.warningManager.addParsingWarning(`Missing required ${missingElementName} in element <${parentElement.tagName}> of ${this.currentFile}, replacing it by the default value ${optionalArgs.default}`);
|
|
33176
33213
|
}
|
|
33177
33214
|
else {
|
|
@@ -36124,19 +36161,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36124
36161
|
.filter(({ row }) => !this.env.model.getters.isRowHidden(sheetId, row))
|
|
36125
36162
|
.map(({ col, row }) => this.env.model.getters.getEvaluatedCell({ sheetId, col, row }).formattedValue);
|
|
36126
36163
|
const filterValues = this.env.model.getters.getFilterHiddenValues({ sheetId, ...position });
|
|
36127
|
-
const
|
|
36128
|
-
const
|
|
36129
|
-
|
|
36130
|
-
const
|
|
36131
|
-
|
|
36132
|
-
|
|
36133
|
-
|
|
36134
|
-
|
|
36135
|
-
|
|
36136
|
-
|
|
36137
|
-
|
|
36138
|
-
|
|
36139
|
-
|
|
36164
|
+
const normalizedFilteredValues = new Set(filterValues.map(toLowerCase));
|
|
36165
|
+
const set = new Set();
|
|
36166
|
+
const values = [];
|
|
36167
|
+
const addValue = (value) => {
|
|
36168
|
+
const normalizedValue = toLowerCase(value);
|
|
36169
|
+
if (!set.has(normalizedValue)) {
|
|
36170
|
+
values.push({
|
|
36171
|
+
string: value || "",
|
|
36172
|
+
checked: !normalizedFilteredValues.has(normalizedValue),
|
|
36173
|
+
normalizedValue,
|
|
36174
|
+
});
|
|
36175
|
+
set.add(normalizedValue);
|
|
36176
|
+
}
|
|
36177
|
+
};
|
|
36178
|
+
cellValues.forEach(addValue);
|
|
36179
|
+
filterValues.forEach(addValue);
|
|
36180
|
+
return values.sort((val1, val2) => val1.normalizedValue.localeCompare(val2.normalizedValue, undefined, {
|
|
36181
|
+
numeric: true,
|
|
36182
|
+
sensitivity: "base",
|
|
36183
|
+
}));
|
|
36140
36184
|
}
|
|
36141
36185
|
checkValue(value) {
|
|
36142
36186
|
this.state.selectedValue = value.string;
|
|
@@ -37111,6 +37155,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37111
37155
|
});
|
|
37112
37156
|
};
|
|
37113
37157
|
const CAN_REMOVE_COLUMNS_ROWS = (dimension, env) => {
|
|
37158
|
+
if ((dimension === "COL" && env.model.getters.getActiveRows().size > 0) ||
|
|
37159
|
+
(dimension === "ROW" && env.model.getters.getActiveCols().size > 0)) {
|
|
37160
|
+
return false;
|
|
37161
|
+
}
|
|
37114
37162
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
37115
37163
|
const selectedElements = env.model.getters.getElementsFromSelection(dimension);
|
|
37116
37164
|
const includesAllVisibleHeaders = env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, dimension, selectedElements);
|
|
@@ -40008,11 +40056,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40008
40056
|
* transformation function given
|
|
40009
40057
|
*/
|
|
40010
40058
|
addTransformation(executed, toTransforms, fn) {
|
|
40011
|
-
|
|
40012
|
-
|
|
40013
|
-
|
|
40014
|
-
|
|
40015
|
-
this.content[
|
|
40059
|
+
if (!this.content[executed]) {
|
|
40060
|
+
this.content[executed] = new Map();
|
|
40061
|
+
}
|
|
40062
|
+
for (const toTransform of toTransforms) {
|
|
40063
|
+
this.content[executed].set(toTransform, fn);
|
|
40016
40064
|
}
|
|
40017
40065
|
return this;
|
|
40018
40066
|
}
|
|
@@ -40021,7 +40069,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40021
40069
|
* that the executed command happened.
|
|
40022
40070
|
*/
|
|
40023
40071
|
getTransformation(toTransform, executed) {
|
|
40024
|
-
return this.content[
|
|
40072
|
+
return this.content[executed] && this.content[executed].get(toTransform);
|
|
40025
40073
|
}
|
|
40026
40074
|
}
|
|
40027
40075
|
const otRegistry = new OTRegistry();
|
|
@@ -43311,6 +43359,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43311
43359
|
owl.useEffect(() => {
|
|
43312
43360
|
this.processTokenAtCursor();
|
|
43313
43361
|
}, () => [this.props.composerStore.editionMode !== "inactive"]);
|
|
43362
|
+
owl.useEffect(() => {
|
|
43363
|
+
this.contentHelper.scrollSelectionIntoView();
|
|
43364
|
+
}, () => [
|
|
43365
|
+
this.props.composerStore.composerSelection.start,
|
|
43366
|
+
this.props.composerStore.composerSelection.end,
|
|
43367
|
+
]);
|
|
43314
43368
|
}
|
|
43315
43369
|
// ---------------------------------------------------------------------------
|
|
43316
43370
|
// Handlers
|
|
@@ -43533,6 +43587,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43533
43587
|
// not main button, probably a context menu
|
|
43534
43588
|
return;
|
|
43535
43589
|
}
|
|
43590
|
+
this.debouncedHover.stopDebounce();
|
|
43536
43591
|
this.contentHelper.removeSelection();
|
|
43537
43592
|
}
|
|
43538
43593
|
onMouseup() {
|
|
@@ -43611,7 +43666,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43611
43666
|
const { start, end } = this.props.composerStore.composerSelection;
|
|
43612
43667
|
this.contentHelper.selectRange(start, end);
|
|
43613
43668
|
}
|
|
43614
|
-
this.contentHelper.scrollSelectionIntoView();
|
|
43615
43669
|
}
|
|
43616
43670
|
this.shouldProcessInputEvents = true;
|
|
43617
43671
|
}
|
|
@@ -61477,7 +61531,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61477
61531
|
const ranges = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData));
|
|
61478
61532
|
const union = this.getters.getRangesUnion(ranges);
|
|
61479
61533
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
61480
|
-
|
|
61534
|
+
if (mergesInTarget.length) {
|
|
61535
|
+
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
61536
|
+
}
|
|
61481
61537
|
const id = this.consumeNextId();
|
|
61482
61538
|
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
61483
61539
|
const newTable = cmd.tableType === "dynamic"
|
|
@@ -61576,14 +61632,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61576
61632
|
const zoneToCheckIfEmpty = direction === "down"
|
|
61577
61633
|
? { ...zone, bottom: zone.bottom + 1, top: zone.bottom + 1 }
|
|
61578
61634
|
: { ...zone, right: zone.right + 1, left: zone.right + 1 };
|
|
61579
|
-
for (
|
|
61580
|
-
|
|
61581
|
-
|
|
61582
|
-
|
|
61583
|
-
|
|
61584
|
-
|
|
61585
|
-
|
|
61586
|
-
|
|
61635
|
+
for (let row = zoneToCheckIfEmpty.top; row <= zoneToCheckIfEmpty.bottom; row++) {
|
|
61636
|
+
for (let col = zoneToCheckIfEmpty.left; col <= zoneToCheckIfEmpty.right; col++) {
|
|
61637
|
+
const cellPosition = { sheetId, col, row };
|
|
61638
|
+
// Since this plugin is loaded before CellPlugin, the getters still give us the old cell content
|
|
61639
|
+
const cellContent = this.getters.getCell(cellPosition)?.content;
|
|
61640
|
+
if (cellContent ||
|
|
61641
|
+
this.getters.isInMerge(cellPosition) ||
|
|
61642
|
+
this.getTablesOverlappingZones(sheetId, [positionToZone(cellPosition)]).length) {
|
|
61643
|
+
return "none";
|
|
61644
|
+
}
|
|
61587
61645
|
}
|
|
61588
61646
|
}
|
|
61589
61647
|
return direction;
|
|
@@ -67752,10 +67810,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67752
67810
|
*/
|
|
67753
67811
|
function transformAll(toTransform, executed) {
|
|
67754
67812
|
let transformedCommands = [...toTransform];
|
|
67813
|
+
const possibleTransformations = new Set(otRegistry.getKeys());
|
|
67755
67814
|
for (const executedCommand of executed) {
|
|
67756
|
-
|
|
67757
|
-
|
|
67758
|
-
|
|
67815
|
+
// If the executed command is not in the registry, we skip it
|
|
67816
|
+
// because we know there won't be any transformation impacting the
|
|
67817
|
+
// commands to transform.
|
|
67818
|
+
if (possibleTransformations.has(executedCommand.type)) {
|
|
67819
|
+
transformedCommands = transformedCommands.reduce((acc, cmd) => {
|
|
67820
|
+
const transformed = transform(cmd, executedCommand);
|
|
67821
|
+
if (transformed) {
|
|
67822
|
+
acc.push(transformed);
|
|
67823
|
+
}
|
|
67824
|
+
return acc;
|
|
67825
|
+
}, []);
|
|
67826
|
+
}
|
|
67759
67827
|
}
|
|
67760
67828
|
return transformedCommands;
|
|
67761
67829
|
}
|
|
@@ -69457,7 +69525,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
69457
69525
|
}
|
|
69458
69526
|
const position = this.getters.getCellPosition(cell.id);
|
|
69459
69527
|
const colSize = this.getters.getColSize(sheetId, position.col);
|
|
69460
|
-
if (cell.isFormula) {
|
|
69528
|
+
if (cell.isFormula || this.getters.getArrayFormulaSpreadingOn(position)) {
|
|
69461
69529
|
const content = this.getters.getEvaluatedCell(position).formattedValue;
|
|
69462
69530
|
const evaluatedSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
|
|
69463
69531
|
if (evaluatedSize > evaluatedRowSize && evaluatedSize > DEFAULT_CELL_HEIGHT) {
|
|
@@ -71209,9 +71277,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71209
71277
|
const filteredZone = filter.filteredRange?.zone;
|
|
71210
71278
|
if (!filteredValues || !filteredZone)
|
|
71211
71279
|
continue;
|
|
71280
|
+
const filteredValuesSet = new Set(filteredValues);
|
|
71212
71281
|
for (let row = filteredZone.top; row <= filteredZone.bottom; row++) {
|
|
71213
71282
|
const value = this.getCellValueAsString(sheetId, filter.col, row);
|
|
71214
|
-
if (
|
|
71283
|
+
if (filteredValuesSet.has(value)) {
|
|
71215
71284
|
hiddenRows.add(row);
|
|
71216
71285
|
}
|
|
71217
71286
|
}
|
|
@@ -80641,9 +80710,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
80641
80710
|
exports.tokenize = tokenize;
|
|
80642
80711
|
|
|
80643
80712
|
|
|
80644
|
-
__info__.version = "18.3.
|
|
80645
|
-
__info__.date = "2025-06-
|
|
80646
|
-
__info__.hash = "
|
|
80713
|
+
__info__.version = "18.3.9";
|
|
80714
|
+
__info__.date = "2025-06-19T18:24:02.754Z";
|
|
80715
|
+
__info__.hash = "a820230";
|
|
80647
80716
|
|
|
80648
80717
|
|
|
80649
80718
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|