@odoo/o-spreadsheet 17.4.2 → 17.4.4
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 +217 -195
- package/dist/o-spreadsheet.d.ts +3 -1
- package/dist/o-spreadsheet.esm.js +217 -195
- package/dist/o-spreadsheet.iife.js +217 -195
- package/dist/o-spreadsheet.iife.min.js +361 -351
- package/dist/o_spreadsheet.xml +10 -7
- package/package.json +2 -2
|
@@ -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.4.
|
|
6
|
-
* @date 2024-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.4.4
|
|
6
|
+
* @date 2024-08-09T12:24:07.798Z
|
|
7
|
+
* @hash a43e855
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -2767,13 +2767,16 @@ const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
|
|
|
2767
2767
|
}
|
|
2768
2768
|
return new RegExp("^" + exp + "$", "i");
|
|
2769
2769
|
});
|
|
2770
|
-
function evaluatePredicate(value = "", criterion) {
|
|
2770
|
+
function evaluatePredicate(value = "", criterion, locale) {
|
|
2771
2771
|
const { operator, operand } = criterion;
|
|
2772
2772
|
if (operand === undefined || value === null || operand === null) {
|
|
2773
2773
|
return false;
|
|
2774
2774
|
}
|
|
2775
2775
|
if (typeof operand === "number" && operator === "=") {
|
|
2776
|
-
|
|
2776
|
+
if (typeof value === "string" && (isNumber(value, locale) || isDateTime(value, locale))) {
|
|
2777
|
+
return toNumber(value, locale) === operand;
|
|
2778
|
+
}
|
|
2779
|
+
return value === operand;
|
|
2777
2780
|
}
|
|
2778
2781
|
if (operator === "<>" || operator === "=") {
|
|
2779
2782
|
let result;
|
|
@@ -2855,7 +2858,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
|
|
|
2855
2858
|
for (let k = 0; k < countArg - 1; k += 2) {
|
|
2856
2859
|
const criteriaValue = toMatrix(args[k])[i][j].value;
|
|
2857
2860
|
const criterion = predicates[k / 2];
|
|
2858
|
-
validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
|
|
2861
|
+
validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion, locale);
|
|
2859
2862
|
if (!validatedPredicates) {
|
|
2860
2863
|
break;
|
|
2861
2864
|
}
|
|
@@ -6546,6 +6549,9 @@ function toNormalizedPivotValue(dimension, groupValue) {
|
|
|
6546
6549
|
const groupValueString = typeof groupValue === "boolean"
|
|
6547
6550
|
? toString(groupValue).toLocaleLowerCase()
|
|
6548
6551
|
: toString(groupValue);
|
|
6552
|
+
if (groupValueString === "null") {
|
|
6553
|
+
return null;
|
|
6554
|
+
}
|
|
6549
6555
|
if (!pivotNormalizationValueRegistry.contains(dimension.type)) {
|
|
6550
6556
|
throw new EvaluationError(_t("Field %(field)s is not supported because of its type (%(type)s)", {
|
|
6551
6557
|
field: dimension.displayName,
|
|
@@ -6566,6 +6572,9 @@ function normalizeDateTime(value, granularity) {
|
|
|
6566
6572
|
return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
|
|
6567
6573
|
}
|
|
6568
6574
|
function toFunctionPivotValue(value, dimension) {
|
|
6575
|
+
if (value === null) {
|
|
6576
|
+
return `"null"`;
|
|
6577
|
+
}
|
|
6569
6578
|
if (!pivotToFunctionValueRegistry.contains(dimension.type)) {
|
|
6570
6579
|
return `"${value}"`;
|
|
6571
6580
|
}
|
|
@@ -10569,6 +10578,18 @@ function getDefinedAxis(definition) {
|
|
|
10569
10578
|
useLeftAxis ||= !useRightAxis;
|
|
10570
10579
|
return { useLeftAxis, useRightAxis };
|
|
10571
10580
|
}
|
|
10581
|
+
function formatTickValue(localeFormat) {
|
|
10582
|
+
return (value) => {
|
|
10583
|
+
value = Number(value);
|
|
10584
|
+
if (isNaN(value))
|
|
10585
|
+
return value;
|
|
10586
|
+
const { locale, format } = localeFormat;
|
|
10587
|
+
return formatValue(value, {
|
|
10588
|
+
locale,
|
|
10589
|
+
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
10590
|
+
});
|
|
10591
|
+
};
|
|
10592
|
+
}
|
|
10572
10593
|
|
|
10573
10594
|
/** This is a chartJS plugin that will draw the values of each data next to the point/bar/pie slice */
|
|
10574
10595
|
const chartShowValuesPlugin = {
|
|
@@ -19117,6 +19138,7 @@ const PIVOT_VALUE = {
|
|
|
19117
19138
|
const pivot = this.getters.getPivot(pivotId);
|
|
19118
19139
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
19119
19140
|
addPivotDependencies(this, coreDefinition);
|
|
19141
|
+
pivot.init({ reload: pivot.needsReevaluation });
|
|
19120
19142
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19121
19143
|
if (error) {
|
|
19122
19144
|
return error;
|
|
@@ -19145,6 +19167,7 @@ const PIVOT_HEADER = {
|
|
|
19145
19167
|
const pivot = this.getters.getPivot(_pivotId);
|
|
19146
19168
|
const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
|
|
19147
19169
|
addPivotDependencies(this, coreDefinition);
|
|
19170
|
+
pivot.init({ reload: pivot.needsReevaluation });
|
|
19148
19171
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19149
19172
|
if (error) {
|
|
19150
19173
|
return error;
|
|
@@ -20362,14 +20385,6 @@ for (let category of categories) {
|
|
|
20362
20385
|
}
|
|
20363
20386
|
const notAvailableError = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
|
|
20364
20387
|
function createComputeFunction(descr, functionName) {
|
|
20365
|
-
function runtimeCompute(...args) {
|
|
20366
|
-
try {
|
|
20367
|
-
return vectorizedCompute.apply(this, args);
|
|
20368
|
-
}
|
|
20369
|
-
catch (e) {
|
|
20370
|
-
return handleError(e, functionName);
|
|
20371
|
-
}
|
|
20372
|
-
}
|
|
20373
20388
|
function vectorizedCompute(...args) {
|
|
20374
20389
|
let countVectorizableCol = 1;
|
|
20375
20390
|
let countVectorizableRow = 1;
|
|
@@ -20410,13 +20425,13 @@ function createComputeFunction(descr, functionName) {
|
|
|
20410
20425
|
}
|
|
20411
20426
|
}
|
|
20412
20427
|
if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
|
|
20413
|
-
throw new BadExpressionError(_t("Function
|
|
20428
|
+
throw new BadExpressionError(_t("Function %s expects the parameter '%s' to be reference to a cell or range.", functionName, (i + 1).toString()));
|
|
20414
20429
|
}
|
|
20415
20430
|
}
|
|
20416
20431
|
//#endregion
|
|
20417
20432
|
if (countVectorizableCol === 1 && countVectorizableRow === 1) {
|
|
20418
20433
|
// either this function is not vectorized or it ends up with a 1x1 dimension
|
|
20419
|
-
return
|
|
20434
|
+
return errorHandlingCompute.apply(this, args);
|
|
20420
20435
|
}
|
|
20421
20436
|
const getArgOffset = (i, j) => args.map((arg, index) => {
|
|
20422
20437
|
switch (vectorArgsType?.[index]) {
|
|
@@ -20434,7 +20449,7 @@ function createComputeFunction(descr, functionName) {
|
|
|
20434
20449
|
if (col > vectorizableColLimit - 1 || row > vectorizableRowLimit - 1) {
|
|
20435
20450
|
return notAvailableError;
|
|
20436
20451
|
}
|
|
20437
|
-
const singleCellComputeResult =
|
|
20452
|
+
const singleCellComputeResult = errorHandlingCompute.apply(this, getArgOffset(col, row));
|
|
20438
20453
|
// In the case where the user tries to vectorize arguments of an array formula, we will get an
|
|
20439
20454
|
// array for every combination of the vectorized arguments, which will lead to a 3D matrix and
|
|
20440
20455
|
// we won't be able to return the values.
|
|
@@ -20449,6 +20464,14 @@ function createComputeFunction(descr, functionName) {
|
|
|
20449
20464
|
: singleCellComputeResult;
|
|
20450
20465
|
});
|
|
20451
20466
|
}
|
|
20467
|
+
function errorHandlingCompute(...args) {
|
|
20468
|
+
try {
|
|
20469
|
+
return computeFunctionToObject.apply(this, args);
|
|
20470
|
+
}
|
|
20471
|
+
catch (e) {
|
|
20472
|
+
return handleError(e, functionName);
|
|
20473
|
+
}
|
|
20474
|
+
}
|
|
20452
20475
|
function computeFunctionToObject(...args) {
|
|
20453
20476
|
const result = descr.compute.apply(this, args);
|
|
20454
20477
|
if (!isMatrix(result)) {
|
|
@@ -20464,7 +20487,7 @@ function createComputeFunction(descr, functionName) {
|
|
|
20464
20487
|
}
|
|
20465
20488
|
return matrixMap(result, (row) => ({ value: row }));
|
|
20466
20489
|
}
|
|
20467
|
-
return
|
|
20490
|
+
return vectorizedCompute;
|
|
20468
20491
|
}
|
|
20469
20492
|
function handleError(e, functionName) {
|
|
20470
20493
|
// the error could be an user error (instance of EvaluationError)
|
|
@@ -20781,6 +20804,78 @@ function isCtrlKey(ev) {
|
|
|
20781
20804
|
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
20782
20805
|
}
|
|
20783
20806
|
|
|
20807
|
+
/**
|
|
20808
|
+
* Return the o-spreadsheet element position relative
|
|
20809
|
+
* to the browser viewport.
|
|
20810
|
+
*/
|
|
20811
|
+
function useSpreadsheetRect() {
|
|
20812
|
+
const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
20813
|
+
let spreadsheetElement = null;
|
|
20814
|
+
function updatePosition() {
|
|
20815
|
+
if (!spreadsheetElement) {
|
|
20816
|
+
spreadsheetElement = document.querySelector(".o-spreadsheet");
|
|
20817
|
+
}
|
|
20818
|
+
if (spreadsheetElement) {
|
|
20819
|
+
const { top, left, width, height } = spreadsheetElement.getBoundingClientRect();
|
|
20820
|
+
position.x = left;
|
|
20821
|
+
position.y = top;
|
|
20822
|
+
position.width = width;
|
|
20823
|
+
position.height = height;
|
|
20824
|
+
}
|
|
20825
|
+
}
|
|
20826
|
+
owl.onMounted(updatePosition);
|
|
20827
|
+
owl.onPatched(updatePosition);
|
|
20828
|
+
return position;
|
|
20829
|
+
}
|
|
20830
|
+
/**
|
|
20831
|
+
* Return the component (or ref's component) BoundingRect, relative
|
|
20832
|
+
* to the upper left corner of the screen (<body> element).
|
|
20833
|
+
*
|
|
20834
|
+
* Note: when used with a <Portal/> component, it will
|
|
20835
|
+
* return the portal position, not the teleported position.
|
|
20836
|
+
*/
|
|
20837
|
+
function useAbsoluteBoundingRect(ref) {
|
|
20838
|
+
const rect = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
20839
|
+
function updateElRect() {
|
|
20840
|
+
const el = ref.el;
|
|
20841
|
+
if (el === null) {
|
|
20842
|
+
return;
|
|
20843
|
+
}
|
|
20844
|
+
const { top, left, width, height } = el.getBoundingClientRect();
|
|
20845
|
+
rect.x = left;
|
|
20846
|
+
rect.y = top;
|
|
20847
|
+
rect.width = width;
|
|
20848
|
+
rect.height = height;
|
|
20849
|
+
}
|
|
20850
|
+
owl.onMounted(updateElRect);
|
|
20851
|
+
owl.onPatched(updateElRect);
|
|
20852
|
+
return rect;
|
|
20853
|
+
}
|
|
20854
|
+
/**
|
|
20855
|
+
* Get the rectangle inside which a popover should stay when being displayed.
|
|
20856
|
+
* It's the value defined in `env.getPopoverContainerRect`, or the Rect of the "o-spreadsheet"
|
|
20857
|
+
* element by default.
|
|
20858
|
+
*
|
|
20859
|
+
* Coordinates are expressed expressed as absolute DOM position.
|
|
20860
|
+
*/
|
|
20861
|
+
function usePopoverContainer() {
|
|
20862
|
+
const container = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
20863
|
+
const component = owl.useComponent();
|
|
20864
|
+
const spreadsheetRect = useSpreadsheetRect();
|
|
20865
|
+
function updateRect() {
|
|
20866
|
+
const env = component.env;
|
|
20867
|
+
const newRect = "getPopoverContainerRect" in env ? env.getPopoverContainerRect() : spreadsheetRect;
|
|
20868
|
+
container.x = newRect.x;
|
|
20869
|
+
container.y = newRect.y;
|
|
20870
|
+
container.width = newRect.width;
|
|
20871
|
+
container.height = newRect.height;
|
|
20872
|
+
}
|
|
20873
|
+
updateRect();
|
|
20874
|
+
owl.onMounted(updateRect);
|
|
20875
|
+
owl.onPatched(updateRect);
|
|
20876
|
+
return container;
|
|
20877
|
+
}
|
|
20878
|
+
|
|
20784
20879
|
const arrowMap = {
|
|
20785
20880
|
ArrowDown: "down",
|
|
20786
20881
|
ArrowLeft: "left",
|
|
@@ -21370,7 +21465,9 @@ class Composer extends owl.Component {
|
|
|
21370
21465
|
argToFocus: 0,
|
|
21371
21466
|
});
|
|
21372
21467
|
compositionActive = false;
|
|
21468
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
21373
21469
|
get assistantStyle() {
|
|
21470
|
+
const composerRect = this.composerRef.el.getBoundingClientRect();
|
|
21374
21471
|
const assistantStyle = {};
|
|
21375
21472
|
assistantStyle["min-width"] = `${this.props.rect?.width || ASSISTANT_WIDTH}px`;
|
|
21376
21473
|
const proposals = this.autoCompleteState.provider?.proposals;
|
|
@@ -21397,6 +21494,9 @@ class Composer extends owl.Component {
|
|
|
21397
21494
|
}
|
|
21398
21495
|
else if (this.props.delimitation) {
|
|
21399
21496
|
assistantStyle["max-height"] = `${this.props.delimitation.height}px`;
|
|
21497
|
+
if (composerRect.left + ASSISTANT_WIDTH > this.spreadsheetRect.width) {
|
|
21498
|
+
assistantStyle.right = `0px`;
|
|
21499
|
+
}
|
|
21400
21500
|
}
|
|
21401
21501
|
return cssPropertiesToCss(assistantStyle);
|
|
21402
21502
|
}
|
|
@@ -23608,23 +23708,13 @@ function getBarConfiguration(chart, labels, localeFormat) {
|
|
|
23608
23708
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
23609
23709
|
};
|
|
23610
23710
|
config.options.indexAxis = chart.horizontal ? "y" : "x";
|
|
23611
|
-
const formatCallback = (value) => {
|
|
23612
|
-
value = Number(value);
|
|
23613
|
-
if (isNaN(value))
|
|
23614
|
-
return value;
|
|
23615
|
-
const { locale, format } = localeFormat;
|
|
23616
|
-
return formatValue(value, {
|
|
23617
|
-
locale,
|
|
23618
|
-
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
23619
|
-
});
|
|
23620
|
-
};
|
|
23621
23711
|
config.options.scales = {};
|
|
23622
23712
|
const labelsAxis = { ticks: { padding: 5, color: fontColor } };
|
|
23623
23713
|
const valuesAxis = {
|
|
23624
23714
|
beginAtZero: true, // the origin of the y axis is always zero
|
|
23625
23715
|
ticks: {
|
|
23626
23716
|
color: fontColor,
|
|
23627
|
-
callback:
|
|
23717
|
+
callback: formatTickValue(localeFormat),
|
|
23628
23718
|
},
|
|
23629
23719
|
};
|
|
23630
23720
|
const xAxis = chart.horizontal ? valuesAxis : labelsAxis;
|
|
@@ -23661,7 +23751,7 @@ function getBarConfiguration(chart, labels, localeFormat) {
|
|
|
23661
23751
|
showValues: chart.showValues,
|
|
23662
23752
|
background: chart.background,
|
|
23663
23753
|
horizontal: chart.horizontal,
|
|
23664
|
-
callback:
|
|
23754
|
+
callback: formatTickValue(localeFormat),
|
|
23665
23755
|
};
|
|
23666
23756
|
return config;
|
|
23667
23757
|
}
|
|
@@ -23940,21 +24030,11 @@ function getLineOrScatterConfiguration(chart, labels, options) {
|
|
|
23940
24030
|
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
23941
24031
|
},
|
|
23942
24032
|
};
|
|
23943
|
-
const formatCallback = (value) => {
|
|
23944
|
-
value = Number(value);
|
|
23945
|
-
if (isNaN(value))
|
|
23946
|
-
return value;
|
|
23947
|
-
const { locale, format } = options;
|
|
23948
|
-
return formatValue(value, {
|
|
23949
|
-
locale,
|
|
23950
|
-
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
23951
|
-
});
|
|
23952
|
-
};
|
|
23953
24033
|
const yAxis = {
|
|
23954
24034
|
beginAtZero: true, // the origin of the y axis is always zero
|
|
23955
24035
|
ticks: {
|
|
23956
24036
|
color: fontColor,
|
|
23957
|
-
callback:
|
|
24037
|
+
callback: formatTickValue(options),
|
|
23958
24038
|
},
|
|
23959
24039
|
};
|
|
23960
24040
|
const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition());
|
|
@@ -23985,7 +24065,7 @@ function getLineOrScatterConfiguration(chart, labels, options) {
|
|
|
23985
24065
|
config.options.plugins.chartShowValuesPlugin = {
|
|
23986
24066
|
showValues: chart.showValues,
|
|
23987
24067
|
background: chart.background,
|
|
23988
|
-
callback:
|
|
24068
|
+
callback: formatTickValue(options),
|
|
23989
24069
|
};
|
|
23990
24070
|
return config;
|
|
23991
24071
|
}
|
|
@@ -24260,30 +24340,18 @@ function createComboChartRuntime(chart, getters) {
|
|
|
24260
24340
|
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
24261
24341
|
},
|
|
24262
24342
|
};
|
|
24263
|
-
const formatCallback = (format) => {
|
|
24264
|
-
return (value) => {
|
|
24265
|
-
value = Number(value);
|
|
24266
|
-
if (isNaN(value))
|
|
24267
|
-
return value;
|
|
24268
|
-
const { locale } = localeFormat;
|
|
24269
|
-
return formatValue(value, {
|
|
24270
|
-
locale,
|
|
24271
|
-
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
24272
|
-
});
|
|
24273
|
-
};
|
|
24274
|
-
};
|
|
24275
24343
|
const leftVerticalAxis = {
|
|
24276
24344
|
beginAtZero: true, // the origin of the y axis is always zero
|
|
24277
24345
|
ticks: {
|
|
24278
24346
|
color: fontColor,
|
|
24279
|
-
callback:
|
|
24347
|
+
callback: formatTickValue({ format: mainDataSetFormat, locale }),
|
|
24280
24348
|
},
|
|
24281
24349
|
};
|
|
24282
24350
|
const rightVerticalAxis = {
|
|
24283
24351
|
beginAtZero: true, // the origin of the y axis is always zero
|
|
24284
24352
|
ticks: {
|
|
24285
24353
|
color: fontColor,
|
|
24286
|
-
callback:
|
|
24354
|
+
callback: formatTickValue({ format: lineDataSetsFormat, locale }),
|
|
24287
24355
|
},
|
|
24288
24356
|
};
|
|
24289
24357
|
const definition = chart.getDefinition();
|
|
@@ -24308,7 +24376,7 @@ function createComboChartRuntime(chart, getters) {
|
|
|
24308
24376
|
config.options.plugins.chartShowValuesPlugin = {
|
|
24309
24377
|
showValues: chart.showValues,
|
|
24310
24378
|
background: chart.background,
|
|
24311
|
-
callback:
|
|
24379
|
+
callback: formatTickValue({ format: mainDataSetFormat, locale }),
|
|
24312
24380
|
};
|
|
24313
24381
|
const colors = new ColorGenerator();
|
|
24314
24382
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
@@ -24840,7 +24908,10 @@ function getPieConfiguration(chart, labels, localeFormat) {
|
|
|
24840
24908
|
const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
|
|
24841
24909
|
return xLabel ? `${xLabel}: ${yLabelStr} (${percentage}%)` : `${yLabelStr} (${percentage}%)`;
|
|
24842
24910
|
};
|
|
24843
|
-
config.options.plugins.chartShowValuesPlugin = {
|
|
24911
|
+
config.options.plugins.chartShowValuesPlugin = {
|
|
24912
|
+
showValues: chart.showValues,
|
|
24913
|
+
callback: formatTickValue(localeFormat),
|
|
24914
|
+
};
|
|
24844
24915
|
return config;
|
|
24845
24916
|
}
|
|
24846
24917
|
function getPieColors(colors, dataSetsValues) {
|
|
@@ -25424,6 +25495,7 @@ function getWaterfallConfiguration(chart, labels, dataSeriesLabels, localeFormat
|
|
|
25424
25495
|
config.options.plugins.chartShowValuesPlugin = {
|
|
25425
25496
|
showValues: chart.showValues,
|
|
25426
25497
|
background: chart.background,
|
|
25498
|
+
callback: formatTickValue(localeFormat),
|
|
25427
25499
|
};
|
|
25428
25500
|
return config;
|
|
25429
25501
|
}
|
|
@@ -26239,78 +26311,6 @@ function zoneToRect(zone) {
|
|
|
26239
26311
|
};
|
|
26240
26312
|
}
|
|
26241
26313
|
|
|
26242
|
-
/**
|
|
26243
|
-
* Return the o-spreadsheet element position relative
|
|
26244
|
-
* to the browser viewport.
|
|
26245
|
-
*/
|
|
26246
|
-
function useSpreadsheetRect() {
|
|
26247
|
-
const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
26248
|
-
let spreadsheetElement = null;
|
|
26249
|
-
function updatePosition() {
|
|
26250
|
-
if (!spreadsheetElement) {
|
|
26251
|
-
spreadsheetElement = document.querySelector(".o-spreadsheet");
|
|
26252
|
-
}
|
|
26253
|
-
if (spreadsheetElement) {
|
|
26254
|
-
const { top, left, width, height } = spreadsheetElement.getBoundingClientRect();
|
|
26255
|
-
position.x = left;
|
|
26256
|
-
position.y = top;
|
|
26257
|
-
position.width = width;
|
|
26258
|
-
position.height = height;
|
|
26259
|
-
}
|
|
26260
|
-
}
|
|
26261
|
-
owl.onMounted(updatePosition);
|
|
26262
|
-
owl.onPatched(updatePosition);
|
|
26263
|
-
return position;
|
|
26264
|
-
}
|
|
26265
|
-
/**
|
|
26266
|
-
* Return the component (or ref's component) BoundingRect, relative
|
|
26267
|
-
* to the upper left corner of the screen (<body> element).
|
|
26268
|
-
*
|
|
26269
|
-
* Note: when used with a <Portal/> component, it will
|
|
26270
|
-
* return the portal position, not the teleported position.
|
|
26271
|
-
*/
|
|
26272
|
-
function useAbsoluteBoundingRect(ref) {
|
|
26273
|
-
const rect = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
26274
|
-
function updateElRect() {
|
|
26275
|
-
const el = ref.el;
|
|
26276
|
-
if (el === null) {
|
|
26277
|
-
return;
|
|
26278
|
-
}
|
|
26279
|
-
const { top, left, width, height } = el.getBoundingClientRect();
|
|
26280
|
-
rect.x = left;
|
|
26281
|
-
rect.y = top;
|
|
26282
|
-
rect.width = width;
|
|
26283
|
-
rect.height = height;
|
|
26284
|
-
}
|
|
26285
|
-
owl.onMounted(updateElRect);
|
|
26286
|
-
owl.onPatched(updateElRect);
|
|
26287
|
-
return rect;
|
|
26288
|
-
}
|
|
26289
|
-
/**
|
|
26290
|
-
* Get the rectangle inside which a popover should stay when being displayed.
|
|
26291
|
-
* It's the value defined in `env.getPopoverContainerRect`, or the Rect of the "o-spreadsheet"
|
|
26292
|
-
* element by default.
|
|
26293
|
-
*
|
|
26294
|
-
* Coordinates are expressed expressed as absolute DOM position.
|
|
26295
|
-
*/
|
|
26296
|
-
function usePopoverContainer() {
|
|
26297
|
-
const container = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
26298
|
-
const component = owl.useComponent();
|
|
26299
|
-
const spreadsheetRect = useSpreadsheetRect();
|
|
26300
|
-
function updateRect() {
|
|
26301
|
-
const env = component.env;
|
|
26302
|
-
const newRect = "getPopoverContainerRect" in env ? env.getPopoverContainerRect() : spreadsheetRect;
|
|
26303
|
-
container.x = newRect.x;
|
|
26304
|
-
container.y = newRect.y;
|
|
26305
|
-
container.width = newRect.width;
|
|
26306
|
-
container.height = newRect.height;
|
|
26307
|
-
}
|
|
26308
|
-
updateRect();
|
|
26309
|
-
owl.onMounted(updateRect);
|
|
26310
|
-
owl.onPatched(updateRect);
|
|
26311
|
-
return container;
|
|
26312
|
-
}
|
|
26313
|
-
|
|
26314
26314
|
css /* scss */ `
|
|
26315
26315
|
.o-popover {
|
|
26316
26316
|
position: absolute;
|
|
@@ -35809,6 +35809,14 @@ css /* scss */ `
|
|
|
35809
35809
|
.pivot-dim-operator-label {
|
|
35810
35810
|
min-width: 120px;
|
|
35811
35811
|
}
|
|
35812
|
+
|
|
35813
|
+
&.pivot-dimension-invalid {
|
|
35814
|
+
background-color: #ffdddd;
|
|
35815
|
+
border-color: red !important;
|
|
35816
|
+
select {
|
|
35817
|
+
background-color: #ffdddd;
|
|
35818
|
+
}
|
|
35819
|
+
}
|
|
35812
35820
|
}
|
|
35813
35821
|
`;
|
|
35814
35822
|
class PivotDimension extends owl.Component {
|
|
@@ -47216,12 +47224,13 @@ class BordersPlugin extends CorePlugin {
|
|
|
47216
47224
|
this.clearBorders(cmd.sheetId, cmd.target);
|
|
47217
47225
|
break;
|
|
47218
47226
|
case "REMOVE_COLUMNS_ROWS":
|
|
47219
|
-
|
|
47227
|
+
const elements = [...cmd.elements].sort((a, b) => b - a);
|
|
47228
|
+
for (const group of groupConsecutive(elements)) {
|
|
47220
47229
|
if (cmd.dimension === "COL") {
|
|
47221
|
-
this.shiftBordersHorizontally(cmd.sheetId,
|
|
47230
|
+
this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
|
|
47222
47231
|
}
|
|
47223
47232
|
else {
|
|
47224
|
-
this.shiftBordersVertically(cmd.sheetId,
|
|
47233
|
+
this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
|
|
47225
47234
|
}
|
|
47226
47235
|
}
|
|
47227
47236
|
break;
|
|
@@ -50391,7 +50400,7 @@ class RangeAdapter {
|
|
|
50391
50400
|
* @param sheetXC the string description of a range, in the form SheetName!XC:XC
|
|
50392
50401
|
*/
|
|
50393
50402
|
getRangeFromSheetXC(defaultSheetId, sheetXC) {
|
|
50394
|
-
if (!rangeReference.test(sheetXC)) {
|
|
50403
|
+
if (!rangeReference.test(sheetXC) || !this.getters.tryGetSheet(defaultSheetId)) {
|
|
50395
50404
|
return new RangeImpl({
|
|
50396
50405
|
sheetId: "",
|
|
50397
50406
|
zone: { left: -1, top: -1, right: -1, bottom: -1 },
|
|
@@ -51282,12 +51291,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
51282
51291
|
});
|
|
51283
51292
|
}
|
|
51284
51293
|
if (colIndex > deletedColumn) {
|
|
51285
|
-
this.
|
|
51286
|
-
sheetId: sheet.id,
|
|
51287
|
-
cellId: cellId,
|
|
51288
|
-
col: colIndex - 1,
|
|
51289
|
-
row: rowIndex,
|
|
51290
|
-
});
|
|
51294
|
+
this.setNewPosition(cellId, sheet.id, colIndex - 1, rowIndex);
|
|
51291
51295
|
}
|
|
51292
51296
|
}
|
|
51293
51297
|
}
|
|
@@ -51297,7 +51301,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
51297
51301
|
* Move the cells after a column or rows insertion
|
|
51298
51302
|
*/
|
|
51299
51303
|
moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
|
|
51300
|
-
const
|
|
51304
|
+
const updates = [];
|
|
51301
51305
|
for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
|
|
51302
51306
|
const row = sheet.rows[rowIndex];
|
|
51303
51307
|
if (dimension !== "rows" || rowIndex >= addedElement) {
|
|
@@ -51306,20 +51310,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
51306
51310
|
const cellId = row.cells[i];
|
|
51307
51311
|
if (cellId) {
|
|
51308
51312
|
if (dimension === "rows" || colIndex >= addedElement) {
|
|
51309
|
-
|
|
51310
|
-
type: "UPDATE_CELL_POSITION",
|
|
51313
|
+
updates.push({
|
|
51311
51314
|
sheetId: sheet.id,
|
|
51312
51315
|
cellId: cellId,
|
|
51313
51316
|
col: colIndex + (dimension === "columns" ? quantity : 0),
|
|
51314
51317
|
row: rowIndex + (dimension === "rows" ? quantity : 0),
|
|
51318
|
+
type: "UPDATE_CELL_POSITION",
|
|
51315
51319
|
});
|
|
51316
51320
|
}
|
|
51317
51321
|
}
|
|
51318
51322
|
}
|
|
51319
51323
|
}
|
|
51320
51324
|
}
|
|
51321
|
-
for (let
|
|
51322
|
-
this.
|
|
51325
|
+
for (let update of updates.reverse()) {
|
|
51326
|
+
this.updateCellPosition(update);
|
|
51323
51327
|
}
|
|
51324
51328
|
}
|
|
51325
51329
|
/**
|
|
@@ -51352,12 +51356,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
51352
51356
|
const colIndex = Number(i);
|
|
51353
51357
|
const cellId = row.cells[i];
|
|
51354
51358
|
if (cellId) {
|
|
51355
|
-
this.
|
|
51356
|
-
sheetId: sheet.id,
|
|
51357
|
-
cellId: cellId,
|
|
51358
|
-
col: colIndex,
|
|
51359
|
-
row: rowIndex - numberRows,
|
|
51360
|
-
});
|
|
51359
|
+
this.setNewPosition(cellId, sheet.id, colIndex, rowIndex - numberRows);
|
|
51361
51360
|
}
|
|
51362
51361
|
}
|
|
51363
51362
|
}
|
|
@@ -54054,18 +54053,23 @@ class Evaluator {
|
|
|
54054
54053
|
this.evaluate(this.getAllCells());
|
|
54055
54054
|
console.info("evaluate all cells", performance.now() - start, "ms");
|
|
54056
54055
|
}
|
|
54057
|
-
|
|
54058
|
-
|
|
54059
|
-
|
|
54060
|
-
|
|
54061
|
-
|
|
54062
|
-
|
|
54063
|
-
|
|
54056
|
+
evaluateFormulaResult(sheetId, formulaString) {
|
|
54057
|
+
try {
|
|
54058
|
+
const compiledFormula = compile(formulaString);
|
|
54059
|
+
const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
54060
|
+
this.updateCompilationParameters();
|
|
54061
|
+
const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
|
|
54062
|
+
if (isMatrix(result)) {
|
|
54063
|
+
return result;
|
|
54064
|
+
}
|
|
54065
|
+
if (result.value === null) {
|
|
54066
|
+
return { value: 0, format: result.format };
|
|
54067
|
+
}
|
|
54068
|
+
return result;
|
|
54064
54069
|
}
|
|
54065
|
-
|
|
54066
|
-
return
|
|
54070
|
+
catch (error) {
|
|
54071
|
+
return handleError(error, "");
|
|
54067
54072
|
}
|
|
54068
|
-
return result.value;
|
|
54069
54073
|
}
|
|
54070
54074
|
getAllCells() {
|
|
54071
54075
|
const positions = this.createEmptyPositionSet();
|
|
@@ -54123,6 +54127,9 @@ class Evaluator {
|
|
|
54123
54127
|
if (!this.blockedArrayFormulas.has(position)) {
|
|
54124
54128
|
this.invalidateSpreading(position);
|
|
54125
54129
|
}
|
|
54130
|
+
if (this.spreadingRelations.isArrayFormula(position)) {
|
|
54131
|
+
this.spreadingRelations.removeNode(position);
|
|
54132
|
+
}
|
|
54126
54133
|
const cell = this.getters.getCell(position);
|
|
54127
54134
|
if (cell === undefined) {
|
|
54128
54135
|
return EMPTY_CELL;
|
|
@@ -54165,7 +54172,6 @@ class Evaluator {
|
|
|
54165
54172
|
this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
|
|
54166
54173
|
const nbColumns = formulaReturn.length;
|
|
54167
54174
|
const nbRows = formulaReturn[0].length;
|
|
54168
|
-
this.spreadingRelations.removeNode(formulaPosition);
|
|
54169
54175
|
forEachSpreadPositionInMatrix(nbColumns, nbRows, this.updateSpreadRelation(formulaPosition));
|
|
54170
54176
|
this.assertNoMergedCellsInSpreadZone(formulaPosition, formulaReturn);
|
|
54171
54177
|
forEachSpreadPositionInMatrix(nbColumns, nbRows, this.checkCollision(formulaPosition));
|
|
@@ -54426,6 +54432,7 @@ function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId
|
|
|
54426
54432
|
class EvaluationPlugin extends UIPlugin {
|
|
54427
54433
|
static getters = [
|
|
54428
54434
|
"evaluateFormula",
|
|
54435
|
+
"evaluateFormulaResult",
|
|
54429
54436
|
"getCorrespondingFormulaCell",
|
|
54430
54437
|
"getRangeFormattedValues",
|
|
54431
54438
|
"getRangeValues",
|
|
@@ -54485,12 +54492,14 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
54485
54492
|
// Getters
|
|
54486
54493
|
// ---------------------------------------------------------------------------
|
|
54487
54494
|
evaluateFormula(sheetId, formulaString) {
|
|
54488
|
-
|
|
54489
|
-
|
|
54490
|
-
|
|
54491
|
-
catch (error) {
|
|
54492
|
-
return error.value || CellErrorType.GenericError;
|
|
54495
|
+
const result = this.evaluateFormulaResult(sheetId, formulaString);
|
|
54496
|
+
if (isMatrix(result)) {
|
|
54497
|
+
return matrixMap(result, (cell) => cell.value);
|
|
54493
54498
|
}
|
|
54499
|
+
return result.value;
|
|
54500
|
+
}
|
|
54501
|
+
evaluateFormulaResult(sheetId, formulaString) {
|
|
54502
|
+
return this.evaluator.evaluateFormulaResult(sheetId, formulaString);
|
|
54494
54503
|
}
|
|
54495
54504
|
/**
|
|
54496
54505
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -55873,28 +55882,33 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
55873
55882
|
const pivotRow = position.row - mainPosition.row;
|
|
55874
55883
|
return pivotCells[pivotCol][pivotRow];
|
|
55875
55884
|
}
|
|
55876
|
-
|
|
55877
|
-
|
|
55885
|
+
try {
|
|
55886
|
+
if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
|
|
55887
|
+
const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
|
|
55888
|
+
return {
|
|
55889
|
+
type: "MEASURE_HEADER",
|
|
55890
|
+
domain,
|
|
55891
|
+
measure: args.at(-1)?.toString() || "",
|
|
55892
|
+
};
|
|
55893
|
+
}
|
|
55894
|
+
else if (functionName === "PIVOT.HEADER") {
|
|
55895
|
+
const domain = pivot.parseArgsToPivotDomain(args.slice(1).map((value) => ({ value })));
|
|
55896
|
+
return {
|
|
55897
|
+
type: "HEADER",
|
|
55898
|
+
domain,
|
|
55899
|
+
};
|
|
55900
|
+
}
|
|
55901
|
+
const [measure, ...domainArgs] = args.slice(1);
|
|
55902
|
+
const domain = pivot.parseArgsToPivotDomain(domainArgs.map((value) => ({ value })));
|
|
55878
55903
|
return {
|
|
55879
|
-
type: "
|
|
55904
|
+
type: "VALUE",
|
|
55880
55905
|
domain,
|
|
55881
|
-
measure:
|
|
55906
|
+
measure: measure?.toString() || "",
|
|
55882
55907
|
};
|
|
55883
55908
|
}
|
|
55884
|
-
|
|
55885
|
-
|
|
55886
|
-
return {
|
|
55887
|
-
type: "HEADER",
|
|
55888
|
-
domain,
|
|
55889
|
-
};
|
|
55909
|
+
catch (_) {
|
|
55910
|
+
return EMPTY_PIVOT_CELL;
|
|
55890
55911
|
}
|
|
55891
|
-
const [measure, ...domainArgs] = args.slice(1);
|
|
55892
|
-
const domain = pivot.parseArgsToPivotDomain(domainArgs.map((value) => ({ value })));
|
|
55893
|
-
return {
|
|
55894
|
-
type: "VALUE",
|
|
55895
|
-
domain,
|
|
55896
|
-
measure: measure?.toString() || "",
|
|
55897
|
-
};
|
|
55898
55912
|
}
|
|
55899
55913
|
getPivot(pivotId) {
|
|
55900
55914
|
return this.pivots[pivotId];
|
|
@@ -57762,6 +57776,7 @@ class FormatPlugin extends UIPlugin {
|
|
|
57762
57776
|
* evaluated and updated with the number type.
|
|
57763
57777
|
*/
|
|
57764
57778
|
setDecimal(sheetId, zones, step) {
|
|
57779
|
+
const positionsByFormat = {};
|
|
57765
57780
|
// Find the each cell with a number value and get the format
|
|
57766
57781
|
for (const zone of recomputeZones(zones)) {
|
|
57767
57782
|
for (const position of positions(zone)) {
|
|
@@ -57771,15 +57786,20 @@ class FormatPlugin extends UIPlugin {
|
|
|
57771
57786
|
// of the format
|
|
57772
57787
|
this.getters.getLocale();
|
|
57773
57788
|
const newFormat = changeDecimalPlaces(numberFormat, step);
|
|
57774
|
-
|
|
57775
|
-
|
|
57776
|
-
sheetId,
|
|
57777
|
-
target: [positionToZone(position)],
|
|
57778
|
-
format: newFormat,
|
|
57779
|
-
});
|
|
57789
|
+
positionsByFormat[newFormat] = positionsByFormat[newFormat] || [];
|
|
57790
|
+
positionsByFormat[newFormat].push(position);
|
|
57780
57791
|
}
|
|
57781
57792
|
}
|
|
57782
57793
|
}
|
|
57794
|
+
// consolidate all positions with the same format in bigger zones
|
|
57795
|
+
for (const newFormat in positionsByFormat) {
|
|
57796
|
+
const zones = recomputeZones(positionsByFormat[newFormat].map((position) => positionToZone(position)));
|
|
57797
|
+
this.dispatch("SET_FORMATTING", {
|
|
57798
|
+
sheetId,
|
|
57799
|
+
format: newFormat,
|
|
57800
|
+
target: zones,
|
|
57801
|
+
});
|
|
57802
|
+
}
|
|
57783
57803
|
}
|
|
57784
57804
|
/**
|
|
57785
57805
|
* Take a range of cells and return the format of the first cell containing a
|
|
@@ -63090,6 +63110,8 @@ css /* scss */ `
|
|
|
63090
63110
|
|
|
63091
63111
|
.o-sidePanel-handle-container {
|
|
63092
63112
|
width: 8px;
|
|
63113
|
+
position: fixed;
|
|
63114
|
+
top: 50%;
|
|
63093
63115
|
}
|
|
63094
63116
|
.o-sidePanel-handle {
|
|
63095
63117
|
cursor: col-resize;
|
|
@@ -65709,7 +65731,7 @@ function createEmptyStructure(node) {
|
|
|
65709
65731
|
}
|
|
65710
65732
|
|
|
65711
65733
|
class StateObserver {
|
|
65712
|
-
changes
|
|
65734
|
+
changes;
|
|
65713
65735
|
commands = [];
|
|
65714
65736
|
/**
|
|
65715
65737
|
* Record the changes which could happen in the given callback, save them in a
|
|
@@ -65741,7 +65763,7 @@ class StateObserver {
|
|
|
65741
65763
|
if (value[key] === val) {
|
|
65742
65764
|
return;
|
|
65743
65765
|
}
|
|
65744
|
-
this.changes
|
|
65766
|
+
this.changes?.push({
|
|
65745
65767
|
key,
|
|
65746
65768
|
target: value,
|
|
65747
65769
|
before: value[key],
|
|
@@ -68407,6 +68429,6 @@ exports.tokenColors = tokenColors;
|
|
|
68407
68429
|
exports.tokenize = tokenize;
|
|
68408
68430
|
|
|
68409
68431
|
|
|
68410
|
-
__info__.version = "17.4.
|
|
68411
|
-
__info__.date = "2024-
|
|
68412
|
-
__info__.hash = "
|
|
68432
|
+
__info__.version = "17.4.4";
|
|
68433
|
+
__info__.date = "2024-08-09T12:24:07.798Z";
|
|
68434
|
+
__info__.hash = "a43e855";
|