@odoo/o-spreadsheet 18.0.31 → 18.0.33
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 +99 -52
- package/dist/o-spreadsheet.esm.js +99 -52
- package/dist/o-spreadsheet.iife.js +99 -52
- package/dist/o-spreadsheet.iife.min.js +8 -8
- 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.0.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.0.33
|
|
6
|
+
* @date 2025-06-12T09:17:53.747Z
|
|
7
|
+
* @hash c1d64fb
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -5677,7 +5677,9 @@
|
|
|
5677
5677
|
}
|
|
5678
5678
|
|
|
5679
5679
|
function evaluateLiteral(literalCell, localeFormat) {
|
|
5680
|
-
const value = isTextFormat(localeFormat.format)
|
|
5680
|
+
const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
|
|
5681
|
+
? literalCell.content
|
|
5682
|
+
: literalCell.parsedValue;
|
|
5681
5683
|
const functionResult = { value, format: localeFormat.format };
|
|
5682
5684
|
return createEvaluatedCell(functionResult, localeFormat.locale);
|
|
5683
5685
|
}
|
|
@@ -5726,6 +5728,9 @@
|
|
|
5726
5728
|
if (isEvaluationError(value)) {
|
|
5727
5729
|
return errorCell(value, message);
|
|
5728
5730
|
}
|
|
5731
|
+
if (value === null) {
|
|
5732
|
+
return emptyCell(format);
|
|
5733
|
+
}
|
|
5729
5734
|
if (isTextFormat(format)) {
|
|
5730
5735
|
// TO DO:
|
|
5731
5736
|
// with the next line, the value of the cell is transformed depending on the format.
|
|
@@ -5733,9 +5738,6 @@
|
|
|
5733
5738
|
// to interpret the value as a number.
|
|
5734
5739
|
return textCell(toString(value), format, formattedValue);
|
|
5735
5740
|
}
|
|
5736
|
-
if (value === null) {
|
|
5737
|
-
return emptyCell(format);
|
|
5738
|
-
}
|
|
5739
5741
|
if (typeof value === "number") {
|
|
5740
5742
|
if (isDateTimeFormat(format || "")) {
|
|
5741
5743
|
return dateTimeCell(value, format, formattedValue);
|
|
@@ -10121,7 +10123,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10121
10123
|
textsPositions[xPosition].push(yPosition);
|
|
10122
10124
|
ctx.fillStyle = point.options.backgroundColor;
|
|
10123
10125
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
10124
|
-
|
|
10126
|
+
const valueToDisplay = options.callback(Number(value), dataset, i);
|
|
10127
|
+
drawTextWithBackground(valueToDisplay, xPosition, yPosition, ctx);
|
|
10125
10128
|
}
|
|
10126
10129
|
}
|
|
10127
10130
|
}
|
|
@@ -10135,7 +10138,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10135
10138
|
}
|
|
10136
10139
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
10137
10140
|
const value = dataset._parsed[i].x;
|
|
10138
|
-
const displayValue = options.callback(value
|
|
10141
|
+
const displayValue = options.callback(value, dataset, i);
|
|
10139
10142
|
const point = dataset.data[i];
|
|
10140
10143
|
const yPosition = point.y;
|
|
10141
10144
|
let xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
@@ -10170,10 +10173,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10170
10173
|
const midAngle = (startAngle + endAngle) / 2;
|
|
10171
10174
|
const midRadius = (innerRadius + outerRadius) / 2;
|
|
10172
10175
|
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
10173
|
-
const y = bar.y + midRadius * Math.sin(midAngle)
|
|
10176
|
+
const y = bar.y + midRadius * Math.sin(midAngle);
|
|
10177
|
+
const displayValue = options.callback(value, dataset, i);
|
|
10178
|
+
const textHeight = 12; // ChartJS default
|
|
10179
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: textHeight }, "px");
|
|
10180
|
+
const radius = outerRadius - innerRadius;
|
|
10181
|
+
// Check if the text fits in the slice. Not perfect, but good enough heuristic.
|
|
10182
|
+
if (textWidth >= radius || radius < textHeight) {
|
|
10183
|
+
continue;
|
|
10184
|
+
}
|
|
10185
|
+
const sliceAngle = endAngle - startAngle;
|
|
10186
|
+
const midWidth = 2 * midRadius * Math.tan(sliceAngle / 2);
|
|
10187
|
+
if (sliceAngle < Math.PI / 2 && (textWidth >= midWidth || midWidth < textHeight)) {
|
|
10188
|
+
continue;
|
|
10189
|
+
}
|
|
10174
10190
|
ctx.fillStyle = chartFontColor(options.background);
|
|
10175
10191
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
10176
|
-
const displayValue = options.callback(value);
|
|
10177
10192
|
drawTextWithBackground(displayValue, x, y, ctx);
|
|
10178
10193
|
}
|
|
10179
10194
|
}
|
|
@@ -13390,7 +13405,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13390
13405
|
*/
|
|
13391
13406
|
handleMissingValue(parentElement, missingElementName, optionalArgs) {
|
|
13392
13407
|
if (optionalArgs?.required) {
|
|
13393
|
-
if (optionalArgs?.default) {
|
|
13408
|
+
if (optionalArgs?.default !== undefined) {
|
|
13394
13409
|
this.warningManager.addParsingWarning(`Missing required ${missingElementName} in element <${parentElement.tagName}> of ${this.currentFile}, replacing it by the default value ${optionalArgs.default}`);
|
|
13395
13410
|
}
|
|
13396
13411
|
else {
|
|
@@ -30890,7 +30905,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30890
30905
|
return tooltipLabelCallback(tooltipItem);
|
|
30891
30906
|
};
|
|
30892
30907
|
const callback = config.options.plugins.chartShowValuesPlugin.callback;
|
|
30893
|
-
config.options.plugins.chartShowValuesPlugin.callback = (
|
|
30908
|
+
config.options.plugins.chartShowValuesPlugin.callback = (value, dataset, index) => callback(Math.abs(value), dataset, index);
|
|
30894
30909
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
30895
30910
|
}
|
|
30896
30911
|
|
|
@@ -31165,7 +31180,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31165
31180
|
return new WaterfallChart(definition, this.sheetId, this.getters);
|
|
31166
31181
|
}
|
|
31167
31182
|
}
|
|
31168
|
-
function getWaterfallConfiguration(chart, labels, dataSeriesLabels, localeFormat) {
|
|
31183
|
+
function getWaterfallConfiguration(chart, labels, dataSeriesLabels, localeFormat, dataSetsValues) {
|
|
31169
31184
|
const { locale, format } = localeFormat;
|
|
31170
31185
|
const fontColor = chartFontColor(chart.background);
|
|
31171
31186
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
@@ -31258,10 +31273,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31258
31273
|
},
|
|
31259
31274
|
};
|
|
31260
31275
|
config.options.plugins.waterfallLinesPlugin = { showConnectorLines: chart.showConnectorLines };
|
|
31276
|
+
const subtotalIndexes = dataSetsValues.reduce((subtotalIndexes, ds) => {
|
|
31277
|
+
subtotalIndexes.push((subtotalIndexes.at(-1) || -1) + ds.data.length + 1);
|
|
31278
|
+
return subtotalIndexes;
|
|
31279
|
+
}, []);
|
|
31261
31280
|
config.options.plugins.chartShowValuesPlugin = {
|
|
31262
31281
|
showValues: chart.showValues,
|
|
31263
31282
|
background: chart.background,
|
|
31264
|
-
callback:
|
|
31283
|
+
callback: (value, dataset, index) => {
|
|
31284
|
+
const raw = dataset._dataset.data[index];
|
|
31285
|
+
const delta = raw[1] - raw[0];
|
|
31286
|
+
let sign = delta >= 0 ? "+" : "";
|
|
31287
|
+
if (chart.showSubTotals && subtotalIndexes.includes(index) && sign === "+") {
|
|
31288
|
+
sign = "";
|
|
31289
|
+
}
|
|
31290
|
+
return `${sign}${formatTickValue(localeFormat)(delta)}`;
|
|
31291
|
+
},
|
|
31265
31292
|
};
|
|
31266
31293
|
return config;
|
|
31267
31294
|
}
|
|
@@ -31282,10 +31309,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31282
31309
|
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
31283
31310
|
const locale = getters.getLocale();
|
|
31284
31311
|
const dataSeriesLabels = dataSetsValues.map((dataSet) => dataSet.label);
|
|
31285
|
-
const config = getWaterfallConfiguration(chart, labels, dataSeriesLabels, {
|
|
31286
|
-
format: dataSetFormat,
|
|
31287
|
-
locale,
|
|
31288
|
-
});
|
|
31312
|
+
const config = getWaterfallConfiguration(chart, labels, dataSeriesLabels, { format: dataSetFormat, locale }, dataSetsValues);
|
|
31289
31313
|
config.type = "bar";
|
|
31290
31314
|
const negativeColor = chart.negativeValuesColor || CHART_WATERFALL_NEGATIVE_COLOR;
|
|
31291
31315
|
const positiveColor = chart.positiveValuesColor || CHART_WATERFALL_POSITIVE_COLOR;
|
|
@@ -32507,19 +32531,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
32507
32531
|
.filter(({ row }) => !this.env.model.getters.isRowHidden(sheetId, row))
|
|
32508
32532
|
.map(({ col, row }) => this.env.model.getters.getEvaluatedCell({ sheetId, col, row }).formattedValue);
|
|
32509
32533
|
const filterValues = this.env.model.getters.getFilterHiddenValues({ sheetId, ...position });
|
|
32510
|
-
const
|
|
32511
|
-
const
|
|
32512
|
-
|
|
32513
|
-
const
|
|
32514
|
-
|
|
32515
|
-
|
|
32516
|
-
|
|
32517
|
-
|
|
32518
|
-
|
|
32519
|
-
|
|
32520
|
-
|
|
32521
|
-
|
|
32522
|
-
|
|
32534
|
+
const normalizedFilteredValues = new Set(filterValues.map(toLowerCase));
|
|
32535
|
+
const set = new Set();
|
|
32536
|
+
const values = [];
|
|
32537
|
+
const addValue = (value) => {
|
|
32538
|
+
const normalizedValue = toLowerCase(value);
|
|
32539
|
+
if (!set.has(normalizedValue)) {
|
|
32540
|
+
values.push({
|
|
32541
|
+
string: value || "",
|
|
32542
|
+
checked: !normalizedFilteredValues.has(normalizedValue),
|
|
32543
|
+
normalizedValue,
|
|
32544
|
+
});
|
|
32545
|
+
set.add(normalizedValue);
|
|
32546
|
+
}
|
|
32547
|
+
};
|
|
32548
|
+
cellValues.forEach(addValue);
|
|
32549
|
+
filterValues.forEach(addValue);
|
|
32550
|
+
return values.sort((val1, val2) => val1.normalizedValue.localeCompare(val2.normalizedValue, undefined, {
|
|
32551
|
+
numeric: true,
|
|
32552
|
+
sensitivity: "base",
|
|
32553
|
+
}));
|
|
32523
32554
|
}
|
|
32524
32555
|
checkValue(value) {
|
|
32525
32556
|
this.state.selectedValue = value.string;
|
|
@@ -42346,13 +42377,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42346
42377
|
if (this.selectedMatchIndex === null) {
|
|
42347
42378
|
return;
|
|
42348
42379
|
}
|
|
42380
|
+
this.preserveSelectedMatchIndex = true;
|
|
42349
42381
|
this.model.dispatch("REPLACE_SEARCH", {
|
|
42350
42382
|
searchString: this.toSearch,
|
|
42351
42383
|
replaceWith: this.toReplace,
|
|
42352
42384
|
matches: [this.searchMatches[this.selectedMatchIndex]],
|
|
42353
42385
|
searchOptions: this.searchOptions,
|
|
42354
42386
|
});
|
|
42355
|
-
this.
|
|
42387
|
+
this.preserveSelectedMatchIndex = false;
|
|
42356
42388
|
}
|
|
42357
42389
|
/**
|
|
42358
42390
|
* Apply the replace function to all the matches one time.
|
|
@@ -49697,6 +49729,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49697
49729
|
let deltaX = lastX - clientX;
|
|
49698
49730
|
let deltaY = lastY - clientY;
|
|
49699
49731
|
const elapsedTime = currentTime - lastTime;
|
|
49732
|
+
if (!elapsedTime) {
|
|
49733
|
+
return;
|
|
49734
|
+
}
|
|
49700
49735
|
velocityX = deltaX / elapsedTime;
|
|
49701
49736
|
velocityY = deltaY / elapsedTime;
|
|
49702
49737
|
lastX = clientX;
|
|
@@ -49717,6 +49752,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49717
49752
|
function onTouchEnd(ev) {
|
|
49718
49753
|
isMouseDown = false;
|
|
49719
49754
|
lastX = lastY = 0;
|
|
49755
|
+
if (resetTimeout) {
|
|
49756
|
+
clearTimeout(resetTimeout);
|
|
49757
|
+
}
|
|
49758
|
+
velocityX *= 1.2;
|
|
49759
|
+
velocityY *= 1.2;
|
|
49720
49760
|
requestAnimationFrame(scroll);
|
|
49721
49761
|
}
|
|
49722
49762
|
function scroll() {
|
|
@@ -56009,7 +56049,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56009
56049
|
const ranges = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData));
|
|
56010
56050
|
const union = this.getters.getRangesUnion(ranges);
|
|
56011
56051
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
56012
|
-
|
|
56052
|
+
if (mergesInTarget.length) {
|
|
56053
|
+
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
56054
|
+
}
|
|
56013
56055
|
const id = this.uuidGenerator.smallUuid();
|
|
56014
56056
|
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
56015
56057
|
const newTable = cmd.tableType === "dynamic"
|
|
@@ -56120,14 +56162,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56120
56162
|
const zoneToCheckIfEmpty = direction === "down"
|
|
56121
56163
|
? { ...zone, bottom: zone.bottom + 1, top: zone.bottom + 1 }
|
|
56122
56164
|
: { ...zone, right: zone.right + 1, left: zone.right + 1 };
|
|
56123
|
-
for (
|
|
56124
|
-
|
|
56125
|
-
|
|
56126
|
-
|
|
56127
|
-
|
|
56128
|
-
|
|
56129
|
-
|
|
56130
|
-
|
|
56165
|
+
for (let row = zoneToCheckIfEmpty.top; row <= zoneToCheckIfEmpty.bottom; row++) {
|
|
56166
|
+
for (let col = zoneToCheckIfEmpty.left; col <= zoneToCheckIfEmpty.right; col++) {
|
|
56167
|
+
const cellPosition = { sheetId, col, row };
|
|
56168
|
+
// Since this plugin is loaded before CellPlugin, the getters still give us the old cell content
|
|
56169
|
+
const cellContent = this.getters.getCell(cellPosition)?.content;
|
|
56170
|
+
if (cellContent ||
|
|
56171
|
+
this.getters.isInMerge(cellPosition) ||
|
|
56172
|
+
this.getTablesOverlappingZones(sheetId, [positionToZone(cellPosition)]).length) {
|
|
56173
|
+
return "none";
|
|
56174
|
+
}
|
|
56131
56175
|
}
|
|
56132
56176
|
}
|
|
56133
56177
|
return direction;
|
|
@@ -65452,9 +65496,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65452
65496
|
const filteredZone = filter.filteredRange?.zone;
|
|
65453
65497
|
if (!filteredValues || !filteredZone)
|
|
65454
65498
|
continue;
|
|
65499
|
+
const filteredValuesSet = new Set(filteredValues);
|
|
65455
65500
|
for (let row = filteredZone.top; row <= filteredZone.bottom; row++) {
|
|
65456
65501
|
const value = this.getCellValueAsString(sheetId, filter.col, row);
|
|
65457
|
-
if (
|
|
65502
|
+
if (filteredValuesSet.has(value)) {
|
|
65458
65503
|
hiddenRows.add(row);
|
|
65459
65504
|
}
|
|
65460
65505
|
}
|
|
@@ -65969,11 +66014,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65969
66014
|
},
|
|
65970
66015
|
];
|
|
65971
66016
|
const sheetId = this.getActiveSheetId();
|
|
65972
|
-
const handler = new CellClipboardHandler(this.getters, this.dispatch);
|
|
65973
|
-
const data = handler.copy(getClipboardDataPositions(sheetId, target));
|
|
65974
|
-
if (!data) {
|
|
65975
|
-
return;
|
|
65976
|
-
}
|
|
65977
66017
|
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
65978
66018
|
const pasteTarget = [
|
|
65979
66019
|
{
|
|
@@ -65983,7 +66023,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65983
66023
|
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
65984
66024
|
},
|
|
65985
66025
|
];
|
|
65986
|
-
|
|
66026
|
+
for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
|
|
66027
|
+
const handler = new Handler(this.getters, this.dispatch);
|
|
66028
|
+
const data = handler.copy(getClipboardDataPositions(sheetId, target));
|
|
66029
|
+
if (!data) {
|
|
66030
|
+
continue;
|
|
66031
|
+
}
|
|
66032
|
+
handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
|
|
66033
|
+
}
|
|
65987
66034
|
const selection = pasteTarget[0];
|
|
65988
66035
|
const col = selection.left;
|
|
65989
66036
|
const row = selection.top;
|
|
@@ -74399,9 +74446,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74399
74446
|
exports.tokenize = tokenize;
|
|
74400
74447
|
|
|
74401
74448
|
|
|
74402
|
-
__info__.version = "18.0.
|
|
74403
|
-
__info__.date = "2025-
|
|
74404
|
-
__info__.hash = "
|
|
74449
|
+
__info__.version = "18.0.33";
|
|
74450
|
+
__info__.date = "2025-06-12T09:17:53.747Z";
|
|
74451
|
+
__info__.hash = "c1d64fb";
|
|
74405
74452
|
|
|
74406
74453
|
|
|
74407
74454
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|