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